Skip to main content
GameDev.net gamedev.net
🔒 Locked

Ray Tracing Questions

Started by hick18 Mar 28, 2011 at 12:43 PM 0 replies 1.6k views
Original Post
hick18
hick18
Whats the best way to go about rendering materials with both Transmittance and Reflectance properties? At the moment I have defined my materials to be one of the other, like this

Trace( ray, bounces )
{
material = intersection(ray);

if( material == SPECULAR )
{
return Trace( reflectededray, --bounces )
}
else if( material == REFRACTIVE )
{
return Trace( refractedray, --bounces )
}
else if( material == DIFFUSE )
{
return calculateDiffuse();
}
}


What If i wanted to render plastic? which would have some portion of each? What I want to do is just compute all 3 and then add them up with their particular ratio. But then I would have to have materials that get created like this

material->setDiffuseRatio( 0.25f );
material->setSpecularRatio( 0.25f );
material->setTransparencyRatio( 0.50f, indexOfRefraction );

Is there a better way?

Second, what happens when I perform the tracing of a single ray and it hits multiple perfectly reflectivesurfaces before the number of bounces allowed reaches 0? What should I return? Say I have two mirror balls next to each other and the ray gets into a situation where it just keeps bouncing between the 2. I can solve the infinite recursion by setting the maximum number of bounces to fall out, but what should the pixel colour be?

Third, in my current system, you dont see the light reflected on the objects, because i only compute the diifuse lighting. Am I right in thinking that to add this I have 2 options.

1. Use the phong type specular reflection model and restrict myself to point, spot and directional lights.
2. Use area lighting

Where when using area lighting I have the lighting for a particular point perform ray/surface intersection for each area light, doting the points normal and the light surface point normal. But then how do I compute the amount of light that surface is recieving? The previous compuation doesnt account for the fact that bigger area lights should have more of an effect, ie that the hemisphere above the point being lit sees more of the area light if it is bigger or closer and less if it is smaller and further away. Im not sure how using attenuation would work in this case or if its even valid to do so. Should I instead perform multiple ray samples and then times that by the surface area of the hemisphere? something like


accum = 0.0f;
for( number of sample )
{
ray = computeEquallySpacedRandomRayInHemisphere();
accum += DotRayAreaLight() * (HemispheresurfaceAreaOverNumOfSamples)
}


Its likly that if the area light is small then the rays could very well all miss it, producing incorrect results
Vilem Otte
Vilem Otte
[color="#000000"]There are 2 much better ways, although you have to define your material in a better way. First one (used for ray tracing more), is to define material class in a better way, something like:

struct material
{
float reflect_val; // used for reflection strength
float refract_val; // used for refraction strength
...

material()
{
reflect_val = 0.0f;
refract_val = 0.0f;
...
}
};
[color="#000000"]


[color="#000000"]You can also mix them based upon fresnel (thats the way to mix reflection and refraction correctly). I've used this-like model before in my raytracer ... then your Trace procedure will look like this (with simple blending the reflection and refraction... for real solution you need to perform something better, like fresnel term ... F.e. Shlicks approximation):


Trace[color="#000000"]( ray, bounces )[color="#000000"]
{[color="#000000"]
material = intersection(ray);[color="#000000"]

Trace summedResult = Trace(); // Initialize result, you have to zero out all values in constructor

if( material.reflect_val > 0.0 )[color="#000000"]
{[color="#000000"]
summedResult += material.reflect_val * Trace( reflectededray, --bounces )[color="#000000"]
}[color="#000000"]

if( material.refract_val > 0.0 )[color="#000000"]
{[color="#000000"]
summedResult += material.refract_val * Trace( refractedray, --bounces )[color="#000000"]
}[color="#000000"]

[color="#000000"]summedResult += ComputeDiffuse();
}


Better solution is probably to use some good BRDF (or BSDF to get even better solution). This will make your ray tracer more physically based, although with BRDF based materials or BSDF based materials you're able to switch to full path tracing (and thus achieving physically based result ).

Also note that materials and their implementation are described in PBRT, if you're into ray tracing like me (I'm total fanatic ), buy the book It's worth the money (and Amazon will bring it anywhere)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.