Text archives Help
- From: bigler@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r467 - trunk/Engine/ImageTraversers
- Date: Fri, 5 Aug 2005 12:15:57 -0600 (MDT)
Author: bigler
Date: Fri Aug 5 12:15:56 2005
New Revision: 467
Modified:
trunk/Engine/ImageTraversers/DissolveImageTraverser.cc
trunk/Engine/ImageTraversers/DissolveImageTraverser.h
Log:
Added iters_per_frame class parameter. This would allow you to set
this based on your scene from the commandline. It may be possible (at
some future date) to change this on the fly to attemp to give a set
number of frames per second based on the current performance.
Added a few comments as well as an explaination of the class.
Modified: trunk/Engine/ImageTraversers/DissolveImageTraverser.cc
==============================================================================
--- trunk/Engine/ImageTraversers/DissolveImageTraverser.cc (original)
+++ trunk/Engine/ImageTraversers/DissolveImageTraverser.cc Fri Aug 5
12:15:56 2005
@@ -15,9 +15,6 @@
using namespace Manta;
using SCIRun::InternalError;
-// Defines how many iterations are required to finish a frame.
-#define ITERS_PER_FRAME 16
-
// Use this mask to produce values from 1 to N (in the comments)
unsigned int MaskValues[] = {
/* 00 */ 0x00, // 0
@@ -60,17 +57,18 @@
return new DissolveImageTraverser(args);
}
-DissolveImageTraverser::DissolveImageTraverser(const vector<string>& args)
+DissolveImageTraverser::DissolveImageTraverser(const vector<string>& args):
+ iters_per_frame(16)
{
int argc = static_cast<int>(args.size());
for(int i = 0; i<argc;i++){
string arg = args[i];
- if(arg == "-pixelsPerPass"){
- if(!getArg<unsigned int>(i, args, pixels_per_pass))
- throw IllegalArgument("DissolveImageTraverser -pixelsPerPass",
+ if(arg == "-itersPerFrame"){
+ if(!getArg<unsigned int>(i, args, iters_per_frame))
+ throw IllegalArgument("DissolveImageTraverser -itersPerFrame",
i, args);
- if (pixels_per_pass < 1)
- throw IllegalArgument("-pixelsPerPass must be greater than 0",
+ if (iters_per_frame < 1)
+ throw IllegalArgument("-itersPerFrame must be greater than 0",
i, args);
} else {
throw IllegalArgument("DissolveImageTraverser", i, args);
@@ -100,7 +98,7 @@
context.getResolution(stereo, xres, yres);
// Try an educated guess for the pixels per sample
- pixels_per_pass = (xres*yres)/context.numProcs/ITERS_PER_FRAME;
+ pixels_per_pass = (xres*yres)/context.numProcs/iters_per_frame;
// Compute the mask
unsigned int num_x_bits = numBinaryDigits(xres-1);
@@ -147,6 +145,8 @@
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];
@@ -157,19 +157,23 @@
// 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) {
+ 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++;
}
- int x, y;
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
@@ -182,7 +186,7 @@
}
#endif
image->set(frag);
- // Reset the Fragment
+ // Reset the Fragment, so we can start filling it up again.
frag.resetSize();
}
}
@@ -202,9 +206,8 @@
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
Modified: trunk/Engine/ImageTraversers/DissolveImageTraverser.h
==============================================================================
--- trunk/Engine/ImageTraversers/DissolveImageTraverser.h (original)
+++ trunk/Engine/ImageTraversers/DissolveImageTraverser.h Fri Aug 5
12:15:56 2005
@@ -1,3 +1,25 @@
+/*
+ DissolveImageTraverser
+
+ 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_DissolveImageTraverser_h
#define Manta_Engine_DissolveImageTraverser_h
@@ -24,6 +46,7 @@
DissolveImageTraverser(const DissolveImageTraverser&);
DissolveImageTraverser& operator=(const DissolveImageTraverser&);
+ // Each thread stores where it left off for each channel.
struct ThreadContext {
// next_pixel.size() == numChannels. We'll store both x and y
// in this single variable, where x uses the higher order bits
@@ -33,6 +56,10 @@
vector<ThreadContext> per_thread_data;
+ // 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;
@@ -43,6 +70,10 @@
// This is how many pixels to render on a call to renderImage.
unsigned int pixels_per_pass;
+ // 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;
inline void computeNextSample(unsigned int& val, unsigned int mask) {
if (val & 1)
- [MANTA] r467 - trunk/Engine/ImageTraversers, bigler, 08/05/2005
Archive powered by MHonArc 2.6.16.