// Light's Functions void AreaLight::AccumulateIlluminationAtSurface( const Ray &ray, const Vector<float> &surfaceNormal, const float &surfaceRoughness, const Scene &scene, Color &diffuse, Color &specular ) const { if( _positions.empty() ) return; Color areaLightDiffuse( 0 ); Color areaLightSpecular( 0 ); // Accumulate the illumination from all the positions for(VectorList::const_iterator itr = _positions.begin(); itr != _positions.end(); ++itr ) { const Vector<float> &lightPosition = (*itr); Vector<float> lightRayDirection = lightPosition - ray.Origin(); const float lightRayLength = lightRayDirection.Normalize(); // If the light is out of range of the surface if( lightRayLength > _range ) continue; // The illumination from this light const Ray lightRay( ray.Origin(), lightRayDirection, ray ); const Color illuminationFromLight = Illumination( lightRay, lightRayLength, scene ); if( illuminationFromLight.Magnitude2() < Maths::Tolerance ) continue; // Calculate the illumination at the point on the surface const Color illumination = illuminationFromLight * ( 1 - lightRayLength * _oneOverRange ); // Accumulate the diffuse areaLightDiffuse += illumination * Maths::Max<float>(0, surfaceNormal.Dot( lightRayDirection )); // Accumulate the specular areaLightSpecular += illuminationFromLight * powf( Maths::Max<float>(0, ray.Direction().Dot( lightRayDirection.Reflect( surfaceNormal ) ) ), surfaceRoughness ); } diffuse += areaLightDiffuse * (1.0f / _positions.size()); specular += areaLightSpecular * (1.0f / _positions.size()); }
int Render_SSD(SCENE *ascene, CAMERA *acamera) { /* We clear all pixels */ glClearColor(ascene->bcolor.rgba[0], ascene->bcolor.rgba[1], ascene->bcolor.rgba[2], ascene->bcolor.rgba[3]); glClear (GL_COLOR_BUFFER_BIT); int i,j; double matrixFinal[4][4],mTransform[4][4]; double intermediaM[4][4],mCam[4][4],mInverse[4][4],tmpMatrix[4][4]; double mTranslate[4][4],mRotate[4][4],mScale[4][4]; double homo_coordinates[4] = {0,0,0,1}; //double mInverse[4][4]; matrixInitial(matrixFinal); matrixInitial(mTransform); matrixInitial(mTranslate); matrixInitial(mRotate); matrixInitial(mScale); int screenW = ascene->screen_w; int screenH = ascene->screen_h; buffer = (HIDDEN *)malloc(sizeof(HIDDEN) * screenW * screenH); for(i = 0;i < screenW * screenH;i++) { buffer[i].rgba[0] = ascene->bcolor.rgba[0]; buffer[i].rgba[1] = ascene->bcolor.rgba[1]; buffer[i].rgba[2] = ascene->bcolor.rgba[2]; buffer[i].z = 9999; } /* Camera View */ int ii; matrixInitial(mInverse); matrixInitial(tmpMatrix); matrixInitial(intermediaM); matrixInitial(mCam); double u[3],v[3],w[3]; double gaze[3] = {acamera->gaze.xyzw[0],acamera->gaze.xyzw[1],acamera->gaze.xyzw[2]}; double upVector[3] = {acamera->upVector.xyzw[0],acamera->upVector.xyzw[1],acamera->upVector.xyzw[2]}; vecUnitization(gaze,w); for(ii = 0; ii < 3; ii++){ w[ii] = -w[ii]; } vecCross(upVector,w,u); vecUnitization(u,u); vecCross(w,u,v); ii = 0; for(ii = 0; ii < 3; ii++){ intermediaM[0][ii] = u[ii]; intermediaM[1][ii] = v[ii]; intermediaM[2][ii] = w[ii]; mCam[ii][3] = -acamera->eye.xyzw[ii]; } matrixMultiply(intermediaM,mCam,0); /*inverse matrixMultiply() 0:normal 1:inverse */ matrixInitial(intermediaM); ii = 0; for(ii = 0; ii < 3; ii++){ intermediaM[ii][0] = u[ii]; intermediaM[ii][1] = v[ii]; intermediaM[ii][2] = w[ii]; tmpMatrix[ii][3] = acamera->eye.xyzw[ii]; } matrixMultiply(mInverse,tmpMatrix,1); matrixMultiply(mInverse,intermediaM,1); /*Persective(1) and Orthographic(0) Projection matrix*/ double anglePers, nearPers, farPers, rightOrtho, topOrtho, farOrtho, nearOrtho,pjType; double screenWidth,screenHeight; screenWidth = ascene->screen_w; screenHeight = ascene->screen_h; anglePers = ascene->persp.angle; nearPers = ascene->persp.near; farPers = ascene->persp.far; rightOrtho = ascene->ortho.right; topOrtho = ascene->ortho.top; farOrtho = ascene->ortho.far; nearOrtho = ascene->ortho.near; pjType = ascene->pjType; getFinalTransformMatrix(anglePers, nearPers, farPers, rightOrtho, topOrtho, farOrtho, nearOrtho, pjType, screenWidth, screenHeight, mCam, matrixFinal,mInverse); double vpInverse[4][4]; matrixInitial(vpInverse); vpInverse[0][0] = (double)2/ascene->screen_w; vpInverse[0][3] = (double)(1-ascene->screen_w)/ascene->screen_w; vpInverse[1][1] = (double)2/ascene->screen_h; vpInverse[1][3] = (double)(1-ascene->screen_h)/ascene->screen_h; matrixMultiply(mInverse,vpInverse,1); /* Draw floor */ double xmin,xmax,ymin,ymax,floorEdge; int nX,nY; xmin = ascene->floor.xmin; xmax = ascene->floor.xmax; ymin = ascene->floor.ymin; ymax = ascene->floor.ymax; floorEdge = ascene->floor.size; nY = ((xmax-xmin)/floorEdge) + 1; nX = ((ymax-ymin)/floorEdge) + 1; Line floor[nX + nY]; glLineWidth(2); glBegin(GL_LINES); glColor3f(ascene->floor.color.rgba[0],ascene->floor.color.rgba[1],ascene->floor.color.rgba[2]); drawFloor(xmin,xmax,ymin,ymax,nX,nY,floorEdge,matrixFinal,floor); glEnd(); /* draw axis*/ glLineWidth(ascene->axis.width); glBegin(GL_LINES); if(ascene->isAxis == 1){ double origin[4] = {0,0,0,1}; double axisX[4] = {ascene->axis.length,0,0,1}; double axisY[4] = {0,ascene->axis.length,0,1}; double axisZ[4] = {0,0,ascene->axis.length,1}; matrixApply(matrixFinal,origin); matrixApply(matrixFinal,axisX); matrixApply(matrixFinal,axisY); matrixApply(matrixFinal,axisZ); glColor3f(1,0,0); glVertex2d(origin[0]/origin[3],origin[1]/origin[3]); glVertex2d(axisX[0]/axisX[3],axisX[1]/axisX[3]); glColor3f(0,1,0); glVertex2d(origin[0]/origin[3],origin[1]/origin[3]); glVertex2d(axisY[0]/axisY[3],axisY[1]/axisY[3]); glColor3f(0,0,1); glVertex2d(origin[0]/origin[3],origin[1]/origin[3]); glVertex2d(axisZ[0]/axisZ[3],axisZ[1]/axisZ[3]); } glEnd(); /* implement objects*/ int nT = 0; int nR = 0; int nS = 0; int nM = 0; for(i = 0; i < ascene->nidentities; i++){ matrixInitial(mTransform); for(j = 0; j < ascene->identities[i].inStr_num; j++){ if(ascene->identities[i].instr[j] == TRANSLATE_KEY){ matrixInitial(mTranslate); mTranslate[0][3] = ascene->translate[nT].xyz[0]; mTranslate[1][3] = ascene->translate[nT].xyz[1]; mTranslate[2][3] = ascene->translate[nT].xyz[2]; matrixMultiply(mTranslate,mTransform,0); nT++; } else if(ascene->identities[i].instr[j] == ROTATE_KEY){ double axis[3]; axis[0] = ascene->rotate[nR].xyz[0]; axis[1] = ascene->rotate[nR].xyz[1]; axis[2] = ascene->rotate[nR].xyz[2]; double Pi = 3.141592653; double radian = (ascene->rotate[nR].angle/(double)180) * Pi; rotateMatrix(axis,mRotate,mTransform,radian); nR++; } else if(ascene->identities[i].instr[j] == SCALE_KEY){ matrixInitial(mScale); mScale[0][0] = ascene->scale[nS].xyz[0]; mScale[1][1] = ascene->scale[nS].xyz[1]; mScale[2][2] = ascene->scale[nS].xyz[2]; matrixMultiply(mScale,mTransform,0); nS++; } else if(ascene->identities[i].instr[j] == MESH_KEY){ double tM[4][4]; matrixInitial(tM); matrixMultiply(mTransform,tM,0); matrixMultiply(matrixFinal,tM,0); int k,l,d; /*apply transform matrix to all vertices in world coordinates*/ COLOR_VERTEX colorVertices[ascene->mesh[nM].nvertices]; for(k = 0; k < ascene->mesh[nM].nvertices; k++){ colorVertices[k] = ascene->mesh[nM].vertices[k]; matrixApply(mTransform,colorVertices[k].xyzw); } //flat shading if(ascene->mesh[nM].shading == 0){ for(k = 0; k < ascene->mesh[nM].npolygons; k++){ COLOR_VERTEX vertices[3] = {colorVertices[ascene->mesh[nM].polygons[k].num[0]], colorVertices[ascene->mesh[nM].polygons[k].num[1]], colorVertices[ascene->mesh[nM].polygons[k].num[2]]}; double normal[3]; triangleNormal(vertices[0].xyzw,vertices[1].xyzw,vertices[2].xyzw,normal); double center[3]; center[0] = (vertices[0].xyzw[0] + vertices[1].xyzw[0] + vertices[2].xyzw[0])/(double)3; center[1] = (vertices[0].xyzw[1] + vertices[1].xyzw[1] + vertices[2].xyzw[1])/(double)3; center[2] = (vertices[0].xyzw[2] + vertices[1].xyzw[2] + vertices[2].xyzw[2])/(double)3; Illumination(normal,ascene->mesh[nM].diffuse,ascene->mesh[nM].specular,center); int i; for(i = 0; i < 3; i++){ matrixApply(matrixFinal,vertices[i].xyzw); } toScreen(vertices[0].xyzw,vertices[1].xyzw,vertices[2].xyzw); triRendering(vertices[0].xyzw,vertices[1].xyzw,vertices[2].xyzw,0,0,0,0,0,0,mInverse); } } //phong shading else if (ascene->mesh[nM].shading == 2){ double vertex_normal[ascene->mesh[nM].nvertices][3]; for(k = 0; k < ascene->mesh[nM].nvertices; k++){ double composeNormal[3] = {0,0,0}; for(l = 0; l < ascene->mesh[nM].npolygons; l++){ for(d = 0; d < ascene->mesh[nM].polygons[l].nvertices; d++){ if(ascene->mesh[nM].polygons[l].num[d] == k){ COLOR_VERTEX vertices[3] = {colorVertices[ascene->mesh[nM].polygons[l].num[0]], colorVertices[ascene->mesh[nM].polygons[l].num[1]], colorVertices[ascene->mesh[nM].polygons[l].num[2]]}; double normal[3]; triangleNormal(vertices[0].xyzw,vertices[1].xyzw,vertices[2].xyzw,normal); composeNormal[0] += normal[0]; composeNormal[1] += normal[1]; composeNormal[2] += normal[2]; } } } vecUnitization(composeNormal,composeNormal); int i=0; for(i = 0; i < 3; i++){ colorVertices[k].rgba[i] = composeNormal[i]; } } setBuffer(colorVertices,matrixFinal,nM,ascene->mesh[nM].diffuse,ascene->mesh[nM].specular,2,mInverse); } //smooth shading else{ for(k = 0; k < ascene->mesh[nM].nvertices; k++){ double composeNormal[3] = {0,0,0}; for(l = 0; l < ascene->mesh[nM].npolygons; l++){ for(d = 0; d < ascene->mesh[nM].polygons[l].nvertices; d++){ if(ascene->mesh[nM].polygons[l].num[d] == k){ COLOR_VERTEX vertices[3] = {colorVertices[ascene->mesh[nM].polygons[l].num[0]], colorVertices[ascene->mesh[nM].polygons[l].num[1]], colorVertices[ascene->mesh[nM].polygons[l].num[2]]}; double normal[3]; triangleNormal(vertices[0].xyzw,vertices[1].xyzw,vertices[2].xyzw,normal); composeNormal[0] += normal[0]; composeNormal[1] += normal[1]; composeNormal[2] += normal[2]; } } } vecUnitization(composeNormal,composeNormal); Illumination(composeNormal,ascene->mesh[nM].diffuse,ascene->mesh[nM].specular,colorVertices[k].xyzw); colorVertices[k].rgba[0] = illuColor[0]; colorVertices[k].rgba[1] = illuColor[1]; colorVertices[k].rgba[2] = illuColor[2]; } setBuffer(colorVertices,matrixFinal,nM,0,0,1,mInverse); } glLineWidth(ascene->mesh[nM].width); glBegin(GL_POINTS); for(k = 0; k < ascene->screen_h; k++){ for(l = 0; l < ascene->screen_w; l++){ if(buffer[k*(ascene->screen_w)+l].z < 9999){ glColor3f(buffer[k*(ascene->screen_w) + l].rgba[0],buffer[k*(ascene->screen_w) + l].rgba[1],buffer[k*(ascene->screen_w) + l].rgba[2]); glVertex2i(l,k); } } } glEnd(); nM++; } } } for(i = 0; i < ascene->nlines; i++){ ascene->lines[i].vertices[0].xyzw[3] = 1; ascene->lines[i].vertices[1].xyzw[3] = 1; COLOR_VERTEX vertices[2]; vertices[0] = ascene->lines[i].vertices[0]; vertices[1] = ascene->lines[i].vertices[1]; matrixApply(matrixFinal,vertices[0].xyzw); matrixApply(matrixFinal,vertices[1].xyzw); glLineWidth(ascene->lines[i].width); glBegin(GL_LINES); glColor3f(vertices[0].rgba[0],vertices[0].rgba[1],vertices[0].rgba[2]); glVertex2d(vertices[0].xyzw[0]/vertices[0].xyzw[3],vertices[0].xyzw[1]/vertices[0].xyzw[3]); glColor3f(vertices[1].rgba[0],vertices[1].rgba[1],vertices[1].rgba[2]); glVertex2d(vertices[1].xyzw[0]/vertices[1].xyzw[3],vertices[1].xyzw[1]/vertices[1].xyzw[3]); glEnd(); } free(buffer); glFlush (); glutSwapBuffers(); return 0; }
void triRendering(double v0[],double v1[],double v2[],float c0[],float c1[],float c2[],double d[],double s[],int shading,double mInverse[][4]) { /*triangle constant*/ int xmax,xmin,ymax,ymin; double l0_12,l1_02,l2_01; double x_incr_alpha,x_incr_beta,x_incr_gamma; double y_incr_alpha,y_incr_beta,y_incr_gamma; double alpha0,beta0,gamma0,flag_12,flag_02,flag_01; xmin=min(min(v0[0],v1[0]),v2[0]); xmax=max(max(v0[0],v1[0]),v2[0]); ymin=min(min(v0[1],v1[1]),v2[1]); ymax=max(max(v0[1],v1[1]),v2[1]); /*const*/ l0_12 = decision(v1,v2,v0[0],v0[1]); l1_02 = decision(v0,v2,v1[0],v1[1]); l2_01 = decision(v0,v1,v2[0],v2[1]); x_incr_alpha = (v1[1]-v2[1])/l0_12; x_incr_beta = (v0[1]-v2[1])/l1_02; x_incr_gamma = (v0[1]-v1[1])/l2_01; y_incr_alpha = (v2[0]-v1[0])/l0_12; y_incr_beta = (v2[0]-v0[0])/l1_02; y_incr_gamma = (v1[0]-v0[0])/l2_01; alpha0 = decision(v1,v2,xmin,ymin)/l0_12; beta0 = decision(v0,v2,xmin,ymin)/l1_02; gamma0 = decision(v0,v1,xmin,ymin)/l2_01; /* (-1,-1) or (-2,-1) */ flag_12 = decision(v1,v2,-1,-1); flag_02 = decision(v0,v2,-1,-1); flag_01 = decision(v0,v1,-1,-1); if(flag_12 == 0) flag_12 = decision(v1,v2,-2,-1); if(flag_02 == 0) flag_02 = decision(v0,v2,-2,-1); if(flag_01 == 0) flag_01 = decision(v0,v1,-2,-1); int i,x,y; double alpha,beta,gamma; for (y = ymin; y <= ymax; y++){ alpha = alpha0; beta = beta0; gamma = gamma0; for (x = xmin; x <= xmax; x++){ if(alpha >= 0 && beta >= 0 && gamma >= 0){ if( (alpha > 0 || l0_12 * flag_12 >0) && (beta > 0 || l1_02 * flag_02 >0) && (gamma > 0 || l2_01 * flag_01 > 0)){ double z = alpha * v0[2] + beta * v1[2] + gamma * v2[2]; if(z < buffer[y*thescene.screen_w+x].z){ if(shading == 0){ for(i = 0; i < 3; i++){ buffer[y*thescene.screen_w+x].rgba[i] = illuColor[i]; } buffer[y*thescene.screen_w+x].z = z; } else if(shading == 1){ for(i = 0; i < 3; i++){ buffer[y*thescene.screen_w+x].rgba[i] = alpha * c0[i] + beta * c1[i] + gamma * c2[i]; } buffer[y*thescene.screen_w+x].z = z; } else{ double normal[3]; for(i = 0; i < 3; i++){ normal[i] = alpha * c0[i] + beta * c1[i] + gamma * c2[i]; } vecUnitization(normal,normal); double w = alpha * v0[3] + beta * v1[3] + gamma * v2[3]; double p[4] = {x*w,y*w,z,w}; matrixApply(mInverse,p); Illumination(normal,d,s,p); for(i = 0; i < 3; i++){ buffer[y*thescene.screen_w+x].rgba[i] = illuColor[i]; } buffer[y*thescene.screen_w+x].z = z; } } } } alpha += x_incr_alpha; beta += x_incr_beta; gamma += x_incr_gamma; } alpha0 += y_incr_alpha; beta0 += y_incr_beta; gamma0 += y_incr_gamma; } }