-
RayTracer truble
Hallo,
I am working on a small raytracer and Im now at the point where I want to add lights to it.
But for some reason I allways get no light on the object, so the object becomes black
Here is my code for adding light:
Code:
float r, g, b;
// Check which if there is a light affecting the sphere
for (int currentLight = 0; currentLight <= thisScene.getAmountOfObjects(); currentLight++)
{
Vector3D sphereRayIntersection;
Point rayOrg = currentRay.getOrigin();
// Add the start point of the ray and the direction of the sphere together
// and mult. it with the distance to closest sphere
sphereRayIntersection = currentRay.getDirection();
sphereRayIntersection.setX(sphereRayIntersection.getX() + rayOrg.getX());
sphereRayIntersection.setY(sphereRayIntersection.getY() + rayOrg.getY());
sphereRayIntersection.setZ(sphereRayIntersection.getZ() + rayOrg.getZ());
sphereRayIntersection.scale(closesSphereDistance);
// Find the normal to the sphere at point of intersection
Sphere thisSphere = thisScene.getSphere(closestSphere);
Vector3D normal;
float oneOverRadius = 1/thisSphere.getRadius();
normal = sphereRayIntersection - thisSphere.getPosition();
normal.scale(oneOverRadius);
normal.normalize();
// Get the light direction
Vector3D lightDir;
Sphere thisLight = thisScene.getLight(currentLight);
lightDir = thisLight.getPosition() - sphereRayIntersection;
lightDir.normalize();
// Find light coefficient
float lightCoef = Dot(lightDir,normal);
if (lightCoef < 0)
lightCoef = 0;
// Get the color of the light and how much it affects the sphere
Material thisMaterial = thisLight.getMaterial();
float lightR = thisMaterial.getR() * lightCoef;
float lightG = thisMaterial.getG() * lightCoef;
float lightB = thisMaterial.getB() * lightCoef;
// Add the effect of the light to the color of the sphere
Material sphereColor = thisSphere.getMaterial();
r = ((sphereColor.getR() * lightR) / 255 );
g = ((sphereColor.getG() * lightG) / 255);
b = ((sphereColor.getB() * lightB) / 255);
// Make sure that the color is not higher than 255
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
//std::cout << r << "," << g << "," << b << std::endl;
}
// Assign the color to the pixel
int colorR = r;
int colorG = g;
int colorB = b;
colorBuffer[arrayTracer + 0] = colorR;
colorBuffer[arrayTracer + 1] = colorG;
colorBuffer[arrayTracer + 2] = colorB;
I am almost sure the problem is the "lightCoef" variable, as it is never above 0. So when I later use that to multiply the color the result is 0.
But I am not sure why this happpens.
Sorry if this is the wrong place to post this and thanks for you time.
-
I think you're going to have to print out some of your variables to a file (if you can't output them to the screen) to see what's happening. But as you said, looking at your code, if lightCoef is zero, it would explain things.
-
If lightCoef is coming out negative it means that either the Dot() function is broken, or the angle between the two vectors is more than 90 degrees (which implies that the surface normal at the intersection point is facing away from the light source, in other words, it is shadowed by the rest of the sphere)
When you intersect a ray with a sphere (you didn't post the code that does it), remember that there are usually two intersection points and you should use the closer one. The farther one is obviously shadowed by the sphere.
-
Thanks for your reply.
lightCoef = 0 is only part of the problem. A tryed to do AbsDot() insted of Dot() to see if that helped. Than I got the color and the sphere is displayed, but there is no gradient on the sphere eg. its still a flat color.
I have been printing variables, but still no clue on what is wrong
Any ideas would be great.
-
I think your problem might be here:
// Add the start point of the ray and the direction of the sphere together
// and mult. it with the distance to closest sphere
If you always add the distance to the sphere, all intersection points are the same distance from the view plane, and thus you render a flat surface (which explains the lack of gradient you're seeing).
in the line:
sphereRayIntersection.scale(closesSphereDistance);
is closesSphereDistance the distance from the view plane to the centre of the closest sphere? (this would be wrong). Or is it the distance to the intersection point of the ray and the sphere, to the origin of the ray?
-
I have found at that there is a mistake as you mentioned.
It should be :
Code:
// Add the start point of the ray and the direction of the sphere together
// and mult. it with the distance to closest sphere
sphereRayIntersection = currentRay.getDirection();
sphereRayIntersection.setX(rayOrg.getX() + (sphereRayIntersection.getX() * closesSphereDistance ));
sphereRayIntersection.setY(rayOrg.getY() + (sphereRayIntersection.getY() * closesSphereDistance ));
sphereRayIntersection.setZ(rayOrg.getZ() + (sphereRayIntersection.getZ() * closesSphereDistance ));
Its the distance from where the ray is created to where it hits the sphere