Text archives Help
- 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.