Text archives Help
- From: boulos@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r455 - branches/itanium2/Model/Materials
- Date: Fri, 29 Jul 2005 02:34:56 -0600 (MDT)
Author: boulos
Date: Fri Jul 29 02:34:55 2005
New Revision: 455
Added:
branches/itanium2/Model/Materials/AmbientOcclusion.cc
branches/itanium2/Model/Materials/AmbientOcclusion.h
Modified:
branches/itanium2/Model/Materials/CMakeLists.txt
Log:
Adding an AmbientOcclusion shader. The shader
precomputes a set of num_directions that are
cosine weighted and at shading time transforms
these directions using the surface orientation
into directions for occlusion rays.
Added: branches/itanium2/Model/Materials/AmbientOcclusion.cc
==============================================================================
--- (empty file)
+++ branches/itanium2/Model/Materials/AmbientOcclusion.cc Fri Jul 29
02:34:55 2005
@@ -0,0 +1,124 @@
+#include <Model/Materials/AmbientOcclusion.h>
+#include <Interface/Primitive.h>
+#include <Interface/RayPacket.h>
+#include <Interface/Context.h>
+#include <Interface/Scene.h>
+#include <Model/Textures/Constant.h>
+#include <Core/Math/MT_RNG.h>
+#include <SCIRun/Core/Math/Trig.h>
+
+using namespace Manta;
+
+// TODO: sort the rays generated in generateDirections to make them more
+// coherent for ray packets.
+
+AmbientOcclusion::AmbientOcclusion(const Color& color, float cutoff_dist,
int num_dirs)
+{
+ colortex = new Constant<Color>(color);
+ cutoff_tex = new Constant<float>(cutoff_dist);
+ num_directions = num_dirs;
+ inv_num_directions = 1.f/float(num_directions);
+ generateDirections();
+}
+
+AmbientOcclusion::AmbientOcclusion(const Texture<Color>* color, const
Texture<float>* cutoff_dist, int num_dirs) : colortex(color),
cutoff_tex(cutoff_dist), num_directions(num_dirs)
+{
+ inv_num_directions = 1.f/float(num_directions);
+ generateDirections();
+}
+
+AmbientOcclusion::~AmbientOcclusion()
+{
+ if (directions) delete[] directions;
+}
+
+void AmbientOcclusion::generateDirections()
+
+{
+ directions = new Vector[num_directions];
+ MT_RNG rng;
+ // generate cosine weighted directions
+ for ( int i = 0; i < num_directions; i++ )
+ {
+ double r1 = rng.genRealRand<double>();
+ double r2 = rng.genRealRand<double>();
+
+ double phi = 2.0 * Pi * r1;
+ double r = sqrt(r2);
+ double x = r * Cos(phi);
+ double y = r * Sin(phi);
+ double z = 1.0 - x*x - y*y;
+ z = (z > 0.0) ? sqrt(z) : 0.0;
+
+ directions[i] = Vector(x, y, z);
+ }
+}
+
+void AmbientOcclusion::shade(const RenderContext& context, RayPacket& rays)
const
+{
+ // Compute normals
+ rays.computeNormals(context);
+
+ // Compute colors
+ Color colors[RayPacket::MaxSize];
+ float dists[RayPacket::MaxSize];
+ colortex->mapValues(context, rays, colors);
+ cutoff_tex->mapValues(context, rays, dists);
+
+
+
+ for (int i = 0; i < rays.getSize(); i++)
+ {
+ // for each position, compute a local coordinate frame
+ // and build a set of rays to push into a ray packet
+ RayPacket::Element& e = rays.get(i);
+ Vector U,V,W; // surface ONB
+ W = e.normal;
+ W.normalize();
+ U = Cross(W, Vector(1,0,0));
+ double squared_length = U.length2();
+ if ( squared_length < 1e-6 )
+ {
+ U = Cross(W, Vector(0,1,0));
+ U.normalize();
+ }
+ else
+ U *= 1./sqrt(squared_length);
+ V = Cross(W, U);
+
+ int num_sent = 0;
+ float num_miss = 0.f;
+ while ( num_sent < num_directions )
+ {
+ int start = num_sent + 1;
+ int end = start + RayPacket::MaxSize;
+ if (end > num_directions) end = num_directions;
+
+ RayPacketData occlusion_data;
+ RayPacket occlusion_rays(occlusion_data, end-start,
rays.getDepth(), RayPacket::NormalizedDirections | RayPacket::ConstantOrigin);
+
+ for ( int r = start; r <= end; r++ )
+ {
+ RayPacket::Element& element = occlusion_rays.get(r-start);
+ Vector trans_dir = directions[r][0]*U + directions[r][1]*V +
directions[r][2]*W;
+ element.ray.set(e.hitPosition, trans_dir);
+ // set max distance
+ element.hitInfo.reset(dists[i]);
+ }
+ // packet is ready, test it for shadows
+ context.scene->getObject()->intersect(context, occlusion_rays);
+ // count the number of occluded ones
+ for (int r = start; r <= end; r++ )
+ {
+ RayPacket::Element& element = occlusion_rays.get(r-start);
+ if(!element.hitInfo.wasHit())
+ num_miss+=1.0f;
+ }
+ num_sent = end;
+ }
+
+ // now we can shade our ray
+ *e.color = colors[i]*(num_miss*inv_num_directions);
+ }
+
+}
Added: branches/itanium2/Model/Materials/AmbientOcclusion.h
==============================================================================
--- (empty file)
+++ branches/itanium2/Model/Materials/AmbientOcclusion.h Fri Jul 29
02:34:55 2005
@@ -0,0 +1,33 @@
+#ifndef Manta_Model_AmbientOcclusion_h
+#define Manta_Model_AmbientOcclusion_h
+
+#include <Model/Materials/LitMaterial.h>
+#include <Core/Color/Color.h>
+#include <Interface/Texture.h>
+
+namespace Manta
+{
+ class LightSet;
+
+ class AmbientOcclusion : public LitMaterial
+ {
+ public:
+ AmbientOcclusion(const Color& color, float cutoff_dist, int
num_dirs);
+ AmbientOcclusion(const Texture<Color>* color, const Texture<float>*
cutoff_dist, int num_dirs);
+ AmbientOcclusion() { }
+ ~AmbientOcclusion();
+
+ void generateDirections();
+
+ // generate the directions
+ void shade(const RenderContext& context, RayPacket& rays) const;
+ private:
+ const Texture<Color>* colortex;
+ const Texture<float>* cutoff_tex;
+ Vector* directions;
+ int num_directions;
+ float inv_num_directions;
+ };
+}
+
+#endif
Modified: branches/itanium2/Model/Materials/CMakeLists.txt
==============================================================================
--- branches/itanium2/Model/Materials/CMakeLists.txt (original)
+++ branches/itanium2/Model/Materials/CMakeLists.txt Fri Jul 29 02:34:55
2005
@@ -22,4 +22,6 @@
Materials/CopyColorMaterial.cc
Materials/NormalMaterial.h
Materials/NormalMaterial.cc # Shade the material using it's normal.
+ Materials/AmbientOcclusion.h
+ Materials/AmbientOcclusion.cc
)
- [MANTA] r455 - branches/itanium2/Model/Materials, boulos, 07/29/2005
Archive powered by MHonArc 2.6.16.