void GetColor(GzRender* render,GzRay ray, GzCoord hitPoint,GzCoord* vertexList,GzCoord* pNormalList,GzColor* intensity) //normals of the hit point object
{
//1st interpolate the normals at the hit point
GzCoord normal;
GzColor resultIntensity;
NormalInterpolation(hitPoint,vertexList,pNormalList,&normal);
//now that we have got the normal at the hit point, apply the Shading equation
PhongIllumination(render,ray,normal,&resultIntensity);
resultIntensity[RED] *= 255;
resultIntensity[GREEN] *= 255;
resultIntensity[BLUE] *= 255;
memcpy(intensity,&resultIntensity,sizeof(GzColor));
}
Here is the phong illumination code:
void PhongIllumination(GzRender *render, GzRay ray, GzCoord normal,GzColor *intensity)
{
float colorCoeff = 0.0f;
GzColor specTerm = {0,0,0};
GzColor diffTerm = {0,0,0};
GzCoord Rvec;
GzCoord Evec;
GzCoord tempNorm = {normal[X],normal[Y],normal[Z]};
memcpy(&Evec,&ray.direction,sizeof(GzCoord));
float nl,ne,re; // dot product of N & L, N & E and R & E
bool flag; //to detect if lighting model should be computed
for(int j = 0; j < render->numlights; j++)
{
flag = false;
GzCoord LVec;
memcpy(&LVec,&render->lights[j].direction,sizeof(GzCoord));
//we have to do inverse Xform on the LVec to convert it from image to world space;
NormalTransformation(LVec,render->camera.Xwi,&LVec);
//ImageWorldXform(render,&LVec);
nl = dotProduct(tempNorm, LVec);
ne = dotProduct(tempNorm, Evec);
// check if we should include the light in the lighting model depending on its direction with the camera
if(nl < 0 && ne < 0) //invert the normal and calculate the lighting model
{
tempNorm[X] *= -1;
tempNorm[Y] *= -1;
tempNorm[Z] *= -1;
Normalize(&tempNorm);
nl = dotProduct(tempNorm, LVec);
ne = dotProduct(tempNorm, Evec);
//renormalize N and recompute nl and ne
flag = true;
}
else if(nl > 0 && ne > 0) // compute the lighting model
flag = true;
if(flag)
{
//r = 2(n.l)N - L
Rvec[X] = (2 * nl * tempNorm[X]) - LVec[X];
Rvec[Y] = (2 * nl * tempNorm[Y]) - LVec[Y];
Rvec[Z] = (2 * nl * tempNorm[Z]) - LVec[Z];
Normalize(&Rvec);
re = dotProduct(Rvec,Evec);
//clamp it to [0,1]
// if(re > 1.0)
// re = 1.0f;
// else if(re < 0.0)
// re = 0.0f;
re = pow(re,render->spec); //specular power
specTerm[RED] += render->lights[j].color[RED] * re; //clamp the colors individually as well
specTerm[GREEN] += render->lights[j].color[GREEN] * re;
specTerm[BLUE] += render->lights[j].color[BLUE] * re;
diffTerm[RED] += render->lights[j].color[RED] * nl;
diffTerm[GREEN] +=render->lights[j].color[GREEN] * nl;
diffTerm[BLUE] += render->lights[j].color[BLUE] * nl;
}
//now reset the normal back for the next light
memcpy(tempNorm,normal,sizeof(GzCoord));
}
GzColor specular, diffuse;
memcpy(specular, &specTerm, sizeof(GzColor));
memcpy(diffuse, &diffTerm, sizeof(GzColor));
MultiplyColor(render,specular,diffuse,intensity);
}
void MultiplyColor(GzRender *render, GzColor specular, GzColor diffuse, GzColor* resultant)
{
GzColor result = {0,0,0};
result[RED] = render->Ka[RED] * render->ambientlight.color[RED] + render->Ks[RED] * specular[RED] + render->Kd[RED] * diffuse[RED];
result[GREEN] = render->Ka[GREEN] * render->ambientlight.color[GREEN] + render->Ks[GREEN] * specular[GREEN] + render->Kd[GREEN] * diffuse[GREEN];
result[BLUE] = render->Ka[BLUE] * render->ambientlight.color[BLUE] + render->Ks[BLUE] * specular[BLUE] + render->Kd[BLUE] * diffuse[BLUE];
if(result[RED] > 1.0f)
result[RED] = 1.0f;
if(result[RED] < 0.0f)
result[RED ]= 0.0f;
if(result[GREEN] > 1.0f)
result[GREEN] = 1.0f;
if(result[GREEN] < 0.0f)
result[GREEN] = 0.0f;
if(result[BLUE] > 1.0f)
result[BLUE] = 1.0f;
if(result[BLUE] < 0.0f)
result[BLUE] = 0.0f;
memcpy(resultant,result,sizeof(GzColor));
}