So we can adjust the vertex shader and the fragment shader to make a red rectangle if we want, but that's so trivial we won't bother. Instead we'll skip right to setting a uniform.
First we get the time. GLFW's getTime action gives us a
Maybe Double, so we will convert that around into the
GLfloat that Open GL will accept.
timeValue <- maybe 0 realToFrac <$> GLFW.getTime let greenValue = sin timeValue / 2 + 0.5
-- before the loop we do this once ourColor <- newCString "ourColor" -- inside the loop we do this every frame glUseProgram shaderProgram vertexColorLocation <- glGetUniformLocation shaderProgram ourColor glUniform4f vertexColorLocation 0.0 greenValue 0.0 1.0
We can place more attributes in our vertex info,
-- assign the attribute pointer information let floatSize = (fromIntegral $ sizeOf (0.0::GLfloat)) :: GLsizei -- position attribute glVertexAttribPointer 0 3 GL_FLOAT GL_FALSE (6*floatSize) nullPtr glEnableVertexAttribArray 0 -- color attribute let threeFloatOffset = castPtr $ plusPtr nullPtr (fromIntegral $ 3*floatSize) glVertexAttribPointer 1 3 GL_FLOAT GL_FALSE (6*floatSize) threeFloatOffset glEnableVertexAttribArray 1
And then adjust how we're drawing so that it matches our new vertex stuff,
-- event poll GLFW.pollEvents -- clear the screen glClearColor 0.2 0.3 0.3 1.0 glClear GL_COLOR_BUFFER_BIT -- draw our triangle glUseProgram shaderProgram glBindVertexArray vao glDrawArrays GL_TRIANGLES 0 3 glBindVertexArray 0 -- swap buffers and go again GLFW.swapBuffers window loop
And now we've got a multi-colorized triangle.
Our Own Shader Class?
I don't think that we need to make our own shader class, in the C++ class sense. We have a
loadShader function, and it does the error handling stuff. We can load the string using readFile, and the fact that
readFile is lazy won't affect us much, since we force the whole String right away when we push it out to a Ptr value and all that.