From 74387cf18bf96c9d00969b832715b81244c3d4cc Mon Sep 17 00:00:00 2001 From: nek0 Date: Sat, 29 Aug 2020 10:01:04 +0200 Subject: [PATCH] finished episode 27 --- src/Scenes/Texture2D.hs | 4 ---- src/Shader.hs | 50 +++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/Scenes/Texture2D.hs b/src/Scenes/Texture2D.hs index 953e4bd..e082977 100644 --- a/src/Scenes/Texture2D.hs +++ b/src/Scenes/Texture2D.hs @@ -97,10 +97,6 @@ instance SceneClass Texture2D where [ ShaderSource GL.VertexShader "./res/shaders/vert.shader" , ShaderSource GL.FragmentShader "./res/shaders/frag.shader" ] - [ "u_color" - , "u_texture" - , "u_mvp" - ] bind sp setUniform sp "u_texture" (texSlot tex) diff --git a/src/Shader.hs b/src/Shader.hs index 0b6acaf..81601cb 100644 --- a/src/Shader.hs +++ b/src/Shader.hs @@ -16,6 +16,8 @@ import qualified Data.ByteString as B import Data.Maybe (fromJust) +import Control.Concurrent.MVar + import Linear import Foreign.Marshal.Utils (with) @@ -28,7 +30,7 @@ import BindableClass data Shader = Shader { shaderId :: GL.Program , shaderSources :: [ShaderSource] - , shaderUniforms :: [ShaderUniform] + , shaderUniforms :: MVar [ShaderUniform] } -- make Shader Bindable @@ -75,8 +77,8 @@ isRowMajor :: GL.MatrixOrder -> GL.GLboolean isRowMajor p = if (GL.RowMajor == p) then 1 else 0 -- create new data object of type Shader -newShader :: [ShaderSource] -> [String] -> IO Shader -newShader shaderSrc uniforms = do +newShader :: [ShaderSource] -> IO Shader +newShader shaderSrc = do -- create program Object program <- GL.createProgram @@ -110,27 +112,37 @@ newShader shaderSrc uniforms = do -- throw away the shaders, since they are linked into the shader program mapM_ (\s -> GL.deleteObjectName s) (map snd compilates) - -- retrieve locations of all uniforms and store them - uniLocs <- mapM - (\name -> do - loc <- get $ GL.uniformLocation program name - return (ShaderUniform name loc) - ) - uniforms - -- return data object - return (Shader program shaderSrc uniLocs) + Shader program shaderSrc <$> newMVar [] -- pass uniform values into Shader program setUniform :: (GL.Uniform a) => Shader -> String -> a -> IO () -setUniform shader uniname data_ = do - -- retrieve uniform location - let [ShaderUniform _ loc] = filter - (\(ShaderUniform name _) -> name == uniname) - (shaderUniforms shader) +setUniform (Shader shaderProgram _ shaderUniforms) uniname data_ = do + -- check if uniform location is already cached + locs <- readMVar shaderUniforms - -- set the data - GL.uniform loc $= data_ + -- retrieve uniform location + let unilocs = filter + (\(ShaderUniform name _) -> name == uniname) + locs + + case unilocs of + [] -> do + print ("Unknown uniform: " <> uniname) + print "Retrieving uniform location from shader program" + loc@(GL.UniformLocation locNum) <- get $ GL.uniformLocation shaderProgram uniname + if locNum < 0 + then + print ("Uniform does not exist in shader program: " <> uniname) + else do + -- set the data + GL.uniform loc $= data_ + -- add uniform to cache + modifyMVar_ shaderUniforms + (\list -> return $ ShaderUniform uniname loc : list) + [ShaderUniform _ loc] -> + -- set the data + GL.uniform loc $= data_ -- | compile a shader from source compileShaderSource