lambdacube-engine-0.1.1: Graphics/LambdaCube/RenderSystem/GL/GLGpuProgram.hs
module Graphics.LambdaCube.RenderSystem.GL.GLGpuProgram where
import Data.Either
import System.Log.Logger
import Graphics.Rendering.OpenGL (($=))
import qualified Graphics.Rendering.OpenGL as GL
import Graphics.LambdaCube.HardwareVertexBuffer
import Graphics.LambdaCube.GpuProgram
import Graphics.LambdaCube.GpuProgramParams
-- Some drivers (e.g. OS X on nvidia) incorrectly determine the attribute binding automatically
-- and end up aliasing existing built-ins. So avoid! Fixed builtins are:
-- a builtin custom attrib name
-- ----------------------------------------------
-- 0 gl_Vertex vertex
-- 1 n/a blendWeights
-- 2 gl_Normal normal
-- 3 gl_Color colour
-- 4 gl_SecondaryColor secondary_colour
-- 5 gl_FogCoord fog_coord
-- 7 n/a blendIndices
-- 8 gl_MultiTexCoord0 uv0
-- 9 gl_MultiTexCoord1 uv1
-- 10 gl_MultiTexCoord2 uv2
-- 11 gl_MultiTexCoord3 uv3
-- 12 gl_MultiTexCoord4 uv4
-- 13 gl_MultiTexCoord5 uv5
-- 14 gl_MultiTexCoord6 uv6, tangent
-- 15 gl_MultiTexCoord7 uv7, binormal
getFixedAttributeIndex :: VertexElementSemantic -> Int -> Int
getFixedAttributeIndex semantic index = case semantic of
{ VES_POSITION -> 0
; VES_BLEND_WEIGHTS -> 1
; VES_NORMAL -> 2
; VES_DIFFUSE -> 3
; VES_SPECULAR -> 4
; VES_BLEND_INDICES -> 7
; VES_TEXTURE_COORDINATES -> 8 + index
; VES_TANGENT -> 14
; VES_BINORMAL -> 15
--; _ -> error "Missing attribute!"
}
isAttributeValid :: VertexElementSemantic -> Int -> Bool
isAttributeValid semantic index = case semantic of
{ VES_POSITION -> False
; VES_NORMAL -> False
; VES_DIFFUSE -> False
; VES_SPECULAR -> False
; VES_TEXTURE_COORDINATES -> False
; VES_BLEND_WEIGHTS -> True
; VES_BLEND_INDICES -> True
; VES_BINORMAL -> True
; VES_TANGENT -> True
}
{-
data GLGpuProgram
= GLGpuProgram
{ glgpType :: GpuProgramType -- ^ The type of the program
, glgpFilename :: String -- ^ The name of the file to load source from (may be blank)
, glgpSource :: String -- ^ The assembler source of the program (may be blank until file loaded)
, glgpLoadFromFile :: Bool -- ^ Whether we need to load source from file or not
, glgpSyntaxCode :: String -- ^ Syntax code e.g. arbvp1, vs_2_0 etc
, glgpSkeletalAnimation :: Bool -- ^ Does this (vertex) program include skeletal animation?
, glgpMorphAnimation :: Bool -- ^ Does this (vertex) program include morph animation?
, glgpPoseAnimation :: Int -- ^ Does this (vertex) program include pose animation (count of number of poses supported)
, glgpVertexTextureFetch :: Bool -- ^ Does this (vertex) program require support for vertex texture fetch?
, glgpNeedsAdjacencyInfo :: Bool -- ^ Does this (geometry) program require adjacency information?
, glgpDefaultParams :: GpuProgramParameters -- ^ The default parameters for use with this object
, glgpCompileError :: Bool -- ^ Did we encounter a compilation error?
, glgpProgramObject :: GL.Program
}
-}
data GLGpuProgram
= GLGpuProgram
{ glgpShaderObject :: Either GL.VertexShader GL.FragmentShader
}
deriving Eq
data GLLinkedGpuProgram
= GLLinkedGpuProgram
{ gllgpProgramObject :: GL.Program
}
deriving Eq
instance LinkedGpuProgram GLLinkedGpuProgram --where
instance GpuProgram GLGpuProgram --where
-- gpType = undefined
compileShader src = do
[shader] <- GL.genObjectNames 1
GL.shaderSource shader $= [src]
GL.compileShader shader
-- TEMP CODE
infoLog <- GL.get (GL.shaderInfoLog shader)
infoM "ResourceLibrary" $ "infoLog cmp " ++ infoLog
ok <- GL.get (GL.compileStatus shader)
case ok of
{ False -> do
GL.deleteObjectNames [shader]
errl <- GL.get GL.errors
return $ Right $ "shader compilation failed: " ++ concat [show c ++ " - " ++ m ++ "\n" | GL.Error c m <- errl]
; True -> return $ Left shader
}
mkGLGpuProgram ptype src = case ptype of
{ GPT_VERTEX_PROGRAM -> do
debugM "ResourceLibrary" $ "compiling vertex shader: "
s <- compileShader src
case s of
{ Right m -> return $ Right m
; Left sh -> return $ Left $ GLGpuProgram $ Left sh
}
; GPT_FRAGMENT_PROGRAM -> do
debugM "ResourceLibrary" $ "compiling fragment shader: "
s <- compileShader src
case s of
{ Right m -> return $ Right m
; Left sh -> return $ Left $ GLGpuProgram $ Right sh
}
; GPT_GEOMETRY_PROGRAM -> undefined
}
mkGLLinkedGpuProgram :: [GLGpuProgram] -> IO (Either GLLinkedGpuProgram String)
mkGLLinkedGpuProgram pl = do
[p] <- GL.genObjectNames 1
let vp = lefts $ map glgpShaderObject pl
fp = rights $ map glgpShaderObject pl
GL.attachedShaders p $= (vp, fp)
GL.linkProgram p
ok <- GL.get (GL.linkStatus p)
infoLog <- GL.get (GL.programInfoLog p)
infoM "ResourceLibrary" $ "infoLog link " ++ infoLog
case ok of
{ False -> do
GL.deleteObjectNames [p]
errl <- GL.get GL.errors
return $ Right $ "GpuProgram linking failed: " ++ concat [show c ++ " - " ++ m ++ "\n" | GL.Error c m <- errl]
; True -> return $ Left $ GLLinkedGpuProgram p
}