0
votes

I am implementing a ray tracer with mesh points in WebGL. Few words for my implementation.

I am passing vertex values and vertex normals in textures and I unpack them in the fragment shader where the ray tracing algorithm is executed. The spheres consisting of triangles had a flat shaded look, then I multiplied the vertex normals of the triangle with the barycentric coords and I had the smooth look in the triangle spheres. The problem is when I calculate the shadow, it has the same "edgy" look. Ill provide a print screen of the result and the code of how I currently calculate the shadow rays.

enter image description here

As you see the sphere surface appears smooth but the shadow is not.

here is the calcShadow function i use:

vec3 calcShadow(Sphere lightSource, vec3 hitPos){
    vec3 color;

    vec3 lightDir =  normalize(lightSource.center-hitPos);
    Ray shadowRay = Ray(hitPos, lightDir);

    float isHitLight = hitLightSource(shadowRay,lightSource);
    float isHitMesh = hitMesh(shadowRay);

    if (isHitMesh < isHitLight) {
        color = vec3(0.5,0.5,0.5);
    }else{
        color = vec3(1.,1.,1.);    
    }
    return color;
}

the hitMesh:

float hitMesh(Ray R_){
    float mindist = 1000.;
    vec4 a = vec4(0.0), b = vec4(0.0), c = vec4(0.0);
    vec3 intersect = vec3(0.0,0.0,0.0);

    for (int i = 0; i < vertsCount; i += 3) {
        a = texelFetch(uMeshData, ivec2(i, 0), 0);
        b = texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(1, 0));
        c = texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(2, 0));

        vec3 triangleNormal;
        vec3 uvt;
        float z;

        bool isHit = hitTriangleSecond(R_.orig, R_.dir, a.xyz, b.xyz, c.xyz, uvt, triangleNormal, intersect, z);;
        if (isHit) {
            if (z<mindist && z > 0.001)  mindist = z;
        } 

    }
    return mindist;
}

and this is the hitTriangke second method for the triangle intersection test:

bool hitTriangleSecond( vec3 orig, vec3 dir, vec3 a, vec3 b, vec3 c,
                        out vec3 uvt, out vec3 N, out vec3 x, out float dist) {

    float eps=1e-8;

    vec3 ab = b - a;
    vec3 ac = c - a;

    N = normalize(cross(ab, ac));

    dist = dot(a - orig, N) / dot(dir, N);
    x    = orig + dir * dist;

    vec3 ax = x - a;

    float d00 = dot(ab, ab);
    float d01 = dot(ab, ac);
    float d11 = dot(ac, ac);
    float d20 = dot(ax, ab);
    float d21 = dot(ax, ac);

    float denom = d00 * d11 - d01 * d01; // determinant

    // if the determinant is negative the triangle is backfacing
    // if the determinant is close to 0, the ray misses the triangl
    if ( denom <= eps )
        return false;

    uvt.y = (d11 * d20 - d01 * d21) / denom;
    if ( uvt.y < 0.0 || uvt.y > 1.0 )
        return false;

    uvt.z = (d00 * d21 - d01 * d20) / denom;
    if ( uvt.z < 0.0 || uvt.z > 1.0 )
        return false;

    uvt.x = 1.0 - uvt.y - uvt.z;
    if ( uvt.x < 0.0 || uvt.x > 1.0 )
        return false;

    return true;
}

I know that there is no calculation of the interpolated triangle normal but my question is, Do I need to update the hitTriangle function to return the interpolated normal, based on the vertex normals? or I need to calculate the barycentric coords and then insert it to the hit triangle function? I kinda not understand how to implement smooth shadows...

below is my trace for loop where I unpack the mesh and calculate the interpolated normal of the hit and this is how I got the smooth surface look:

for (int i = 0; i < vertsCount; i += 3) {

            a = texelFetch(uMeshData, ivec2(i, 0), 0);
            b = texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(1, 0));
            c = texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(2, 0));

            aN = texelFetch(uNormData, ivec2(i, 0), 0);
            bN = texelFetchOffset(uNormData, ivec2(i, 0), 0, ivec2(1, 0));
            cN = texelFetchOffset(uNormData, ivec2(i, 0), 0, ivec2(2, 0));

            vec3 uvt;
            vec3 intersect;
            float z;
            bool isHit = hitTriangleSecond(R_.orig, R_.dir, a.xyz, b.xyz, c.xyz, uvt, triangleNormal, intersect, z);
            if (isHit) {

                if (z<mindist && z > 0.001) {
                    hitPos1 = intersect;

                    mindist = z;
                    weHitSomething = true;
                    material.type = DIEL;
                    material.albedo = vec3(.8, .3, .4);
                    normal = aN.xyz*uvt.x + bN.xyz*uvt.y + cN.xyz*uvt.z;

                    hitPos = hitPos1;            
                }
            }      
        } 
1
I cannot figure it out no matter what i test.. Some insight of the problem would be nice. Thank youThodoris Koutsis
Why do you expect not to get an edgy look to the shadows? The mesh used for the ray hit test is still the low resolution triangle mesh, even if you mess around with normals for correcting the lighting calculation. What you really need for shadows is true displacement of the silhouette edge, but I'm not sure even correcting for the normals would really give you that (surface orientation != surface displacement).solidpixel
@solidpixel I understand that the shadows will show like that, this is why I asked , but can you explain what you mean by the term "true displacement of the silhouette edge"? I wanted to know how If there is a way of having smooth Shadows.Thodoris Koutsis
Turned this into an answer ...solidpixel

1 Answers

1
votes

The mesh used for the ray hit test is still the low resolution triangle mesh, even if you mess around with normals for correcting the lighting calculation, so the sharp corners in the shadows are somewhat expected.

Ray casting is reliant on triangle intersection, so for smooth shadows you need smooth geometry in the shadow caster - i.e. more triangles. Techniques like normal mapping work for lighting because you can fake an approximate light intensity based on a modified orientation, but there isn't actually any surface displacement which changes the physical geometry, so that won't help to correct any incorrect hit testing.

What you really need for shadows is more geometry so that you accurately describe the shape of the shadow casting silhouette edge using real triangles.