00001
00012 #ifdef MT_OPENMP
00013 #include <omp.h>
00014 #endif
00015
00019 #include <sstream>
00020 #include <iostream>
00021
00025 #include "Image.h"
00026
00030 #include "Object.h"
00031 #include "Scene.h"
00032 #include "Sphere.h"
00033
00037 #include "PerspectiveCamera.h"
00038 #include "CylindricCamera.h"
00039 #include "DepthOfFieldCamera.h"
00040
00044 #include "PointLight.h"
00045 #include "QuadAreaLight.h"
00046
00050 #include "Texture2D.h"
00051 #include "FlatShader.h"
00052 #include "DebugShader.h"
00053 #include "EdgeShader.h"
00054 #include "FlatTransparentShader.h"
00055 #include "MirrorShader.h"
00056 #include "EyeLightShader.h"
00057 #include "PhongShader.h"
00058 #include "CloudShader.h"
00059 #include "PlasmaShader.h"
00060 #include "MarbleShader.h"
00061 #include "BumpMappedDebugShader.h"
00062 #include "BumpMappedPhongShader.h"
00063 #include "BumpMappedMarblePhongShader.h"
00064 #include "TransparentShader.h"
00065 #include "UniAxialCrystalShader.h"
00066 #include "MixShader.h"
00067 #include "MapShader.h"
00068 #include "WoodShader.h"
00069 #include "BumpMappedWoodPhongShader.h"
00070 #include "GoldShader.h"
00071 #include "SilverShader.h"
00072 #include "SteelShader.h"
00073 #include "CopperShader.h"
00074
00078 #include "SampleGenerator.h"
00079 #include "RegularSampleGenerator.h"
00080 #include "RandomSampleGenerator.h"
00081 #include "StratifiedSampleGenerator.h"
00082 #include "PoissonDiskSampleGenerator.h"
00083
00084 using namespace std;
00085
00099 Object* AddObject(char* fileName, Scene& scene, bool useAcc = true, const Object::PrimitiveFactory& factory = Object::TriangleFactory() )
00100 {
00101 Object* obj = new Object(useAcc);
00102 obj->ParseOBJ(fileName, factory);
00103 obj->setColor(ColorRGBA(1,1,1));
00104 obj->BuildAccelStructure();
00105
00106 scene.AddObject(obj);
00107
00108 return obj;
00109 }
00110
00119 Object* AddSphere(Sphere* sphere, Scene& scene, bool useAcc = true)
00120 {
00121 Object* obj = new Object(useAcc);
00122 obj->Add(sphere);
00123 obj->setColor(Vector3D(1,1,1));
00124 obj->BuildAccelStructure();
00125
00126 scene.AddObject(obj);
00127
00128 return obj;
00129 }
00130
00146 void RenderFrame (Scene* scene, string prefix,
00147 Vector3D pos, Vector3D dir, float angle,
00148 int resX, int resY)
00149 {
00150
00151 stringstream s;
00152 s << prefix << scene->timer.GetTime() << ".png";
00153
00154
00155 printf("render %s (%dx%d)\n", s.str().c_str(), resX, resY);
00156
00157
00158 Image img(resX, resY);
00159
00160
00161 PerspectiveCamera camera(pos, dir, Vector3D(0,1,0), angle, resX, resY);
00162
00163 #ifdef MT_OPENMP
00164 #pragma omp parallel
00165 {
00166 #pragma omp for schedule(dynamic) nowait
00167 #endif
00168
00169
00170 for (int y=0; y < resY; y++) {
00171 for (int x=0; x < resX; x++) {
00172
00173 Ray ray = camera.InitRay(x, y);
00174
00175
00176 ColorRGBA color = scene->RayTrace(ray);
00177 color.normalize();
00178 img.setPixel(color, x, y);
00179 }
00180 }
00181
00182 #ifdef MT_OPENMP
00183 }
00184 #endif
00185
00186
00187 img.WritePNG(s.str().c_str());
00188 }
00189
00208 void RenderSupersampledFrame(Scene* scene, string prefix,
00209 Vector3D pos, Vector3D dir, float angle,
00210 int resX, int resY,
00211 const SampleGenerator& sampler = SampleGenerator(), int sampleCount = 1)
00212 {
00213
00214 stringstream s;
00215 s << prefix << scene->timer.GetTime() << ".png";
00216
00217
00218 printf("render supersampled %s (%dx%d)\n", s.str().c_str(), resX, resY);
00219
00220
00221 Image img(resX, resY);
00222
00223
00224 PerspectiveCamera camera(pos, dir, Vector3D(0,1,0), angle, resX, resY);
00225
00226 #ifdef MT_OPENMP
00227 #pragma omp parallel
00228 {
00229 #endif
00230
00231
00232 float* xv = new float[sampleCount];
00233 float* yv = new float[sampleCount];
00234 float* weight = new float[sampleCount];
00235
00236 #ifdef MT_OPENMP
00237 #pragma omp for schedule(dynamic) nowait
00238 #endif
00239
00240
00241 for (int y=0; y < resY; y++) {
00242 for (int x=0; x < resX; x++) {
00243 ColorRGBA color(0,0,0);
00244 sampler.GetSamples(sampleCount, xv, yv, weight);
00245 for (int s=0; s < sampleCount; s++) {
00246
00247 Ray ray = camera.InitRay(x + xv[s], y + yv[s]);
00248
00249
00250 color = color + weight[s] * scene->RayTrace(ray);
00251 }
00252 color.normalize();
00253 img.setPixel(color, x, y);
00254 }
00255 }
00256
00257
00258 delete [] xv;
00259 delete [] yv;
00260 delete [] weight;
00261
00262 #ifdef MT_OPENMP
00263 }
00264 #endif
00265
00266
00267 img.WritePNG(s.str().c_str());
00268 }
00269
00289 void RenderDepthOfFieldFrame(Scene* scene, string prefix,
00290 Vector3D pos, Vector3D dir, float angle,
00291 int resX, int resY,
00292 float lensRadius, float focalDistance,
00293 const SampleGenerator& sampler = SampleGenerator(), int sampleCount = 1)
00294 {
00295
00296 stringstream s;
00297 s << prefix << scene->timer.GetTime() << ".png";
00298
00299
00300 printf("render %s (%dx%d)\n", s.str().c_str(), resX, resY);
00301
00302
00303 Image img(resX, resY);
00304
00305 #ifdef MT_OPENMP
00306 #pragma omp parallel
00307 {
00308 #endif
00309
00310
00311 float* xv = new float[sampleCount];
00312 float* yv = new float[sampleCount];
00313 float* weight = new float[sampleCount];
00314
00315 #ifdef MT_OPENMP
00316 #pragma omp for schedule(dynamic) nowait
00317 #endif
00318
00319
00320 for (int y=0; y < resY; y++) {
00321 for (int x=0; x < resX; x++) {
00322 ColorRGBA color(0,0,0);
00323 sampler.GetSamples(sampleCount, xv, yv, weight);
00324 for (int s=0; s < sampleCount; s++) {
00325
00326 DepthOfFieldCamera camera(pos, dir, Vector3D(0,1,0), angle, resX, resY, lensRadius, focalDistance, xv[s], yv[s]);
00327
00328
00329 Ray ray = camera.InitRay(x, y);
00330
00331
00332 color = color + weight[s] * scene->RayTrace(ray);
00333 }
00334 color.normalize();
00335 img.setPixel(color, x, y);
00336 }
00337 }
00338
00339
00340 delete [] xv;
00341 delete [] yv;
00342 delete [] weight;
00343
00344 #ifdef MT_OPENMP
00345 }
00346 #endif
00347
00348
00349 img.WritePNG(s.str().c_str());
00350 }
00351
00352
00367 void RenderLinearFramePath (Scene* scene, string prefix,
00368 Vector3D pos, Vector3D dir, float angle,
00369 int resX, int resY,
00370 Vector3D path, int times)
00371 {
00372
00373 Image img(resX, resY);
00374
00375 for (int i=0; i < times; i++) {
00376
00377 stringstream s;
00378 s << prefix << scene->timer.GetTime() << ".png";
00379
00380
00381 printf("render %s (%dx%d)\n", s.str().c_str(), resX, resY);
00382
00383
00384 PerspectiveCamera camera(pos + i * path, dir, Vector3D(0,1,0), angle, resX, resY);
00385
00386 #ifdef MT_OPENMP
00387 #pragma omp parallel
00388 {
00389 #pragma omp for schedule(dynamic) nowait
00390 #endif
00391
00392
00393 for (int y=0; y < resY; y++) {
00394 for (int x=0; x < resX; x++) {
00395
00396 Ray ray = camera.InitRay(x, y);
00397
00398
00399 ColorRGBA color = scene->RayTrace(ray);
00400 color.normalize();
00401 img.setPixel(color, x, y);
00402 }
00403 }
00404
00405 #ifdef MT_OPENMP
00406 }
00407 #endif
00408
00409
00410 img.WritePNG(s.str().c_str());
00411
00412
00413 scene->timer.Tick();
00414 }
00415 }
00416
00430 void RenderStereoFrame (Scene* scene, string prefix,
00431 Vector3D pos, Vector3D dir, float angle,
00432 int resX, int resY,
00433 float distance = 0.01f)
00434 {
00435
00436 stringstream s;
00437 s << prefix << scene->timer.GetTime() << ".png";
00438
00439
00440 printf("render %s (%dx%d)\n", s.str().c_str(), resX, resY);
00441
00442
00443 Image img(resX, resY);
00444
00445
00446 Vector3D greenpos = pos + Vector3D(distance,0,0);
00447 Vector3D greendir = (pos + dir) - greenpos;
00448 PerspectiveCamera red(pos, dir, Vector3D(0,1,0), angle, resX, resY);
00449 PerspectiveCamera green(greenpos, greendir, Vector3D(0,1,0), angle, resX, resY);
00450
00451 #ifdef MT_OPENMP
00452 #pragma omp parallel
00453 {
00454 #pragma omp for schedule(dynamic) nowait
00455 #endif
00456
00457
00458 for (int y=0; y < resY; y++) {
00459 for (int x=0; x < resX; x++) {
00460
00461 Ray redray = red.InitRay(x, y);
00462 Ray greenray = green.InitRay(x, y);
00463
00464
00465 ColorRGBA color;
00466 color.red() = scene->RayTrace(redray).average();
00467 color.green() = scene->RayTrace(greenray).average();
00468 color.normalize();
00469 img.setPixel(color, x, y);
00470 }
00471 }
00472
00473 #ifdef MT_OPENMP
00474 }
00475 #endif
00476
00477
00478 img.WritePNG(s.str().c_str());
00479 }
00480
00489 void moveSphere(Sphere* sphere, float deltaRadius, float rotAngle, Vector3D posOffset)
00490 {
00491 rotAngle *= M_PI / 180;
00492 sphere->ChangeRadius(deltaRadius);
00493 Vector3D pos = sphere->GetPosition();
00494 sphere->SetPosition(Vector3D(posOffset.x() + (cos(rotAngle)*pos.x() + sin(rotAngle)*pos.z()), posOffset.y() + pos.y(), posOffset.z() + (-sin(rotAngle)*pos.x() + cos(rotAngle)*pos.z())));
00495 }
00496
00504 Vector3D rotateVec(Vector3D vec, float rotAngle)
00505 {
00506 rotAngle *= M_PI / 180;
00507 return Vector3D((cos(rotAngle)*vec.x() + sin(rotAngle)*vec.z()), vec.y(), (-sin(rotAngle)*vec.x() + cos(rotAngle)*vec.z()));
00508 }
00509
00515 void hideSphere(Sphere* sphere)
00516 {
00517 sphere->SetRadius(0.0);
00518 }
00519
00520 #define USE_KDTREE 1
00521
00533 #define USE_KDTREE 1
00534 int main (int argc, char **argv)
00535 {
00536 int resX, resY;
00537 if (argc > 2) {
00538 resX = atoi(argv[1]);
00539 resY = atoi(argv[2]);
00540 } else {
00541 resX = 320;
00542 resY = 256;
00543 }
00544
00546
00547
00548 Scene* scene = new Scene();
00549 scene->setBgColor(Vector3D(0,0,0));
00550
00551
00552
00553 QuadAreaLight* light1 = new QuadAreaLight(ColorRGBA(250.0,250.0,250.0), Vector3D(0.1, 10.03, -20.2), Vector3D(2.0,0,0), Vector3D(0,1.5,1.5));
00554 PointLight* light2 = new PointLight(Vector3D(0, 10, 0), ColorRGBA(25));
00555
00556 light1->SetNumberOfRays(25);
00557 scene->AddLight(light1);
00558 scene->AddLight(light2);
00559 scene->castShadows = true;
00560
00561
00562
00563 Object* cow = AddObject("mesh/cow.obj", *scene, USE_KDTREE, Object::TexturedSmoothTriangleFactory());
00564 Texture* cowtex = new Texture2D("textures/cowspots.png");
00565 Shader* cowshader1 = new PhongShader(scene, Vector3D(0.8, 0.7, 0.6), 0, 0.8, 0.4, 12.0);
00566 cowshader1->addTexture(cowtex);
00567 Shader* cowshader2 = new BumpMappedWoodPhongShader(scene, ColorRGBA(0.9,0.9,1), 0, 1, 0, 0.5, cowtex, 0.2, Vector3D(0,0,0));
00568 Shader* cowshader3 = new PlasmaShader(scene);
00569 Shader* cowshader = new MixShader(scene, cowshader2, cowshader1);
00570 cow->setShader(cowshader1);
00571
00572
00573
00574 Object* ground = AddObject("mesh/plane.obj", *scene, USE_KDTREE, Object::TexturedSmoothTriangleFactory());
00575 Texture* bumptex = new Texture2D("textures/bump.png");
00576 bumptex->setWrapMode(Texture::REPEAT);
00577 bumptex->setInterpolationMode(Texture::LINEAR);
00578 Texture* mixmap = new Texture2D("textures/mandala.png");
00579 mixmap->setWrapMode(Texture::REPEAT);
00580 mixmap->setInterpolationMode(Texture::LINEAR);
00581 Shader* groundshader3 = new GoldShader(scene);
00582 Shader* groundshader2 = new PhongShader(scene, ColorRGBA(0.9,0.9,1), 0, 1, 0, 0.5);
00583 Shader* groundshader1 = new BumpMappedMarblePhongShader(scene, ColorRGBA(0,0.4,0.25), 0, 1, 0, 0.5, bumptex, 0, Vector3D(0,0,0));
00584 Shader* groundshader = new MapShader(scene, groundshader3, groundshader1, mixmap);
00585 ground->setShader(groundshader1);
00586
00587
00588
00589 Object* sky = AddObject("mesh/skydome.obj", *scene, 0, Object::TexturedSmoothTriangleFactory());
00590
00591 Shader* skyshader = new CloudShader(scene);
00592 sky->setShader(skyshader);
00593
00594
00595
00596 Object* b1 = AddSphere(Vector3D(-0.1,0.12,0.8), 0.05, *scene);
00597 Object* b2 = AddSphere(Vector3D(-0.1,0.11,0.6), 0.05, *scene);
00598 Object* b3 = AddSphere(Vector3D(-0.1,0.1,0.4), 0.05, *scene);
00599 Object* b4 = AddSphere(Vector3D(-0.1,0.065,0.2), 0.1, *scene);
00600 Object* b5 = AddSphere(Vector3D(-0.1,0.065,0.2), 0.05, *scene);
00601 Object* b6 = AddSphere(Vector3D(-0.1,0.05,-0.08), 0.05, *scene);
00602 Object* b7 = AddSphere(Vector3D(-0.1,0.04,-0.2), 0.05, *scene);
00603 Shader* s5 = new SilverShader(scene);
00604 Shader* s2 = new GoldShader(scene);
00605 Shader* s3 = new SteelShader(scene);
00606 Shader* s4 = new TransparentShader(scene, 1, 1.5);
00607 Shader* s1 = new BumpMappedWoodPhongShader(scene, ColorRGBA(0.9,0.9,1), 0, 1, 0, 0.5, bumptex, 0, Vector3D(0,0,0));
00608 Shader* s6 = new CopperShader(scene);
00609 Shader* s7 = new TransparentShader(scene, 1, 1.5);
00610 b1->setShader(s1);
00611 b2->setShader(s2);
00612 b3->setShader(s3);
00613 b4->setShader(s4);
00614 b5->setShader(s5);
00615 b6->setShader(s6);
00616 b7->setShader(s7);
00617
00618
00620
00621
00623
00624
00625
00626
00627
00628 float fl = (cow->center - Vector3D(0.35,0.1,-0.33)).Length();
00629 RenderDepthOfFieldFrame(scene, "rdoff", Vector3D(0.35,0.1,-0.33), Vector3D(-0.1,-0.02,0.12), 60, resX, resY, 0.001, fl, RandomSampleGenerator(), 36);
00630
00632
00633
00635
00636 delete cowtex;
00637 delete cowshader1;
00638 delete cowshader2;
00639 delete cowshader;
00640 delete bumptex;
00641 delete groundshader;
00642 delete skyshader;
00643 delete s1;
00644 delete s2;
00645 delete s3;
00646 delete scene;
00648 }