Text archives Help
- From: boulos@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r400 - in branches/itanium2: Core/Math Engine/PixelSamplers Interface
- Date: Tue, 21 Jun 2005 02:09:40 -0600 (MDT)
Author: boulos
Date: Tue Jun 21 02:09:37 2005
New Revision: 400
Added:
branches/itanium2/Core/Math/CheapRNG.h
Modified:
branches/itanium2/Engine/PixelSamplers/JitterSampler.cc
branches/itanium2/Engine/PixelSamplers/JitterSampler.h
branches/itanium2/Interface/RayPacket.h
Log:
Fixes for the JitterSampler (resetting the
raypacket flags so they can be reused with
a fresh slate after intersecting things in
the scene).
Tested on my laptop only.
Added: branches/itanium2/Core/Math/CheapRNG.h
==============================================================================
--- (empty file)
+++ branches/itanium2/Core/Math/CheapRNG.h Tue Jun 21 02:09:37 2005
@@ -0,0 +1,72 @@
+/*
+ * CheapRNG
+ *
+ * Cheap refers to the cost to store and to seed the random number.
+ * The speed is about twice as slow as the Mersenne Twister, however
+ * seeding is several orders of magnitude faster. This is useful if
+ * you want to reseed for only a relatively few samples and you just
+ * want a reasonably random sequence.
+ *
+ * The period for this RNG is 2^32 with ranges of [0..4294967295] (or
+ * [0..2^32-1]). Consequently the floating point results are
+ * [0..1]. If you want an exclusive interval [0..1) divide genuint()
+ * by 4294967296.0.
+ *
+ * The algorithms are taken from chapter 7 of Numerical Recipies in C:
+ * The Art of Scientific Computing.
+ *
+ * Author: James Bigler
+ * Date: June 16, 2005
+ *
+ */
+
+// All these values are u_int32_t to make sure we have an unsigned 32
+// bit integer, because the computation relies on the overflow
+// properties of integer multiplication.
+
+// For the Real type
+#include <MantaTypes.h>
+
+namespace Manta {
+
+ class CheapRNG {
+ public:
+ // You need to make sure that this is 32 bits or you are in
+ // trouble. It also needs to be public to initialize the static
+ // members.
+ typedef unsigned int uint32;
+ protected:
+
+ uint32 val;
+
+ public:
+ // Your seed value is upto the fates. You should call seed.
+ CheapRNG() {}
+
+ inline void seed(uint32 seed_val) {
+ val = seed_val;
+ }
+
+ inline uint32 randInt() {
+ val = 1664525*val + 1013904223;
+ return val;
+ }
+
+ // [0..1]
+ inline Real rand() {
+ return Real(randInt())*Real(1./4294967295.);
+ }
+
+ // real number in [0,1)
+ inline Real randExc() {
+ return Real(randInt())*Real(1./4294967296.);
+ }
+
+ // real number in (0,1)
+ inline Real randDblExc() {
+ return ( Real(randInt()) + Real(0.5) ) * Real(1./4294967296.);
+ }
+
+ }; // end class CheapRNG
+
+}
Modified: branches/itanium2/Engine/PixelSamplers/JitterSampler.cc
==============================================================================
--- branches/itanium2/Engine/PixelSamplers/JitterSampler.cc (original)
+++ branches/itanium2/Engine/PixelSamplers/JitterSampler.cc Tue Jun 21
02:09:37 2005
@@ -7,6 +7,7 @@
#include <Interface/RayPacket.h>
#include <Interface/Renderer.h>
+#include <Core/Math/CheapRNG.h>
#include <Engine/PixelSamplers/Sample.h>
#include <stdio.h>
@@ -20,24 +21,26 @@
PixelSampler* JitterSampler::create(const vector<string>& args)
{
-
+
return new JitterSampler(args);
}
-JitterSampler::JitterSampler(const vector<string>& args)
+JitterSampler::JitterSampler(const vector<string>& args):
+ num_samples(4), use_cheaprng(true)
{
- num_samples = 4;
int argc = static_cast<int>(args.size());
for(int i = 0; i<argc;i++){
string arg = args[i];
if(arg == "-numberOfSamples"){
if(!getIntArg(i, args, num_samples))
- throw IllegalArgument("JitterSampler -numberOfSamples", i, args);
+ throw IllegalArgument("JitterSampler -numberOfSamples", i, args);
if (num_samples < 1)
throw IllegalArgument("-numberOfSamples must be greater than 0",
i, args);
+ } else if (arg == "-nocheap") {
+ use_cheaprng = false;
}
-
+
else {
throw IllegalArgument("JitterSampler", i, args);
}
@@ -55,7 +58,15 @@
void JitterSampler::setupBegin(const SetupContext& context, int numChannels)
{
channelInfo.resize(numChannels);
- random = new MT_RNG[context.numProcs];
+ if ( !use_cheaprng )
+ {
+ random = new MT_RNG[context.numProcs];
+ for ( int i = 0; i < context.numProcs; i++ )
+ {
+ random[i] = MT_RNG();
+ random[i].seed_rng( (unsigned long) i );
+ }
+ }
context.renderer->setupBegin(context, numChannels);
}
@@ -70,7 +81,7 @@
ci.yscale = ci.xscale;
ci.xoffset = (-ci.xres+1)*(Real)0.5*ci.xscale; // Offset to pixel center
ci.yoffset = (-ci.yres+1)*(Real)0.5*ci.yscale;
-
+
context.renderer->setupDisplayChannel(context);
}
@@ -79,94 +90,89 @@
context.renderer->setupFrame(context);
}
-
-// Ohh, man. Is this code wacked or what? Anyway, the point of this
-// code it to gather up all the samples that belong to a single
-// fragment, then update the color in the fragment. Fagments' samples
-// can exists across multiple RayPackets, so we have to be careful
-// here. Also with the way the loop works you have to make sure you
-// pick up the last sample if it is part of a newrun (see
-// compute_last_ave below). Anyway, I know there is probably a more
-// elegant solution out there, but this works for all sorts of
-// combinations of fragment sizes and number of samples.
-void JitterSampler::computeAverages(Fragment& fragment, RayPacket& rays,
- Color* sample_color,
- int* fragment_owning_sample) {
- // At this point we have rays.getSize() number of samples
- // that can belong to at most fragment.getSize() number of
- // fragments. We need to sum the colors from the samples
- // for a single fragment then divide it by the total
- // number of samples and add it to the fragment's total.
- int slot_index = 0;
- int num_samples_per_fragment = 1;
- int current_fragment = fragment_owning_sample[slot_index];
- Color fragment_color = sample_color[slot_index];
- // If the last sample is a new run, you need to add it after the for loop.
- bool compute_last_ave = false;
- for(int slot_index = 1; slot_index < rays.getSize(); slot_index++){
- bool compute_average = false;
- if (current_fragment == fragment_owning_sample[slot_index]) {
- fragment_color += sample_color[slot_index];
- num_samples_per_fragment++;
- // Now the case where the last sample is has been
- // reached, we must force it to be averaged.
- if (slot_index == rays.getSize()-1)
- compute_average = true;
- } else {
- // Now we have a break in the fragment, so time to
- // compute the average.
- compute_average = true;
- // If however we have a break at the last pixel, we need to
- // signal to pick up that extra sample.
- if (slot_index == rays.getSize()-1)
- compute_last_ave = true;
- }
- if (compute_average) {
- // Divide the color by the number of samples and
- // increment it with the fragment.
- fragment.get(current_fragment).color +=
- fragment_color / num_samples;
- // Now update for the next fragment run
- fragment_color = sample_color[slot_index];
- current_fragment = fragment_owning_sample[slot_index];
- num_samples_per_fragment = 1;
+// The fragment, sample_color, and sample_color_size paramters are
+// obvious enough, but the other two need some explaination.
+//
+// samples_collected_return represent the number of samples that have
+// already been used to color a fragment element. If a fragment
+// element's samples span more than one RayPacket, then we account for
+// that with this variable.
+//
+// current_fragment_return keeps track of which fragment elements have
+// had their color computed.
+void JitterSampler::computeAverages(Fragment& fragment, Color* sample_color,
+ int sample_color_size,
+ int& samples_collected_return,
+ int& current_fragment_return) {
+ // Copy the values, so the we can hopefully use the cache when
+ // assigning the values.
+ int samples_collected = samples_collected_return;
+ int current_fragment = current_fragment_return;
+ Color fragment_color = Color::black();
+
+ for(int sample_index = 0; sample_index < sample_color_size;
sample_index++) {
+ //double val = (double)current_fragment/(double)fragment.getSize();
+ //fragment_color += Color(RGBColor(val, val, val));
+ fragment_color += sample_color[sample_index];
+ samples_collected++;
+ // We've collected enough samples, so compute the average and
+ // assign it to the fragment.
+ if(samples_collected == num_samples) {
+ fragment.get(current_fragment).color += fragment_color / num_samples;
+ // Reset our accumulation variables
+ fragment_color = Color::black();
+ samples_collected = 0;
+ current_fragment++;
}
- } // end slot_index loop
-
- // Pick up the last sample if we need to
- if (compute_last_ave)
+ }
+ // Pick up left over fragments. It is OK if this is a partial sum.
+ // The remaining sum will be picked up in the next call to
+ // computeAverages.
+ if (samples_collected > 0) {
fragment.get(current_fragment).color += fragment_color / num_samples;
+ }
+ // Assign the values back to the parameters.
+ samples_collected_return = samples_collected;
+ current_fragment_return = current_fragment;
}
void JitterSampler::renderFragment(const RenderContext& context,
- Fragment& fragment)
+ Fragment& fragment)
{
ChannelInfo& ci = channelInfo[context.channelIndex];
int thd_num = context.proc;
-
+
int flags = RayPacket::HaveImageCoordinates;
if(fragment.getFlags() & Fragment::ConstantEye)
flags |= RayPacket::ConstantEye;
- int next_slot = 0;
- Color sample_color[RayPacket::MaxSize];
- int fragment_owning_sample[RayPacket::MaxSize];
-
int consecutivex_flag = fragment.getFlags() & Fragment::ConsecutiveX;
+ CheapRNG rng;
if (consecutivex_flag) {
Fragment::Element& fe = fragment.get(0);
- random[thd_num].seed_rng(fe.x*ci.xres+fe.y);
+ if (use_cheaprng)
+ rng.seed(fe.x*ci.xres+fe.y);
+ else
+ random[thd_num].seed_rng(fe.x*ci.xres+fe.y);
}
int depth = 0;
+
RayPacketData raydata;
RayPacket rays(raydata, RayPacket::MaxSize, depth, flags);
Real inx = (Real)1/nx;
Real iny = (Real)1/ny;
Real px, py;
-
+
+ int sample_count = 0;
+ Color sample_color[RayPacket::MaxSize];
+ // No samples accumulated yet.
+ int samples_collected = 0;
+ // Index to the first fragment's element.
+ int current_fragment = 0;
+
// We can compute at most RayPacket::MaxSize number of rays at time.
for(int frag_index = 0; frag_index < fragment.getSize(); frag_index++) {
// Initialize the color
@@ -175,49 +181,61 @@
Fragment::Element& fe0 = fragment.get(frag_index);
if (!consecutivex_flag) {
- random[thd_num].seed_rng(fe0.x*ci.xres+fe0.y);
+ if (use_cheaprng)
+ rng.seed(fe0.x*ci.xres+fe0.y);
+ else
+ random[thd_num].seed_rng(fe0.x*ci.xres+fe0.y);
}
-
+
// For each fragment start filling up the RayPacket with samples.
// When you filled up the empty_slots compute the rays, do the
// average, and store the results in the fragment.
for(int xs = 0; xs < nx; xs++)
for(int ys = 0; ys < ny; ys++)
{
- Real x_sample = (xs + random[thd_num].genRealRand<Real>()) * inx;
- Real y_sample = (ys + random[thd_num].genRealRand<Real>()) * iny;
+ Real x_sample, y_sample;
+ if (use_cheaprng) {
+ x_sample = (xs + rng.rand()) * inx;
+ y_sample = (ys + rng.rand()) * iny;
+ } else {
+ x_sample = (xs + random[thd_num].genRealRand<Real>()) * inx;
+ y_sample = (ys + random[thd_num].genRealRand<Real>()) * iny;
+ }
px = (fe0.x+(x_sample))*ci.xscale+ci.xoffset;
py = (fe0.y+(y_sample))*ci.yscale+ci.yoffset;
- rays.setPixel(next_slot, 0, px, py, &sample_color[next_slot]);
- fragment_owning_sample[next_slot] = frag_index;
- next_slot++;
-
- if (next_slot == RayPacket::MaxSize) {
+
+ rays.setPixel(sample_count, 0, px, py,
+ &sample_color[sample_count]);
+ sample_count++;
+
+ if (sample_count == RayPacket::MaxSize) {
// Filled up the ray packet, so send them off!
- rays.resize(next_slot);
+ rays.resize(sample_count);
context.renderer->traceEyeRays(context, rays);
- computeAverages(fragment, rays,
- sample_color, fragment_owning_sample);
-
+ computeAverages(fragment, sample_color, rays.getSize(),
+ samples_collected, current_fragment);
+
// Now reset the index, so that we can start filling up
// the RayPacket again.
- next_slot = 0;
+ sample_count = 0;
// Make sure we start with a fresh slate
rays.resetHit();
- // rays.resetFlag(flags);
+ rays.setFlags(flags);
+ //rays.setDepth(depth);
}
} // end sample filling loops
} // end fragment loop
// Pick up any stragling samples
- if (next_slot > 0) {
- rays.resize(next_slot);
+ if (sample_count > 0) {
+ rays.resize(sample_count);
context.renderer->traceEyeRays(context, rays);
-
- computeAverages(fragment, rays, sample_color, fragment_owning_sample);
+
+ computeAverages(fragment, sample_color, rays.getSize(),
+ samples_collected, current_fragment);
}
-}
+}
Modified: branches/itanium2/Engine/PixelSamplers/JitterSampler.h
==============================================================================
--- branches/itanium2/Engine/PixelSamplers/JitterSampler.h (original)
+++ branches/itanium2/Engine/PixelSamplers/JitterSampler.h Tue Jun 21
02:09:37 2005
@@ -31,12 +31,14 @@
JitterSampler(const JitterSampler&);
JitterSampler& operator=(const JitterSampler&);
- void computeAverages(Fragment& fragment, RayPacket& rays,
- Color* sample_color, int* fragment_owning_sample);
+ void computeAverages(Fragment& fragment, Color* sample_color,
+ int sample_color_size,
+ int& samples_collected, int& current_fragment);
int num_samples;
// nx*ny == num_samples where nx~=ny (or as close as you can get it).
int nx, ny;
+ bool use_cheaprng;
struct ChannelInfo {
Real xscale;
Modified: branches/itanium2/Interface/RayPacket.h
==============================================================================
--- branches/itanium2/Interface/RayPacket.h (original)
+++ branches/itanium2/Interface/RayPacket.h Tue Jun 21 02:09:37 2005
@@ -30,9 +30,9 @@
HaveUnitNormals = 0x300,
HaveInverseDirections = 0x800 };
-
+
inline RayPacket(RayPacketData& data, int size, int depth, int flags);
-
+
// Create a subset of another raypacket
RayPacket(RayPacket& parent, int start, int end)
: data(parent.data+start), size(end-start), depth(parent.depth),
@@ -47,6 +47,10 @@
int getFlags() const {
return flags;
}
+ int setFlags(int new_flags)
+ {
+ flags = new_flags;
+ }
void setFlag(int flag) {
flags |= flag;
}
@@ -94,7 +98,7 @@
return data[which];
}
void setPixel(int which, int whichEye, double imageX, double imageY,
- Color* color) {
+ Color* color) {
data[which].color = color;
data[which].imageX = imageX;
data[which].imageY = imageY;
@@ -102,7 +106,7 @@
}
void useLocalColors() {
for(int i=0;i<size;i++)
- data[i].color = &data[i].localColor;
+ data[i].color = &data[i].localColor;
}
HitInfo& hitInfo(int which) {
return data[which].hitInfo;
@@ -117,7 +121,7 @@
{
if(flags & NormalizedDirections)
return;
-
+
if(flags & HaveHitRecords){
for(int i=0;i<size;i++){
double length = data[i].ray.normalizeDirection();
@@ -146,7 +150,7 @@
data[i].inverseDirection = Vector(1./data[i].ray.direction().x(),
1./data[i].ray.direction().y(),
1./data[i].ray.direction().z());
-
+
// Set the sign mask at the same time.
data[i].signMask[0] = (data[i].inverseDirection[0] < 0.0);
data[i].signMask[1] = (data[i].inverseDirection[1] < 0.0);
@@ -176,7 +180,7 @@
void computeFrame(const RenderContext& context)
{
if(flags & HaveFrame)
- return;
+ return;
Element& e0 = data[0];
const UVMapping* uv = e0.hitInfo.hitPrimitive()->getUVMapping();
uv->computeFrame(context, *this);
@@ -191,7 +195,7 @@
int end;
int i = 0;
-
+
// Compute normals
while (i<size) {
@@ -202,11 +206,11 @@
while(end < size && data[end].hitInfo.hitPrimitive() == prim)
end++;
-
+
RayPacket subPacket(*this, i, end);
prim->computeNormal(context, subPacket);
-
+
i=end;
}
@@ -242,7 +246,7 @@
};
inline RayPacket::RayPacket(RayPacketData& data, int size,
- int depth, int flags)
+ int depth, int flags)
: data(&data.data[0]), size(size), depth(depth), flags(flags)
{
}
- [MANTA] r400 - in branches/itanium2: Core/Math Engine/PixelSamplers Interface, boulos, 06/21/2005
Archive powered by MHonArc 2.6.16.