00001 #include <pthread.h>
00002 #include <string>
00003 #include <sstream>
00004 #include <iostream>
00005 #include <iomanip>
00006
00007 #include "Renderer.h"
00008
00009 #include "Camera.h"
00010 #include "MirrorShader.h"
00011 #include "Object.h"
00012 #include "PNGImage.h"
00013 #include "PerspectiveCamera.h"
00014 #include "PhongShader.h"
00015 #include "PointLight.h"
00016 #include "QuadAreaLight.h"
00017 #include "RGBAColor.h"
00018 #include "StratifiedSampleGenerator.h"
00019 #include "Texture2D.h"
00020 #include "TransparentShader.h"
00021 #include "CloudShader.h"
00022 #include "WoodShader.h"
00023 #include "CombineShader.h"
00024 #include "defines.h"
00025 #include "SceneBuilder.h"
00026 #include "OBJObject.h"
00027 #include "CameraAnimator.h"
00028
00029
00030 #include "DepthOfFieldCamera.h"
00031
00032 pthread_mutex_t mMutexImage;
00033
00034 Renderer::Renderer(const std::string & filename)
00035 :mCamera(NULL),
00036 mSupersampled(false),
00037 mSampleCount(1),
00038 mSampler(NULL),
00039 mFileName(filename),
00040 mCameraAnimator(NULL)
00041 {
00042
00043 srand(time(0));
00044 srand48(time(0));
00045 }
00046
00047 Renderer::~Renderer()
00048 {
00049 if (!mCameraAnimator)
00050 delete mCamera;
00051 delete mSampler;
00052 delete mCameraAnimator;
00053 }
00054
00055 void Renderer::buildScene()
00056 {
00057 buildTestScene();
00058 }
00059
00060 void Renderer::render()
00061 {
00062 std::cout << "Rendering...\n" << std::endl;
00063 PNGImage img(mCamera->resX(), mCamera->resY());
00064
00065 int result;
00066 pthread_attr_t attribute;
00067 pthread_attr_init(&attribute);
00068 pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_JOINABLE);
00069
00070
00071 pthread_t threads[NUMBER_OF_THREADS+1];
00072 ThreadArgs threadargs[NUMBER_OF_THREADS+1];
00073 pthread_mutex_init(&mMutexImage, NULL);
00074
00075 const int ratio = (mCamera->resY() ) / NUMBER_OF_THREADS;
00076 int start = 0;
00077 int stop = ratio;
00078
00079
00080
00081 for(int i=0; i<NUMBER_OF_THREADS; i++)
00082 {
00083 LOG("Threading Debug: start " << start << " stop: " << stop);
00084 threadargs[i].mStartY = start;
00085 threadargs[i].mStopY = stop;
00086 threadargs[i].mSupersampled = mSupersampled;
00087 threadargs[i].mSampleCount = mSampleCount;
00088 threadargs[i].mImage = &img;
00089 threadargs[i].mCamera = mCamera;
00090 threadargs[i].mScene = &mScene;
00091 threadargs[i].mSampler = mSampler;
00092
00093 void* args = static_cast<void*>(&threadargs[i]);
00094 LOG("starting thread " << i );
00095 result = pthread_create(&threads[i], &attribute, &Renderer::renderFromTo, args );
00096 if(result)
00097 LOG("Some error in thread create");
00098
00099 start += ratio;
00100 stop +=ratio;
00101
00102 }
00103 stop -=ratio;
00104 bool notall = (stop!=mCamera->resY() );
00105 LOG("b: " << notall<<" " << stop << " c: " << mCamera->resY() );
00106 int realnumberofthreads = NUMBER_OF_THREADS;
00107 if(notall)
00108 {
00109 assert(false);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 }
00129
00130
00131
00132 for(int i=0; i<realnumberofthreads; i++)
00133 {
00134 LOG("Thread Debug: Joining thread " << i);
00135 result = pthread_join(threads[i],0);
00136 if(result)
00137 LOG("Something wrong with joining");
00138 }
00139
00140 LOG("writing file");
00141 pthread_mutex_destroy(&mMutexImage);
00142
00143 std::cout << "Writing to \"" << mFileName << "\"\n" << std::endl;
00144 img.write(mFileName);
00145 }
00146
00147 void* Renderer::renderFromTo(void* threadargs)
00148 {
00149 assert(threadargs!=0);
00150
00151 ThreadArgs* args = static_cast<ThreadArgs*>(threadargs);
00152 Camera* camera = args->mCamera;
00153 Image* image = args->mImage;
00154 Scene* scene = args->mScene;
00155 SampleGenerator* sampler = args->mSampler;
00156
00157 assert(camera!=0);
00158 assert(image!=0);
00159 assert(scene!=0);
00160
00161
00162 LOG("Threading Debug: Rendering in thread from: " << args->mStartY << " to:" << args->mStopY);
00163 if(!args->mSupersampled)
00164 {
00165 for(int y=args->mStartY; y < args->mStopY; y++)
00166 {
00167 for(int x=0; x<camera->resX(); x++)
00168 {
00169 RGBAColor colorvalue;
00170 for(int i=0; i<camera->depthSamples(); i++)
00171 {
00172 Ray ray = camera->initRay(x, y);
00173 colorvalue += min(max( scene->rayTrace(ray), RGBAColor(0)), RGBAColor(1) );
00174 }
00175 colorvalue = colorvalue / camera->depthSamples();
00176
00177 pthread_mutex_lock(&mMutexImage);
00178 image->setPixel(min(max( colorvalue, RGBAColor(0, 0, 0, 1)), RGBAColor(1)), x, y);
00179 pthread_mutex_unlock(&mMutexImage);
00180 }
00181 if (y%100 == 99)
00182 {
00183 LOG(y+1 << " / " << camera->resY());
00184 }
00185 }
00186 }
00187 else
00188 {
00189 assert(sampler!=0);
00190 LOG("SUPERSAMPLED");
00191
00192 float * u = new float[args->mSampleCount];
00193 float * v = new float[args->mSampleCount];
00194 float * w = new float[args->mSampleCount];
00195
00196
00197 for (int y=args->mStartY; y < args->mStopY ; y++)
00198 {
00199 for (int x=0; x < camera->resX(); x++)
00200 {
00201
00202 sampler->samples(args->mSampleCount, u, v, w);
00203 RGBAColor color;
00204 for (int i=0; i<args->mSampleCount; i++)
00205 {
00206 RGBAColor depthcolor;
00207 for(int k=0; k<camera->depthSamples(); k++)
00208 {
00209 float xpos = static_cast<float>(x) + u[i] - 0.5f;
00210 float ypos = static_cast<float>(y) + v[i] - 0.5f;
00211 Ray ray = camera->initRay(xpos, ypos);
00212 depthcolor += scene->rayTrace(ray);
00213 }
00214 depthcolor = depthcolor / camera->depthSamples();
00215 color += depthcolor * w[i];
00216 }
00217 pthread_mutex_lock(&mMutexImage);
00218 image->setPixel(min(max( color, RGBAColor(0, 0, 0, 1)), RGBAColor(1)), x, y);
00219 pthread_mutex_unlock(&mMutexImage);
00220
00221 }
00222 if (y%50 == 49)
00223 {
00224 LOG(y+1 << " / " << camera->resY());
00225 }
00226 }
00227
00228 delete [] u;
00229 delete [] v;
00230 delete [] w;
00231 }
00232 LOG("finished thread from " << args->mStartY << " to " << args->mStopY);
00233 pthread_exit(0);
00234 }
00235
00236
00237 void Renderer::renderAnimated()
00238 {
00239 assert(mCameraAnimator!=0);
00240 std::string prefix = "vid/";
00241 for(unsigned int i=0;i<mStartFrame;i++)
00242 {
00243 LOG("skipping frame: " << i);
00244
00245 mCameraAnimator->animate();
00246 mScene.step();
00247 }
00248 delete mCamera;
00249 for(unsigned int i=mStartFrame;i<mEndFrame;i++)
00250 {
00251 LOG("rendering frame: " << i);
00252 std::stringstream stream;
00253 stream << prefix << std::setw(5) << std::setfill('0') << i << ".png";
00254 mFileName = stream.str();
00255
00256
00257 Camera* newcam = mCameraAnimator->animate();
00258 mCamera = newcam;
00259
00260
00261 mScene.step();
00262
00263 LOG("Frame " << i << " ...");
00264 render();
00265 }
00266 }
00267
00268
00269
00270 void Renderer::buildTestScene()
00271 {
00272 const bool depthoffield = false;
00273 const bool bumpmapping = false;
00274 const bool cooktorrance = false;
00275 const bool woodshader = false;
00276 const bool gun = false;
00277 const bool supersampling = false;
00278 const bool buddha = false;
00279 const bool refractive = true;
00280 const bool terrain = false;
00281 const bool balls = false;
00282 const bool table = true;
00283
00284 if (supersampling || terrain)
00285 {
00286 setupSupersampling(9);
00287 }
00288
00289 if (depthoffield)
00290 {
00291 buildScene("scene/depthoffield.scene");
00292 return;
00293 }
00294
00295 if (bumpmapping)
00296 {
00297 buildScene("scene/bumpmapping.scene");
00298 return;
00299 }
00300
00301 if (cooktorrance)
00302 {
00303 buildScene("scene/cooktorrance.scene");
00304 return;
00305 }
00306
00307 if (woodshader)
00308 {
00309 buildScene("scene/woodshader.scene");
00310 return;
00311 }
00312
00313 if (gun)
00314 {
00315 buildScene("scene/gun-54642-tris.scene");
00316 return;
00317 }
00318
00319 if (buddha)
00320 {
00321 buildScene("scene/happy-buddha.scene");
00322 return;
00323 }
00324
00325 if (refractive)
00326 {
00327 buildScene("scene/refractive.scene");
00328 return;
00329 }
00330
00331 if (terrain)
00332 {
00333 buildScene("scene/terrain.scene");
00334 return;
00335 }
00336
00337 if (balls)
00338 {
00339 buildScene("scene/ballstest.scene");
00340 return;
00341 }
00342
00343 if (table)
00344 {
00345 buildScene("scene/billiard-table.scene");
00346 return;
00347 }
00348
00349
00350 buildScene("scene/test.scene");
00351 }
00352
00353
00356 void Renderer::buildScene(const std::string & sceneFile)
00357 {
00358 std::cout << "Building scene \"" << sceneFile << "\"\n" << std::endl;
00359 SceneBuilder builder;
00360 delete mCamera;
00361 mCamera = NULL;
00362 builder.load(mScene, mCamera, sceneFile);
00363 }
00364
00365
00368 void Renderer::setupAnimation(std::string filename, unsigned int startframe, unsigned int endframe)
00369 {
00370 mCameraAnimator = new CameraAnimator(filename);
00371 mStartFrame = startframe;
00372 mEndFrame = endframe;
00373 }
00374
00375
00382 int Renderer::setupSupersampling(int samples)
00383 {
00384 delete mSampler;
00385 if (samples >= 4)
00386 {
00387 mSampler = new StratifiedSampleGenerator();
00388 mSupersampled = true;
00389 mSampleCount = static_cast<int>(floorf(sqrtf(samples)));
00390 mSampleCount *= mSampleCount;
00391 }
00392 else
00393 {
00394 mSampler = NULL;
00395 mSupersampled = false;
00396 mSampleCount = 1;
00397 }
00398 return mSampleCount;
00399 }
00400
00401