//============================================================================ // softgl_lighting.hpp //============================================================================ #include #include "softgl.hpp" #include "vec3fv.hpp" #define MAX(A,B) ((A)>(B)?(A):(B)) #define PI_OVER_180 0.017453292 //---------------------------------------------------------------------------- // Based on the given current vertex in eye coords (p), the current normal // in eye coords (n), the location of the eye (or camera) in eye coords // at the origin, the current state of the lights and lighting model, and the // current material properties for both the front and back sides of polygons // (as determined by the vertex normal), compute the final vertex color. The // components of the final vertex color must be clamped to the range [0,1]. // Normal is assumed to already be normalized. Directional light direction // is also assumed to already be normalized (w component of light position // equals 0, L=(x,y,z) and is already normalized). We have to pass in the // front and back materials properties corresponding to the current vertex // (front is ColorMaterials[0] and back is ColorMaterials[1]). If // LightModelTwoSide=0, then only the front material is used. The IsBackfacing // flag indicates if the triangle that this vertex belongs to is backfacing or // frontfacing, this value is only used if LightModelTwoSide=1. //---------------------------------------------------------------------------- void SoftGL::CalcLighting(float FinalVertexColor[4], const float p[4], const float n[3], MaterialParams ColorMaterials[2], const int IsBackfacing) { int i; // index for color computations // make non-constant copies of vecors to use in Vec3fv functions float P[4] = {p[0], p[1], p[2], p[3]}; float N[4] = {n[0], n[1], n[2], n[3]}; // set state for backfacing polygons int MaterialIndex = (IsBackfacing && LightModelTwoSide)?1:0; if(IsBackfacing) for(i=0;i<3;i++) N[i] = -N[i]; // start with emissive light component for(i=0;i<3;i++) FinalVertexColor[i] = ColorMaterials[MaterialIndex].Emission[i]; // add ambient light component for(i=0;i<3;i++) FinalVertexColor[i] += ColorMaterials[MaterialIndex].Ambient[i] * LightModelAmbient[i]; // calculate contributions from each light for(int light=0; light 0) { // only do specular component if vertex is facing the light float viewVector[3] = {0,0,0}; if(!LightModelLocalViewer) // non-local view mode -> every vertex has z axis as view vector viewVector[2] = 1; else { // view vector is between the vertex and the eye position (0,0,0) for(i=0;i<3;i++) viewVector[i] = -P[i]; Normalize3fv(viewVector); } float S[3]; // sum vector for specular model Add3fv(S, lightVector, viewVector); Normalize3fv(S); // compute a specular factyor and raise it to a power // for shinyness float specularFactor = MAX(DotProd3fv(S, N), 0); float specular = 1; for(int j = 0; j < ColorMaterials[MaterialIndex].Shininess; j++) specular *= specularFactor; for(i=0;i<3;i++) contribution[i] += specular * ColorMaterials[MaterialIndex].Specular[i] * Lights[light].Specular[i]; } //************************************************************************* // compute attenuation factor float attenuation; if(Lights[light].Position[3] = 0.0) attenuation = 1; else attenuation = 1/( Lights[light].ConstantAttenuation + Lights[light].LinearAttenuation*lightDistance + Lights[light].QuadraticAttenuation*lightDistance); for(i=0;i<3;i++) contribution[i] *= attenuation; //********************************************************************** // compute spotlight effect float spotEffect; if (Lights[light].SpotCutoff = 180.0) // not a spot light spotEffect = 1; else { // light is a spot light float V[3]; // unit vector from light vertex for(i=0;i<3;i++) V[i] = -lightVector[i]; // spot falloff factor float spotFactor = MAX(DotProd3fv(V, Lights[light].SpotDirection), 0); if(spotFactor < cosf(PI_OVER_180* Lights[light].SpotCutoff)) // point is outside spotlight cone spotEffect = 0; else { // point is inside spotlight cone spotEffect = 1; for(int j= 0;j 1) FinalVertexColor[i] = 1; } } }