The major problem i'm having with my render is that when i try to incorporate the normals associated
with each vertex with the light source i get a wrong output. It's meant to be smoothly shaded but
it's not even close. I'm using the obj model that comes with the course that has the normals given per vertex
Screenshots:
The first one is when i don't check if the interpolated intensity is > 0
The other is when i do
Here's the code(somewhat abbreviated):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | v3f lightDir(1.0f, -1.0f, 1.0f); void drawModel() { int[] zBuffer = new int[width*height]; // zBuffer filled with lowest possible int value for(int i = 0; i < model->nfaces(); i++) { std::vector<int> faces = model->faces(i); v3i screen_coords[3]; v3f world_coords[3]; float intensity[3]; for(int j = 0; j < 3; j++) { v3f triangleVertex = model->vertex(faces[i]); int x = (int)(triangleVertex.x+1.0f * width / 2); int y = (int)(triangleVertex.y+1.0f * height / 2); screen_coords[j] = v3i(x, y, (int)triangleVertex.z); world_coords[j] = triangleVertex; //This gets the normal associated with this vertex v3f vertexNormal = model->norm(i, j).normalize(); // dot product of the light and the normal( for diffuse lighting) intensity[j] = vertexNormal*lightDir; } drawTriangle(screen_coords, intensity, zBuffer); } } |
The drawTriangle function computes the barycentric coordinates for each point
in the bounding box of the triangle to be drawn and checks if they are positive and
if their sum is less than 1
My code for rendering triangles
The scalars associated with each vertex are u, v, and q
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | void drawTriangle(v3i* screen_coords, float* intensity, int* zBuffer) { // sort the vertices of the triangles using x and intensity relative to the sort // assume we have the min, max x and min, max y values that enclose the bounding box v3i v0 = screen_coords[2] - screen_coords[0]; v3i v1 = screen_coords[1] - screen_coords[0]; float dot00 = v0*v0; float dot01 = v0*v1; float dot11 = v1*v1; float u, v; float denom = 1.0f / (dot00 *dot11 - dot01 *dot01); for(int y = ymin; y < ymax; y++) { for(int x= xmin; x < xmax; x++) { v3i p(x, y, 0); v3i v2 = p - screen_coords[0]; float dot02 = v0*v2; float dot12 = v1*v2; u = (dot02*dot11 - dot12*dot01) * denom; v = (dot00*dot12 - dot01*dot02) * denom; if((u >= 0) && (v >= 0) && (u+v < 1)) { q = 1-u-v; float bc[] = {u, v, q}; //interpolate z for(int i =0; i < 3; i++) { p.z += (screen_coords[i].z * bc[i]); } if(zBuffer[x+y*width] < p.z) { // where i actually use the intensity for gouraud shading float intensity = intensity[0]*u + intensity[1]*v + intensity[2]*q; // multiplies the intensity by 255.0f for r, g, b components and // or's the values together to get the color int color = createColor(intensity); setPixel(x, y, color); } } } } } |
Thanks