Abstract Shaders into own module
This commit is contained in:
parent
c2014e41c5
commit
90d2ef73e6
3 changed files with 138 additions and 84 deletions
|
@ -31,5 +31,6 @@ executable renderer-tutorial
|
||||||
, VertexBuffer
|
, VertexBuffer
|
||||||
, VertexArray
|
, VertexArray
|
||||||
, IndexBuffer
|
, IndexBuffer
|
||||||
|
, Shader
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
98
src/Main.hs
98
src/Main.hs
|
@ -36,6 +36,7 @@ import BufferClass
|
||||||
import VertexArray
|
import VertexArray
|
||||||
import VertexBuffer
|
import VertexBuffer
|
||||||
import IndexBuffer
|
import IndexBuffer
|
||||||
|
import Shader
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
|
@ -121,21 +122,16 @@ main = do
|
||||||
|
|
||||||
-- -- SHADERS
|
-- -- SHADERS
|
||||||
|
|
||||||
-- read in shaders from source file
|
sp <- newShader
|
||||||
vertSrc <- B.readFile "./res/shaders/vert.shader"
|
[ ShaderSource GL.VertexShader "./res/shaders/vert.shader"
|
||||||
fragSrc <- B.readFile "./res/shaders/frag.shader"
|
, ShaderSource GL.FragmentShader "./res/shaders/frag.shader"
|
||||||
|
]
|
||||||
sp <- createShaderProgram vertSrc fragSrc
|
[ "u_color"
|
||||||
GL.currentProgram $= Just sp
|
]
|
||||||
|
|
||||||
-- -- UNIFORMS
|
-- -- UNIFORMS
|
||||||
|
|
||||||
-- -- get the uniform's location out of the shader program
|
-- create MVars for pulsating red channel
|
||||||
-- uniLoc <- get $ GL.uniformLocation sp "u_color"
|
|
||||||
-- -- write data to the uniform
|
|
||||||
-- GL.uniform uniLoc $= (GL.Color4 1 0.5 0 1 :: GL.Color4 GL.GLfloat)
|
|
||||||
|
|
||||||
-- create an MVar for pulsating red channel
|
|
||||||
red <- newMVar 0
|
red <- newMVar 0
|
||||||
increment <- newMVar 0.05
|
increment <- newMVar 0.05
|
||||||
|
|
||||||
|
@ -149,7 +145,7 @@ main = do
|
||||||
GL.bindVertexArrayObject $= Nothing
|
GL.bindVertexArrayObject $= Nothing
|
||||||
unbind vbo
|
unbind vbo
|
||||||
unbind ibo
|
unbind ibo
|
||||||
GL.currentProgram $= Nothing
|
unbind sp
|
||||||
|
|
||||||
-- -- LOOPING
|
-- -- LOOPING
|
||||||
|
|
||||||
|
@ -177,18 +173,17 @@ main = do
|
||||||
bind vao
|
bind vao
|
||||||
-- (note the missing bindings to the vertex buffer and the attrib pointer)
|
-- (note the missing bindings to the vertex buffer and the attrib pointer)
|
||||||
bind ibo
|
bind ibo
|
||||||
GL.currentProgram $= Just sp
|
bind sp
|
||||||
|
|
||||||
-- throw away previous errors
|
-- throw away previous errors
|
||||||
-- void $ get GL.errors
|
-- void $ get GL.errors
|
||||||
|
|
||||||
-- get the uniform's location out of the shader program
|
|
||||||
uniLoc <- get $ GL.uniformLocation sp "u_color"
|
|
||||||
-- write data to the uniform
|
|
||||||
redValue <- takeMVar red
|
|
||||||
incrementValue <- takeMVar increment
|
incrementValue <- takeMVar increment
|
||||||
|
redValue <- takeMVar red
|
||||||
let newRed = redValue + incrementValue
|
let newRed = redValue + incrementValue
|
||||||
GL.uniform uniLoc $= (GL.Color4 newRed 0.5 0 1 :: GL.Color4 GL.GLfloat)
|
|
||||||
|
-- write data to the uniform
|
||||||
|
setUniform sp "u_color" (GL.Color4 newRed 0.5 0 1 :: GL.Color4 GL.GLfloat)
|
||||||
|
|
||||||
-- the actual drawing happens here
|
-- the actual drawing happens here
|
||||||
GL.drawElements GL.Triangles 6 GL.UnsignedInt nullPtr
|
GL.drawElements GL.Triangles 6 GL.UnsignedInt nullPtr
|
||||||
|
@ -223,68 +218,3 @@ main = do
|
||||||
|
|
||||||
-- This is the end.
|
-- This is the end.
|
||||||
putStrLn "Bye!"
|
putStrLn "Bye!"
|
||||||
|
|
||||||
|
|
||||||
----------------------- Supplemantary functions -------------------------------
|
|
||||||
|
|
||||||
-- | create the actual Shader programs from source
|
|
||||||
createShaderProgram
|
|
||||||
:: B.ByteString -- ^ vertex shader source
|
|
||||||
-> B.ByteString -- ^ fragment shader source
|
|
||||||
-> IO GL.Program
|
|
||||||
createShaderProgram vertSrc fragSrc = do
|
|
||||||
-- create program Object
|
|
||||||
program <- GL.createProgram
|
|
||||||
|
|
||||||
-- create shaders from the source codes given
|
|
||||||
vs <- compileShaderSource GL.VertexShader vertSrc
|
|
||||||
fs <- compileShaderSource GL.FragmentShader fragSrc
|
|
||||||
|
|
||||||
-- attach, link and validate the shader program
|
|
||||||
GL.attachedShaders program $= [vs, fs]
|
|
||||||
GL.linkProgram program
|
|
||||||
GL.validateProgram program
|
|
||||||
|
|
||||||
ok <- get (GL.validateStatus program)
|
|
||||||
if ok
|
|
||||||
then
|
|
||||||
putStrLn "Shaderprogram linked successfully!"
|
|
||||||
else do
|
|
||||||
info <- get (GL.programInfoLog program)
|
|
||||||
putStrLn "Shaderprogram linking failed!\nInfo log says:"
|
|
||||||
putStrLn info
|
|
||||||
GL.deleteObjectName program
|
|
||||||
|
|
||||||
-- throw away the shaders, since they are linked into the shader program
|
|
||||||
mapM_ (\s -> GL.deleteObjectName s) [fs, vs]
|
|
||||||
|
|
||||||
return program
|
|
||||||
|
|
||||||
-- | compile a shader from source
|
|
||||||
compileShaderSource
|
|
||||||
:: GL.ShaderType -- ^ what type of shader we are compiling
|
|
||||||
-> B.ByteString -- ^ its source code
|
|
||||||
-> IO GL.Shader
|
|
||||||
compileShaderSource type_ source = do
|
|
||||||
-- create shader object of specified type
|
|
||||||
shaderObject <- GL.createShader type_
|
|
||||||
|
|
||||||
-- assign source code to shader object
|
|
||||||
GL.shaderSourceBS shaderObject $= source
|
|
||||||
|
|
||||||
-- actually compile the shader
|
|
||||||
GL.compileShader shaderObject
|
|
||||||
|
|
||||||
-- error handling
|
|
||||||
ok <- GL.compileStatus shaderObject
|
|
||||||
|
|
||||||
if ok
|
|
||||||
then
|
|
||||||
putStrLn (show type_ ++ ": compilation successful!")
|
|
||||||
else do
|
|
||||||
info <- get (GL.shaderInfoLog shaderObject)
|
|
||||||
putStrLn (show type_ ++ ": compilation failed!\nInfo log says:")
|
|
||||||
putStrLn info
|
|
||||||
GL.deleteObjectName shaderObject
|
|
||||||
|
|
||||||
return shaderObject
|
|
||||||
|
|
123
src/Shader.hs
Normal file
123
src/Shader.hs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
module Shader where
|
||||||
|
|
||||||
|
import SDL (($=), get)
|
||||||
|
|
||||||
|
import qualified Graphics.Rendering.OpenGL as GL
|
||||||
|
|
||||||
|
import Data.List as L
|
||||||
|
|
||||||
|
import qualified Data.ByteString as B
|
||||||
|
|
||||||
|
-- internal imports
|
||||||
|
|
||||||
|
import BindableClass
|
||||||
|
|
||||||
|
data Shader = Shader
|
||||||
|
{ shaderId :: GL.Program
|
||||||
|
, shaderSources :: [ShaderSource]
|
||||||
|
, shaderUniforms :: [ShaderUniform]
|
||||||
|
}
|
||||||
|
|
||||||
|
-- make Shader Bindable
|
||||||
|
instance Bindable Shader where
|
||||||
|
|
||||||
|
bind s = GL.currentProgram $= Just (shaderId s)
|
||||||
|
|
||||||
|
unbind _ = GL.currentProgram $= Nothing
|
||||||
|
|
||||||
|
data ShaderSource = ShaderSource
|
||||||
|
{ shaderSourceType :: GL.ShaderType
|
||||||
|
, shaderPath :: FilePath
|
||||||
|
}
|
||||||
|
|
||||||
|
data ShaderUniform = ShaderUniform
|
||||||
|
{ shaderUniformName :: String
|
||||||
|
, shaderUniformLocation :: GL.UniformLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
-- cerate new data object of type Shader
|
||||||
|
newShader :: [ShaderSource] -> [String] -> IO Shader
|
||||||
|
newShader shaderSrc uniforms = do
|
||||||
|
-- create program Object
|
||||||
|
program <- GL.createProgram
|
||||||
|
|
||||||
|
-- create shaders from the source codes given
|
||||||
|
compilates <- mapM
|
||||||
|
(\(ShaderSource type_ path) -> do
|
||||||
|
-- read in shader source from File
|
||||||
|
source<- B.readFile path
|
||||||
|
|
||||||
|
-- compile the shader
|
||||||
|
compiledShader <- compileShaderSource type_ source
|
||||||
|
return (type_, compiledShader)
|
||||||
|
)
|
||||||
|
shaderSrc
|
||||||
|
|
||||||
|
-- attach, link and validate the shader program
|
||||||
|
GL.attachedShaders program $= map snd compilates
|
||||||
|
GL.linkProgram program
|
||||||
|
GL.validateProgram program
|
||||||
|
|
||||||
|
ok <- get (GL.validateStatus program)
|
||||||
|
if ok
|
||||||
|
then
|
||||||
|
putStrLn "Shaderprogram linked successfully!"
|
||||||
|
else do
|
||||||
|
info <- get (GL.programInfoLog program)
|
||||||
|
putStrLn "Shaderprogram linking failed!\nInfo log says:"
|
||||||
|
putStrLn info
|
||||||
|
GL.deleteObjectName program
|
||||||
|
|
||||||
|
-- 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)
|
||||||
|
|
||||||
|
-- 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)
|
||||||
|
|
||||||
|
-- set the data
|
||||||
|
GL.uniform loc $= data_
|
||||||
|
|
||||||
|
-- | compile a shader from source
|
||||||
|
compileShaderSource
|
||||||
|
:: GL.ShaderType -- ^ what type of shader we are compiling
|
||||||
|
-> B.ByteString -- ^ its source code
|
||||||
|
-> IO GL.Shader
|
||||||
|
compileShaderSource type_ source = do
|
||||||
|
-- create shader object of specified type
|
||||||
|
shaderObject <- GL.createShader type_
|
||||||
|
|
||||||
|
-- assign source code to shader object
|
||||||
|
GL.shaderSourceBS shaderObject $= source
|
||||||
|
|
||||||
|
-- actually compile the shader
|
||||||
|
GL.compileShader shaderObject
|
||||||
|
|
||||||
|
-- error handling
|
||||||
|
ok <- GL.compileStatus shaderObject
|
||||||
|
|
||||||
|
if ok
|
||||||
|
then
|
||||||
|
putStrLn (show type_ ++ ": compilation successful!")
|
||||||
|
else do
|
||||||
|
info <- get (GL.shaderInfoLog shaderObject)
|
||||||
|
putStrLn (show type_ ++ ": compilation failed!\nInfo log says:")
|
||||||
|
putStrLn info
|
||||||
|
GL.deleteObjectName shaderObject
|
||||||
|
|
||||||
|
return shaderObject
|
Loading…
Reference in a new issue