1

yesterday i posted this:

Lambertian Shader not working

My shader is still not working, I've done some debugging to try to find the reason. When I run my program and hit a sphere, shader.shade(renderable.colour) is called and this code is run:

public Colour shade(Intersection intersection, Light light){
    Vector3D lightDirection =  light.location.subtract(intersection.point);
    lightDirection.normalise();
    Normal normal = intersection.normal;
    normal.normalise();

    Colour finalColour = new Colour();
    float lambCoef = (float) normal.dot(lightDirection);

    if(lambCoef>0){
        finalColour.r = Math.max(0.0f, diffuseColour.r * lambCoef * light.intensity.r);
        finalColour.g = Math.max(0.0f, diffuseColour.g * lambCoef * light.intensity.g);
        finalColour.b = Math.max(0.0f, diffuseColour.b * lambCoef * light.intensity.b);


    }
    return finalColour;

}

I'm getting different values for lambCoef each time but not by very much for example for the red sphere, for pixels about 20 pixels vertical from each other, I get: 0.9446402 0.94463843 0.9446326 0.94462925 For to get the normal for the sphere I use:

public Normal getNormalAt(Vector3D point) {

    Normal normal = new Normal(point);
    normal = normal.subtract(center);
    normal = normal.multiply(-1);
    normal.normalise();
    return normal;

}

which seems to work. Then for my dot and cross code I use:

public double dot(Vector3D vector){
    return x*vector.x + y*vector.y +z*vector.z;
}

public double dot(Point3D point){
    return x*point.x + y*point.y +z*point.z;
}

public double dot(Normal normal){
    return x*normal.x + y*normal.y +z*normal.z;
}

public Vector3D cross(Vector3D vector) {

    Vector3D crossedVector =  new Vector3D();

    crossedVector.x = y*vector.z - z*vector.y;
    crossedVector.y = z*vector.x - x*vector.z;
    crossedVector.z = x*vector.y - y*vector.x;

    return crossedVector;

}

Which also seems to be correct. Any help would really be appreciated, and I'll be happy to provide more info if needed.

I'm now getting this sort of image:

enter image description here

Which sort of makes sense since the plane is at a much shallower angle to the spheres. It's still wrong though.

Community
  • 1
  • 1
user2320239
  • 1,021
  • 2
  • 18
  • 43

1 Answers1

0

+1 for using discrete Normal, Point, and Vector classes. In your shade() method, it doesn't look to me like you're accounting for the distance of the light source to the intersection point. Basically, you want intersection points that are further away from a given light to receive less light than points that are closer to the light. You can fudge this for point light sources by adjusting the light's intensity by a factor of c / (distance * distance), where c is an empirically-determined lightness correction factor (start with 1 and then adjust upward if the result is too dark) and distance is the distance between the point light source and your intersection point. When I say adjust I mean add that term to the finalColour calculation, not actually change the value of light.intensity.

Once you get that working, you may want to think about sampling light sources in terms of PDFs instead of using the 1/d*d hack.

Daniel A. Thompson
  • 1,904
  • 1
  • 17
  • 26