void run() { Scene* scene = new Scene(); SceneParser* p = new SceneParser(scene); p->assignVariable(L"test-predefined-a", 30); p->parse_file(SchemeFilenames::toString(getLoadPrefix() + "/scheme/test-mesh.scm")); assertTrue(lookupInt(L"tetrahedron-vertices-num") == 4); assertTrue(lookupInt(L"tetrahedron-faces-num") == 4); assertTrue(lookupInt(L"tetrahedron-edges-num") == 6); assertTrue(lookupInt(L"hexahedron-vertices-num") == 8); assertTrue(lookupInt(L"hexahedron-faces-num") == 6*2); assertTrue(lookupInt(L"hexahedron-edges-num") == 12+6); assertTrue(lookupInt(L"octahedron-vertices-num") == 6); assertTrue(lookupInt(L"octahedron-faces-num") == 8); assertTrue(lookupInt(L"octahedron-edges-num") == 12); assertTrue(lookupInt(L"dodecahedron-vertices-num") == 20); assertTrue(lookupInt(L"dodecahedron-faces-num") == 12*3); assertTrue(lookupInt(L"dodecahedron-edges-num") == 30 + 12*2); assertTrue(lookupInt(L"icosahedron-vertices-num") == 12); assertTrue(lookupInt(L"icosahedron-faces-num") == 20); assertTrue(lookupInt(L"icosahedron-edges-num") == 30); }
bool ParsedBlockImpl::getIntersectableProp(const char* name, Intersectable** value) { PBEGIN; Geometry* g = parser->findGeometryByName(value_s); if (g) { *value = g; return true; } Node* node = parser->findNodeByName(value_s); if (!node) throw SyntaxError(line, "Intersectable by that name not defined"); *value = node; return true; }
bool ParsedBlockImpl::getFilenameProp(const char* name, char* value) { PBEGIN; strcpy(value, value_s); if (parser->resolveFullPath(value)) return true; else throw FileNotFoundError(line, value_s); }
bool ParsedBlockImpl::getBitmapFileProp(const char* name, Bitmap& bmp) { PBEGIN; char filename[256]; strcpy(filename, value_s); if (!parser->resolveFullPath(filename)) throw FileNotFoundError(line, filename); return bmp.loadImage(filename); }
bool ParsedBlockImpl::getNodeProp(const char* name, Node** value) { PBEGIN; Node* n = parser->findNodeByName(value_s); if (!n) throw SyntaxError(line, "Node not defined"); *value = n; return true; }
bool ParsedBlockImpl:: getTextureProp(const char* name, Texture** value) { PBEGIN; Texture* t = parser->findTextureByName(value_s); if (!t) throw SyntaxError(line, "Texture not defined"); *value = t; return true; }
bool ParsedBlockImpl::getShaderProp(const char* name, Shader** value) { PBEGIN; Shader* s = parser->findShaderByName(value_s); if (!s) throw SyntaxError(line, "Shader not defined"); *value = s; return true; }
bool ParsedBlockImpl::getGeometryProp(const char* name, Geometry** value) { PBEGIN; Geometry* g = parser->findGeometryByName(value_s); if (!g) throw SyntaxError(line, "Geometry not defined"); *value = g; return true; }
int main( int argc, char* argv[] ) { // Fill in your implementation here. // This loop loops over each of the input arguments. // argNum is initialized to 1 because the first // "argument" provided to the program is actually the // name of the executable (in our case, "a4"). for( int argNum = 1; argNum < argc; ++argNum ) { std::cout << "Argument " << argNum << " is: " << argv[argNum] << std::endl; } int w, h ; //img size float depthMin, depthMax; char filename[80]; char output[80]; char depthOutput[80]; char normalsOutput[80]; bool depthMode = false, normalsMode = false, imageMode = false; int max_bounces = 0; float cutoff_weight; bool shadows = false; bool refraction = false; int uniform_samples = 0; int jitter_samples = 0; float box_filter_radius; bool render_samples = false; char* render_samples_outfile; int zoom_factor; for( int i = 0 ; i < argc ; i++) { if(!strcmp(argv[i], "-input")){ strcpy(filename, argv[i+1]); } else if(!strcmp(argv[i], "-size")){ w = atoi(argv[i+1]); h = atoi(argv[i+2]); } else if(!strcmp(argv[i], "-output")){ strcpy(output , argv[i+1]); imageMode = true; } else if(!strcmp(argv[i], "-depth")){ depthMode = true; depthMin = atof(argv[i+1]); depthMax = atof(argv[i+2]); strcpy(depthOutput , argv[i+3]); } else if(!strcmp(argv[i], "-normals")){ normalsMode = true; strcpy(normalsOutput , argv[i+1]); } else if(!strcmp(argv[i], "-bounces")){ max_bounces = atoi(argv[i+1]); } else if(!strcmp(argv[i], "-weight")){ cutoff_weight = atoi(argv[i+1]); } else if(!strcmp(argv[i], "-shadows")){ shadows = true; } else if(!strcmp(argv[i], "-uniform_samples")){ uniform_samples = atoi(argv[i+1]); } else if(!strcmp(argv[i], "-jittered_samples")){ jitter_samples = atoi(argv[i+1]); } else if(!strcmp(argv[i], "-box_filter")){ box_filter_radius = atof(argv[i+1]); } else if(!strcmp(argv[i], "-render_samples")){ // strcpy(render_samples_outfile, argv[i+1]); render_samples_outfile = argv[i+1]; zoom_factor = atoi(argv[i+2]); render_samples = true; } else if (!strcmp(argv[i], "-refraction")){ refraction = true; } } // First, parse the scene using SceneParser. // Then loop over each pixel in the image, shooting a ray // through that pixel and finding its intersection with // the scene. Write the color at the intersection to that // pixel in your output image. SceneParser sp = SceneParser(filename); RayTracer rt = RayTracer(&sp, max_bounces, cutoff_weight, shadows, refraction); Image image( w , h ); Image depth( w , h ); Image normals( w,h ); Camera* camera = sp.getCamera(); // Variables for anti-aliasing SampleDebugger *sd; Hit hit; int num_samples = max(uniform_samples, jitter_samples); if (render_samples) { // cout << "render samples - now making the sample_debugger" << endl; sd = new SampleDebugger(w, h, num_samples); } // cout << "now starting iteration through pixels" << endl; for( int j = 0 ; j < h ; j++ ) { for ( int i = 0 ; i < w ; i++ ) { // if (i > 144 && j > 43) {cout << "at beginning of loop i = " << i<< "j = " << j << endl;} Vector3f pixelColor; Vector3f normalVal; // if (i > 144 && j > 43) {cout << " checking num_samples" << endl;} if (num_samples > 0) { float grid_width = sqrt(num_samples); float max_offset = 1.0/grid_width; float offset = 0; // if (i > 144 && j > 43) {cout << " where is this getting stuck - jitter samples?" << endl;} if (jitter_samples > 0) { offset += (float)rand()/RAND_MAX * max_offset; } int count = 0; Vector3f color_sum = Vector3f(0.0, 0.0, 0.0); // if (i > 144 && j > 43) {cout << " where is this getting stuck - for loop?" << endl;} for (int grid_x = 0; grid_x < grid_width; grid_x++) { for (int grid_y = 0; grid_y < grid_width; grid_y++) { // if (i > 144 && j > 43) {cout << " in second for loop: grid_x = " << grid_x << "grid y =" << grid_y << endl;} float xin = grid_x*max_offset + i + offset; float yin = grid_y*max_offset + j + offset; float normX = (float)((float)(xin-((float)w)/2))/((float)w/2); float normY = (float)((float)(yin-((float)h)/2))/((float)h/2); Ray ray = camera->generateRay( Vector2f( normX , normY ) ); hit = Hit(INFINITY, NULL, Vector3f(1,0,0)); Vector3f local_color = rt.traceRay(ray, camera->getTMin(), max_bounces, cutoff_weight, hit); color_sum += local_color; // if (i > 144 && j > 43) {cout << " where is this getting stuck first render sampels?" << endl;} if (render_samples) { cout << "1) count = " << count << endl; Vector2f offset_vec = Vector2f(max_offset*grid_x+offset, max_offset*grid_y+offset); sd->setSample(i, j, count, offset_vec, local_color); count++; } } } // if (i > 144 && j > 43) {cout << " where is this getting stuck - setting pixel color?" << endl;} pixelColor = color_sum/num_samples; } else { // float x = 2*((float)j/((float)w - 1.0f)) - 1.0f; // float y = 2*((float)i/((float)h - 1.0f)) - 1.0f; float x = (float)((float)(i+0.25-((float)w)/2))/((float)w/2); float y = (float)((float)(j+0.25-((float)h)/2))/((float)h/2); Ray ray = camera->generateRay( Vector2f( x , y ) ); // if (i > 144 && j > 43) {cout << " where is this getting stuck - tracing the ray?" << endl;} // group->intersect( ray , hit , camera->getTMin() ) ; hit = Hit(INFINITY, NULL, Vector3f(1,0,0)); Vector3f color_normal = rt.traceRay(ray, camera->getTMin(), max_bounces, cutoff_weight, hit); // if (i > 144 && j > 43) {cout << " made it through traceRay?" << endl;} pixelColor = color_normal; // if( hit.getMaterial()==NULL){ //background // // pixelColor = Scene.getBackgroundColor(); // normalVal = Vector3f(0.0,0.0,0.0); // } // else{ // //ambient light // pixelColor = PhongMaterial::pointwiseDot( Scene.getAmbientLight(), hit.getMaterial()->getDiffuseColor()); // //defussion light // for( int i = 0 ; i < Scene.getNumLights(); i++){ // Light* light = Scene.getLight(i); // Vector3f dirToLight, lightColor ; // Vector3f position = ray.pointAtParameter(hit.getT()); // float dist = hit.getT(); // light->getIllumination( position , dirToLight , lightColor , dist); // // pixelColor += hit.getMaterial()->Shade( ray , hit , dirToLight , lightColor ) ; // } // // //normal map // Vector3f n = hit.getNormal(); // normalVal = Vector3f( abs(n[0]),abs(n[1]),abs(n[2])); // } } float d = clampedDepth( hit.getT(), depthMin , depthMax); // cout << "setting pixel for i,j = " << i << ", " << j << endl; depth.SetPixel( i , j , Vector3f(d,d,d)); image.SetPixel( i , j , pixelColor ); // if (i > 144) {cout << "where is this getting stuck?" << endl;} normalVal = hit.getNormal(); for (int k = 0; k < 3; k++) { // if (i > 144) {cout << "where is this getting stuck? in normals?" << endl;} normalVal[k] = fabs(normalVal[k]); } // if (i > 144) {cout << "where is this getting stuck? setting normals?" << endl;} normals.SetPixel( i , j , normalVal) ; // if (i > 144) {cout << "where is this getting stuck? redner samples??" << endl;} // if (i > 144) {cout << "where is this getting stuck? before starting the next loop?" << endl;} } } cout << "output = " << output << "should not be null!" << endl; if(imageMode){image.SaveTGA(output);} if( depthMode){ depth.SaveTGA(depthOutput);} if( normalsMode){ normals.SaveTGA(normalsOutput);} if (render_samples) { sd->renderSamples(render_samples_outfile, zoom_factor); } return 0; }
int main( int argc, char* argv[] ) { // Fill in your implementation here. // This loop loops over each of the input arguments. // argNum is initialized to 1 because the first // "argument" provided to the program is actually the // name of the executable (in our case, "a4"). string sceneInput; int sizeX; int sizeY; string outputFile; string normalFile; int depth1; int depth2; string depthFile; bool shadows = false; int bounces = 0; float weight = 0.1; int numSamples = 0; bool uniformSamples = true; bool jitteredSamples = false; float boxFilterRadius = 0.0f; bool antialiasing = false; string renderSamplesFile; int renderSamplesFactor = 1; for( int argNum = 1; argNum < argc; ++argNum ) { //std::cout << "Argument " << argNum << " is: " << argv[argNum] << std::endl; string arg = argv[argNum]; if (arg == "-input") { argNum++; sceneInput = argv[argNum]; } else if (arg == "-size") { argNum++; sscanf(argv[argNum], "%d", &sizeX); argNum++; sscanf(argv[argNum], "%d", &sizeY); } else if (arg == "-output") { argNum++; outputFile = argv[argNum]; } else if (arg == "-normals") { argNum++; normalFile = argv[argNum]; } else if (arg == "-depth") { argNum++; sscanf(argv[argNum], "%d", &depth1); argNum++; sscanf(argv[argNum], "%d", &depth2); argNum++; depthFile = argv[argNum]; } else if (arg == "-bounces") { argNum++; sscanf(argv[argNum], "%d", &bounces); } else if (arg == "-weight") { argNum++; sscanf(argv[argNum], "%f", &weight); } else if (arg == "-shadows") { shadows = true; } else if (arg == "-uniform_samples") { uniformSamples = true; argNum++; sscanf(argv[argNum], "%d", &numSamples); } else if (arg == "-jittered_samples") { jitteredSamples = true; argNum++; sscanf(argv[argNum], "%d", &numSamples); } else if (arg == "-box_filter") { argNum++; sscanf(argv[argNum], "%f", &boxFilterRadius); antialiasing = true; } else if (arg == "-render_samples") { argNum++; renderSamplesFile = argv[argNum]; argNum++; sscanf(argv[argNum], "%d", &renderSamplesFactor); } else { std::cout << "Argument not implemented " << argNum << " is: " << argv[argNum] << std::endl; } } assert(sceneInput != ""); SceneParser* sceneParser = new SceneParser( (char*)sceneInput.c_str() ); Camera* camera = sceneParser->getCamera(); Group* objects = sceneParser->getGroup(); // First, parse the scene using SceneParser. // Then loop over each pixel in the image, shooting a ray // through that pixel and finding its intersection with // the scene. Write the color at the intersection to that // pixel in your output image. float stepX = 2.0f/(sizeX); float stepY = 2.0f/(sizeY); float stepXStart = 3.0 * stepX / 8.0f; float stepYStart = 3.0 * stepY / 8.0f; int rootNumSamples = (int)sqrt(numSamples); float stepRoot = 1.0f / rootNumSamples; float stepRootStart = stepRoot / 2.0f; //float stepXrender = 2.0f/(sizeX - 1)/renderSamplesFactor; //float stepYrender = 2.0f/(sizeY - 1)/renderSamplesFactor; Image* output; Image* depth; Image* normal; SampleDebugger* render; if (outputFile != "") { output = new Image( sizeX, sizeY ); output->SetAllPixels( sceneParser->getBackgroundColor() ); } if (depthFile != "") { depth = new Image( sizeX, sizeY ); depth->SetAllPixels( Vector3f::ZERO ); } if (normalFile != "") { normal = new Image( sizeX, sizeY ); normal->SetAllPixels( Vector3f::ZERO ); } if (renderSamplesFile != "") { render = new SampleDebugger( sizeX, sizeY, numSamples ); } RayTracer rayTracer = RayTracer( sceneParser, bounces, weight, shadows ); for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { Vector2f point = Vector2f(-1 + ((x + 0.5f) * stepX), -1 + ((y + 0.5f) * stepY)); Ray ray = camera->generateRay( point ); Hit hit = Hit(); float tmin = camera->getTMin(); if (renderSamplesFile != "") { for (int i = 0; i < numSamples; i++) { int row = floor((float)i / (float)rootNumSamples); int col = i % rootNumSamples; Vector2f offset = Vector2f( stepRootStart + col * stepRoot, stepRootStart + row * stepRoot); if (jitteredSamples) { offset = Vector2f( nextFloat(), nextFloat()); } Vector3f color = sceneParser->getBackgroundColor(); Ray renderRay = camera->generateRay( point - Vector2f(0.5f * stepX, 0.5f * stepY) + (offset) * Vector2f(stepX, stepY) ); Hit renderHit = Hit(); if (objects->intersect(renderRay, renderHit, tmin)) { color = rayTracer.traceRay( renderRay, tmin, 0, 1.0, renderHit, 1.0 ); } render->setSample( x, y, i, offset, color ); } } //cout << "testing ray at " << ray << tmin << endl; bool intersected = objects->intersect( ray, hit, tmin ); if (intersected || antialiasing) { //cout << "found an intersection for " << ray << "at " << hit.getT() << endl; if (outputFile != "") { Vector3f pixelColor = sceneParser->getBackgroundColor(); if (antialiasing) { Vector3f color = Vector3f( 0 ); for (int i = 0; i < numSamples; i++) { int row = floor((float)i / (float)rootNumSamples); int col = i % rootNumSamples; Vector2f offset = Vector2f( stepRootStart + col * stepRoot, stepRootStart + row * stepRoot); if (jitteredSamples) { offset = Vector2f( nextFloat(), nextFloat() ); } Vector3f aColor = sceneParser->getBackgroundColor(); Ray renderRay = camera->generateRay( point - Vector2f(0.5f * stepX, 0.5f * stepY) + (offset) * Vector2f(2.0 * boxFilterRadius * stepX, 2.0 * boxFilterRadius * stepY) ); Hit renderHit = Hit(); if (objects->intersect(renderRay, renderHit, tmin)) { aColor = rayTracer.traceRay( renderRay, tmin, 0, 1.0, renderHit, 1.0 ); } color += aColor; } pixelColor = color / numSamples; } else if (intersected) { pixelColor = rayTracer.traceRay( ray, tmin, 0, 1.0, hit, 1.0 ); } /* Vector3f pixelColor = sceneParser->getAmbientLight() * hit.getMaterial()->getDiffuseColor(); for (int i = 0; i < sceneParser->getNumLights(); i++) { Light* light = sceneParser->getLight(i); Vector3f p = ray.pointAtParameter( hit.getT() ); Vector3f dir = Vector3f(); Vector3f col = Vector3f(); float distance = 0; light->getIllumination(p, dir, col, distance); pixelColor += hit.getMaterial()->shade( ray, hit, dir, col ); } //cout << "final pixel color: "; //pixelColor.print(); //cout << endl; */ output->SetPixel(x, y, VecUtils::clamp(pixelColor)); } if (depthFile != "") { Vector3f clamped = VecUtils::clamp(Vector3f(hit.getT()), depth1, depth2); Vector3f grayscale = (Vector3f(depth2) - clamped) / (float)(depth2 - depth1); //clamped.print(); //grayscale.print(); depth->SetPixel(x, y, grayscale); } if (normalFile != "") { normal->SetPixel(x, y, VecUtils::absoluteValue(hit.getNormal()) ); } } } } if (outputFile != "") { output->SaveTGA( (char *)outputFile.c_str() ); } if (depthFile != "") { depth->SaveTGA( (char *)depthFile.c_str() ); //printf("depth %d %d\n", depth1, depth2); } if (normalFile != "") { normal->SaveTGA( (char *)normalFile.c_str() ); } if (renderSamplesFile != "") { render->renderSamples( (char *)renderSamplesFile.c_str(), renderSamplesFactor ); } return 0; }
int main( int argc, char* argv[] ) { // Fill in your implementation here. // Things we get from the input arguments const char* input_filename; int img_height; int img_width; const char* output_filename; int depth_min; int depth_max; const char* depth_output_filename = NULL; const char* normals_output_filename = NULL; cout << "All variables declared in main..." << endl; // This loop loops over each of the input arguments. // argNum is initialized to 1 because the first // "argument" provided to the program is actually the // name of the executable (in our case, "a4"). for( int argNum = 1; argNum < argc; ++argNum ) { std::cout << "Argument " << argNum << " is: " << argv[argNum] << std::endl; if (string(argv[argNum]) == "-input") { assert (argNum+1 <= argc && "Did not specify argument for flag -input"); // make sure there is something after the flag input_filename = argv[argNum+1]; argNum += 1; // move past the flag you just read } if (string(argv[argNum]) == "-size") { assert (argNum+2 <= argc && "Did not specify enough arguments for flag -size"); // make sure there is something after the flag img_height = atoi(argv[argNum+1]); img_width = atoi(argv[argNum+2]); argNum += 2; } if (string(argv[argNum]) == "-output") { assert (argNum+1 <= argc && "Did not specify argument for flag -output"); // make sure there is something after the flag output_filename = argv[argNum+1]; argNum+=1; } if (string(argv[argNum]) == "-depth") { assert (argNum+3 <= argc && "Did not specify enough arguments for flag -depth (should have 3)"); depth_min = atoi(argv[argNum+1]); depth_max = atoi(argv[argNum+2]); depth_output_filename = argv[argNum+3]; argNum+=3; } if (string(argv[argNum]) == "-normals") { assert (argNum+1 <= argc && "Did not specify enough arguments for flag -normals (should have 1)"); normals_output_filename = argv[argNum+1]; argNum+=1; } } cout << "Input arguments parsed" << endl; // From the handout: Write a main function that: // 1) reads the scene (using the parsing code provided) // 2) loops over the pixesl in the image plane // 3) generates a ray using your camera class // 4) intersects it with the high lievel Group that stores the objects of the scene // 5) writes the color of the closest intersected object // read the scene using SceneParser SceneParser* parser = new SceneParser(input_filename); Camera* camera = parser->getCamera(); Group* group = parser->getGroup(); Vector3f background_color = parser->getBackgroundColor(); // Loop over pixels in the image plane Image* img = new Image(img_width, img_height); Image* depth_img = new Image(img_width, img_height); Image* normals_img = new Image(img_width, img_height); cout << "now starting to produce image" << endl; cout << "camera's tmin = " << camera->getTMin() << endl; for (int j = 0; j < img_height; j++) { for (int i = 0; i < img_width; i++) { // cout << "for pixel " << i << "," << j << ": "; // Generate ray using cmaera class float tmin = camera->getTMin(); Hit hit = Hit(FLT_MAX, NULL, NULL); // is this supposed to be something more...profound? // we want it to map from (-1,-1) to (1,1) float x = (2.0/(float)img_width)*(float)i - 1.0; float y = (2.0/(float)img_height)*(float)j - 1.0; Vector2f pixel = Vector2f(x, y); Ray ray = camera->generateRay(pixel); // intersect the ray with the high level group for the scene if (group->intersect(ray, hit, tmin)) { // write color of the closest intersected object Material* material = hit.getMaterial(); if (material->getDiffuseColor()[0] == 1) { cout << "color = " << material->getDiffuseColor(); } // cout << "material = " << material << endl; if (parser->getNumLights() == 0) { Vector3f color = material->getDiffuseColor(); if (material->getDiffuseColor()[0] == 1) { cout << "writing color = " << material->getDiffuseColor(); } img->SetPixel(i, j, color); } else { Vector3f light_color(0,0,0);// we want to iteratively add the light from black for (int k = 0; k < parser->getNumLights(); k++) { Light* light = parser->getLight(k); Vector3f p = ray.pointAtParameter(hit.getT()); Vector3f dir; Vector3f col; float distanceToLight = 10.0; light->getIllumination(p, dir, col, distanceToLight); // what should distance to light actually be? float coeff = Vector3f::dot(hit.getNormal().normalized(), dir.normalized()); light_color += material->getDiffuseColor() * col * coeff; } if (material->getDiffuseColor()[0] == 1) { cout << "writing color = " << material->getDiffuseColor(); } img->SetPixel(i, j, light_color); } // Visualize Depth (QUESTION: should this be a separate routine? // I don't think so because all of the tests also have depth // but this can be commented out for testing if it doesn't work... if (depth_output_filename != NULL) { float d = hit.getT(); // d+=1; // d = -d; // cout << "d = " << d << endl; // if t is within the correct range // cout << "depthMin = " << depth_min << ", depth max = " << depth_max << endl; if (d >= depth_min && d <= depth_max) { float depth_val = (d - depth_min)/(depth_max - depth_min); // cout << "depth val = " << depth_val << endl; depth_val = 1-depth_val; depth_img->SetPixel(i, j, Vector3f(depth_val, depth_val, depth_val)); } } if (normals_output_filename != NULL) { Vector3f normal = hit.getNormal(); Vector3f fab_norm = Vector3f(fabs(normal[0]), fabs(normal[1]), fabs(normal[2])); normals_img->SetPixel(i, j, fab_norm); // QUESTION: just color the normal? } } else { // cout << "writing background color" << endl; img->SetPixel(i, j, background_color); depth_img->SetPixel(i, j, background_color); } } } // Instructions for Depth: // Implement a second rendering style to visualize the depth t of // objects in the scene. Two input depth values specify the range // of depth values which should be mapped to shades of gray in // the visualization. Depth values outside this range = clamped // Instructions for Normals: // Implement a new rendering mode, normal visualization // Write outfiles! cout << "images produced, writing outfiles" << endl; img->SaveTGA(output_filename); if (depth_output_filename != NULL) { depth_img->SaveTGA(depth_output_filename); } if (normals_output_filename != NULL) { normals_img->SaveTGA(normals_output_filename); } return 0; }
int main(int argc, char* argv[]) { // ======================================================== // ======================================================== // Some sample code you might like to use for parsing // command line arguments char *input_file = NULL; int width = 100; int height = 100; char *output_file = NULL; float depth_min = 0; float depth_max = 1; char *depth_file = NULL; // sample command line: // raytracer -input scene1_1.txt -size 200 200 -output output1_1.tga -depth 9 10 depth1_1.tga for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-input")) { i++; assert(i < argc); input_file = argv[i]; } else if (!strcmp(argv[i], "-size")) { i++; assert(i < argc); width = atoi(argv[i]); i++; assert(i < argc); height = atoi(argv[i]); } else if (!strcmp(argv[i], "-output")) { i++; assert(i < argc); output_file = argv[i]; } else if (!strcmp(argv[i], "-depth")) { i++; assert(i < argc); depth_min = atof(argv[i]); i++; assert(i < argc); depth_max = atof(argv[i]); i++; assert(i < argc); depth_file = argv[i]; } else { printf("whoops error with command line argument %d: '%s'\n", i, argv[i]); assert(0); } } // ======================================================== // ======================================================== //Use the input file parsing code provided to load the camera, //background color and objects of the scene. SceneParser* sceneParser = new SceneParser(input_file); Image *image = new Image(width, height); Image *image2 = new Image(width, height); image->SetAllPixels(sceneParser->getBackgroundColor()); image2->SetAllPixels(sceneParser->getBackgroundColor()); Camera *camera = sceneParser->getCamera(); Group *group = sceneParser->getGroup(); Vec3f black(0.0f, 0.0f, 0.0f); Material *init = new Material(black); /* Write a main function that reads the scene (using the parsing code provided), loops over the pixels in the image plane, generates a ray using your OrthographicCamera class, intersects it with the high-level Group that stores the objects of the scene, and writes the color of the closest intersected object. */ /* ray casting: for every pixel construct a ray from the eye for every object in the scene find intersection with the ray keep if closest */ for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) { float x = i*1.0 / width; float y = j*1.0 / height; Ray ray = camera->generateRay(Vec2f(x, y)); Hit hit(0.0f, init); //ray:带入参数 hit:带出信息 if (group->intersect(ray, hit, camera->getTMin()))//撞到了 { image->SetPixel(i,j,hit.getMaterial()->getDiffuseColor()); //k值越大说明越远,颜色应该越深 float k = (hit.getT() - depth_min)*1.0 / (depth_max - depth_min); if (k > 1.0f) k = 1.0f; if (k < 0.0f) k = 0.0f; Vec3f gray(1.0f - k, 1.0f - k, 1.0f - k); image2->SetPixel(i, j, gray); } } image->SaveTGA(output_file); image2->SaveTGA(depth_file); /* Implement a second rendering style to visualize the depth t of objects in the scene. Two input depth values specify the range of depth values which should be mapped to shades of gray in the visualization. Depth values outside this range are simply clamped. */ return 0; }
int main(int argc, char *argv[]) { SDL_Window * win = nullptr; SDL_Renderer * rendererSDL = nullptr; int width = 512, height = 512; if (SDL_Init(SDL_INIT_VIDEO) < 0) SDLExit("Unable to initialize SDL"); checkSDLError(__LINE__);//on Win7 would cause a ERROR about SHCore.dll, just ignore it. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); checkSDLError(__LINE__); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); checkSDLError(__LINE__); json config = readJson("config.json"); width = config["width"], height = config["height"]; std::string title = config["title"]; win = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); if (!win) SDLExit("Unable to create window"); SDL_GLContext glContext = SDL_GL_CreateContext(win); checkSDLError(__LINE__); SDLFilm film(width, height); SceneParser parser; SceneDesc desc = parser.parse(config); desc.setFilm(&film); desc.init(); SDL_SetWindowSize(win, desc.width, desc.height); rendererSDL = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); SDL_Texture* texture = SDL_CreateTexture(rendererSDL, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, desc.width, desc.height); checkSDLError(__LINE__); film.texture = texture; Renderer renderer(desc); double angle = 0; SDL_Point screenCenter = { width / 2, height / 2 }; SDL_RendererFlip flip = SDL_FLIP_NONE; renderer.beginAsyncRender(desc); while (1) { SDL_Event e; if (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { break; } } SDL_Rect& updatedRect = static_cast<SDLFilm*>(desc.film)->lockRect; renderer.getRenderRect(desc, &updatedRect.x, &updatedRect.y, &updatedRect.w, &updatedRect.h); desc.film->beforeSet(); for (int x = updatedRect.x; x < updatedRect.x + updatedRect.w; x++) { int _p = updatedRect.y * desc.width + x; Color& c = renderer.colorArray[_p]; desc.film->set(x, updatedRect.y, c.rInt(), c.gInt(), c.bInt()); } desc.film->afterSet(); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); int ret = SDL_RenderCopyEx(rendererSDL, texture, &updatedRect, &updatedRect, angle, &screenCenter, flip); if (ret == -1) SDLExit("SDL_RenderCopy failed"); SDL_RenderPresent(rendererSDL); SDL_Delay(1); } renderer.endAsyncRender(); SDL_DestroyTexture(texture); SDL_DestroyRenderer(rendererSDL); SDL_GL_DeleteContext(glContext); SDL_DestroyWindow(win); SDL_Quit(); return 0; }
void run() { Scene* scene = new Scene(); SceneParser* p = new SceneParser(scene); cout << endl; p->parse_file(SchemeFilenames::toString(getLoadPrefix() + "/scheme/tests.scm")); }
GLuint render(RayTracer& ray_tracer, SceneParser& scene, const Args& args) { auto image_pixels = Vec2i(args.width, args.height); // Construct images unique_ptr<Image> image, depth_image, normals_image; if (!args.output_file.empty()) { image.reset(new Image(image_pixels, ImageFormat::RGBA_Vec4f)); image->clear(Vec4f()); } if (!args.depth_file.empty()) { depth_image.reset(new Image(image_pixels, ImageFormat::RGBA_Vec4f)); depth_image->clear(Vec4f()); } if (!args.normals_file.empty()) { normals_image.reset(new Image(image_pixels, ImageFormat::RGBA_Vec4f)); normals_image->clear(Vec4f()); } // EXTRA // The Filter and Film objects are not used by the starter code. They provide starting points // for implementing smarter supersampling, whereas the required type of less fancy supersampling // can be implemented by taking the average of the samples drawn from each pixel. // unique_ptr<Filter> filter(Filter::constructFilter(args.reconstruction_filter, args.filter_radius)); // Film film(image.get(), filter.get())); // progress counter atomic<int> lines_done = 0; // Main render loop! // Loop through all the pixels in the image // Generate all the samples // Fire rays // Compute shading // Accumulate into image // Loop over scanlines. #pragma omp parallel for // Uncomment this & enable OpenMP in project for parallel rendering (see handout) for (int j = 0; j < args.height; ++j) { // Print progress info if (args.show_progress) ::printf("%.2f%% \r", lines_done * 100.0f / image_pixels.y); // Construct sampler. auto sampler = unique_ptr<Sampler>(Sampler::constructSampler(args.sampling_pattern, args.num_samples)); // Loop over pixels on a scanline for (int i = 0; i < args.width; ++i) { // Loop through all the samples for this pixel. Vec3f sample_color = Vec3f(0.0f); Vec3f depth_color = Vec3f(0.0f); Vec3f normal_color = Vec3f(0.0f); for (int n = 0; n < args.num_samples; ++n) { // Get the offset of the sample inside the pixel. // You need to fill in the implementation for this function when implementing supersampling. // The starter implementation only supports one sample per pixel through the pixel center. Vec2f offset = sampler->getSamplePosition(n); // Convert floating-point pixel coordinate to canonical view coordinates in [-1,1]^2 // You need to fill in the implementation for Camera::normalizedImageCoordinateFromPixelCoordinate. Vec2f ray_xy = Camera::normalizedImageCoordinateFromPixelCoordinate(Vec2f(float(i), float(j)) + offset, image_pixels); // Generate the ray using the view coordinates // You need to fill in the implementation for this function. Ray r = scene.getCamera()->generateRay(ray_xy); // Trace the ray! Hit hit; float tmin = scene.getCamera()->getTMin(); // You should fill in the gaps in the implementation of traceRay(). // args.bounces gives the maximum number of reflections/refractions that should be traced. sample_color = sample_color + ray_tracer.traceRay(r, tmin, args.bounces, 1.0f, hit, Vec3f(1.0f)); // YOUR CODE HERE (R9) // This starter code only supports one sample per pixel and consequently directly // puts the returned color to the image. You should extend this code to handle // multiple samples per pixel. Also sample the depth and normal visualization like the color. // The requirement is just to take an average of all the samples within the pixel // (so-called "box filtering"). Note that this starter code does not take an average, // it just assumes the first and only sample is the final color. // For extra credit, you can implement more sophisticated ones, such as "tent" and bicubic // "Mitchell-Netravali" filters. This requires you to implement the addSample() // function in the Film class and use it instead of directly setting pixel values in the image. if (depth_image) { // YOUR CODE HERE (R2) // Here you should map the t range [depth_min, depth_max] to the inverted range [1,0] for visualization // Note that closer objects should appear brighter. // //What is the current color? Change the shade im think.... float x = hit.t; //distance float f = 1-(x-args.depth_min) / (args.depth_max - args.depth_min); //Ensure the value is calmped between 1 and 0 f = FW::max(f, 0.0f); f = FW::min(f, 1.0f); depth_color = depth_color + f; //depth_image->setVec4f(Vec2i(i, j), Vec4f(Vec3f(f), 1)); } if (normals_image) { Vec3f n = hit.normal; Vec3f color(fabs(n[0]), fabs(n[1]), fabs(n[2])); color = color.clamp(Vec3f(0), Vec3f(1)); normal_color = normal_color + color; //normals_image->setVec4f( Vec2i( i, j ), Vec4f( color, 1 ) ); } } sample_color = sample_color / (1.0*args.num_samples); depth_color = depth_color / (1.0*args.num_samples); normal_color = normal_color / (1.0*args.num_samples); image->setVec4f(Vec2i(i, j), Vec4f(sample_color, 1)); if (depth_image) depth_image->setVec4f(Vec2i(i, j), Vec4f(Vec3f(depth_color), 1)); if (normals_image) normals_image->setVec4f(Vec2i(i, j), Vec4f(normal_color, 1)); } ++lines_done; } // YOUR CODE HERE (EXTRA) // When you implement smarter filtering, you should normalize the filter weight // carried in the 4th channel. if (image) { } // And finally, save the images as PNG! if (image) { FW::File f(args.output_file.c_str(), FW::File::Create); exportLodePngImage(f, image.get()); } if (depth_image) { FW::File f(args.depth_file.c_str(), FW::File::Create); exportLodePngImage(f, depth_image.get()); } if (normals_image) { FW::File f(args.normals_file.c_str(), FW::File::Create); exportLodePngImage(f, normals_image.get()); } return image->createGLTexture(); }