2

So i'm making a raytracer in OpenGL, fully shader based, and i'm struggling to know where the problem is with my Shadow rays. If i multiply the radiance of the object by the shadowRay output, it seems like only the "edge" of the sphere is lighten up

I verified multiple times the code without finding where the problem comes from.

This is what i get:

Result

vec3 TraceShadowRay(vec3 hitPoint, vec3 normal, Object objects[3])
{
    Light pointLight;

    pointLight.position = vec3(0, 80, 0);
    pointLight.intensity = 2;

    Ray ShadowRay;
    ShadowRay.origin = hitPoint + normal * 1e-4;
    ShadowRay.dir = normalize(pointLight.position - ShadowRay.origin);
    ShadowRay.t = 100000;
    //ShadowRay.dir = vec3(0, 1, 0);

    for(int i = 0; i < 3; ++i)
    {
        if(objects[i].type == 0)
        {
            if(interectSphere(objects[i].position, objects[i].radius, ShadowRay))
            {
                return vec3(0);
            }
        }
        if(objects[i].type == 1)
        {
            if(intersectPlane(objects[i].normal, objects[i].position, ShadowRay))
            {
                return vec3(0);
            }
        }
    }
    float AngleNormalShadow = dot(ShadowRay.dir, normal);
    clamp(AngleNormalShadow, 0, 1);

    return GetLight(ShadowRay.origin, pointLight);// * AngleNormalShadow;
}

The getLight function:

vec3 GetLight(vec3 origin, Light light)
{
    return vec3(1, 1, 1) * light.intensity;
    //float dist = sqrt( ((origin.x - light.position.x) * (origin.x - light.position.x))  +   ((origin.y - light.position.y) * (origin.y - light.position.y)));
    //return (vec3(1, 1, 1) * light.intensity) / (4 * M_PI * ((origin - light.position).length * (origin - light.position).length));
}

The intersectSphere function:

bool interectSphere(const vec3 center, float radius, inout Ray r)
{
    vec3 o = r.origin;
    vec3 d = r.dir;

    vec3 v = o - center;

    float b = 2 * dot(v, d);
    float c = dot(v, v) - radius*radius;
    float delta = b*b - 4 * c;

    if(delta < 1e-4)
        return false;

    float t1 = (-b - sqrt(delta))/2;
    float t2 = (-b + sqrt(delta))/2;

    if(t1 < t2)
    {
        r.t = t1;
        r.t2 = t2;
    }
    else if(t2 < t1)
    {
        r.t = t2;
        r.t2 = t1;
    }

    r.reflectionNormal = normalize((r.origin + r.dir * r.t) - center);

    return true;
}

The result expected is a nice shaded sphere with light coming from the top of the spheres

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • see [ray and ellipsoid intersection accuracy improvement](https://stackoverflow.com/q/25470493/2521214) to cross check your intersection equations. You can compare your raycasting with mine: [Reflection and refraction impossible without recursive ray tracing?](https://stackoverflow.com/a/45140313/2521214) some times comparing with working code helps to discover hidden bugs. Also try to use double instead of float ... if the situation imporves you are hitting accuracy problems (its common on spheres with ray tracers especially in GLSL due to lower precision of floats) – Spektre Jul 13 '19 at 09:41

1 Answers1

1

Could it be a missing negation? Looks like interectSphere() returns true when there is a collision, but the calling code in TraceShadowRay() bails out when it returns true.

old:

        if(interectSphere(objects[i].position, objects[i].radius, ShadowRay))
        {
            return vec3(0);
        }

new:

        if(!interectSphere(objects[i].position, objects[i].radius, ShadowRay))
        {
            return vec3(0);
        }
fifoforlifo
  • 724
  • 5
  • 9