Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[Manta] r1868 - trunk/Engine/Renderers


Chronological Thread 
  • From: sparker@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [Manta] r1868 - trunk/Engine/Renderers
  • Date: Mon, 26 Nov 2007 07:41:20 -0700 (MST)

Author: sparker
Date: Mon Nov 26 07:40:59 2007
New Revision: 1868

Modified:
   trunk/Engine/Renderers/KajiyaPathtracer.cc
   trunk/Engine/Renderers/KajiyaPathtracer.h
Log:
Added a framework for experimenting with various pathtracing options.  
Current mode
is one bounce plus ambient.


Modified: trunk/Engine/Renderers/KajiyaPathtracer.cc
==============================================================================
--- trunk/Engine/Renderers/KajiyaPathtracer.cc  (original)
+++ trunk/Engine/Renderers/KajiyaPathtracer.cc  Mon Nov 26 07:40:59 2007
@@ -1,11 +1,6 @@
-// TODO
-// Need to determine light area and normal
-// If single pixel, use a single accumulator
-// Put background rays at end to make alignment easier - DO BACKGROUND RAYS 
ALL AT ONCE!!!
-// Try sorting after MC by direction/origin and do not sort by matl
-// shadow rays with important sampling?
-// Russian roulette for shadow rays?
+
 #include <Engine/Renderers/KajiyaPathtracer.h>
+#include <Engine/Shadows/NoDirect.h>
 #include <Interface/Background.h>
 #include <Interface/Camera.h>
 #include <Interface/Context.h>
@@ -32,6 +27,22 @@
 
 KajiyaPathtracer::KajiyaPathtracer(const vector<string>& /*args*/)
 {
+  ambient_only_sa = new NoDirect();
+  override_maxdepth = -1;
+  // No presorting, since none are implemented yet.
+  presort_mode.push_back(PreSortNone);
+
+  // Full sort on materials
+  matlsort_mode.push_back(MatlSortBackgroundSweep);
+  matlsort_mode.push_back(MatlSortSweep);
+  matlsort_mode.push_back(MatlSortFull);
+
+  // Do RR only after the first bounce
+  russian_roulette_mode.push_back(RussianRouletteNone);
+  russian_roulette_mode.push_back(RussianRouletteFull);
+
+  do_ambient_on_maxdepth = true;
+  override_maxdepth = 2;
 }
 
 KajiyaPathtracer::~KajiyaPathtracer()
@@ -63,6 +74,41 @@
   array[j] = tmp;
 }
 
+/*

+  Basic algorithm:
+
+  while there are active rays and depth < maxdepth
+    1. Pre-sort rays in the packet according to some criteria
+       Options for each depth
+       a. No sort
+       b. Sort using a space filling curve on origin (not implemented yet)
+       c. Sort using a space filling curve on direction (not implemented yet)
+       d. Sort using a space filling curve in 5D
+    2. intersect
+    3. Sort on materials, separating background rays
+       Options for each depth
+       a. Only partition out background rays
+       b. Group identical materials based on a sweep
+       c. Full sort on material
+    4. compute new rays and reflectance
+    5. compute direct light
+    6. Russian roulete to kill rays
+       Options for each depth
+       a. No russian roulette
+       b. Full russian roulette
+
+  After the loop:
+  (optional) for remaining rays, compute ambient light
+  compute background for all rays that struck the background
+
+  Presort (step 1), material sort (step 3), and russian roulette (step 4) 
can all be controlled
+  per depth with the presort, matlsort, and russian_roulette arrays, 
respectively.  Each array
+  contains an enum with the option for that depth.  If the depth is larger 
than the array, the
+  last element is used.
+
+*/
+
 void KajiyaPathtracer::traceEyeRays(const RenderContext& context, RayPacket& 
rays)
 {
   ASSERT(rays.getFlag(RayPacket::HaveImageCoordinates));
@@ -86,101 +132,78 @@
 
   RayPacketData* data = rays.data;
   int depth = 0;
-  int maxdepth = context.scene->getRenderParameters().maxDepth;
+  int maxdepth = override_maxdepth >= 0? 
override_maxdepth:context.scene->getRenderParameters().maxDepth;
   for(;;){
 
+    // 1. Pre-sort rays in the packet according to some criteria
+    PreSortMode psm = depth >= 
static_cast<int>(presort_mode.size())?presort_mode[presort_mode.size()-1]:presort_mode[depth];
+    switch(psm){
+    case PreSortOrigin:
+      presort_origin(context, rays, result, total_attenuation, permute);
+      break;
+    case PreSortDirection:
+      presort_direction(context, rays, result, total_attenuation, permute);
+      break;
+    case PreSort5D:
+      presort_5d(context, rays, result, total_attenuation, permute);
+      break;
+    case PreSortNone:
+    default:
+      // Do nothing
+      break;
+    }
+
+    // 2. intersect
     rays.resetHits();
     context.scene->getObject()->intersect(context, rays);
+    rays.computeHitPositions();
+    rays.safeComputeNormals(context);
+    rays.computeFFNormals(context); // Must do this before writing over the 
ray direction
 
-    // Sort the rays based on the material that they hit
-    // Simple bubble sort for now - performance will come later
-    // This may not be worthwhile if we sort by directions, but
-    // we would still need to sort out the background rays (one pass)
-    // Another option is to use a sort that picks one unique value and then
-    // searches for all pointers of this type.   It could probably be SSEd.
-    for(int i=rays.begin();i<rays.end()-1;i++){
-      for(int j=i+1;j<rays.end();j++){
-        if(sort_needs_swap(data, i, j)){
-          // Move hitPrim, hitMatl, hitTex, origin, direction, minT, time
-          swap(data->hitPrim, i, j);
-          swap(data->hitMatl, i, j);
-          swap(data->hitTex, i, j);
-          for(int k=0;k<3;k++)
-            swap(data->origin[k], i, j);
-          for(int k=0;k<3;k++)
-            swap(data->direction[k], i, j);
-          swap(data->minT, i, j);
-          swap(data->time, i, j);
-
-          // Conditionally: normal
-          for(int k=0;k<3;k++)
-            swap(data->normal[k], i, j);
-
-          // Conditionally: ffnormal,
-          for(int k=0;k<3;k++)
-            swap(data->ffnormal[k], i, j);
-
-          // Conditionally: hitPosition,
-          for(int k=0;k<3;k++)
-            swap(data->hitPosition[k], i, j);
-
-          // Conditionally: texCoords, dPdu, dpDv
-          for(int k=0;k<3;k++)
-            swap(data->texCoords[k], i, j);
-          for(int k=0;k<3;k++)
-            swap(data->dPdu[k], i, j);
-          for(int k=0;k<3;k++)
-            swap(data->dPdv[k], i, j);
-
-          // Move sample_id, region_id
-          swap(data->sample_id, i, j);
-          swap(data->region_id, i, j);
-
-          // Move scratchpads???
-          // Move result
-          for(int k=0;k<3;k++)
-            swap(result.colordata[k], i, j);
-
-          // Move total attenuation
-          for(int k=0;k<3;k++)
-            swap(total_attenuation.colordata[k], i, j);
-
-          // Move permute
-          swap(permute.data, i, j);
-        }
-      }
+    // 3. Sort on materials, separating background rays
+    MatlSortMode msm = depth >= 
static_cast<int>(matlsort_mode.size())?matlsort_mode[matlsort_mode.size()-1]:matlsort_mode[depth];
+    switch(msm){
+    case MatlSortSweep:
+      matlsort_sweep(context, rays, result, total_attenuation, reflectance, 
permute);
+      break;
+    case MatlSortFull:
+      matlsort_full(context, rays, result, total_attenuation, permute);
+      break;
+    case MatlSortBackgroundSweep:
+    default:
+      matlsort_bgsweep(context, rays, result, total_attenuation, permute);
+      break;
     }
-    // Skip background rays - they will be shaded all at once below
-    int newBegin = rays.begin();
-    while(!rays.wasHit(newBegin))
-      newBegin++;
-    rays.resize(newBegin, rays.end());
     if(rays.begin() == rays.end())
       break;
-
-    // Clear inverseDirection, corner_dir, signs
-    rays.flags &= ~(RayPacket::HaveCornerRays | 
RayPacket::HaveInverseDirections | RayPacket::HaveSigns);
-
-    rays.computeHitPositions();
-    rays.computeFFNormals(context); // Must do this before writing over the 
ray direction
-
-    // Compute new rays and reflectance for anything that hit a surface
-    for(int i = rays.begin();i<rays.end();){
-      const Material* hit_matl = rays.getHitMaterial(i);
-      int end = i+1;
-      while(end < rays.end() &&  rays.getHitMaterial(end) == hit_matl)
-        end++;
-      RayPacket subPacket(rays, i, end);
-      hit_matl->sampleBSDF(context, subPacket, reflectance);
-      i=end;
+      
+    // 4. compute new rays and reflectance
+    // For MatlSortSweep, this was already done simultaneous with sorting
+    if(msm != MatlSortSweep){
+      for(int i = rays.begin();i<rays.end();){
+        const Material* hit_matl = rays.getHitMaterial(i);
+        int end = i+1;
+        while(end < rays.end() &&  rays.getHitMaterial(end) == hit_matl)
+          end++;
+        RayPacket subPacket(rays, i, end);
+        hit_matl->sampleBSDF(context, subPacket, reflectance);
+        i=end;
+      }
     }
 
+    // Propagate reflectance
     for(int i=rays.begin();i<rays.end();i++){
       for(int j=0;j<3;j++)
         total_attenuation.colordata[j][i] *= reflectance.colordata[j][i];
     }
 
-    // Cast shadow rays
+    rays.flags &= ~(RayPacket::HaveCornerRays | 
RayPacket::HaveInverseDirections | RayPacket::HaveSigns);
+    // For now, assume that the rays coming out of sampleBSDF are unit 
length.  With
+    // transformations, this may not be true, so consider gathering the unit 
length
+    // flags from sampleBSDF above
+    rays.flags |= RayPacket::NormalizedDirections;
+
+    // 5. compute direct light
     ShadowAlgorithm::StateBuffer shadowState;
     do {
       RayPacketData shadowData;
@@ -200,7 +223,6 @@
           // Not in shadow, so compute the direct lighting contributions.
           Vector normal = rays.getFFNormal(i);
           Vector light_dir = shadowRays.getDirection(i);
-          light_dir.normalize();
           double weight=Dot(normal, light_dir);
           Color light_color = shadowRays.getColor(i);
           result.set(i, result.get(i) + total_attenuation.get(i) * 
light_color * weight);
@@ -208,83 +230,50 @@
       }
     } while(!shadowState.done());
 
-    // Russian roulette and collapse
-    bool do_russian_roulette = (depth > 0);
-    if(do_russian_roulette){
-      Packet<Real> rr;
-      context.sample_generator->nextSeeds(context, rr, rays);
-      int newEnd = rays.end();
-      for(int i=rays.begin();i<newEnd;i++){
-        double max = reflectance.get(i).maxComponent();
-        if(rr.get(i) > max){
-          // Kill it by swapping with the last ray
-          // We may not need to move origin/direction back....
-          --newEnd;
-          // Move origin, direction
-          // Look at one-way move optimization
-          for(int j=0;j<3;j++)
-            swap(data->origin[j], i, newEnd);
-          for(int j=0;j<3;j++)
-            swap(data->direction[j], i, newEnd);
-          
-          // Move ffnormal
-          for(int j=0;j<3;j++)
-            swap(data->ffnormal[j], i, newEnd);
-
-          // Move hitPosition
-          for(int j=0;j<3;j++)
-            swap(data->hitPosition[j], i, newEnd);
-
-          // Move time
-          // Look at one-way move optimization
-          swap(data->time, i, newEnd);
-          
-          // Move sample_id, region_id
-          // Look at one-way move optimization
-          swap(data->sample_id, i, newEnd);
-          swap(data->region_id, i, newEnd);
-          
-          // Move result
-          for(int j=0;j<3;j++)
-            swap(result.colordata[j], i, newEnd);
-          
-          // Move reflectance
-          // Look at one-way move optimization
-          for(int j=0;j<3;j++)
-            swap(reflectance.colordata[j], i, newEnd);
-          
-          // Move total attenuation
-          // Look at one-way move optimization
-          for(int j=0;j<3;j++)
-            swap(total_attenuation.colordata[j], i, newEnd);
-          
-          // Move rr
-          // Look at one-way move optimization
-          swap(rr.data, i, newEnd);
-
-          // Move permute
-          swap(permute.data, i, newEnd);
-
-          --i;
-        } else {
-          Real scale = Real(1.)/max;
-          for(int j=0;j<3;j++)
-            reflectance.colordata[j][i] *= scale;
-          for(int j=0;j<3;j++)
-            total_attenuation.colordata[j][i] *= scale;
-        }
-      
-        rays.resize(rays.begin(), newEnd);
-        if(rays.begin() == rays.end())
-          break;
-      }
+    // 6. Russian roulete to kill rays
+    RussianRouletteMode rrm = depth >= 
static_cast<int>(russian_roulette_mode.size())?russian_roulette_mode[russian_roulette_mode.size()-1]:russian_roulette_mode[depth];
+    switch(rrm){
+    case RussianRouletteFull:
+      if(depth != maxdepth-1)
+        russian_roulette_full(context, rays, result, total_attenuation, 
reflectance, permute);
+      break;
+    case RussianRouletteNone:
+    default:
+      // Do nothing
+      break;
     }
+    if(rays.begin() == rays.end())
+      break;
 
     depth++;
     if(depth >= maxdepth)
       break;
 
-    rays.flags &= RayPacket::ConstantEye |  RayPacket::ConstantPixel | 
RayPacket::ConstantSampleRegion;
+    rays.flags &= RayPacket::ConstantEye |  RayPacket::ConstantPixel | 
RayPacket::ConstantSampleRegion | RayPacket::NormalizedDirections;
+    rays.shape = RayPacket::UnknownShape;
+  }
+
+  // Add ambient contribution for any remaining rays
+  if(do_ambient_on_maxdepth){
+    // Should there be an option here for doing a sweep/sort on the 
remaining rays???
+    ShadowAlgorithm* save_sa = context.shadowAlgorithm;
+    // Sneaky ugly cast-away-const.  Consider making RenderContext not const 
for this reason
+    const_cast<RenderContext&>(context).shadowAlgorithm = ambient_only_sa;
+    for(int i = rays.begin();i<rays.end();){
+      const Material* hit_matl = rays.getHitMaterial(i);
+      int end = i+1;
+      while(end < rays.end() &&  rays.getHitMaterial(end) == hit_matl)
+        end++;
+      RayPacket subPacket(rays, i, end);
+      hit_matl->shade(context, subPacket);
+      i=end;
+    }
+    const_cast<RenderContext&>(context).shadowAlgorithm = save_sa;
+    
+    for(int i = rays.begin(); i < rays.end(); i++){
+      for(int j=0;j<3;j++)
+        result.colordata[j][i] += data->color[j][i] * 
total_attenuation.colordata[j][i];
+    }
   }
 
   // Add contribution from background rays, which will be at the beginning.  
 
@@ -301,13 +290,336 @@
   rays.resetHits();
   rays.flags &= RayPacket::ConstantEye |  RayPacket::ConstantPixel | 
RayPacket::ConstantSampleRegion;
   rays.flags |= RayPacket::NormalizedDirections;
-  rays.shape = RayPacket::UnknownShape;
 
   for(int i=rays.begin();i<rays.end();i++){
     rays.setColor(permute.get(i), result.get(i));
   }
 
 }
+
+void KajiyaPathtracer::matlsort_full(const RenderContext& context, 
RayPacket& rays,
+                                      Packet<Color>& result,
+                                      Packet<Color>& total_attenuation,
+                                      Packet<int>& permute)
+{
+  // Sort the rays based on the material that they hit
+  // Simple bubble sort for now - performance will come later
+  // This may not be worthwhile if we sort by directions, but
+  // we would still need to sort out the background rays (one pass)
+  // Another option is to use a sort that picks one unique value and then
+  // searches for all pointers of this type.   It could probably be SSEd.
+  RayPacketData* data = rays.data;
+  for(int i=rays.begin();i<rays.end()-1;i++){
+    for(int j=i+1;j<rays.end();j++){
+      if(sort_needs_swap(data, i, j)){
+        // Move hitPrim, hitMatl, hitTex, origin, direction, minT, time
+        swap(data->hitPrim, i, j);
+        swap(data->hitMatl, i, j);
+        swap(data->hitTex, i, j);
+        for(int k=0;k<3;k++)
+          swap(data->origin[k], i, j);
+        for(int k=0;k<3;k++)
+          swap(data->direction[k], i, j);
+        swap(data->minT, i, j);
+        swap(data->time, i, j);
+
+        // Conditionally: normal
+        for(int k=0;k<3;k++)
+          swap(data->normal[k], i, j);
+
+        // Conditionally: ffnormal,
+        for(int k=0;k<3;k++)
+          swap(data->ffnormal[k], i, j);
+
+        // Conditionally: hitPosition,
+        for(int k=0;k<3;k++)
+          swap(data->hitPosition[k], i, j);
+
+        // Conditionally: texCoords, dPdu, dpDv
+        // Perhaps these do not need to be moved???
+        for(int k=0;k<3;k++)
+          swap(data->texCoords[k], i, j);
+        for(int k=0;k<3;k++)
+          swap(data->dPdu[k], i, j);
+        for(int k=0;k<3;k++)
+          swap(data->dPdv[k], i, j);
+        
+        // Move sample_id, region_id
+        swap(data->sample_id, i, j);
+        swap(data->region_id, i, j);
+
+        // Move result
+        for(int k=0;k<3;k++)
+          swap(result.colordata[k], i, j);
+
+        // Move total attenuation
+        for(int k=0;k<3;k++)
+          swap(total_attenuation.colordata[k], i, j);
+
+        // Move permute
+        swap(permute.data, i, j);
+      }
+    }
+  }
+  // Pull out background rays - they will be shaded all at once below
+  int newBegin = rays.begin();
+  while(newBegin < rays.end() && !rays.wasHit(newBegin))
+    newBegin++;
+  rays.resize(newBegin, rays.end());
+}
+
+void KajiyaPathtracer::russian_roulette_full(const RenderContext& context, 
RayPacket& rays,
+                                             Packet<Color>& result,
+                                             Packet<Color>& 
total_attenuation,
+                                             Packet<Color>& reflectance,
+                                             Packet<int>& permute)
+{
+  Packet<Real> rr;
+  context.sample_generator->nextSeeds(context, rr, rays);
+  RayPacketData* data = rays.data;
+
+  int newEnd = rays.end()-1;
+  while(newEnd >= rays.begin() && rr.get(newEnd) >= 
reflectance.get(newEnd).maxComponent())
+    newEnd--;
+  
+  for(int i=rays.begin();i<=newEnd;i++){
+    double max = reflectance.get(i).maxComponent();
+    if(rr.get(i) > max){
+      // Kill it by swapping with the last ray
+      // We may not need to move origin/direction back....
+      // Move origin, direction
+      // Look at one-way move optimization
+      for(int j=0;j<3;j++)
+        swap(data->origin[j], i, newEnd);
+      for(int j=0;j<3;j++)
+        swap(data->direction[j], i, newEnd);
+      
+      // Move ffnormal
+      for(int j=0;j<3;j++)
+        swap(data->ffnormal[j], i, newEnd);
+
+      // Move hitPosition
+      for(int j=0;j<3;j++)
+        swap(data->hitPosition[j], i, newEnd);
+
+      // Move time
+      // Look at one-way move optimization
+      swap(data->time, i, newEnd);
+          
+      // Move sample_id, region_id
+      // Look at one-way move optimization
+      swap(data->sample_id, i, newEnd);
+      swap(data->region_id, i, newEnd);
+          
+      // Move result
+      for(int j=0;j<3;j++)
+        swap(result.colordata[j], i, newEnd);
+      
+      // Move reflectance
+      // Look at one-way move optimization
+      for(int j=0;j<3;j++)
+        swap(reflectance.colordata[j], i, newEnd);
+          
+      // Move total attenuation
+      // Look at one-way move optimization
+      for(int j=0;j<3;j++)
+        swap(total_attenuation.colordata[j], i, newEnd);
+          
+      // Move rr
+      // Look at one-way move optimization
+      swap(rr.data, i, newEnd);
+
+      // Move permute
+      swap(permute.data, i, newEnd);
+
+      i--;
+      newEnd--;
+      while(newEnd > i && rr.get(newEnd) >= 
reflectance.get(newEnd).maxComponent())
+        newEnd--;
+    }
+  }
+  for(int i=newEnd+1;i<rays.end();i++){
+    float max = reflectance.get(i).maxComponent();
+    Real scale = Real(1.)/max;
+    for(int j=0;j<3;j++)
+      reflectance.colordata[j][i] *= scale;
+    for(int j=0;j<3;j++)
+      total_attenuation.colordata[j][i] *= scale;
+  }
+
+  rays.resize(rays.begin(), newEnd+1);
+}
+
+void KajiyaPathtracer::presort_origin(const RenderContext&, RayPacket&, 
Packet<Color>&, Packet<Color>&, Packet<int>&)
+{
+  NOT_FINISHED("KajiyaPathtracer::traceEyeRays");
+}
+
+void KajiyaPathtracer::matlsort_sweep(const RenderContext& context, 
RayPacket& rays,
+                                      Packet<Color>& result,
+                                      Packet<Color>& total_attenuation,
+                                      Packet<Color>& reflectance,
+                                      Packet<int>& permute)
+{
+  matlsort_bgsweep(context, rays, result, total_attenuation, permute);
+  // Sort the rays into two groups - those that hit an object
+  // and those that hit the background.  The background rays should
+  // be first, so those are processed first by the bgsweep.
+  // Technically, this is O(N^2), but if there are relatively few unique
+  // materials in an average packet, this should perform pretty well.
+  // We try to minimize movement of rays wherever possible.
+  RayPacketData* data = rays.data;
+  for(int i=rays.begin(); i < rays.end();){
+    const Material* matl = data->hitMatl[i];
+    int begin = i;
+    i++;
+
+    // Skip to find the next hole
+    while(i < rays.end() && data->hitMatl[i] == matl)
+      i++;
+
+    // Find any other rays that also hit that material.  Start from the end 
so that
+    // We can fill in gaps and minimize the total number of moves in many 
cases
+    for(int j=rays.end()-1;j>=i+1;j--){
+      // Skip over all of the rays that hit the same material
+      if(data->hitMatl[j] == matl){
+        // Move hitPrim, hitMatl, hitTex, origin, direction, minT, time
+        swap(data->hitPrim, i, j);
+        swap(data->hitMatl, i, j);
+        swap(data->hitTex, i, j);
+        for(int k=0;k<3;k++)
+          swap(data->origin[k], i, j);
+        for(int k=0;k<3;k++)
+          swap(data->direction[k], i, j);
+        swap(data->minT, i, j);
+        swap(data->time, i, j);
+
+        // Conditionally: normal
+        for(int k=0;k<3;k++)
+          swap(data->normal[k], i, j);
+
+        // Conditionally: ffnormal,
+        for(int k=0;k<3;k++)
+          swap(data->ffnormal[k], i, j);
+
+        // Conditionally: hitPosition,
+        for(int k=0;k<3;k++)
+          swap(data->hitPosition[k], i, j);
+
+        // Conditionally: texCoords, dPdu, dpDv
+        // Perhaps these do not need to be moved???
+        for(int k=0;k<3;k++)
+          swap(data->texCoords[k], i, j);
+        for(int k=0;k<3;k++)
+          swap(data->dPdu[k], i, j);
+        for(int k=0;k<3;k++)
+          swap(data->dPdv[k], i, j);
+        
+        // Move sample_id, region_id
+        swap(data->sample_id, i, j);
+        swap(data->region_id, i, j);
+
+        // Move result
+        for(int k=0;k<3;k++)
+          swap(result.colordata[k], i, j);
+
+        // Move total attenuation
+        for(int k=0;k<3;k++)
+          swap(total_attenuation.colordata[k], i, j);
+
+        // Move permute
+        swap(permute.data, i, j);
+        i++;
+        // Find another hole
+        while(i <= j && data->hitMatl[i] == matl)
+          i++;
+      }
+    }
+    RayPacket subPacket(rays, begin, i);
+    matl->sampleBSDF(context, subPacket, reflectance);
+  }
+}
+
+void KajiyaPathtracer::presort_direction(const RenderContext&, RayPacket&, 
Packet<Color>&, Packet<Color>&, Packet<int>&)
+{
+  NOT_FINISHED("KajiyaPathtracer::presort_direction");
+}
+
+void KajiyaPathtracer::presort_5d(const RenderContext&, RayPacket&, 
Packet<Color>&, Packet<Color>&, Packet<int>&)
+{
+  NOT_FINISHED("KajiyaPathtracer::presort_5d");
+}
+
+void KajiyaPathtracer::matlsort_bgsweep(const RenderContext&, RayPacket& 
rays,
+                                        Packet<Color>& result,
+                                        Packet<Color>& total_attenuation,
+                                        Packet<int>& permute)
+{
+  // Sort the rays into two groups - those that hit an object
+  // and those that hit the background.  The background rays should
+  // be first, so we start and the end and push rays to the beginning
+  // that did not hit anything
+  RayPacketData* data = rays.data;
+  int newBegin = rays.begin();
+  while(!data->hitMatl[newBegin] && newBegin < rays.end())
+    newBegin++;
+  for(int i=rays.end()-1;i>=newBegin;i--){
+    if(!data->hitMatl[i]){
+      // Move hitPrim, hitMatl, hitTex, origin, direction, minT, time
+      swap(data->hitPrim, i, newBegin);
+      swap(data->hitMatl, i, newBegin);
+      swap(data->hitTex, i, newBegin);
+      for(int k=0;k<3;k++)
+        swap(data->origin[k], i, newBegin);
+      for(int k=0;k<3;k++)
+        swap(data->direction[k], i, newBegin);
+      swap(data->minT, i, newBegin);
+      swap(data->time, i, newBegin);
+
+      // Conditionally: normal
+      for(int k=0;k<3;k++)
+        swap(data->normal[k], i, newBegin);
+
+      // Conditionally: ffnormal,
+      for(int k=0;k<3;k++)
+        swap(data->ffnormal[k], i, newBegin);
+
+      // Conditionally: hitPosition,
+      for(int k=0;k<3;k++)
+        swap(data->hitPosition[k], i, newBegin);
+
+      // Conditionally: texCoords, dPdu, dpDv
+      // Perhaps these do not need to be moved???
+      for(int k=0;k<3;k++)
+        swap(data->texCoords[k], i, newBegin);
+      for(int k=0;k<3;k++)
+        swap(data->dPdu[k], i, newBegin);
+      for(int k=0;k<3;k++)
+        swap(data->dPdv[k], i, newBegin);
+        
+      // Move sample_id, region_id
+      swap(data->sample_id, i, newBegin);
+      swap(data->region_id, i, newBegin);
+
+      // Move result
+      for(int k=0;k<3;k++)
+        swap(result.colordata[k], i, newBegin);
+
+      // Move total attenuation
+      for(int k=0;k<3;k++)
+        swap(total_attenuation.colordata[k], i, newBegin);
+
+      // Move permute
+      swap(permute.data, i, newBegin);
+      newBegin++;
+      while(!data->hitMatl[newBegin] && newBegin < i)
+        newBegin++;
+      i++;
+    }
+  }
+  rays.resize(newBegin, rays.end());
+}
+
 
 void KajiyaPathtracer::traceRays(const RenderContext& context, RayPacket& 
rays)
 {

Modified: trunk/Engine/Renderers/KajiyaPathtracer.h
==============================================================================
--- trunk/Engine/Renderers/KajiyaPathtracer.h   (original)
+++ trunk/Engine/Renderers/KajiyaPathtracer.h   Mon Nov 26 07:40:59 2007
@@ -3,6 +3,7 @@
 #define Manta_Engine_KajiyaPathtracer_h
 
 #include <Interface/Renderer.h>
+#include <Interface/Packet.h>
 #include <sgi_stl_warnings_off.h>
 #include <string>
 #include <vector>
@@ -14,6 +15,16 @@
 
   class KajiyaPathtracer : public Renderer {
   public:
+    enum PreSortMode {
+      PreSortNone, PreSortDirection, PreSortOrigin, PreSort5D
+    };
+    enum MatlSortMode {
+      MatlSortBackgroundSweep, MatlSortSweep, MatlSortFull
+    };
+    enum RussianRouletteMode {
+      RussianRouletteNone, RussianRouletteFull
+    };
+
     KajiyaPathtracer() {}
     KajiyaPathtracer(const vector<string>& args);
     virtual ~KajiyaPathtracer();
@@ -29,6 +40,31 @@
   private:
     KajiyaPathtracer(const KajiyaPathtracer&);
     KajiyaPathtracer& operator=(const KajiyaPathtracer&);
+
+    std::vector<PreSortMode> presort_mode;
+    std::vector<MatlSortMode> matlsort_mode;
+    std::vector<RussianRouletteMode> russian_roulette_mode;
+    ShadowAlgorithm* ambient_only_sa;
+    int override_maxdepth;
+    bool do_ambient_on_maxdepth;
+
+    void presort_origin(const RenderContext& context, RayPacket& rays, 
Packet<Color>& result,
+                        Packet<Color>& total_attenuation, Packet<int>& 
permute);
+    void presort_direction(const RenderContext& context, RayPacket& rays, 
Packet<Color>& result,
+                           Packet<Color>& total_attenuation, Packet<int>& 
permute);
+    void presort_5d(const RenderContext& context, RayPacket& rays, 
Packet<Color>& result,
+                    Packet<Color>& total_attenuation, Packet<int>& permute);
+
+    void matlsort_sweep(const RenderContext& context, RayPacket& rays, 
Packet<Color>& result,
+                        Packet<Color>& total_attenuation, Packet<Color>& 
reflectance, Packet<int>& permute);
+    void matlsort_bgsweep(const RenderContext& context, RayPacket& rays,  
Packet<Color>& result,
+                          Packet<Color>& total_attenuation, Packet<int>& 
permute);
+    void matlsort_full(const RenderContext& context, RayPacket& rays, 
Packet<Color>& result,
+                       Packet<Color>& total_attenuation, Packet<int>& 
permute);
+
+    void russian_roulette_full(const RenderContext& context, RayPacket& 
rays, Packet<Color>& result,
+                               Packet<Color>& total_attenuation, 
Packet<Color>& reflectance,
+                               Packet<int>& permute);
   };
 }
 




  • [Manta] r1868 - trunk/Engine/Renderers, sparker, 11/26/2007

Archive powered by MHonArc 2.6.16.

Top of page