def drawObjModel(viewToClipTfm, worldToViewTfm, modelToWorldTfm, model): # Lighting/Shading is very often done in view space, which is why a transformation that lands positions in this space is needed modelToViewTransform = worldToViewTfm * modelToWorldTfm # this is a special transform that ensures that normal vectors remain orthogonal to the # surface they are supposed to be even in the prescence of non-uniform scaling. # It is a 3x3 matrix as vectors don't need translation anyway and this transform is only for vectors, # not points. If there is no non-uniform scaling this is just the same as Mat3(modelToViewTransform) modelToViewNormalTransform = lu.inverse( lu.transpose(lu.Mat3(modelToViewTransform))) # Bind the shader program such that we can set the uniforms (model.render sets it again) glUseProgram(model.defaultShader) # transform (rotate) light direction into view space (as this is what the ObjModel shader wants) viewSpaceLightDirection = [0.0, 0.0, -1.0] glUniform3fv( glGetUniformLocation(model.defaultShader, "viewSpaceLightDirection"), 1, viewSpaceLightDirection) # This dictionary contains a few transforms that are needed to render the ObjModel using the default shader. # it would be possible to just set the modelToWorld transform, as this is the only thing that changes between # the objects, and compute the other matrices in the vertex shader. # However, this would push a lot of redundant computation to the vertex shader and makes the code less self contained, # in this way we set all the required parameters explicitly. transforms = { "modelToClipTransform": viewToClipTfm * worldToViewTfm * modelToWorldTfm, "modelToViewTransform": modelToViewTransform, "modelToViewNormalTransform": modelToViewNormalTransform, } model.render(None, None, transforms)
def setCommonUniforms(self, shader, view, modelToWorldTransform): # Concatenate the transformations to take vertices directly from model space to clip space modelToClipTransform = view.viewToClipTransform * view.worldToViewTransform * modelToWorldTransform # Transform to view space from model space (used for the shading) modelToViewTransform = view.worldToViewTransform * modelToWorldTransform # Transform to view space for normals, need to use the inverse transpose unless only rigid body & uniform scale. modelToViewNormalTransform = lu.inverse( lu.transpose(lu.Mat3(modelToViewTransform))) # Set the standard transforms, these vary per object and must be set each time an object is drawn (since they have different modelToWorld transforms) lu.setUniform(shader, "modelToClipTransform", modelToClipTransform) lu.setUniform(shader, "modelToViewTransform", modelToViewTransform) lu.setUniform(shader, "modelToViewNormalTransform", modelToViewNormalTransform) # These transforms are the same for the current view and could be set once for all the objects lu.setUniform(shader, "worldToViewTransform", view.worldToViewTransform) lu.setUniform(shader, "viewToClipTransform", view.viewToClipTransform) # Lighting parameters as could these viewSpaceLightPosition = lu.transformPoint(view.worldToViewTransform, g_sunPosition) lu.setUniform(shader, "viewSpaceLightPosition", viewSpaceLightPosition) lu.setUniform(shader, "globalAmbientLight", g_globalAmbientLight) lu.setUniform(shader, "sunLightColour", g_sunLightColour) lu.bindTexture(g_TU_shadow, g_shadowTexId) lu.setUniform(shader, "shadowMapTexture", g_shadowTexId)
def render_frame(width, height): """ Renders the frame """ global g_shader global g_squares global g_square_colors global g_square_normals global g_cam global g_light_1 global g_light_color_1 global g_ambi_color global g_spec_color # Make the camera position eye_pos = g_cam look_at = [1.5, 1.5, -1.5] up_dir = [0, 1, 0] y_fov = 45 # Light constants ambient_light = g_ambi_color specular_light = g_spec_color world_to_view = lu.make_lookAt(eye_pos, look_at, up_dir) view_to_clip = lu.make_perspective(y_fov, width / height, 0.1, 260) world_to_clip = view_to_clip * world_to_view model_to_view_normal = lu.inverse(lu.transpose(lu.Mat3(world_to_view))) # Make openGL use transform from screen space to NDC glViewport(0, 0, width, height) # Set the clear colour (i.e. background colour) glClearColor(0.7, 0.8, 1.0, 1.0) make_squares() make_texture_coords() # Unbind the buffers glBindBuffer(GL_ARRAY_BUFFER, 0) glBindVertexArray(0) # Clear the colour and depth buffers glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT) # Buffer the world to clip transform matrix tfm_uniform_index = glGetUniformLocation(g_shader, "worldToClipTfm") glUseProgram(g_shader) glUniformMatrix4fv(tfm_uniform_index, 1, GL_TRUE, world_to_clip.getData()) glBindVertexArray(g_vertex_array) model_uniform_index = glGetUniformLocation(g_shader, "modelToView") glUseProgram(g_shader) glUniformMatrix4fv(model_uniform_index, 1, GL_TRUE, world_to_view.getData()) norm_uniform_index = glGetUniformLocation(g_shader, "modelToViewNormal") glUseProgram(g_shader) glUniformMatrix3fv(norm_uniform_index, 1, GL_TRUE, model_to_view_normal.getData()) lu.setUniform(g_shader, "camPos", eye_pos) # Add light 1 uniforms lu.setUniform(g_shader, "lightColourAndIntensity1", g_light_color_1) lu.setUniform(g_shader, "viewSpaceLightPosition1", g_light_1) # Add light 2 uniforms lu.setUniform(g_shader, "lightColourAndIntensity2", g_light_color_2) lu.setUniform(g_shader, "viewSpaceLightPosition2", g_light_2) # Add light 3 uniforms lu.setUniform(g_shader, "lightColourAndIntensity3", g_light_color_3) lu.setUniform(g_shader, "viewSpaceLightPosition3", g_light_3) # Add light 4 uniforms lu.setUniform(g_shader, "lightColourAndIntensity4", g_light_color_4) lu.setUniform(g_shader, "viewSpaceLightPosition4", g_light_4) lu.setUniform(g_shader, "ambientLightColourAndIntensity", ambient_light) lu.setUniform(g_shader, "materialSpecular", specular_light) # Fog settings lu.setUniform(g_shader, "fogColor", g_fog_color) lu.setUniform(g_shader, "fogDensityConst", g_fog_density) lu.setUniform(g_shader, "fogHeightConst", g_fog_height) lu.setUniform(g_shader, "fogMax", g_fog_max) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, g_texture_id) loc = glGetUniformLocation(g_shader, "plasticTexture") glUniform1i(loc, 0) for i in range(int(len(g_squares) / 4)): lu.setUniform(g_shader, "squareColorIndex", g_square_colors[i]) lu.setUniform(g_shader, "squareNormal", g_square_normals[i]) glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4)