00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "globalphotontracer.h"
00024 #include "common/math/point3.h"
00025 #include "common/math/real.h"
00026 #include "common/math/vector3.h"
00027 #include "color3.h"
00028 #include "context.h"
00029 #include "hit.h"
00030 #include "ibdf.h"
00031 #include "ilight.h"
00032 #include "isurfaceshader.h"
00033 #include "photonmap.h"
00034 #include "ray.h"
00035 #include "scene.h"
00036 #include "statistics.h"
00037 #include "surfacebasis.h"
00038 #include "utilities.h"
00039
00040 #include <cassert>
00041
00042 using namespace sheep;
00043 using namespace toxic;
00044
00045 void GlobalPhotonTracer::trace_photon(const Context &context,
00046 PhotonMap *photonmap,
00047 const Scene *scene,
00048 Ray ray,
00049 Color3 power) const
00050 {
00051 assert(photonmap);
00052 assert(scene);
00053
00054 bool directillum = true;
00055
00056 while(true) {
00057 Hit hit;
00058
00059 ++context.m_statistics->m_photon_rays;
00060
00061 assert(ray.m_direction.IsUnitLength());
00062
00063 if(!scene->Trace(context, ray, &hit)) {
00064
00065 break;
00066 }
00067
00068
00069 Point3 point;
00070 Vector3 geometric_normal;
00071 hit.ExtractIntersection(ray, &point, &geometric_normal, 0);
00072 const ISurfaceShader *surface_shader = hit.m_object->GetSurfaceShader();
00073
00074 const SurfaceBasis surfacebasis(geometric_normal);
00075
00076 ShadingData shadingdata;
00077 surface_shader->Shade(hit, &shadingdata);
00078
00079 if(shadingdata.m_bdf->IsDiffuse()) {
00080
00081
00082 if(!directillum) {
00083 ++context.m_statistics->m_gpm_photons;
00084 photonmap->StorePhoton(
00085 point,
00086 power,
00087 -ray.m_direction
00088 #ifdef ENABLE_RADIANCES_PRECOMPUTATION
00089 , geometric_normal
00090 #endif
00091 );
00092 }
00093 }
00094
00095
00096 const Real scattering_prob = shadingdata.m_reflectance.Average();
00097 if(context.m_rng->RandomReal1() > scattering_prob)
00098 break;
00099 power /= scattering_prob;
00100
00101 directillum = false;
00102
00103 const Vector3 local_incoming = surfacebasis.TransformToLocal(-ray.m_direction);
00104
00105 Vector3 scattereddir;
00106 Real prob;
00107 Real bsdf_value;
00108
00109 shadingdata.m_bdf->Sample(
00110 context,
00111 local_incoming,
00112 &scattereddir,
00113 &prob,
00114 &bsdf_value);
00115
00116 const Vector3 world_scattereddir = surfacebasis.TransformToWorld(scattereddir);
00117
00118 power *= bsdf_value * shadingdata.m_reflectance * (world_scattereddir * geometric_normal) / prob;
00119
00120
00121 ray.NewId();
00122 ray.m_origin = point + 1.0e-8 * geometric_normal;
00123 ray.m_direction = world_scattereddir;
00124 }
00125 }