Coordinate Systems
Learn OpenGL - Coordinate Systems
Going 3D
Assuming we setup all our CStrings and pointers:
-- the names of our uniforms
ourColor <- newCString "ourColor"
ourTexture0 <- newCString "ourTexture0"
ourTexture1 <- newCString "ourTexture1"
model <- newCString "model"
view <- newCString "view"
projection <- newCString "projection"
-- the pointers for our uniforms
modelP <- malloc
viewP <- malloc
projP <- malloc
Then we can also use the updated shader code (Vertex, and Fragment) along with some new uniform assignments to make our thing appear like it's a floor section
-- assign our uniforms
modelLoc <- glGetUniformLocation shaderProgram model
viewLoc <- glGetUniformLocation shaderProgram view
projectionLoc <- glGetUniformLocation shaderProgram projection
let modelMat = mkTransformation (axisAngle (V3 (1::GLfloat) 0 0) (-55*pi/180)) (V3 0 0 0)
let viewMat = mkTransformation (axisAngle (V3 (0::GLfloat) 0 1) 0) (V3 0 0 (-3))
let screenWidthF = fromIntegral x :: GLfloat
let screenHeightF = fromIntegral y :: GLfloat
-- this is from Linear.Projection
let projMat = perspective 45 (screenWidthF / screenHeightF) 0.1 100.0
poke modelP (transpose modelMat)
poke viewP (transpose viewMat)
poke projP (transpose projMat)
glUniformMatrix4fv modelLoc 1 GL_FALSE (castPtr modelP)
glUniformMatrix4fv viewLoc 1 GL_FALSE (castPtr viewP)
glUniformMatrix4fv projectionLoc 1 GL_FALSE (castPtr projP)
And now we have a tilted over picture. Code
More 3D
Now if we just update our vertex data, our attribute pointers to match,
-- assign the attribute pointer information
let floatSize = (fromIntegral $ sizeOf (0.0::GLfloat)) :: GLsizei
-- position attribute
glVertexAttribPointer 0 3 GL_FLOAT GL_FALSE (5*floatSize) nullPtr
glEnableVertexAttribArray 0
-- texture information
let threeFloatOffset = castPtr $ plusPtr nullPtr (fromIntegral $ 3*floatSize)
glVertexAttribPointer 2 2 GL_FLOAT GL_FALSE (5*floatSize) threeFloatOffset
glEnableVertexAttribArray 2
And we rotate the model matrix over time,
timeValue <- maybe 0 realToFrac <$> GLFW.getTime
let modelMat = mkTransformation (axisAngle (V3 (0.5::GLfloat) 1 0) timeValue) (V3 0 0 0)
We can draw all the triangles,
glDrawArrays GL_TRIANGLES 0 36
And then get a goofy looking cube rotation that doesn't do depth properly. Code
Z Buffer
Turning on the depth testing is simple. After we calibrate the viewport we call glEnable GL_DEPTH_TEST
, and in the main loop we replace glClear GL_COLOR_BUFFER_BIT
with glClear (GL_COLOR_BUFFER_BIT .|. GL_DEPTH_BUFFER_BIT)
. Note that we have to import the Data.Bits
module to use the (.|.) operator.
More Cubes!
If we add some cube vectors
cubes :: [V3 GLfloat]
cubes = [
V3 0 0 0,
V3 2 5 (-15),
V3 (-1.5) (-2.2) (-2.5),
V3 (-3.8) (-2) (-12.3),
V3 2.4 (-0.4) (-3.5),
V3 (-1.7) 3 (-7.5),
V3 1.3 (-2) (-2.5),
V3 1.5 2 (-2.5),
V3 1.5 0.2 (-1.5),
V3 (-1.3) 1 (-1.5)
]
And then we use forM_ to loop over our cube data and draw them all
forM_ (zip cubes [0..]) $ \(cube,i) -> do
let angle = 20*i
let modelMat = mkTransformation (axisAngle (V3 (1::GLfloat) 0.3 0.5) angle) cube
poke modelP (transpose modelMat)
glUniformMatrix4fv modelLoc 1 GL_FALSE (castPtr modelP)
glDrawArrays GL_TRIANGLES 0 36
Then we get a pile of cubes! Code