Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    def update(self, dt, keyStateMap):
        info = self.terrain.getInfoAt(self.position)
        # Select max speed based on material
        maxSpeed = self.maxSpeedRoad if info.material == TerrainInfo.M_Road else self.maxSpeedRough

        targetVel = vec3(0.0)
        if keyStateMap["UP"]:
            targetVel = self.heading * maxSpeed
        if keyStateMap["DOWN"]:
            targetVel = self.heading * -maxSpeed

        # linearly interpolate towards the target velocity - this means it is tied to the frame rate, which kind of is bad.
        self.velocity = lu.mix(self.velocity, targetVel, 0.01)

        self.speed = lu.length(self.velocity)

        rotationMat = lu.Mat4()
        if keyStateMap["LEFT"]:
            rotationMat = lu.make_rotation_z(dt * self.angvel)
        if keyStateMap["RIGHT"]:
            rotationMat = lu.make_rotation_z(dt * -self.angvel)

        self.heading = lu.Mat3(rotationMat) * self.heading

        # get height of ground at this point.

        self.position += self.velocity * dt

        # TODO 1.1: After the terrain height is correct, uncomment this line to make the racer follow the ground height
        self.position[2] = lu.mix(self.position[2], info.height + self.zOffset,
                                  0.1)
Ejemplo n.º 4
0
def update(dt, keyStateMap, mouseDelta):
    global g_sunPosition
    global g_sunAngle
    global g_globalAmbientLight
    global g_sunLightColour
    global g_sunAngle
    global g_updateSun
    global g_viewTarget
    global g_viewPosition
    global g_followCamOffset
    global g_followCamLookOffset

    if g_updateSun:
        g_sunAngle += dt * 0.25
        g_sunAngle = g_sunAngle % (2.0 * math.pi)

    g_sunPosition = lu.Mat3(
        lu.make_rotation_x(g_sunAngle)) * g_sunStartPosition

    g_sunLightColour = sampleKeyFrames(
        lu.dot(lu.normalize(g_sunPosition), vec3(0.0, 0.0, 1.0)),
        g_sunKeyFrames)
    g_globalAmbientLight = sampleKeyFrames(
        lu.dot(lu.normalize(g_sunPosition), vec3(0.0, 0.0, 1.0)),
        g_ambientKeyFrames)

    g_racer.update(dt, keyStateMap)

    # TODO 1.2: Make the camera look at the racer. Code for updating the camera should be done after the
    # racer, otherwise the offset will lag and it generally looks weird.

    if imgui.tree_node("Camera", imgui.TREE_NODE_DEFAULT_OPEN):
        _, g_followCamOffset = imgui.slider_float("FollowCamOffset ",
                                                  g_followCamOffset, 2.0,
                                                  100.0)
        _, g_followCamLookOffset = imgui.slider_float("FollowCamLookOffset",
                                                      g_followCamLookOffset,
                                                      0.0, 100.0)
        imgui.tree_pop()

    if imgui.tree_node("Racer", imgui.TREE_NODE_DEFAULT_OPEN):
        g_racer.drawUi()
        imgui.tree_pop()

    if imgui.tree_node("Terrain", imgui.TREE_NODE_DEFAULT_OPEN):
        g_terrain.drawUi()
        imgui.tree_pop()

    if imgui.tree_node("Lighting", imgui.TREE_NODE_DEFAULT_OPEN):
        _, g_globalAmbientLight = lu.imguiX_color_edit3_list(
            "GlobalAmbientLight", g_globalAmbientLight
        )  #, imgui.GuiColorEditFlags_Float);// | ImGuiColorEditFlags_HSV);
        _, g_sunLightColour = lu.imguiX_color_edit3_list(
            "SunLightColour", g_sunLightColour
        )  #, imgui.GuiColorEditFlags_Float);// | ImGuiColorEditFlags_HSV);
        _, g_sunAngle = imgui.slider_float("SunAngle", g_sunAngle, 0.0,
                                           2.0 * math.pi)
        _, g_updateSun = imgui.checkbox("UpdateSun", g_updateSun)
        imgui.tree_pop()
Ejemplo n.º 5
0
def renderFrame(uiWidth, width, height):
    global g_triangleVerts
    global g_cameraDistance
    global g_cameraYawDeg
    global g_cameraPitchDeg
    global g_yFovDeg

    global g_lightYaw
    global g_lightDistance
    global g_lightPitch

    # This configures the fixed-function transformation from Normalized Device Coordinates (NDC)
    # to the screen (pixels - called 'window coordinates' in OpenGL documentation).
    #   See: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glViewport.xhtml
    glViewport(0, 0, width, height)
    # Set the colour we want the frame buffer cleared to,
    glClearColor(0.2, 0.5, 0.1, 1.0)
    # Tell OpenGL to clear the render target to the clear values for both depth and colour buffers (depth uses the default)
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)

    viewToClipTransform = lu.make_perspective(g_yFovDeg, width / height, 0.1,
                                              50.0)

    eyePos = lu.Mat3(lu.make_rotation_y(
        math.radians(g_cameraYawDeg))) * lu.Mat3(
            lu.make_rotation_x(
                math.radians(g_cameraPitchDeg))) * [0, 0, g_cameraDistance]
    worldToViewTransform = magic.make_lookAt(eyePos, [0, 0, 0], [0, 1, 0])

    worldToClipTransform = viewToClipTransform * worldToViewTransform

    lightRotation = lu.Mat3(lu.make_rotation_y(
        math.radians(g_lightYaw))) * lu.Mat3(
            lu.make_rotation_x(math.radians(g_lightPitch)))
    lightPosition = [0.02, 0, 0] + lu.vec3(0, 23, 0.2)

    draw_court(worldToClipTransform, lightPosition)
    lu.drawSphere([0.23, -0.45, 0.1, 0], 0.007, [0, 1, 0, 0.5],
                  viewToClipTransform, worldToViewTransform)
    lu.drawSphere(lightPosition, 0.01, [1, 1, 0, 1], viewToClipTransform,
                  worldToViewTransform)
Ejemplo n.º 6
0
    def render(self, shaderProgram=None, renderFlags=None, transforms={}):
        if not renderFlags:
            renderFlags = self.RF_All

        if not shaderProgram:
            shaderProgram = self.defaultShader

        # Filter chunks based of render flags
        chunks = [ch for ch in self.chunks if ch[3] & renderFlags]

        glBindVertexArray(self.vertexArrayObject)
        glUseProgram(shaderProgram)

        # define defaults (identity)
        defaultTfms = {
            "modelToClipTransform": lu.Mat4(),
            "modelToViewTransform": lu.Mat4(),
            "modelToViewNormalTransform": lu.Mat3(),
        }
        # overwrite defaults
        defaultTfms.update(transforms)
        # upload map of transforms
        for tfmName, tfm in defaultTfms.items():
            loc = magic.getUniformLocationDebug(shaderProgram, tfmName)
            tfm._set_open_gl_uniform(loc)

        previousMaterial = None
        for material, chunkOffset, chunkCount, renderFlags in chunks:
            # as an optimization we only do this if the material has changed between chunks.
            # for more efficiency still consider sorting chunks based on material (or fusing them?)
            if material != previousMaterial:
                previousMaterial = material
                if self.overrideDiffuseTextureWithDefault:
                    bindTexture(self.TU_Diffuse, self.defaultTextureOne,
                                self.defaultTextureOne)
                else:
                    bindTexture(self.TU_Diffuse,
                                material["texture"]["diffuse"],
                                self.defaultTextureOne)
                bindTexture(self.TU_Opacity, material["texture"]["opacity"],
                            self.defaultTextureOne)
                bindTexture(self.TU_Specular, material["texture"]["specular"],
                            self.defaultTextureOne)
                bindTexture(self.TU_Normal, material["texture"]["normal"],
                            self.defaultNormalTexture)
                # TODO: can I do uniform buffers from python (yes, I need to use that struct thingo!)
                #uint32_t matUniformSize = sizeof(MaterialProperties_Std140);
                #glBindBufferRange(GL_UNIFORM_BUFFER, UBS_MaterialProperties, m_materialPropertiesBuffer, (uint32_t)chunk.material->offset * matUniformSize, matUniformSize);
                # TODO: this is very slow, it should be packed into an uniform buffer as per above!
                for k, v in material["color"].items():
                    glUniform3fv(
                        magic.getUniformLocationDebug(shaderProgram,
                                                      "material_%s_color" % k),
                        1, v)
                glUniform1f(
                    magic.getUniformLocationDebug(
                        shaderProgram, "material_specular_exponent"),
                    material["specularExponent"])
                glUniform1f(
                    magic.getUniformLocationDebug(shaderProgram,
                                                  "material_alpha"),
                    material["alpha"])

            glDrawArrays(GL_TRIANGLES, chunkOffset, chunkCount)

        glUseProgram(0)
Ejemplo n.º 7
0
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)