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.

Code

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

results matching ""

    No results matching ""