1 #include "stdafx.h"
  2 #include "defines.h"
  3 
  4 #define NOPHOTONMAP    0
  5 #define WRITEPHOTONMAP 1
  6 #define READPHOTONMAP  2
  7 
  8 #include "Scene.hxx"
  9 #include "Image.hxx"
 10 
 11 #include "Triangle.hxx"
 12 #include "Sphere.hxx"
 13 #include "InfinitePlane.hxx"
 14 
 15 #include "PerspectiveCamera.hxx"
 16 #include "DepthOfFieldCamera.hxx"
 17 #include "SphericalCamera.hxx"
 18 
 19 #include "FlatShader.hxx"
 20 #include "EyeLightShader.hxx"
 21 #include "PhongShader.hxx"
 22 #include "SchlickShader.hxx"
 23 #include "SchlickPhotonShader.hxx"
 24 #include "BumpMappedPhongShader.hxx"
 25 #include "TexturedEyeLightShader.hxx"
 26 
 27 #include "PointLight.hxx"
 28 #include "QuadAreaLight.hxx"
 29 
 30 #include "SampleGenerator.hxx"
 31 #include "RegularSampleGenerator.hxx"
 32 #include "RandomSampleGenerator.hxx"
 33 #include "StratifiedSampleGenerator.hxx"
 34 
 35 #include "ProceduralHeightTexture.hxx"
 36 #include "ProceduralCarpet.hxx"
 37 #include "ProceduralGranite.hxx"
 38 #include "ProceduralPaper.hxx"
 39 #include "ProceduralWave.hxx"
 40 #include "ProceduralWater.hxx"
 41 #include "ProceduralWood.hxx"
 42 #include "ProceduralWoodTiles.hxx"
 43 
 44 #include "FractalMountain.hxx"
 45 
 46 #include "PhotonKDTree.hxx"
 47 #include "SchlickPhotonDistributor.hxx"
 48 
 49 #include "SchlickMaterialFactory.hxx"
 50 #include "SchlickPhotonMaterialFactory.hxx"
 51 #include "HouseMaterialDescription.hxx"
 52 
 53 #include "Randomizer.hxx"
 54 
 55 #ifdef RANDOMSEED
 56 Randomizer randomizer(RANDOMSEED);
 57 #else
 58 Randomizer randomizer;
 59 #endif
 60 
 61 PhotonKDTree *photon_tree;
 62 
 63 // The rendering loop
 64 void RenderFrame(Scene &aScene, int aSampleCnt, SampleGenerator *aSampler)
 65 {
 66 	Image img(aScene.camera->resX,aScene.camera->resY);      // Image array
 67 	Ray   ray;						 // Primary ray
 68 
 69 	for (int y = 0; y < aScene.camera->resY; ++y)
 70 	{
 71 #ifdef NODES
 72 		// This is needed for parallisation. Only every nth line is created and afterwards the resulting images
 73 		// are simply copied together. Bad, but this is the quick way :-)
 74 		if (y % NODES == NODE)
 75 #endif
 76 		{
 77 			for (int x = 0; x < aScene.camera->resX; ++x)
 78 			{
 79 				float u[aSampleCnt],
 80 				      v[aSampleCnt],
 81 				      weight[aSampleCnt];
 82 
 83 				aSampler->GetSamples(aSampleCnt, u, v, weight);
 84 
 85 				img[y][x] = 0;
 86 
 87 				for (int i = 0; i < aSampleCnt; ++i)
 88 				{
 89 #ifndef STEREOVIEW
 90 					// In the usual case, we simply do what everybody does
 91 					aScene.camera->InitRay(x + u[i], y + v[i], ray); // Initialize ray
 92 					img[y][x] += weight[i] * aScene.RayTrace(ray);
 93 #else
 94 					// In this case, we create a red/blue stereo image by rendering the scene twice and
 95 					// by afterwards overlaying the different channels
 96 					Vec3f red, blue;
 97 					aScene.camera->InitRay(x + u[i], y + v[i], ray, -STEREOVIEW);
 98 					red  = aScene.RayTrace(ray);
 99 
100 					aScene.camera->InitRay(x + u[i], y + v[i], ray,  STEREOVIEW);
101 					blue = aScene.RayTrace(ray);
102 					
103 					img[y][x] += weight[i] * Vec3f((red.x + red.y + red.z) / 3.0f, 0, (blue.x + blue.y + blue.z) / 3.0f);
104 #endif
105 				}
106 
107 				// Color values must be clamped between 0 and 1
108 				img[y][x] = Min(Max(img[y][x],Vec3f(0,0,0)),Vec3f(1,1,1));
109 			}
110 		}
111 	}
112 
113 	img.WritePPM("result.ppm"); // Write final image
114 }
115 
116 // This method creates a photon map for a scene and exports it to a file
117 void BuildPhotonMap(Scene &scene, float photon_count, string filename)
118 {
119 	vector<Photon*> list;
120 	float	        lightscount = static_cast<float>(scene.lights.size());
121 	long long       limit       = static_cast<long long>(photon_count);
122 
123 	float totalenergy = 0.0f;
124 	// Get the total energy of the light sources and calculate the percentual part each photon takes
125 	for (unsigned int i = 0; i < scene.lights.size(); ++i)
126 		totalenergy += Length(scene.lights[i]->intensity);
127 
128 	// Now we know how much every light participates. Start the photon shooting...
129 	cout << "Playing around with the photon cannon - stand by and watch out..." << endl;
130 	for (long long number = 0; number < limit; ++number)
131 	{
132 		// Get a light source
133 		int light = static_cast<int>(randomizer.drand() * lightscount);
134 
135 		// Travelling photons know more than normal photons (basically they are rays, but shhhht... ;-) )
136 		TravellingPhoton photon;
137 
138 		// Init the photons
139 		photon.dir = Vec3f(randomizer.drand() - 0.5, randomizer.drand() - 0.5, randomizer.drand() - 0.5);
140 		Normalize(photon.dir);
141 
142 		photon.hit = NULL;
143 		photon.t   = Infinity;
144 
145 		scene.lights[light]->Initialize(photon, photon.energy);
146 
147 		// And trace them
148 		scene.PhotonTrace(photon, list);
149 	}
150 
151 	// We now have a vector. Organize it into a tree
152 	cout << "Building a photon tree..." << endl;
153 	photon_tree = new PhotonKDTree(list);
154 
155 	// Save (serialize) the tree
156 	cout << "Cutting the tree into planks and packing it into the box..." << endl;
157 	photon_tree->Save(filename);
158 }
159 
160 int main(int argc, char* argv[])
161 {
162 	int exNum = -1;
163 	if(argc > 1)
164 		exNum = atol(argv[1]);
165 
166 	Scene scene(true);
167 
168 	// Material for the SmoothTriangleFactory (for simple unicolor renderings)
169 	Material *mat = new Material(Vec3f(1.0, 0.5, 0.0));
170 	mat->SetSchlickParams(0.3f,  0.8f,  0.6f);
171 
172 	Scene::SmoothTriangleFactory *smoothTriangleFactory = new Scene::SmoothTriangleFactory;
173 	smoothTriangleFactory->shader	     = new SchlickShader(&scene, mat);
174 	smoothTriangleFactory->photon_distributor = new SchlickPhotonDistributor(&scene, mat);
175 
176 	// Material for the dice in the caustic scene
177 	mat = new Material(Vec3f(1.0,0.8,0.8));
178 	mat->SetTransparencyParams(0.7f,1.5f,0.8f);
179 	Scene::SmoothTriangleFactory *DiceFactory = new Scene::SmoothTriangleFactory;
180 	DiceFactory->shader	                  = new SchlickShader(&scene, mat);
181 	DiceFactory->photon_distributor           = new SchlickPhotonDistributor(&scene, mat);
182 
183 	// Supersampling
184 	SampleGenerator *sampler = new RegularSampleGenerator;
185 	int sampleCount = 1;
186 	if(argc >= 4)
187 	{
188 		sampleCount = atol(argv[3]);
189 		if(strcmp(argv[2], "random") == 0)
190 			sampler = new RandomSampleGenerator;
191 		if(strcmp(argv[2], "stratified") == 0)
192 			sampler = new StratifiedSampleGenerator;
193 	}
194 
195 	// Parse the photon mapping related command line parameters and work upon them
196 	int	     photonmap       = NOPHOTONMAP;
197 	float	     numberofphotons = 1E6f;
198 	string       photonmapname;
199 
200 	photon_tree    = NULL;
201 	if (argc >= 6)
202 	{
203 		if (!strcmp(argv[4], "write"))
204 			photonmap = WRITEPHOTONMAP;
205 		if (!strcmp(argv[4], "read"))
206 			photonmap = READPHOTONMAP;
207 
208 		photonmapname = argv[5];
209 
210 		if (argc >= 7)
211 			numberofphotons = atof(argv[6]);
212 
213 		if (photonmap == READPHOTONMAP)
214 			photon_tree = new PhotonKDTree(photonmapname);
215 	}
216 
217 	// The initially unmaterialized factory for the tokyo hotel scene
218 	Scene::SmoothTriangleFactory *houseTriangles = new Scene::SmoothTriangleFactory();
219 
220 	// Get the target image and start rendering
221 	switch(exNum)
222 	{
223 		case 0: // LOWRES
224 		case 1: // HIRES
225 		case 2: // 360* in fish tank
226 			{
227 				// Our house - in the middle of the street... LOWRES
228 				houseTriangles->mFactory		     = new SchlickMaterialFactory(&scene);
229 				houseTriangles->mFactory->sceneDescription   = new HouseMaterialDescription();
230 
231 				// The house itself
232 				scene.ParseOBJ("house_Scene.obj", houseTriangles);
233 
234 				Shader	          *shd;
235 				Material	  *mat;
236 
237 				// The mountains outside
238 				mat   = new Material (Vec3f(1.0f,1.0f,1.0f));
239 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);
240 				mat->procedural.push_back(new ProceduralHeightTexture(true, false, Vec3f(0,0,0), Vec3f(0,0,1), 3.0, 0.1, Vec3f(0.8), Vec3f(0.35,0.53,0.0)));
241 				shd   = new SchlickShader(&scene, mat);
242 				
243 				FractalMountain(&scene, Vec3f(-2.0f,7.0f,-3.0f), Vec3f(2.0f,7.0f,-3.0f), Vec3f(0.0f,10.0f,2.0f),
244 						100, 0.95f, 2.0f, 15, 0.3f, shd, NULL);
245 
246 				// The underwater hills
247 				mat   = new Material (Vec3f(1.0f,1.0f,1.0f));
248 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);
249 				mat->procedural.push_back(new ProceduralHeightTexture(true, false, Vec3f(0,0,-1.5), Vec3f(0,0,1), 1.0, 0.1));
250 				shd   = new SchlickShader(&scene, mat);
251 				
252 				FractalMountain(&scene, Vec3f(-5.6,-2.5,-1.5), Vec3f(-0.1,-2.5,-1.5), Vec3f(-5.6,3.0,-1.5),
253 						150, 0.95f, 2.0f, 15, 0.4f, shd, NULL);
254 
255 				// Sky planes behind the windows
256 				mat   = new Material (Vec3f(1.0f,1.0f,1.0f));
257 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);
258 				mat->ambient = 0.8;
259 				mat->procedural.push_back(new ProceduralPaper(true,false,10,Vec3f(1.0),Vec3f(0.64,0.82,1.0)));
260 				scene.Add(new InfinitePlane(Vec3f(0.0,10.0,0.0),Vec3f(0.0,-1.0,0.0),new SchlickShader(&scene,mat),new SchlickPhotonDistributor(&scene,mat)));
261 				scene.Add(new InfinitePlane(Vec3f(0.0,-10.0,0.0),Vec3f(0.0,1.0,0.0),new SchlickShader(&scene,mat),new SchlickPhotonDistributor(&scene,mat)));
262 
263 				// Outside lamp
264 				scene.Add(new QuadAreaLight(&scene, Vec3f(500000), Vec3f(-0.35,9.9,2.4), Vec3f(-0.3,9.9,2.4), Vec3f(-0.3,10.0,2.35), Vec3f(-0.35,10.0,2.35)));
265 
266 				// Left paper lamp
267 				// -3.762 4.338 1.736
268 				scene.Add(new QuadAreaLight(&scene, Vec3f(100000,85000,51000), Vec3f(-3.75,3.3,1.7), Vec3f(-3.8,3.3,1.7), Vec3f(-3.8,3.35,1.7), Vec3f(-3.75,3.35,1.7)));
269 
270 				// Right paper lamp
271 				// 1.286, 5.389, 1.693
272 				scene.Add(new QuadAreaLight(&scene, Vec3f(100000,85000,51000), Vec3f(1.25,5.4,1.7), Vec3f(1.3,5.4,1.7), Vec3f(1.3,5.35,1.7), Vec3f(1.25,5.35,1.7)));
273 
274 				// Large window set
275 				// -3.810 -4.553 0.95 <-> -0.114 -4.553 2.749
276 				scene.Add(new QuadAreaLight(&scene, Vec3f(20), Vec3f(-0.114,-4.553,2.749), Vec3f(-3.810,-4.553,2.749), Vec3f(-3.810,-4.553,0.95), Vec3f(-0.114,-4.553,0.95)));
277 
278 				// Diffuse corner light
279 				// 6.633 -5.160 1.469
280 				scene.Add(new PointLight(&scene, Vec3f(6.633, -5.160, 1.469), Vec3f(15)));
281 				scene.Add(new PointLight(&scene, Vec3f(2,4,1.5), Vec3f(4)));
282 
283 				// Fishtank lights
284 				scene.Add(new PointLight(&scene, Vec3f(-3.079, 1.431,-0.230), Vec3f(1)));
285 				scene.Add(new PointLight(&scene, Vec3f(-3.079, 0.125,-0.230), Vec3f(1)));
286 				scene.Add(new PointLight(&scene, Vec3f(-3.079,-1.181,-0.230), Vec3f(1)));
287 				scene.Add(new PointLight(&scene, Vec3f(-5.470, 1.431,-0.230), Vec3f(1)));
288 				scene.Add(new PointLight(&scene, Vec3f(-5.470, 0.125,-0.230), Vec3f(1)));
289 				scene.Add(new PointLight(&scene, Vec3f(-5.470,-1.181,-0.230), Vec3f(1)));
290 
291 				// Cameras
292 				switch (exNum)
293 				{
294 					case 0:
295 					scene.camera = new DepthOfFieldCamera(Vec3f(-6.6,-4.0,1.9),Vec3f(0.5852, 0.8126, -0.2756),Vec3f(0,0,1),45,0.01f,320,256,3.5f);
296 					break;
297 
298 					case 1:
299 					scene.camera = new DepthOfFieldCamera(Vec3f(-6.6,-4.0,1.9),Vec3f(0.5852, 0.8126, -0.2756),Vec3f(0,0,1),45,0.01f,1280,1024,3.5f);
300 					break;
301 
302 					case 2:
303 					scene.camera = new SphericalCamera(Vec3f(-4.720,0.121,-0.403),Vec3f(1.0, 0.0, 0.0),Vec3f(0,0,1),800,400);
304 					break;
305 				}
306 			}
307 			break;
308 		case 3: // "Balls" test scene with normal SchlickShader. No PM.
309 			{
310 				Shader	          *shd;
311 				Material	  *mat;
312 
313 				//shd = new BumpMappedPhongShader(&scene, Vec3f(1,0,0), 0.1f, 0.5f, 0.5f, 40); // Red surface
314 				mat   = new Material (Vec3f(1,0,0));			       // Red
315 				mat->SetMirrorParams (0.6f,  0.5f);			       // Mirror 0.6 in 0.5 object color
316 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		       // Looking cool (whatever it imitates)
317 				shd   = new SchlickShader(&scene, mat);
318 				scene.Add(new Sphere(Vec3f(-2, 1.7f, 0), 2, shd, NULL));
319 
320 				//shd = new	   PhongShader(&scene, Vec3f(0,1,1), 0.1f, 0.5f, 0.5f, 40); // Cyan surface
321 				mat   = new Material       (Vec3f(0,1,1));		        // Cyan
322 				mat->SetTransparencyParams (0.8f,  1.5f);		        // Trans 0.8 w/ refrac 1.5
323 				mat->SetSchlickParams      (0.3f,  0.9f,  0.5f);		// Looking cool (whatever it imitates)
324 				shd   = new SchlickShader(&scene, mat);
325 				scene.Add(new Sphere(Vec3f(1, -1, 1), 2.2f, shd, NULL));
326 
327 				//shd = new	   PhongShader(&scene, Vec3f(0,0,1), 0.1f, 0.5f, 0.5f, 40); // Blue surface
328 				mat   = new Material   (Vec3f(0,0,1));			        // Blue
329 				mat->SetSchlickParams  (0.0802f,  0.9f,  0.4f);	                // Looking cool (Aluminium oxide)
330 				shd   = new SchlickShader(&scene, mat);
331 				scene.Add(new Sphere(Vec3f(3, 0.8f, -2), 2, shd, NULL));
332 
333 				//shd = new BumpMappedPhongShader(&scene, Vec3f(1,1,0), 0.1f, 0.5f, 0.5f, 40); // Yellow surface
334 				mat   = new Material  (Vec3f(1,1,0));
335 				mat->SetSchlickParams (0.3f,  0.9f,  0.5f);		        // Looking cool (whatever it imitates)
336 				mat->procedural.push_back(new ProceduralWave(true, true));      // Bumpmapper as in the BumpMappedPhongShader
337 				shd   = new SchlickShader(&scene, mat);
338 				scene.Add(new InfinitePlane(Vec3f(0, -1, 0), Vec3f(0, 1, 0), shd, NULL));
339 
340 				//shd = new	   PhongShader(&scene, Vec3f(0,1,1), 0.1f, 0.5f, 0.5f, 40); // Cyan surface
341 				mat   = new Material       (Vec3f(1,0.6,0));		        // Orange
342 				mat->SetMirrorParams       (0.1f,  0.5f);		        // Trans 0.8 w/ refrac 1.5 (glas) and slight reflection
343 				mat->SetTransparencyParams (0.8f,  1.5f,  0.2f);		// Trans 0.8 w/ refrac 1.5 (glas) and slight reflection
344 				mat->SetSchlickParams      (0.3f,  0.9f,  0.5f);		// Looking cool (whatever it imitates)
345 				shd   = new SchlickShader(&scene, mat);
346 				scene.Add(new Sphere(Vec3f(3, 1, 5), 1.0f, shd, NULL));
347 
348 				mat   = new Material   (Vec3f(1,1,1));
349 				mat->SetMirrorParams(1.0);
350 				shd   = new SchlickShader(&scene, mat);
351 				scene.Add(new InfinitePlane(Vec3f(10,0,-10), Vec3f(-1, -1, 1), shd, NULL));
352 
353 				// QAL and QAL visualization
354 				Vec3f a = Vec3f(-14,3,12),
355 				      b = Vec3f(-10,3,15),
356 				      c = Vec3f(-10,5,15),
357 				      d = Vec3f(-14,5,12);
358 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
359 
360 				// QAL and QAL visualization
361 				      a = Vec3f( -6,3,18),
362 				      b = Vec3f( -2,3,21),
363 				      c = Vec3f( -2,5,21),
364 				      d = Vec3f( -6,5,18);
365 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
366 
367 				// QAL and QAL visualization
368 				      a = Vec3f(  2,3,24),
369 				      b = Vec3f(  6,3,28),
370 				      c = Vec3f(  6,5,28),
371 				      d = Vec3f(  2,5,24);
372 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
373 
374 				// QAL and QAL visualization
375 				      a = Vec3f( 10,3,32),
376 				      b = Vec3f( 14,3,36),
377 				      c = Vec3f( 14,5,36),
378 				      d = Vec3f( 10,5,32);
379 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
380 
381 				// Camera
382 				scene.camera = new PerspectiveCamera(Vec3f(0,0,10),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 640, 480);
383 
384 				// The remaining camera positions are those of some images we present on the web page
385 				//scene.camera = new DepthOfFieldCamera(Vec3f(0,0,10),Vec3f(0.1,0.2,-1), Vec3f(0,1,0), 60, 0.005f, 1280, 1024); //640, 480);
386 				//scene.camera = new SphericalCamera(Vec3f(0,1,2),Vec3f(0,0,-1), Vec3f(0,1,0), 1000, 500);
387 			}
388 			break;
389 		case 4: // Ol' friend Barney. No PM.
390 			{
391 				Scene::TexturedSmoothTriangleFactory *texTriangleFactory = new Scene::TexturedSmoothTriangleFactory;
392 				Material *mat = new Material(Vec3f(1,1,1));
393 				mat->SetSchlickParams(0.3f, 0.5f, 0.6f);
394 				mat->LoadTexture("barney.ppm");
395 				texTriangleFactory->shader = new SchlickShader(&scene, mat);
396 				texTriangleFactory->photon_distributor = NULL;
397 				scene.ParseOBJ("barney.obj", texTriangleFactory);
398 
399 				scene.Add(new QuadAreaLight(&scene, Vec3f(300), Vec3f(-11,4,20), Vec3f(-9,4,20), Vec3f(-9,6,20), Vec3f(-11,6,20)));
400 				scene.Add(new QuadAreaLight(&scene, Vec3f(300,300,100), Vec3f(-11,14,20), Vec3f(-9,14,20), Vec3f(-9,16,20), Vec3f(-11,16,20)));
401 				scene.camera = new PerspectiveCamera(Vec3f(0,8,25),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 640, 480);
402 			}
403 			break;
404 		case 5: // Checkers. No PM.
405 			{
406 				Scene::TexturedSmoothTriangleFactory *texTriangleFactory = new Scene::TexturedSmoothTriangleFactory;
407 				texTriangleFactory->shader = new TexturedEyeLightShader(&scene, Vec3f(9.f, 9.f, 9.f), "cb.ppm");
408 				scene.ParseOBJ("ground.obj", texTriangleFactory);
409 				scene.camera = new DepthOfFieldCamera(Vec3f(0,1.6f,25),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 0.05f, 640, 480);
410 			}
411 			break;
412 		case 6: // Wooden balls. No PM.
413 			{
414 				// Procedural shading approach
415 				Shader	          *shd;
416 				Material	  *mat;
417 
418 				mat   = new Material   (Vec3f(1.0));
419 				mat->procedural.push_back(new ProceduralWood(true, true, Vec3f(0), Vec3f(0.3,0.5,1.0), 0.2f, 0.3f, 3.0));
420 				mat->SetSchlickParams(0.8f,  0.8f,  0.6f, 1.0f, 0.9f, 0.3f);
421 				mat->SetMirrorParams(0.05f);
422 				shd   = new SchlickShader(&scene, mat);
423 				scene.Add(new Sphere(Vec3f(0), 4.0f, shd, NULL));
424 				scene.Add(new Sphere(Vec3f( 1.8f,  1.8f,  1.8f), 1.5f, shd, NULL));
425 				scene.Add(new Sphere(Vec3f(-1.8f,  1.8f,  1.8f), 1.5f, shd, NULL));
426 				scene.Add(new Sphere(Vec3f( 0.0f,  0.0f,  3.1f), 1.5f, shd, NULL));
427 				scene.Add(new InfinitePlane(Vec3f(0, 1.5, 0), Vec3f(-0.3, 0.5, 0.5), shd, NULL));
428 
429 				// QAL and QAL visualization
430 				Vec3f a = Vec3f(-14,3,12),
431 				      b = Vec3f(-10,3,15),
432 				      c = Vec3f(-10,5,15),
433 				      d = Vec3f(-14,5,12);
434 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
435 
436 				// Camera
437 				scene.camera = new PerspectiveCamera(Vec3f(0,0,10),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 640, 480);
438 			break;
439 			}
440 		case 7: // "Balls" scene with photon mapping (rest equal to 3). PM.
441 			{
442 				// Identical to 3, but with photon mapping
443 				Shader            *shd;
444 				PhotonDistributor *pdist;
445 				Material	  *mat;
446 
447 				//shd = new BumpMappedPhongShader(&scene, Vec3f(1,0,0), 0.1f, 0.5f, 0.5f, 40); // Red surface
448 				mat   = new Material (Vec3f(1,0,0));			  // Red
449 				mat->SetMirrorParams (0.6f,  0.5f);			   // Mirror 0.6 in 0.5 object color
450 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		    // Looking cool (whatever it imitates)
451 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
452 				pdist = new SchlickPhotonDistributor(&scene, mat);
453 				scene.Add(new Sphere(Vec3f(-2, 1.7f, 0), 2, shd, pdist));
454 
455 				//shd = new	   PhongShader(&scene, Vec3f(0,1,1), 0.1f, 0.5f, 0.5f, 40); // Cyan surface
456 				mat   = new Material       (Vec3f(0,1,1));		    // Cyan
457 				mat->SetTransparencyParams (0.8f,  1.5f);		     // Trans 0.8 w/ refrac 1.5
458 				mat->SetSchlickParams      (0.3f,  0.9f,  0.5f);	      // Looking cool (whatever it imitates)
459 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
460 				pdist = new SchlickPhotonDistributor(&scene, mat);
461 				scene.Add(new Sphere(Vec3f(1, -1, 1), 2.2f, shd, pdist));
462 
463 				//shd = new	   PhongShader(&scene, Vec3f(0,0,1), 0.1f, 0.5f, 0.5f, 40); // Blue surface
464 				mat   = new Material   (Vec3f(0,0,1));			  // Blue
465 				mat->SetSchlickParams(0.0802f,  0.9f,  0.4f);		   // Looking cool (Aluminium oxide)
466 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
467 				pdist = new SchlickPhotonDistributor(&scene, mat);
468 				scene.Add(new Sphere(Vec3f(3, 0.8f, -2), 2, shd, pdist));
469 
470 				//shd = new BumpMappedPhongShader(&scene, Vec3f(1,1,0), 0.1f, 0.5f, 0.5f, 40); // Yellow surface
471 				mat   = new Material   (Vec3f(1,1,0));
472 				mat->SetSchlickParams(0.3f,  0.9f,  0.5f);		      // Looking cool (whatever it imitates)
473 				mat->procedural.push_back(new ProceduralWave(true, true));      // Bumpmapper as in the BumpMappedPhongShader
474 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
475 				pdist = new SchlickPhotonDistributor(&scene, mat);
476 				scene.Add(new InfinitePlane(Vec3f(0, -1, 0), Vec3f(0, 1, 0), shd, pdist));
477 
478 				//shd = new	   PhongShader(&scene, Vec3f(0,1,1), 0.1f, 0.5f, 0.5f, 40); // Cyan surface
479 				mat   = new Material       (Vec3f(1,0.6,0));		    // Orange
480 				mat->SetMirrorParams       (0.1f,  0.5f);		       // Trans 0.8 w/ refrac 1.5 (glas) and slight reflection
481 				mat->SetTransparencyParams (0.8f,  1.5f,  0.2f);		// Trans 0.8 w/ refrac 1.5 (glas) and slight reflection
482 				mat->SetSchlickParams      (0.3f,  0.9f,  0.5f);		// Looking cool (whatever it imitates)
483 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
484 				pdist = new SchlickPhotonDistributor(&scene, mat);
485 				scene.Add(new Sphere(Vec3f(3, 1, 5), 1.0f, shd, pdist));
486 
487 				mat   = new Material  (Vec3f(1,1,1));
488 				mat->SetMirrorParams  (1.0);
489 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
490 				pdist = new SchlickPhotonDistributor(&scene, mat);
491 				scene.Add(new InfinitePlane(Vec3f(10,0,-10), Vec3f(-1, -1, 1), shd, pdist));
492 
493 				//scene.Add(new PointLight(&scene, Vec3f(-3,5,+4), Vec3f(30)));
494 				//scene.Add(new PointLight(&scene, Vec3f(0,1,+4), Vec3f(30)));
495 
496 				// QAL and QAL visualization
497 				Vec3f a = Vec3f( -6,25,18),
498 				      b = Vec3f( -6,20,21),
499 				      c = Vec3f( -2,20,21),
500 				      d = Vec3f( -2,25,18);
501 				scene.Add(new QuadAreaLight(&scene, Vec3f(50), a, b, c, d));
502 				shd   = new FlatShader(&scene, Vec3f(1,1,1));
503 				pdist = new SchlickPhotonDistributor(&scene, new Material(Vec3f(1,1,1)));
504 
505 				// Camera
506 				//scene.camera = new PerspectiveCamera(Vec3f(0,0,10),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 640, 480);
507 				scene.camera = new DepthOfFieldCamera(Vec3f(0,0,10),Vec3f(0.1,0.2,-1), Vec3f(0,1,0), 60, 0.005f, 640, 480);
508 			}
509 			break;
510 		case 8: // Wooden tiles. No PM.
511 			{
512 				// Procedural shading approach
513 				Shader     *shd;
514 				Material   *mat = new Material(Vec3f(1.0f));
515 				Procedural *pwt = new ProceduralWoodTiles(true, true,
516 									  Vec3f(1,0,0),	   Vec3f(0,0,1),	  0.2,  0.8,
517 									  Vec3f( 15.0,10.0,0.0),  Vec3f( 0.0,0.1,-0.3), 0.02,
518 									  Vec3f(-10.0,10.0,1.0),  Vec3f(-0.1,0.1, 0.9), 0.02,
519 									  Vec3f( 10.0,10.0,2.0),  Vec3f( 0.1,0.2,-0.7), 0.02,
520 									  0.01, 5.0);
521 				mat->procedural.push_back(pwt);
522 				mat->SetSchlickParams(0.8, 0.5, 0.5);
523 				shd   = new SchlickShader(&scene, mat);
524 				scene.Add(new InfinitePlane(Vec3f(0), Vec3f(0, 1, 0), shd, NULL));
525 				Vec3f a = Vec3f(-10,5,0),
526 				      b = Vec3f(-10,5,50),
527 				      c = Vec3f( 10,5,50),
528 				      d = Vec3f( 10,5,0);
529 				scene.Add(new QuadAreaLight(&scene, Vec3f(1.0), a, b, c, d));
530 				scene.camera = new PerspectiveCamera(Vec3f(0,1.6f,25),Vec3f(0,-0.3,-1), Vec3f(0,1,-0.3), 60, 1280, 1024);
531 			}
532 			break;
533 		case 9: // Water. PM.
534 			{
535 				// Procedural shading approach
536 				Shader	    *shd;
537 				PhotonDistributor *pdist;
538 				Material	  *mat;
539 
540 				mat   = new Material (Vec3f(1,0,0));			      // Red
541 				mat->SetMirrorParams  (0.6f,  0.5f);			      // Mirror 0.6 in 0.5 object color
542 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
543 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
544 				pdist = new SchlickPhotonDistributor(&scene, mat);
545 				scene.Add(new Sphere(Vec3f(-2, 1.7f, 0), 2, shd, pdist));
546 
547 				mat   = new Material   (Vec3f(1,1,1));
548 				mat->SetTransparencyParams(1.0,1.333,0.0);
549 				mat->SetSchlickParams(0.02f,  0.5f,  0.6f);		      // Looking cool (water)
550 				mat->procedural.push_back(new ProceduralWater(0.7, Vec3f(0,0,1)));
551 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
552 				pdist = new SchlickPhotonDistributor(&scene, mat);
553 				scene.Add(new InfinitePlane(Vec3f(0, -1, 0), Vec3f(0, 1, 0), shd, pdist));
554 
555 				mat   = new Material   (Vec3f(0.8,0.8,0.8));
556 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
557 				mat->procedural.push_back(new ProceduralWater(0.2, Vec3f(0,0,1)));
558 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
559 				pdist = new SchlickPhotonDistributor(&scene, mat);
560 				scene.Add(new InfinitePlane(Vec3f(0, -5, 0), Vec3f(0, 1, 0), shd, pdist));
561 
562 				mat   = new Material (Vec3f(0,0,1));                          // Blue
563 				mat->SetMirrorParams  (0.6f,  0.5f);                          // Mirror 0.6 in 0.5 object color
564 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
565 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
566 				pdist = new SchlickPhotonDistributor(&scene, mat);
567 				scene.Add(new Sphere(Vec3f(1.5, -1.5, -2), 2, shd, pdist));
568 
569 				mat   = new Material (Vec3f(0,1,0));                          // Green
570 				mat->SetMirrorParams  (0.6f,  0.5f);                          // Mirror 0.6 in 0.5 object color
571 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);                    // Looking cool (whatever it imitates)
572 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
573 				pdist = new SchlickPhotonDistributor(&scene, mat);
574 				scene.Add(new Sphere(Vec3f(1, -3.0f, 1), 1, shd, pdist));
575 
576 				// QAL and QAL visualization
577 				Vec3f a = Vec3f(-0.2,25, 0.2),
578 				      b = Vec3f( 0.2,25, 0.2),
579 				      c = Vec3f( 0.2,25,-0.2),
580 				      d = Vec3f(-0.2,25,-0.2);
581 				scene.Add(new QuadAreaLight(&scene, Vec3f(100), a, b, c, d));
582 				shd   = new FlatShader(&scene, Vec3f(1,1,1));
583 				pdist = new SchlickPhotonDistributor(&scene, new Material(Vec3f(1,1,1)));
584 				scene.Add(new Triangle(a, b, c, shd, pdist));
585 				scene.Add(new Triangle(a, c, d, shd, pdist));
586 
587 				// Camera
588 				scene.camera = new DepthOfFieldCamera(Vec3f(0,0,10),Vec3f(0.1,0,-1), Vec3f(0,1,0), 60, 0.005f, 1280, 1024); //640, 480);
589 			}
590 			break;
591 		case 10: // Caustic test. PM.
592 			{
593 				// Procedural shading approach
594 				Shader	          *shd;
595 				PhotonDistributor *pdist;
596 				Material	  *mat;
597 
598 				mat   = new Material       (Vec3f(1,1,1));
599 				mat->SetTransparencyParams (1.0, 1.5);
600 				mat->SetSchlickParams      (0.3f,  0.5f,  0.6f);             // Irrelevant
601 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
602 				pdist = new SchlickPhotonDistributor(&scene, mat);
603 				scene.Add(new Sphere(Vec3f(0, 4, 0), 3, shd, pdist));
604 
605 				mat   = new Material  (Vec3f(0.8,0.8,0.8));
606 				mat->SetSchlickParams (0.3f,  0.5f,  0.6f);                  // Looking cool (whatever it imitates)
607 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
608 				pdist = new SchlickPhotonDistributor(&scene, mat);
609 				scene.Add(new InfinitePlane(Vec3f(0, 0, 0), Vec3f(0, 1, 0), shd, pdist));
610 
611 				// QAL and QAL visualization
612 				Vec3f a = Vec3f(-21.5,25,-20.5),
613 				      b = Vec3f(-20.5,25,-20.5),
614 				      c = Vec3f(-20.5,25,-21.5),
615 				      d = Vec3f(-21.5,25,-21.5);
616 				scene.Add(new QuadAreaLight(&scene, Vec3f(200), a, b, c, d));
617 
618 				scene.ParseOBJ("Tutorials-cube_final_Scene.obj", DiceFactory, Vec3f(-1.0,1.0,5));
619 
620 				// QAL and QAL visualization
621 				      a = Vec3f(-22.5,26,-21.5),
622 				      b = Vec3f(-21.5,26,-21.5),
623 				      c = Vec3f(-21.5,26,-22.5),
624 				      d = Vec3f(-22.5,26,-22.5);
625 				scene.Add(new QuadAreaLight(&scene, Vec3f(10), a, b, c, d));
626 
627 				// Camera
628 				//scene.camera = new PerspectiveCamera(Vec3f(0,0,10),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 640, 480);
629 				scene.camera = new DepthOfFieldCamera(Vec3f(0,1,10),Vec3f(0,0.0,-1), Vec3f(0,1,0), 60, 0.005f, 640, 480);
630 			}
631 			break;
632 		case 11: // Subsurface scattered barney. PM.
633 			{
634 				Material *mat;
635 
636 				Scene::SmoothTriangleFactory *texTriangleFactory1 = new Scene::SmoothTriangleFactory;
637 				mat = new Material(Vec3f(0.5,1,0.5));
638 				mat->SetSchlickParams(0.3f, 0.5f, 0.6f);
639 				mat->SetSubsurfaceScattering(1.0);
640 				texTriangleFactory1->shader	        = new SchlickPhotonShader(&scene, mat, photon_tree);
641 				texTriangleFactory1->photon_distributor = new SchlickPhotonDistributor(&scene, mat);
642 				scene.ParseOBJ("barney.obj", texTriangleFactory1, Vec3f(8,0,0));
643 
644 				Scene::SmoothTriangleFactory *texTriangleFactory2 = new Scene::SmoothTriangleFactory;
645 				mat = new Material(Vec3f(0.5,1,0.5));
646 				mat->SetSchlickParams(0.3f, 0.5f, 0.6f);
647 				texTriangleFactory2->shader	        = new SchlickPhotonShader(&scene, mat, photon_tree);
648 				texTriangleFactory2->photon_distributor = new SchlickPhotonDistributor(&scene, mat);
649 				scene.ParseOBJ("barney.obj", texTriangleFactory2, Vec3f(-8,0,0));
650 
651 				scene.Add(new QuadAreaLight(&scene, Vec3f(10), Vec3f(-16.2,10.2,1), Vec3f(-15.8,10.2,-2), Vec3f(-15.8,9.8,-2), Vec3f(-16.2,9.8,1)));
652 				scene.Add(new QuadAreaLight(&scene, Vec3f(10), Vec3f(-0.2,10.2,1), Vec3f(0.2,10.2,-2), Vec3f(0.2,9.8,-2), Vec3f(-0.2,9.8,1)));
653 
654 				scene.camera = new DepthOfFieldCamera(Vec3f(0,8,25),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 0.005f, 1280, 1024);
655 			}
656 			break;
657 		case 12: // Subsurface scattered barney, only once to take photos from the same position (for the web page). PM.
658 			{
659 				Material *mat;
660 
661 				Scene::SmoothTriangleFactory *texTriangleFactory1 = new Scene::SmoothTriangleFactory;
662 				mat = new Material(Vec3f(0.5,1,0.5));
663 				mat->SetSchlickParams(0.3f, 0.1f, 0.9f);
664 				mat->SetSubsurfaceScattering(0.10);
665 				texTriangleFactory1->shader	        = new SchlickPhotonShader(&scene, mat, photon_tree);
666 				texTriangleFactory1->photon_distributor = new SchlickPhotonDistributor(&scene, mat);
667 				scene.ParseOBJ("barney.obj", texTriangleFactory1);
668 
669 				scene.Add(new QuadAreaLight(&scene, Vec3f(10), Vec3f(-3.2,20.2,1), Vec3f(-3.2,20.2,-1), Vec3f(-3.6,19.8,-1), Vec3f(-3.6,19.8,1)));
670 
671 				scene.camera = new DepthOfFieldCamera(Vec3f(0,8,25),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 0.005f, 640, 480);
672 			}
673 			break;
674 		case 13: // Glossy. PM.
675 			{
676 				// Procedural shading approach
677 				Shader	    *shd;
678 				PhotonDistributor *pdist;
679 				Material	  *mat;
680 
681 				mat   = new Material (Vec3f(1,0,0));			      // Red
682 				mat->SetMirrorParams  (0.6f,  0.5f);			      // Mirror 0.6 in 0.5 object color
683 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
684 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
685 				pdist = new SchlickPhotonDistributor(&scene, mat);
686 				scene.Add(new Sphere(Vec3f(-2, 1.7f, 0), 2, shd, pdist));
687 
688 				mat   = new Material   (Vec3f(1,1,1));
689 				mat->SetGlossyMirrorParams(1.0);
690 				mat->SetSchlickParams(0.3f,  0.7f,  0.1f);		      // Looking cool (whatever it imitates)
691 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
692 				pdist = new SchlickPhotonDistributor(&scene, mat);
693 				scene.Add(new InfinitePlane(Vec3f(0, -1, 0), Vec3f(0, 1, 0), shd, pdist));
694 
695 				mat   = new Material (Vec3f(0,0,1));			      // Blue
696 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
697 				shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
698 				pdist = new SchlickPhotonDistributor(&scene, mat);
699 				scene.Add(new Sphere(Vec3f(3, 1.3, -2), 2, shd, pdist));
700 
701                                 mat   = new Material (Vec3f(1,1,1));
702                                 mat->SetGlossyTransparencyParams(1.0);
703 				mat->SetTransparencyParams(UNDEF,1.5);                        // We need the refraction coefficient somehow
704                                 mat->SetSchlickParams(0.3f,  0.5f,  0.6f);                    // Looking cool (whatever it imitates)
705                                 shd   = new SchlickPhotonShader(&scene, mat, photon_tree);
706                                 pdist = new SchlickPhotonDistributor(&scene, mat);
707                                 scene.Add(new Sphere(Vec3f(4, 1.6, 1.0), 1, shd, pdist));
708 
709 				// QAL and QAL visualization
710 				Vec3f a = Vec3f(-0.2,7,15.2),
711 				      b = Vec3f( 0.2,7,15.2),
712 				      c = Vec3f( 0.2,10,14.8),
713 				      d = Vec3f(-0.2,10,14.8);
714 				scene.Add(new QuadAreaLight(&scene, Vec3f(30), a, b, c, d));
715 
716 				// Camera
717 				//scene.camera = new PerspectiveCamera(Vec3f(0,0,10),Vec3f(0,0,-1), Vec3f(0,1,0), 60, 640, 480);
718 				scene.camera = new DepthOfFieldCamera(Vec3f(0,0,10),Vec3f(0.1,0,-1), Vec3f(0,1,0), 60, 0.005f, 1280, 1024); //640, 480);
719 			}
720 			break;
721 		case 15: // Depth of field test
722 			{
723 				Shader	    *shd;
724 				PhotonDistributor *pdist;
725 				Material	  *mat;
726 
727 				mat   = new Material (Vec3f(1,0,0));			      // Red
728 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
729 				shd   = new SchlickShader(&scene, mat);
730 				pdist = new SchlickPhotonDistributor(&scene, mat);
731 				scene.Add(new Sphere(Vec3f(-5, 1.7f, 0), 2, shd, pdist));
732 
733 				mat   = new Material (Vec3f(1,0.5,0));			      // Orange
734 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
735 				shd   = new SchlickShader(&scene, mat);
736 				pdist = new SchlickPhotonDistributor(&scene, mat);
737 				scene.Add(new Sphere(Vec3f(-3, 1.7f, -2), 2, shd, pdist));
738 
739 				mat   = new Material (Vec3f(1,1,0));			      // Yellow
740 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
741 				shd   = new SchlickShader(&scene, mat);
742 				pdist = new SchlickPhotonDistributor(&scene, mat);
743 				scene.Add(new Sphere(Vec3f(-1, 1.7f, -4), 2, shd, pdist));
744 
745 				mat   = new Material (Vec3f(0,1,0));			      // Green
746 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
747 				shd   = new SchlickShader(&scene, mat);
748 				pdist = new SchlickPhotonDistributor(&scene, mat);
749 				scene.Add(new Sphere(Vec3f(1, 1.7f, -6), 2, shd, pdist));
750 
751 				mat   = new Material (Vec3f(0,0.1,1));                        // Blue
752 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
753 				shd   = new SchlickShader(&scene, mat);
754 				pdist = new SchlickPhotonDistributor(&scene, mat);
755 				scene.Add(new Sphere(Vec3f(3, 1.7f, -8), 2, shd, pdist));
756 
757 				mat   = new Material (Vec3f(0.5,0,1));			      // Violet
758 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
759 				shd   = new SchlickShader(&scene, mat);
760 				pdist = new SchlickPhotonDistributor(&scene, mat);
761 				scene.Add(new Sphere(Vec3f(5, 1.7f, -10), 2, shd, pdist));
762 
763 				mat   = new Material   (Vec3f(1,1,1));
764 				mat->SetSchlickParams(0.3f,  0.7f,  0.1f);		      // Looking cool (whatever it imitates)
765 				shd   = new SchlickShader(&scene, mat);
766 				pdist = new SchlickPhotonDistributor(&scene, mat);
767 				scene.Add(new InfinitePlane(Vec3f(0,-1,0), Vec3f(0,1,0), shd, pdist));
768 
769 				Vec3f a = Vec3f(-14,3,12),
770 				      b = Vec3f(-10,3,15),
771 				      c = Vec3f(-10,5,15),
772 				      d = Vec3f(-14,5,12);
773 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
774 
775 				      a = Vec3f( -6,3,18),
776 				      b = Vec3f( -2,3,21),
777 				      c = Vec3f( -2,5,21),
778 				      d = Vec3f( -6,5,18);
779 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
780 
781 				      a = Vec3f(  2,3,24),
782 				      b = Vec3f(  6,3,28),
783 				      c = Vec3f(  6,5,28),
784 				      d = Vec3f(  2,5,24);
785 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
786 
787 				      a = Vec3f( 10,3,32),
788 				      b = Vec3f( 14,3,36),
789 				      c = Vec3f( 14,5,36),
790 				      d = Vec3f( 10,5,32);
791 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
792 
793 				scene.camera = new DepthOfFieldCamera(Vec3f(0,0,10),Vec3f(-0.1,0,-1), Vec3f(0,1,0), 60, 5.0f, 640, 480, 14.0f);
794 			}
795 			break;
796 		case 16: // Fractal mountains. No PM.
797 			{
798 				Shader	          *shd;
799 				Material	  *mat;
800 
801 				mat   = new Material (Vec3f(1.0f));			      // Textured
802 				mat->SetSchlickParams(0.3f,  0.5f,  0.6f);		      // Looking cool (whatever it imitates)
803 				mat->procedural.push_back(new ProceduralHeightTexture(true, false, Vec3f(0,0,-5), Vec3f(0,1,0), 2.7, 0.1, Vec3f(0.8), Vec3f(0.35,0.53,0.0)));
804 				shd   = new SchlickShader(&scene, mat);
805 				
806 				FractalMountain(&scene, Vec3f(-5,0,0), Vec3f(5,0,0), Vec3f(-5,0,-10),
807 						200, 0.95f, 2.0f, 15, 0.9f, shd, NULL);
808 
809 				Vec3f a = Vec3f( 3,11,-3),
810 				      b = Vec3f(-3,11,-3),
811 				      c = Vec3f(-3,6,0),
812 				      d = Vec3f( 3,6,0);
813 				scene.Add(new QuadAreaLight(&scene, Vec3f(25), a, b, c, d));
814 
815 				scene.camera = new DepthOfFieldCamera(Vec3f(0,6,6),Vec3f(0,-0.5,-1), Vec3f(0,1,0), 60, 0.1f, 1280, 1024, 6.0f);
816 			}
817 			break;
818 		case 17: // Granite. No PM.
819 			{
820 				Shader	          *shd;
821 				Material	  *mat;
822 
823 				mat   = new Material (Vec3f(1,0.19,0.19));		      // Red granite
824 				mat->SetSchlickParams(0.3f,  0.2f,  1.0f);		      // Looking cool (whatever it imitates)
825 				mat->procedural.push_back(new ProceduralGranite(true, false, 20));
826 				shd   = new SchlickShader(&scene, mat);
827 				scene.Add(new Sphere(Vec3f(-4, 3.7f, 0), 4, shd, NULL));
828 
829 				mat   = new Material (Vec3f(1));		              // Pure granite
830 				mat->SetSchlickParams(0.3f,  0.2f,  1.0f);		      // Looking cool (whatever it imitates)
831 				mat->procedural.push_back(new ProceduralGranite(true, false, 20));
832 				shd   = new SchlickShader(&scene, mat);
833 				scene.Add(new Sphere(Vec3f(4, 3.7f, -2), 4, shd, NULL));
834 
835 				mat   = new Material   (Vec3f(1,1,1));
836 				mat->SetMirrorParams(1.0);
837 				shd   = new SchlickShader(&scene, mat);
838 				scene.Add(new InfinitePlane(Vec3f(0,-1,0), Vec3f(0,1,0), shd, NULL));
839 
840 				Vec3f a = Vec3f(-14,3,12),
841 				      b = Vec3f(-10,3,15),
842 				      c = Vec3f(-10,5,15),
843 				      d = Vec3f(-14,5,12);
844 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
845 
846 				      a = Vec3f( -6,3,18),
847 				      b = Vec3f( -2,3,21),
848 				      c = Vec3f( -2,5,21),
849 				      d = Vec3f( -6,5,18);
850 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
851 
852 				      a = Vec3f(  2,3,24),
853 				      b = Vec3f(  6,3,28),
854 				      c = Vec3f(  6,5,28),
855 				      d = Vec3f(  2,5,24);
856 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
857 
858 				      a = Vec3f( 10,3,32),
859 				      b = Vec3f( 14,3,36),
860 				      c = Vec3f( 14,5,36),
861 				      d = Vec3f( 10,5,32);
862 				scene.Add(new QuadAreaLight(&scene, Vec3f(150), a, b, c, d));
863 
864 				scene.camera = new PerspectiveCamera(Vec3f(0,0,10),Vec3f(-0.1,0,-1), Vec3f(0,1,0), 60, 640, 480);
865 			}
866 			break;
867 		default:
868 			{		
869 				std::cerr << "Usage: " << argv[0] << "<scene-number> [<sampler> <sample-count> [(write|read) <photonmap> [number]]]" << std::endl;
870 				std::cerr << "  Please refer to the 'makefile' or 'README' for further instructions on command line parameters." << std::endl;
871 				std::cerr << "  Starting the program with wrong parameters might in the worst case lead to segfaults." << std::endl << std::endl;
872 
873 				std::cerr << "<sampler> = " << std::endl;
874 				std::cerr << "  regular (default)" << std::endl;
875 				std::cerr << "  random" << std::endl;
876 				std::cerr << "  stratified" << std::endl;
877 				std::cerr << " " << std::endl;
878 				std::cerr << "'write' creates and 'read' uses the <photonmap>," << std::endl;
879 				std::cerr << " where writing requires a number of photons to be shot" << std::endl;
880 				exit(1);
881 			}
882 	}
883 
884 	scene.BuildAccelStructure();
885 
886 	if (photonmap == WRITEPHOTONMAP)
887 		BuildPhotonMap(scene, numberofphotons, photonmapname);
888 	else
889 		RenderFrame(scene, sampleCount, sampler);
890 }


syntax highlighted by Code2HTML, v. 0.9.1