00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "causticsphotontracer.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 CausticsPhotonTracer::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 specularbounce = false;
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() && specularbounce) {
00080 ++context.m_statistics->m_cpm_photons;
00081 photonmap->StorePhoton(
00082 point,
00083 power,
00084 -ray.m_direction
00085 #ifdef ENABLE_RADIANCES_PRECOMPUTATION
00086 , geometric_normal
00087 #endif
00088 );
00089 }
00090
00091 if(!shadingdata.m_bdf->IsSpecular())
00092 break;
00093
00094 specularbounce = true;
00095
00096 const Vector3 local_incoming = surfacebasis.TransformToLocal(-ray.m_direction);
00097
00098 Vector3 scattereddir;
00099 Real prob;
00100 Real bsdf_value;
00101
00102 shadingdata.m_bdf->Sample(
00103 context,
00104 local_incoming,
00105 &scattereddir,
00106 &prob,
00107 &bsdf_value);
00108
00109 const Vector3 world_scattereddir = surfacebasis.TransformToWorld(scattereddir);
00110
00111 power *= bsdf_value * shadingdata.m_reflectance * (world_scattereddir * geometric_normal) / prob;
00112
00113
00114 ray.NewId();
00115 ray.m_origin = point + 1.0e-8 * geometric_normal;
00116 ray.m_direction = world_scattereddir;
00117 }
00118 }