Program5
Compute vertex normals from triangle faces. Then, shade the model with Phong reflectance and Gouraud and Phong shading. Your repository will contain template code. Be sure to fill in all the TODO blocks. You will need to modify Model.h and the shader programs.
Constants
- L (light intensity) should be (1, 1, 1)
- ka (ambient) RGB should be (0.1, 0.1, 0.1)
- kd (diffuse) should be the normal vector scaled to [0, 1]
- ks (specular) RGB should be (1.0, 1.0, 1.0)
- The alpha term for specular reflectance should be 10.
-
The uploaded uniforms are these values:
uniform mat4 P; //projection matrix uniform mat4 C; //camera matrix uniform mat4 mT; //model transform uniform mat4 mR; //model rotation uniform mat4 M; //modelview matrix: M = C * mR * mT uniform mat4 N; //inverse transpose of M uniform mat4 L; //light rotation matrix
Hints
-
You can control the view with the Q, W, E, R, T keys:
Q : Show kd (diffuse color) without lighting
W : Use Gouraud shading
E : Use Phong shading
R : Toggle model rotation
T : Toggle light rotation
- You do not need to handle attenuation.
- You don't need to scale the ambient, diffuse, and specular terms; they should not overflow in this assignment.
- Normal vectors are in the range [-1, 1]. This range is not valid for use as an RGB color. You can scale the normal to view as a color:
vec3 color = (normal + vec3(1)) * 0.5;
Remember to scale back to [-1, 1] before using as a normal vector! - These GLSL functions may be helpful in your shaders: clamp, dot, normalize, reflect. Be sure the read the documentation linked from the resources page!
Fixes to make things work
-
In RenderEngine.h,
setupShader()
, replace the light shader setup with this code:char const * lightVPath = "resources/lightPos.vert"; char const * lightFPath = "resources/lightPos.frag"; lightProg = ShaderManager::shaderFromFile(&lightVPath, &lightFPath, 1, 1);
- In the Visual Studio project, you may want to add a new filter 'resources'. Then add the existing shader files to the filter so you can edit them easily.
Code
Here is the code we wrote in class. It goes in Model.hinit()
. You will need to comment out the code that sets the color to white!
colors.resize( positions.size() ); //TODO compute the vertex normals by averaging the face normals for(size_t i=0; i<elements.size(); i+=3) { size_t vertexId[3]; for(size_t v=0; v<3; v++) vertexId[v] = elements[i+v]; glm::vec3 vertexPos[3]; for(size_t v=0; v<3; v++) for(size_t c=0; c<3; c++) vertexPos[v][c] = positions[ vertexId[v]*3 + c ]; glm::vec3 a = vertexPos[1] - vertexPos[0]; glm::vec3 b = vertexPos[2] - vertexPos[1]; glm::vec3 faceNormal = glm::normalize(glm::cross(a, b)); //scale to RGB range (undo this when using as a normal vector!) faceNormal = (faceNormal + 1.0f) * 0.5f; for(size_t v=0; v<3; v++) for(size_t c=0; c<3; c++) colors[ vertexId[v]*3 + c ] = faceNormal[c]; }
Rubric
Vertex normals computed, uploaded, and used as colors | -1: No normals | 0: Face normals only | 1: Correct vertex normals |
Ambient reflectance | 0: No ambient | 1: Ambient reflectance | |
Diffuse reflectance | 0: No diffuse | 1: Phong diffuse term correctly uses normal and light vector | |
Specular reflectance | 0: No specular | 1: Phong specular term correctly using view and light vector | |
Light rotation | 0: Incorrect rotation | 1: Correct reflectance for rotating light | |
Object position transformation | 0: Incorrect reflectance after transform | 1: Correct reflectance after transform | |
Object normal transformation | 0: Incorrect reflectance after transform | 1: Correct reflectance after transform | |
Gouraud shading | 0: No shading | 1: One reflectance per vertex, then color interpolated | |
Phong shading | 0: No shading | 2: Normals interpolated, then a reflectance per interpolated normal |