Example #1
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;
}
Example #2
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;
}
Example #3
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;
}