src/Renderer.cpp

Go to the documentation of this file.
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     //this shouldn't hurt
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];      //+1 here for safety, if we didn't catch every y (see the following if)
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 //start threads
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 //TODO if we really need this we have to reconsider why there is a lag between the difference between the lines threads do and the lines thread not do
00111 //perhaps this just happens on uneven numbers
00112 /*        realnumberofthreads++;
00113 
00114         threadargs[NUMBER_OF_THREADS+1].mStartY = start;
00115         threadargs[NUMBER_OF_THREADS+1].mStopY = mCamera->resY();
00116         threadargs[NUMBER_OF_THREADS+1].mSupersampled = mSupersampled;
00117         threadargs[NUMBER_OF_THREADS+1].mSampleCount = mSampleCount;
00118         threadargs[NUMBER_OF_THREADS+1].mImage = &img;
00119         threadargs[NUMBER_OF_THREADS+1].mCamera = mCamera;
00120         threadargs[NUMBER_OF_THREADS+1].mScene = &mScene;
00121         threadargs[NUMBER_OF_THREADS+1].mSampler = mSampler;
00122 
00123         void* args = static_cast<void*>(&threadargs[0]);
00124         result = pthread_create(&threads[0], 0,&Renderer::renderFromTo, args );
00125         if(result)
00126             LOG("Some error in thread create");
00127 */
00128     }
00129 
00130 
00131 //joining
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         //FIXME i think this is bad, but at the moment we don't have a const mSampleCount
00192         float * u = new float[args->mSampleCount];
00193         float * v = new float[args->mSampleCount];
00194         float * w = new float[args->mSampleCount];
00195         
00196         // render the scene
00197         for (int y=args->mStartY; y < args->mStopY ; y++)
00198         {
00199             for (int x=0; x < camera->resX(); x++)
00200             {
00201                 // init samples
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         // apply animations
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         // apply camera animation
00257         Camera* newcam = mCameraAnimator->animate();
00258         mCamera = newcam;
00259 
00260         // apply physics and object animations
00261         mScene.step();
00262 
00263         LOG("Frame " << i << " ...");
00264         render();
00265     }
00266 }
00267 
00268 
00269 //if more than once called we have memory leaks
00270 void Renderer::buildTestScene()
00271 {
00272     const bool depthoffield     = false;    // depth of field test scene
00273     const bool bumpmapping      = false;    // bump mapping test scene
00274     const bool cooktorrance     = false;    // cook torrance test scene
00275     const bool woodshader       = false;    // wood shader test scene
00276     const bool gun              = false;    // gun for sah testing
00277     const bool supersampling    = false;    // for super-sampling
00278     const bool buddha           = false;    // happy Buddha model for sah benching
00279     const bool refractive       = true;    // refractive shader test scene
00280     const bool terrain          = false;    // scene from MicroTrace05
00281     const bool balls            = false;    // test scene for balls
00282     const bool table            = true;     // blubb
00283     //super sampling
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     // normal cow
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 

Generated on Fri Feb 1 00:01:42 2008 for Grayfall by  doxygen 1.5.1