void TMesh::RenderFilled(PPC *ppc, FrameBuffer *fb, unsigned int color, V3 L, float ka, float se, int tm, int tl) { //Project all vertices V3 *pverts = new V3[vertsN]; for (int vi = 0; vi < vertsN; vi++) { ppc->Project(verts[vi], pverts[vi]); } for (int tri = 0; tri < trisN; tri++) { int vinds[3]; vinds[0] = tris[tri*3+0]; vinds[1] = tris[tri*3+1]; vinds[2] = tris[tri*3+2]; // Do not render triangle if any of its vertices had an invalid projection if (pverts[vinds[0]][0] == FLT_MAX || pverts[vinds[1]][0] == FLT_MAX || pverts[vinds[2]][0] == FLT_MAX) continue; // Compute bounding box aabb of projected vertices AABB aabb(pverts[vinds[0]]); aabb.AddPoint(pverts[vinds[1]]); aabb.AddPoint(pverts[vinds[2]]); // Clip aabb with frame if (!aabb.Clip(0.0f, (float) fb->w, 0.0f, (float) fb->h)) { continue; } // Setup edge equations ee0, ee1, ee2 V3 eeqs[3]; SetEEQS(pverts[vinds[0]], pverts[vinds[1]], pverts[vinds[2]], eeqs); //Setup coefficient matrix M33 ptm; ptm[0] = pverts[vinds[0]]; ptm[1] = pverts[vinds[1]]; ptm[2] = pverts[vinds[2]]; ptm.setColumn(2, V3(1.0f, 1.0f, 1.0f)); ptm = ptm.inverse(); //Get colors at verts V3 reds(cols[vinds[0]][0], cols[vinds[1]][0], cols[vinds[2]][0]); V3 greens(cols[vinds[0]][1], cols[vinds[1]][1], cols[vinds[2]][1]); V3 blues(cols[vinds[0]][2], cols[vinds[1]][2], cols[vinds[2]][2]); // Setup screen space interpolation of depth: zABC V3 zABC = ptm*V3(pverts[vinds[0]][2], pverts[vinds[1]][2], pverts[vinds[2]][2]); //Setup screen space interpolation of normals V3 nxABC = ptm*V3(normals[vinds[0]][0], normals[vinds[1]][0], normals[vinds[2]][0]); V3 nyABC = ptm*V3(normals[vinds[0]][1], normals[vinds[1]][1], normals[vinds[2]][1]); V3 nzABC = ptm*V3(normals[vinds[0]][2], normals[vinds[1]][2], normals[vinds[2]][2]); //Model space interpolation parameters M33 msiQ = GetMSIQ(verts[vinds[0]], verts[vinds[1]], verts[vinds[2]], ppc); V3 denABC = msiQ[0] + msiQ[1] + msiQ[2]; V3 redNABC(msiQ.getColumn(0) * reds, msiQ.getColumn(1) * reds, msiQ.getColumn(2) * reds); V3 greenNABC(msiQ.getColumn(0) * greens, msiQ.getColumn(1) * greens, msiQ.getColumn(2) * greens); V3 blueNABC(msiQ.getColumn(0) * blues, msiQ.getColumn(1) * blues, msiQ.getColumn(2) * blues); //Texture coordinates interpolation V3 sNumABC, tNumABC, sABC, tABC; if (tcs) { V3 ss(tcs[2*vinds[0]+0], tcs[2*vinds[1]+0], tcs[2*vinds[2]+0]); V3 ts(tcs[2*vinds[0]+1], tcs[2*vinds[1]+1], tcs[2*vinds[2]+1]); sNumABC = V3(msiQ.getColumn(0) * ss, msiQ.getColumn(1) * ss, msiQ.getColumn(2) * ss); tNumABC = V3(msiQ.getColumn(0) * ts, msiQ.getColumn(1) * ts, msiQ.getColumn(2) * ts); sABC = ptm * ss; tABC = ptm * ts; } // For every pixel in the bounding box int top = (int) (aabb.corners[0][1] + 0.5f); int bottom = (int) (aabb.corners[1][1] - 0.5f); int left = (int) (aabb.corners[0][0] + 0.5f); int right = (int) (aabb.corners[1][0] - 0.5f); for (int v = top; v <= bottom; v++) { for (int u = left; u <= right; u++) { V3 pixv(.5f + (float)u, .5f + (float)v, 1.0f); //Check edge equations if (eeqs[0]*pixv < 0.0f || eeqs[1]*pixv < 0.0f || eeqs[2]*pixv < 0.0f) continue; // Check z-buffer float currz = zABC * pixv; if (fb->IsFarther(u, v, currz)) continue; fb->SetZ(u, v, currz); V3 currColor; float msdn = denABC * pixv; V3 fullColor; if (tcs) { float currs = sABC * pixv; float currt = tABC * pixv; int ut, vt; ut=vt=0; if (tm == 0) { //nearest neighbor ut = (int) (currs * (float) texture->w); vt = (int) (currt * (float) texture->h); } else if(tm == 1) { //bilinear } fullColor.setFromColor(texture->Get(ut, vt)); } else { fullColor = V3(redNABC * pixv, greenNABC * pixv, blueNABC * pixv) / msdn; } V3 currNormal, lv; V3 pp(pixv); pp[2] = currz; lv = (L - ppc->UnProject(pp)).normalize(); currNormal = V3(nxABC*pixv, nyABC*pixv, nzABC*pixv).normalize(); float kd = lv * currNormal; kd = (kd < 0.0f) ? 0.0f : kd; float ks = 0; //pow(reflectedLightVector * eyeVector, se) currColor = fullColor * (ka + (1.0f-ka)*kd + ks); fb->Set(u, v, currColor.getColor()); } } } delete []pverts; }
/* Render Modes are * -Vertex Color Interpolation * -Texture Mapping * Renders the triangle mess, shades using the sence lights. * Shadow Mapping implimented */ void TMesh::RenderFilled(PPC *ppc, FrameBuffer *fb, unsigned int color, int lightsN, Light **L, float ka, FrameBuffer *texture, enviromap *cube, int renderMode) { //Project vertices on to the camera vector *pverts = new vector[vertsN]; for (int vi = 0; vi < vertsN; vi++) { ppc->Project(verts[vi], pverts[vi]); } for (int tri = 0; tri < trisN; tri++) { int vinds[3]; vinds[0] = tris[tri*3+0]; vinds[1] = tris[tri*3+1]; vinds[2] = tris[tri*3+2]; if( pverts[vinds[0]][2] == FLT_MAX || pverts[vinds[1]][2] == FLT_MAX || pverts[vinds[2]][2] == FLT_MAX ) continue; //Compute bounding box aabb of projected vertices AABB aabb(pverts[vinds[0]]); aabb.AddPoint(pverts[vinds[1]]); aabb.AddPoint(pverts[vinds[2]]); //Clip aabb with frame if(!aabb.Clip(0.0f, (float) fb->w, 0.0f, (float) fb->h)) continue; int left = (int)(aabb.corners[0][0] + 0.5f); int right = (int)(aabb.corners[1][0] - 0.5f); int top = (int)(aabb.corners[0][1] + 0.5f); int bottom = (int)(aabb.corners[1][1] - 0.5f); vector red( cols[vinds[0]][0], cols[vinds[1]][0], cols[vinds[2]][0]); vector green( cols[vinds[0]][1], cols[vinds[1]][1], cols[vinds[2]][1]); vector blue( cols[vinds[0]][2], cols[vinds[1]][2], cols[vinds[2]][2]); vector depth( pverts[vinds[0]][2], pverts[vinds[1]][2], pverts[vinds[2]][2] ); vector rABC, gABC, bABC, zABC, nxABC, nyABC, nzABC, sABC, tABC; vector DEF; vector eeqs[3]; SetEEQS( pverts[vinds[0]], pverts[vinds[1]], pverts[vinds[2]], eeqs); matrix ptm(pverts[vinds[0]], pverts[vinds[1]], pverts[vinds[2]]); ptm.setCol(2, vector(1.0f, 1.0f, 1.0f)); ptm = invert(ptm); // Set up for normals vector nx( normals[vinds[0]][0], normals[vinds[1]][0], normals[vinds[2]][0] ); vector ny( normals[vinds[0]][1], normals[vinds[1]][1], normals[vinds[2]][1] ); vector nz( normals[vinds[0]][2], normals[vinds[1]][2], normals[vinds[2]][2] ); // Set depth interpolation through screen space interpolation zABC = ptm * depth; //Matrix for Model Space interpolation matrix Q; Q = ComputeRastMatrix(ppc, verts[vinds[0]], verts[vinds[1]], verts[vinds[2]]); DEF = Q[0] + Q[1] + Q[2]; //Compute Model Space interpolation constants SetModelRast(Q, nx, &nxABC); SetModelRast(Q, ny, &nyABC); SetModelRast(Q, nz, &nzABC); //SetModelRast(Q, depth, &zABC); if( renderMode == VCI ) { // Setup screen space linear variation of color rABC = ptm * red; gABC = ptm * green; bABC = ptm * blue; }else if( renderMode == MCI ) { // Set Color Model Space Constants SetModelRast(Q, red, &rABC); SetModelRast(Q, green, &gABC); SetModelRast(Q, blue, &bABC); }else if( renderMode == TM) { //Get texture model space parameters vector s( tcs[2*vinds[0]+0], tcs[2*vinds[1]+0], tcs[2*vinds[2]+0]); vector t( tcs[2*vinds[0]+1], tcs[2*vinds[1]+1], tcs[2*vinds[2]+1]); SetModelRast(Q, s, &sABC); SetModelRast(Q, t, &tABC); } for( int v = top; v <= bottom; v++ ){ for ( int u = left; u <= right; u++ ) { if(fb->IsOutsideFrame(u,v)) continue; vector pv((float)u+0.5f, (float)v+0.5f, 1.0f); //Check whether pixel is inside triangle if (eeqs[0]*pv < 0.0f || eeqs[1]*pv < 0.0f || eeqs[2]*pv < 0.0f) continue; // Check whether triangle is closer than what was previously // seen at this pixel float currz = zABC * pv; //currz /= (DEF * pv); if (fb->IsFarther(u, v, currz)) continue; fb->SetZ(u, v, currz); // pixel is inside triangle and triangle is visible at pixel // compute color of pixel based on current triangle vector currColor; if ( renderMode == SM) continue; if ( renderMode == VCI ){ currColor = vector( rABC * pv, gABC * pv, bABC * pv ); }else if ( renderMode == MCI ) { float r = ModelInterpolation(u, v, rABC, DEF); float g = ModelInterpolation(u, v, gABC, DEF); float b = ModelInterpolation(u, v, bABC, DEF); currColor = vector(r,g,b); } if ( renderMode == TM) { int w = texture->w; int h = texture->h; float miS = ModelInterpolation(u, v, sABC, DEF); float miT = ModelInterpolation(u, v, tABC, DEF); miS = (miS * (float)w); miT = (miT * (float)h); int st = (h-1-(int)(miT)%h) * w+(int)(miS)%w; if(st < 0 || st > h*w) continue; currColor.SetFromColor(texture->pix[st]); } vector currNormal = vector(nxABC*pv/(DEF*pv), nyABC*pv/(DEF*pv), nzABC*pv/(DEF*pv)).norm(); if ( renderMode == RFL ) { vector eye = ppc->C; vector P = ppc->UnProject(pv); vector ev = (eye - P); vector rv = currNormal*(currNormal*ev)*2.0f - ev; rv = rv.norm(); //currColor = (rv + vector(1.0f, 1.0f, 1.0f))/2.0f; currColor.SetFromColor(cube->getColor(rv)); } //Calculated Color at pixel using phong equation for( int li = 0; li < lightsN; li++ ){ if(!L[li]->on) continue; vector fullColor; fullColor.SetFromColor(color); vector lv; vector pp(pv); pp[2] = currz; lv = (L[li]->L->C - ppc->UnProject(pp)).norm(); float kd = lv * currNormal; kd = (kd < 0.0f) ? 0.0f : kd; //currColor = currColor * ka ; //currColor = currColor * (ka + (1.0f-ka)*kd); vector point = ppc->UnProject(pp); vector SMp; L[li]->L->Project(point, SMp); float ul = SMp[0]; float vl = SMp[1]; if(L[li]->sm->IsOutsideFrame(ul, vl)) { currColor = currColor * ka ; //fb->Set(u,v, currColor.GetColor()); continue; } //Check depth from light to calculate shadows float e = SMp[2]*.01; if(L[li]->sm->IsFarther((int)ul, (int)vl, SMp[2]+e)) { currColor = currColor * ka ; //fb->Set(u,v, currColor.GetColor()); }else { currColor *= ka +(1.0f-ka)*kd; //fb->Set(u,v, currColor.GetColor()); } } fb->Set(u,v, currColor.GetColor()); } } } delete []pverts; }