// RayTracer.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #include #include #include #include "vec3.h" #include "mat3.h" #include "vertex.h" #include "image.h" #include "intersectionTest.h" #include "Scene.h" #include "light.h" Scene scene; //this needs to return a color value for the pixel found by the primary ray vec3 recursiveTrace(intersectionTest test, int passes) { //set up a light object for debug purposes, Kevin, you'll need to remove this and pipe the lights through the scene (let them be read in through the file and looped through) light l = light('p', vec3(100, 0, 100), 0, vec3(1,1,1), vec3(1,0,0));//default light //this recurses through the secondary rays... which include shadow, reflection and refraction. If we're in shadow then return 0 for the color //if we're at a point in the scene if(test.foundPoint == true) { // if(test.reflectiveIndex == 0 || passes > 5)//if there's no reflection or we've had 5 bounces // { // test.intersectionDistance = sqrt( pow(test.intersectionPosition.x - scene.cam.position.x, 2) + pow(test.intersectionPosition.y - scene.cam.position.y, 2) + pow(test.intersectionPosition.z - scene.cam.position.z, 2) ); // return vec3(test.intersectionDistance*15, test.intersectionDistance*15, 0); //for each light do the full lighting calculation at this point vec3 lightContribution = vec3(0,0,0); //need to find texture color at this pixel, first need to know our current texture's size int xLookup = (int)(test.texture.columns*test.texCoords.x)%test.texture.columns; int yLookup = (int)(test.texture.rows*test.texCoords.y)%test.texture.rows; //find colors double rColor = getPixelColor(&test.texture,yLookup, xLookup, 1); double gColor = getPixelColor(&test.texture,yLookup, xLookup, 2); double bColor = getPixelColor(&test.texture,yLookup, xLookup, 3); for(int i = 0; i < scene.lights.size(); i++) //hardcode this to 1 for now { char type; vec3 pos; double a; vec3 c; vec3 atten; if(scene.lights[i].type == DIRECTIONAL){ type = 'd'; pos.x = scene.lights[i].dir[0]; pos.y = scene.lights[i].dir[1]; pos.z = scene.lights[i].dir[2]; a = 0; c.x = scene.lights[i].color[0]; c.y = scene.lights[i].color[1]; c.z = scene.lights[i].color[2]; atten.x = scene.lights[i].attenuation[0]; atten.y = scene.lights[i].attenuation[1]; atten.z = scene.lights[i].attenuation[2]; } else if(scene.lights[i].type == AREA){ type = 'a'; pos.x = scene.lights[i].loc[0]; pos.y = scene.lights[i].loc[1]; pos.z = scene.lights[i].loc[2]; a = scene.lights[i].radius; c.x = scene.lights[i].color[0]; c.y = scene.lights[i].color[1]; c.z = scene.lights[i].color[2]; atten.x = scene.lights[i].attenuation[0]; atten.y = scene.lights[i].attenuation[1]; atten.z = scene.lights[i].attenuation[2]; } else if(scene.lights[i].type == POINT){ type = 'p'; pos.x = scene.lights[i].loc[0]; pos.y = scene.lights[i].loc[1]; pos.z = scene.lights[i].loc[2]; a = 0; c.x = scene.lights[i].color[0]; c.y = scene.lights[i].color[1]; c.z = scene.lights[i].color[2]; atten.x = scene.lights[i].attenuation[0]; atten.y = scene.lights[i].attenuation[1]; atten.z = scene.lights[i].attenuation[2]; } //type,position,area, color, attenuation l= light(type,pos,a, c, atten); //check if we're in shadow double intensity = l.findShadow(test.intersectionPosition, scene); //intensity = 1.0; //turn off shadows test.normalDirection.normalize(); //get diffuse component vec3 diffuse = l.findDiffuseComponent(test); vec3 specular = l.findSpecularComponent(scene.cam.position, test); lightContribution.x += intensity*l.color.x*(diffuse.x + specular.x); lightContribution.y += intensity*l.color.y*(diffuse.y + specular.y); lightContribution.z += intensity*l.color.z*(diffuse.z + specular.z); //return vec3((int)(rColor), (int)(gColor), (int)(bColor)); } lightContribution = vec3( (double)min(lightContribution.x + test.ambientColor.x, 1.0)*rColor, (double)min(lightContribution.y + test.ambientColor.y, 1.0)*gColor, (double)min(lightContribution.z + test.ambientColor.z, 1.0)*bColor ); //if the material is in some way transparent or reflective then calculate the two rays and make the contribuation vec3 reflectionContribution = vec3(0, 0, 0); if(test.reflectivity > 0 && passes < scene.maxdepth) { //first need to compute the reflected ray vec3 reflected = test.viewVec.reflection(test.normalDirection); intersectionTest reflectionTest = scene.testScene(test.intersectionPosition, reflected); reflectionContribution = recursiveTrace(reflectionTest, ++passes); } vec3 refractionContribution = vec3(0, 0, 0); if(test.translucency > 0 && passes < scene.maxdepth) { //first need to compute the refracted ray vec3 refracted = test.viewVec.refraction(test.normalDirection, test.dielectric); //remember that we move our ray outside of the object a little bit so everything wont be self shadowed, now we want our ray to go through the object so we need to move it forward a little test.intersectionPosition = vec3(test.intersectionPosition.x + refracted.x*0.01, test.intersectionPosition.y + refracted.y*0.01, test.intersectionPosition.z + refracted.z*0.01); intersectionTest refractionTest = scene.testScene(test.intersectionPosition, refracted); //remember to change this to the refraction vector refractionContribution = recursiveTrace(refractionTest, ++passes); } vec3 finalLight; finalLight.x = ( (lightContribution.x*(1-test.reflectivity) + reflectionContribution.x*(test.reflectivity)) * (1-test.translucency) + refractionContribution.x*(test.translucency) ); finalLight.y = ( (lightContribution.y*(1-test.reflectivity) + reflectionContribution.y*(test.reflectivity)) * (1-test.translucency) + refractionContribution.y*(test.translucency) ); finalLight.z = ( (lightContribution.z*(1-test.reflectivity) + reflectionContribution.z*(test.reflectivity)) * (1-test.translucency) + refractionContribution.z*(test.translucency) ); //add emission term (light is emitting from this object) finalLight.x += test.emissionColor.x; finalLight.y += test.emissionColor.y; finalLight.z += test.emissionColor.z; return finalLight; } else //no intersection, return red { return vec3(0,0,0); } return vec3(0,0,0); } int main(int argc, char* argv[]) { scene.load(argv[1]); //scene file's camera "lookat" value is in world space (its a point), our lookat should be a direction that the camera is pointing, thus we need to subtract the camera point from the lookat and normalize it //scene.cam.lookat = vec3(scene.cam.position.x - scene.cam.lookat.x, scene.cam.position.y - scene.cam.lookat.y, scene.cam.position.z - scene.cam.lookat.z); scene.cam.lookat = vec3(scene.cam.lookat.x - scene.cam.position.x, scene.cam.lookat.y - scene.cam.position.y, scene.cam.lookat.z - scene.cam.position.z); scene.cam.lookat.normalize(); ImageColor bitmap; int screenWidth = scene.sizex; int screenHeight = scene.sizey; int passed = setSizeColor(&bitmap, screenHeight, screenWidth); int pixels = screenWidth*screenHeight; //scene.cam.setCamera(vec3(-20, -30, 50), vec3(0, 0, 0), screenWidth, screenHeight, 3.14f/2.0f);//temp cam scene.globalLight = vec3(1,0,1); scene.globalLight.normalize(); int percent = 0; //image rendering loop vec3 position = scene.cam.getPosition(); vec3 viewVec; for(int i = 1; i <= screenWidth; i++) { for(int j = 1; j <= screenHeight; j++) { viewVec = scene.cam.calculateRay(i, j); //do the primary ray intersectionTest primaryTest = scene.testScene(position, viewVec);//tempscene(position, viewVec); //secondary ray (reflect and light test) vec3 color = recursiveTrace(primaryTest, 0); int pass = setPixelColor(&bitmap, screenHeight - j, screenWidth - i, color.x, color.y, color.z); //int grayLevel; //if(primaryTest.foundPoint == true) //{ // //do lighting! // grayLevel = primaryTest.normalDirection.dotProduct(globalLightDirection)*255;//test.intersectionPosition.x*100; // grayLevel = max(0, grayLevel); // int pass = setPixelColor(&bitmap, screenHeight - j, screenWidth - i, grayLevel, grayLevel, grayLevel); //} //else //{ // int pass = setPixelColor(&bitmap, screenHeight - j, screenWidth - i, 0, 0, 0); //} if( ((double)(i*screenHeight + j)/(double)pixels)*100 > percent) { percent++; //DEBUG fprintf(stderr, "%d \n ", percent); } } } //create a new output file for our final rendered image passed = writeImageColor(&bitmap, "result.ppm"); return 0; }