3

In a similar way than in this related question, I am trying to render complex shapes by the mean of ray-tracing inside a cube: This is, 12 triangles are used to generate a bounding box and each fragment is used to render the given shape by ray-tracing.

enter image description here

For this example, I am using the easiest shape: a sphere.

Without discarding external fragments

The problem is that when the cube is rotated, different triangle angles are distording the sphere:

enter image description here

What I have attempted so far:

  1. I tried making the raytracing in World space, also in View-space as suggested in the related question.

  2. I checked that the worldCoordinate of the fragment is correct, by making a reverse projection from gl_fragCoord, with the same output.

  3. I switched to orthographic projection, where the distortion is reversed:

enter image description here

My conclusion is that, as described in the related question, the interpolant of the coordinates and the projection are the origin of the problem.

I could project the cube to a plane perpendicular to the camera direction, but I would like to understand the bottom of the question.

Related code:

Vertex shader:

#version 420 core

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

in vec3 in_Position;
in vec3 in_Normal;

out Vertex
{
    vec4 worldCoord;
    vec4 worldNormal;
} v;

void main(void)
{
    mat4 mv = view * model;

    // Position
    v.worldCoord = model * vec4(in_Position, 1.0);
    gl_Position = projection * mv * vec4(in_Position, 1.0);

    // Normal
    v.worldNormal = normalize(vec4(in_Normal, 0.0));
}

Fragment shader:

#version 420 core

uniform mat4 view;
uniform vec3 cameraPosView;

in Vertex
{
    vec4 worldCoord;
    vec4 worldNormal;
} v;

out vec4 out_Color;

bool sphereIntersection(vec4 rayOrig, vec4 rayDirNorm, vec4 spherePos, float radius, out float t_out)
{
    float r2 = radius * radius;
    vec4 L = spherePos - rayOrig;
    float tca = dot(L, rayDirNorm);

    float d2 = dot(L, L) - tca * tca;
    if(d2 > r2)
    {
        return false;
    }

    float thc = sqrt(r2 - d2);
    float t0 = tca - thc;
    float t1 = tca + thc;

    if (t0 > 0)
    {
        t_out = t0;
        return true;
    }

    if (t1 > 0)
    {
        t_out = t1;
        return true;
    }

    return false;
}


void main()
{
    vec3 color = vec3(1);

    vec4 spherePos = vec4(0.0, 0.0, 0.0, 1.0);
    float radius = 1.0;
    float t_out=0.0;

    vec4 cord = v.worldCoord;
    vec4 rayOrig = (inverse(view) * vec4(-cameraPosView, 1.0));
    vec4 rayDir = normalize(cord-rayOrig);

    if (sphereIntersection(rayOrig, rayDir, spherePos, 0.3, t_out))
    {
        out_Color = vec4(1.0);
    }
    else
    {
        discard;
    }

}
Adrian Maire
  • 14,354
  • 9
  • 45
  • 85
  • 1
    just a wild guess (without dissecting your code) but the animation looks like inconsistent ray origin/direction among the faces of BBOX. make sure all of your rays intersect focal point of your camera instead of znear plane. That is common bug in rookie ray tracing: combining view/projection matrices with ray vectors. Also make sure you test on square view to rule out aspect ratio problems (they can be weird sometimes and mislead a lot) – Spektre Jan 28 '22 at 09:24
  • thank you for your suggestion @Spektre, the second about aspect-ratio is promising, I am going to dig that part. – Adrian Maire Jan 28 '22 at 09:50
  • I bet is the first one ... point `(0,0,0)` in camera space might not be the focal point usually its translated in Z axis by focal length of your projection matrix in reverse direction to view direction... so usually `(0,0,+focal_length)` is the focal point (ray origin) ... see [vertex shader in here](https://stackoverflow.com/a/45140313/2521214) on how I cast the rays. If you render normaly over your ray trace the outputs should overlap perfectly – Spektre Jan 28 '22 at 11:02

0 Answers0