Sign in to follow this  
Kronecker

Ray Tracing Ring Artifact

Recommended Posts

I've recently started working on a ray tracer as a side-project. I have written everything from scratch so far and have some kind of odd results. In the scene below you'll see three spheres lit by two lights. The rings (including the dark circles on the undersides) seem to show up where the lambertian multipliers are around the 0.6 or so neighborhood.
If anybody has any experience with this artifact I'd be great to hear how you worked past it. I haven't found any resources online that point me in the right direction regarding this yet.

Share this post


Link to post
Share on other sites
How are you computing the lighting for the spheres? I can't say for sure, but my wild guess is that you're not clipping n.l (the dot product between the normal and the point-to-light vector) to [0, 1], and that values less than 0 are having a subtractive effect on light. Just a wild guess, though.

Share this post


Link to post
Share on other sites
Here is the code that does the diffuse lighting. Please excuse its messyness (its obviously still in the works)



float illuminationR = 0.0f;
float illuminationG = 0.0f;
float illuminationB = 0.0f;

for(int i = 0; i < lights.length; i++){
float closestT = 10000;
float closestIndex = -1;

for(int j = 0; j < shapes.length; j++){
float t = shapes[j].getCollisionDistance(shadows[i]);

if(Constants.verbose)
System.out.println(" Collision Distance: "+t);

if(t < closestT && t > Constants.epsilon){
closestT = t;
closestIndex = j;
}
}

if(closestIndex == -1){
float lambertianConst = Math.abs(Vector3D.dot(cp.normal,shadows[i].r0));
//lambertHistogram[(int)(lambertianConst*199)]++;

if(Constants.verbose){
System.out.println(" Angle between Light and Normal: "+(Vector3D.angle(shadows[i].r0,cp.normal)*180/Math.PI));
System.out.println(" Lambertian Const: "+lambertianConst);
}

illuminationR += (lights[i].c.getRed()/255.0)*lights[i].intensity*lambertianConst;
illuminationG += (lights[i].c.getGreen()/255.0)*lights[i].intensity*lambertianConst;
illuminationB += (lights[i].c.getBlue()/255.0)*lights[i].intensity*lambertianConst;
}
}
Color col;

illuminationR += (ambient.c.getRed()/255.0f)*ambient.intensity;
illuminationG += (ambient.c.getGreen()/255.0f)*ambient.intensity;
illuminationB += (ambient.c.getBlue()/255.0f)*ambient.intensity;

float finalR = illuminationR*(shapes[lowestIndex].mat.c.getRed()/255.0f);
float finalG = illuminationG*(shapes[lowestIndex].mat.c.getGreen()/255.0f);
float finalB = illuminationB*(shapes[lowestIndex].mat.c.getBlue()/255.0f);



As you can see, I took the absolute value of the dot product to make sure it is greater than zero... also, since both the normal vector and the shadow ray's vector are unit vectors - the upper bound for lambertianConst will be 1.

Share this post


Link to post
Share on other sites
you don't want the absolute value, that makes negative n.l values into positive n.l values, which will make the backside of an object wrt the light be lit up. Instead, make any n.l value < 0 equal to 0.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
One way to debug that sort of thing is to assign different colors to things. Ambient set to full red, diffuse set to full blue and specular set to full green. Make all the objects the same. Then turn each component off one by one to determine which one contributes to the problem. Since this is a raytracer, you might also want to limit to primary rays and turn that effect on (and increase the number of levels) once you have determine the problem is not the base lighting equation.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this