PDA

View Full Version : Ray Tracer Phong Shader Problem


appleGuy
07-17-2007, 04:52 AM
Hi,

Ive tried to implement the phong shading model. However I cant seem to get it to work correctly. Its based of a lambert shader and the shader actually looks like a lambert shader, however there are no specular highlights or other defining features that make a phong shader.

Code That calculates Shader Colour at pixel level:

public colourRGBA calcPhongShader(ray Ray, float distance, Vector Lights){
Vector3f cameraSpherePath = new Vector3f(Ray.getDirection());
cameraSpherePath.scaleAdd(distance, Ray.getOrigin());

//Calculate Sphere Normal
float oneOverRadius = (1 / _radius);
Vector3f normal = new Vector3f();
normal.sub(cameraSpherePath, _centre);
normal.scale(oneOverRadius);
normal.normalize();

//Calculate The Bounce Point (Sphere) light Vector
Vector lightPathArray = new Vector();
Vector lightPathReflectionArray = new Vector();

lightObject light;

for(int lightIter = 0; lightIter < Lights.size(); lightIter++){
//ObjectToLight
Vector3f sphereLight = new Vector3f();
light = (lightObject)Lights.get(lightIter);
sphereLight.sub(light.lightPosition, cameraSpherePath);
sphereLight.normalize();
lightPathArray.add(sphereLight);

//Reflection Of Object To Light
Vector3f reflect = new Vector3f();
Vector3f reflectVar = new Vector3f();
reflectVar.scale(Ray.getDirection().dot(normal), normal);
reflectVar.scale(2.0f);

reflect.sub(Ray.getDirection(), reflectVar);

//R = V – 2 * (V·N) * N

reflect.normalize();


lightPathReflectionArray.add(reflect);
}

//View Direction Object To Camera
Vector3f objToCam = new Vector3f();
objToCam.sub(Ray.getOrigin(), cameraSpherePath);
objToCam.normalize();

colourRGBA colour = new colourRGBA();

colour.red = this.Ka[0]; // MULTIPLIES BY IAMBENT?
colour.green = this.Ka[1]; // MULTIPLIES BY IAMBENT?
colour.blue = this.Ka[2]; // MULTIPLIES BY IAMBENT?

for(int lightIter = 0; lightIter < Lights.size(); lightIter++){
Vector3f currentLightPath = (Vector3f)lightPathArray.get(lightIter);
Vector3f currentLightReflection = (Vector3f)lightPathReflectionArray.get(lightIter);
lightObject currentLight = (lightObject)Lights.get(lightIter);

float cameraDOTReflection = objToCam.dot(currentLightReflection);

float camDotRefPOW = (float)java.lang.Math.pow(cameraDOTReflection, this.shinyness);

colour.red += (((this.Kd[0] * currentLightPath.dot(normal)) * currentLight.lightDiffuse[0]) + (this.Ks[0] * camDotRefPOW));
colour.green += (((this.Kd[1] * currentLightPath.dot(normal)) * currentLight.lightDiffuse[1]) + (this.Ks[1] * camDotRefPOW));
colour.blue += (((this.Kd[2] * currentLightPath.dot(normal)) * currentLight.lightDiffuse[2]) + (this.Ks[2] * camDotRefPOW));
}

return colour;
}


Thanks For Any Help
Cheers,
-Alex

anubis
07-17-2007, 06:51 AM
I haven't read your code but a common problem ist that you mix up the directions of your light and eye vector. They should both be pointing away from the surface point. Maybe I have some time to look at the code when I'm back from work...

appleGuy
07-17-2007, 07:48 AM
I haven't read your code but a common problem ist that you mix up the directions of your light and eye vector. They should both be pointing away from the surface point. Maybe I have some time to look at the code when I'm back from work...

Yeah if you could please have a look that would be great.

The point on sphere to light vector has got to be correct as the lambert shader would not work, which it does.

It seems like the Reflection or sphere to camera origin vectors are incorrect. As that part of the equation is the extension that takes a lambert to a phong.

Also what value for the shinyness (the n power) is used. 0 - 1.0, 0 - 100 ?

Cheers,
Alex

anubis
07-17-2007, 08:02 AM
Well... what exactly isn't working ? Picture ? I think 10 for the power value is reasonable for testing purposes.

Edit: Sorry... reread your post. If you are not seeing any highlights... What value are you using right now for the shininess ?

appleGuy
07-17-2007, 08:05 AM
Well... what exactly isn't working ? Picture ? I think 10 for the power value is reasonable for testing purposes.

Well my phong shader just looks liker a lambert shader. No specular highlights. Ive made sure that my specular colour is white and the light is in the correct position to create a visible specular mark..
Image:
http://img.photobucket.com/albums/v315/blade99261/renderOutputERR0RPLANE.jpg

edit: im using a specular power of 25.0f

roel
07-17-2007, 10:52 AM
Just write the calculated values of the highlight (and the used values in your compuation like vectors, results of dot products, etc) to your debug output and you'll spot the error. Learn to debug, stuff like this is trivial, if you are already stuck in this phase you'll never write an interesting ray tracer.

appleGuy
07-17-2007, 11:46 AM
Just write the calculated values of the highlight (and the used values in your compuation like vectors, results of dot products, etc) to your debug output and you'll spot the error. Learn to debug, stuff like this is trivial, if you are already stuck in this phase you'll never write an interesting ray tracer.

That was a helpful post....

Like I've SAID i know where the problem is as its still producing a lambert shader. Hence SPHERETOCAM_DOT_REFLECTION to the specular power is incorrect.

Maybe I'm just learning the basics and not trying to create THE WORLD'S GREATEST RAY TRACER!

Just for the record I know how to debug, but not sure where the math is going wrong as I have followed the formula to the tee.

Please don't post if your not going to contribute positively

-Alex

z80
07-17-2007, 12:32 PM
Hmm.. A few things look strange to me..

You compute the "reflect" for every light source and put it into an array.. Why? It is calculated from the normal and the direction of the ray.. The light source parameters dont go into this formula.. So why calculate it for every light source?

Then it looks to me like you compute camDotRefPOW as the dot between the vector pointing towards the cam and the reflect vector.. Shouldnt this be the vector pointing towards the light and the reflect vector instead? Think about it, it makes sense: When the ray coming from the eye get reflected and hits near the lightsource you get a highlight.

You probably also wanna check if camDotRefPOW is above zero before using it in your colour-calculation. You could have a negative value there introducing strangeness.

I used this page (http://www.groovyvis.com/other/raytracing/specular.html) for reference.

Nicholas Christopher
07-17-2007, 12:40 PM
Just an idea here... maybe what you could do is see how you would implement
the lambert shader. Then analyze the differences and similarities between the lambert and phong and you might gain some insight into your problem..

Sorry if I cant give you a more concise answer that would pinpoint exactly what is the problem.

anubis
07-17-2007, 02:17 PM
That was a helpful post....

Like I've SAID i know where the problem is as its still producing a lambert shader. Hence SPHERETOCAM_DOT_REFLECTION to the specular power is incorrect.

Maybe I'm just learning the basics and not trying to create THE WORLD'S GREATEST RAY TRACER!

Just for the record I know how to debug, but not sure where the math is going wrong as I have followed the formula to the tee.

Please don't post if your not going to contribute positively


Please don't tell people to shut up... As long as it's civil everybody can write whatever he/she wants. You don't have to take the advice. Afterall you are expecting that people read and debug your code here.

edit: i'm using a specular power of 25.0f

In general a higher shininess means a narrower spotlight on the surface, which makes sense, since you are taking the power of a dot product from normalized vectors, which is going to be between -1 and 1 (0 and 1 actually, since you are only interested in light sources in front of the surface).


Then it looks to me like you compute camDotRefPOW as the dot between the vector pointing towards the cam and the reflect vector.. Shouldnt this be the vector pointing towards the light and the reflect vector instead? Think about it, it makes sense: When the ray coming from the eye get reflected and hits near the lightsource you get a highlight.


Doesn't it make just as much sense, that you see a highlight, when the reflected light ray is close to the eye ?

http://en.wikipedia.org/wiki/Phong_reflection_model

Wikipedia uses it this way and so does

http://www.devmaster.net/wiki/Phong_shading

our own wiki :) And I think that it's really arbitrary, although so far I've only seen the formulation with the reflected light vector. But then of course you would have to compute the reflected light vector, which also would make a lot more sense in the loop there...

z80
07-17-2007, 02:24 PM
Doesn't it make just as much sense, that you see a highlight, when the reflected light ray is close to the eye ?

Same thing, but the opposite direction. Guess I was thinking a bit backwards because that is the direction the rays travel in a backward raytracer like appleGuy is writing.

But then of course you would have to compute the reflected light vector, which also would make a lot more sense in the loop there...

Why not use the eye-to-object vector and reflect that using the normal to get the reflected eye vector? Then you can compute the dot product of this and the direction towards the light. The result is the same but this method is faster since you only have to reflect one vector instead of one reflection per light source.

EDIT: A bit of pseudo-code:

D = eye ray direction
P = intersection point
N = normal

// Compute reflected eye vector
R = D - 2 * (D . N) * N

for each lightsource
L = normalize(lightsource.pos - P)
specular = R . L
if (specular > 0)
color +=
material.spec_color *
pow(specular, material.spec_power);

anubis
07-17-2007, 03:14 PM
Well... either way. You are taking the dot product using the reflected light and the object to eye vector or you are doing it in reverse. As I see it the code is taking the dot product between the reflected ray and the object to eye vector. That's got to be wrong I guess the intention really was to compute the reflected light... Why else would it be in the loop ?

He even calls it currentLightReflection in the second loop, which it's clearly not...