Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r472 - trunk/Engine/ImageTraversers


Chronological Thread 
  • From: bigler@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r472 - trunk/Engine/ImageTraversers
  • Date: Mon, 15 Aug 2005 22:05:09 -0600 (MDT)

Author: bigler
Date: Mon Aug 15 22:05:07 2005
New Revision: 472

Added:
   trunk/Engine/ImageTraversers/DissolveTiledImageTraverser.cc
   trunk/Engine/ImageTraversers/DissolveTiledImageTraverser.h
Modified:
   trunk/Engine/ImageTraversers/DissolveImageTraverser.cc
Log:

DissolveImageTraverser.cc

  Make MaskValues a non global static variable.

DissolveTiledImageTraverser.cc
DissolveTiledImageTraverser.h

  Variation on DissolveImageTraverser that breaks up the image into
  tiles and attemps to render them in a pseudo random order.  This
  code doesn't quite work yet, but it won't be compiled by default.





Modified: trunk/Engine/ImageTraversers/DissolveImageTraverser.cc
==============================================================================
--- trunk/Engine/ImageTraversers/DissolveImageTraverser.cc      (original)
+++ trunk/Engine/ImageTraversers/DissolveImageTraverser.cc      Mon Aug 15 
22:05:07 2005
@@ -16,7 +16,7 @@
 using SCIRun::InternalError;
 
 // Use this mask to produce values from 1 to N (in the comments)
-unsigned int MaskValues[] = {
+static unsigned int MaskValues[] = {
   /* 00 */       0x00,  //             0
   /* 01 */       0x01,  //             1
   /* 02 */       0x03,  //             3

Added: trunk/Engine/ImageTraversers/DissolveTiledImageTraverser.cc
==============================================================================
--- (empty file)
+++ trunk/Engine/ImageTraversers/DissolveTiledImageTraverser.cc Mon Aug 15 
22:05:07 2005
@@ -0,0 +1,225 @@
+
+#include <Engine/ImageTraversers/DissolveTiledImageTraverser.h>
+#include <Core/Exceptions/IllegalArgument.h>
+#include <Core/Exceptions/InternalError.h>
+#include <Core/Util/Args.h>
+#include <Interface/Context.h>
+#include <Interface/FrameState.h>
+#include <Interface/Fragment.h>
+#include <Interface/Image.h>
+#include <Interface/LoadBalancer.h>
+#include <Interface/PixelSampler.h>
+#include <Core/Thread/Mutex.h>
+#include <Core/Util/NotFinished.h>
+
+using namespace Manta;
+using SCIRun::InternalError;
+
+// Use this mask to produce values from 1 to N (in the comments)
+static unsigned int MaskValues[] = {
+  /* 00 */       0x00,  //             0
+  /* 01 */       0x01,  //             1
+  /* 02 */       0x03,  //             3
+  /* 03 */       0x06,  //             7
+  /* 04 */       0x0C,  //            15
+  /* 05 */       0x14,  //            31
+  /* 06 */       0x30,  //            63
+  /* 07 */       0x60,  //           127
+  /* 08 */       0xB8,  //           255
+  /* 09 */     0x0110,  //           511
+  /* 10 */     0x0240,  //         1,023
+  /* 11 */     0x0500,  //         2,047
+  /* 12 */     0x0CA0,  //         4,095
+  /* 13 */     0x1B00,  //         8,191
+  /* 14 */     0x3500,  //        16,383
+  /* 15 */     0x6000,  //        32,767
+  /* 16 */     0xB400,  //        65,535
+  /* 17 */ 0x00012000,  //       131,071
+  /* 18 */ 0x00020400,  //       262,143
+  /* 19 */ 0x00072000,  //       524,287
+  /* 20 */ 0x00090000,  //     1,048,575
+  /* 21 */ 0x00140000,  //     2,097,151
+  /* 22 */ 0x00300000,  //     4,194,303
+  /* 23 */ 0x00400000,  //     8,388,607
+  /* 24 */ 0x00D80000,  //    16,777,215
+  /* 25 */ 0x01200000,  //    33,554,431
+  /* 26 */ 0x03880000,  //    67,108,863
+  /* 27 */ 0x07200000,  //   134,217,727
+  /* 28 */ 0x09000000,  //   268,435,575
+  /* 29 */ 0x14000000,  //   536,870,911
+  /* 30 */ 0x32800000,  // 1,073,741,823
+  /* 31 */ 0x48000000,  // 2,147,483,647
+  /* 32 */ 0xA3000000   // 4,294,967,295
+};
+
+ImageTraverser* DissolveTiledImageTraverser::create(const vector<string>& 
args)
+{
+  return new DissolveTiledImageTraverser(args);
+}
+
+DissolveTiledImageTraverser::DissolveTiledImageTraverser(const 
vector<string>& args):
+  xtilesize(32), ytilesize(2), iters_per_frame(16)
+{
+  int argc = static_cast<int>(args.size());
+  for(int i = 0; i<argc;i++){
+    string arg = args[i];
+    if(arg == "-itersPerFrame"){
+      if(!getArg<unsigned int>(i, args, iters_per_frame))
+       throw IllegalArgument("DissolveTiledImageTraverser -itersPerFrame",
+                              i, args);
+      if (iters_per_frame < 1)
+        throw IllegalArgument("-itersPerFrame must be greater than 0",
+                              i, args);
+    if(arg == "-tilesize"){
+      if(!getResolutionArg(i, args, xtilesize, ytilesize))
+       throw IllegalArgument("TiledImageTraverser -tilesize", i, args);
+    } else {
+      throw IllegalArgument("DissolveTiledImageTraverser", i, args);
+    }
+  }
+}
+
+DissolveTiledImageTraverser::~DissolveTiledImageTraverser()
+{
+}
+
+void DissolveTiledImageTraverser::setupBegin(SetupContext& context, int 
numChannels)
+{
+  per_thread_data.resize(context.numProcs);
+  for(size_t i = 0; i < per_thread_data.size(); i++) {
+    per_thread_data[i].channel_data.resize(numChannels);
+  }
+
+  context.pixelSampler->setupBegin(context, numChannels);
+}
+
+void DissolveTiledImageTraverser::setupDisplayChannel(SetupContext& context)
+{
+  bool stereo;
+  int xres, yres;
+  context.getResolution(stereo, xres, yres);
+
+  // Figure out how many tiles we have
+  unsigned int xtiles = (xres + xtilesize-1)/xtilesize;
+  unsigned int ytiles = (yres + ytilesize-1)/ytilesize;
+  unsigned int numAssignments = xtiles * ytiles;
+
+  // Try an educated guess for the tiles per sample
+  unsigned int tiles_per_pass =
+    (xtiles*ytiles)/context.numProcs/iters_per_frame;
+
+  // Compute the mask
+  unsigned int num_x_bits = numBinaryDigits(xres-1);
+  unsigned int num_y_bits = numBinaryDigits(yres-1);
+  unsigned int num_all_bits = num_x_bits + num_y_bits;
+  if (num_all_bits > 32)
+    throw 
InternalError("DissolveTiledImageTraverser::setupDisplayChannel::number of 
bits needed for random number exceeds 32", __FILE__, __LINE__);
+
+  ChannelContext& cdata = channel_data[context.channelIndex];
+  cdata.mask = MaskValues[num_all_bits];
+  cdata.num_y_bits = num_y_bits;
+  cdata.y_bit_mask = (1 << num_y_bits) - 1;
+  
+  // Reset the starting pixel
+  unsigned int next_pixel = 1;
+  per_thread_data[0].next_pixel[context.channelIndex] = next_pixel;
+  for(size_t i = 1; i < per_thread_data.size(); i++) {
+    int x,y;
+    do {
+      computeNextSample(next_pixel, cdata.mask);
+      x = next_pixel >> cdata.num_y_bits;
+      y = next_pixel &  cdata.y_bit_mask;
+    } while (x >= xres || y >= yres);
+    per_thread_data[i].next_pixel[context.channelIndex] = next_pixel;
+  }
+  
+  // Single bufferd, please.
+  context.constrainPipelineDepth(1,1);
+
+  //  context.loadBalancer->setupDisplayChannel(context, numAssignments);
+  context.pixelSampler->setupDisplayChannel(context);
+}
+
+void DissolveTiledImageTraverser::setupFrame(const RenderContext& context)
+{
+  //  context.loadBalancer->setupFrame(context);
+  context.pixelSampler->setupFrame(context);
+}
+
+void DissolveTiledImageTraverser::renderImage(const RenderContext& context,
+                                         Image* image)
+{
+  bool stereo;
+  int xres, yres;
+  image->getResolution(stereo, xres, yres);
+
+  // Pull out needed parameters for this frame based on the channel
+  // and the processor index.
+  unsigned int next_pixel = 
per_thread_data[context.proc].next_pixel[context.channelIndex];
+  ChannelContext& cdata = channel_data[context.channelIndex];
+
+  Fragment frag;
+  frag.setFlags(Fragment::ConstantEye);
+  unsigned int pixel = 0;
+  // We need to render the (0,0) pixel every once in a while, so see
+  // if we are the last processor and if we've gone through so many
+  // frames.
+  if (context.proc == context.numProcs-1 &&
+      context.frameState->frameNumber%iters_per_frame == 0) {
+    frag.addElement(0,0,0);
+    // In order to make sure the compute the same number of pixels per
+    // iteration pixel should not be incremented.
+    pixel++;
+  }
+  while ( pixel < pixels_per_pass ) {
+    int x = next_pixel >> cdata.num_y_bits;
+    int y = next_pixel &  cdata.y_bit_mask;
+    if (x < xres && y < yres) {
+      // This is a good pixel so let's add it.
+      pixel++;
+      frag.addElement(x, y, 0);
+      if(stereo){
+        // I'm not sure you want to do stereo
+      }
+      // Check to see if your fragment is full.  If it is, then render it.
+      if (frag.getSize() == Fragment::MaxFragmentSize) {
+        context.pixelSampler->renderFragment(context, frag);
+#if 0
+        for(int f = 0; f < frag.getSize(); f++)
+          switch (context.proc) {
+          case 0: frag.setColor(f, Color(RGBColor(1,0,0))); break;
+          case 1: frag.setColor(f, Color(RGBColor(0,0,1))); break;
+          case 2: frag.setColor(f, Color(RGBColor(0,1,0))); break;
+          case 3: frag.setColor(f, Color(RGBColor(1,1,0))); break;
+          }
+#endif
+        image->set(frag);
+        // Reset the Fragment, so we can start filling it up again.
+        frag.resetSize();
+      }
+    }
+    // Generate the next pixel.  But we need to find the Nth good
+    // pixel, so only count pixels if we find them.
+    for(int i = 0; i < context.numProcs;) {
+      computeNextSample(next_pixel, cdata.mask);
+      int x = next_pixel >> cdata.num_y_bits;
+      int y = next_pixel &  cdata.y_bit_mask;
+      // Found a good pixel, so find the next one.
+      if (x < xres && y < yres) i++;
+    }
+  }
+  // Pick up strays
+  if (frag.getSize()) {
+    context.pixelSampler->renderFragment(context, frag);
+    image->set(frag);
+  }
+
+  // Stash out next_pixel for the next iteration of the frame.
+  per_thread_data[context.proc].next_pixel[context.channelIndex] = 
next_pixel;
+
+  // This can potentially happen before the other procesors are finished
+  // rendering, but that is okay because it won't get displayed until
+  // everyone enters the barrier anyway
+  if(context.proc == 0)
+    image->setValid(true);
+}

Added: trunk/Engine/ImageTraversers/DissolveTiledImageTraverser.h
==============================================================================
--- (empty file)
+++ trunk/Engine/ImageTraversers/DissolveTiledImageTraverser.h  Mon Aug 15 
22:05:07 2005
@@ -0,0 +1,111 @@
+/*
+  DissolveTiledImageTraverser
+
+  A frameless rendering image traverser.  It attemps to use a pseudo
+  random number generator with variable period to eventually fill the
+  screen.  The pixel locations are not precomputed but rather computed
+  when needed.  The technique is based on the article "A Digital
+  "Dissolve" Effect" by Mike Morton found in Graphics Gems I
+  (pg. 221-232).
+
+  There are some interesting things about this method.  First for N
+  processors, ever Nth pixel is computed by each thread.  Once the
+  period of the random number generator has been reached it starts
+  over (but not necessarily from the same point).  The net effect is
+  that a single processor can do a different set of pixels the next
+  full frame.  I'm not entirely sure what the implications are for
+  over drawing of pixels, but it looks OK for now.
+  
+  Author: James Bigler
+  Date: Aug. 2005
+
+*/
+
+#ifndef Manta_Engine_DissolveTiledImageTraverser_h
+#define Manta_Engine_DissolveTiledImageTraverser_h
+
+#include <Interface/ImageTraverser.h>
+#include <sgi_stl_warnings_off.h>
+#include <string>
+#include <vector>
+#include <sgi_stl_warnings_on.h>
+
+namespace Manta {
+  using namespace std;
+  class DissolveTiledImageTraverser : public ImageTraverser {
+  public:
+    DissolveTiledImageTraverser(const vector<string>& args);
+    virtual ~DissolveTiledImageTraverser();
+    virtual void setupBegin(SetupContext&, int numChannels);
+    virtual void setupDisplayChannel(SetupContext&);
+    virtual void setupFrame(const RenderContext& context);
+    virtual void renderImage(const RenderContext& context, Image* image);
+
+    static ImageTraverser* create(const vector<string>& args);
+  private:
+    DissolveTiledImageTraverser(const DissolveTiledImageTraverser&);
+    DissolveTiledImageTraverser& operator=(const 
DissolveTiledImageTraverser&);
+
+    int xtilesize;
+    int ytilesize;
+
+    // Since this is a "framed" version of a frameless method, we
+    // attempt to only do a subset of the work required for a frame.
+    // This tells us how many frames are needed to fill a frame.
+    unsigned int iters_per_frame;
+
+    struct ChannelContext {
+      // This is the mask for the random number generator.
+      unsigned int rng_mask;
+      // Which tile to start on next (since this is a framed
+      // implementation).
+      unsigned int next_tile;
+      // This tells us how many tiles to work on for a given thread/context
+      unsigned int numTiles;
+      // This is how many tiles to render on a call to renderImage.  It
+      // is based on the number of iters_per_pass, threads, and pixels
+      // contained in the channels.
+      unsigned int tiles_per_pass;
+    };
+    
+    // Each thread stores where it left off for each channel.
+    struct ThreadContext {
+      vector<ChannelContext> channel_data; // size = numChannels
+    };
+
+    vector<ThreadContext> per_thread_data; // size = numProcs
+
+//     // This is the information needed to produce the next random
+//     // number.  Since the masks are based on the size of the channel,
+//     // each channel must maintain its own set of masks to allow for
+//     // varying sizes of channels.
+//     struct ChannelContext {
+//       unsigned int mask;
+//       unsigned int num_y_bits;
+//       unsigned int y_bit_mask;
+//     };
+//     // channel_masks.size() == numChannels
+//     vector<ChannelContext> channel_data;
+    
+    inline void computeNextSample(unsigned int& val, unsigned int mask) {
+      if (val & 1)
+        val = (val >> 1) ^ mask;
+      else
+        val = val >> 1;
+    }
+
+    // Returns the number of binary digits needed to represent val.
+    unsigned int numBinaryDigits(unsigned int val) {
+      unsigned int num_digits = 0;
+      while (val) {
+        num_digits++;
+        val>>=1;
+      }
+      return num_digits;
+    }
+
+    
+  };
+}
+
+#endif




  • [MANTA] r472 - trunk/Engine/ImageTraversers, bigler, 08/15/2005

Archive powered by MHonArc 2.6.16.

Top of page