0
$\begingroup$

I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:

enter image description here

I am not entirely sure where they are coming from, as I am using nothing but linear operations to render this.

This is how I generate a ray:

vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)
{
    vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));
    r.y /= aspect_ratio;

    return normalize(r);
}

And after that all I do is ray march until I am inside the volume.

This is the full shader:

#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_scalar_block_layout : enable
#extension GL_NV_compute_shader_derivatives : enable

layout (local_size_x = 8, local_size_y = 8) in;

layout(binding = 0) uniform MVPOnlyUbo
{
    mat4 model;
    mat4 view;
    mat4 proj;
};

layout(binding = 1, rgba16f) uniform image2D output_image;

layout(binding = 2) uniform RayTracingData
{
    uint display_width;
    uint display_height;
};

layout(binding = 3) uniform sampler2D albedo;

#include <phong_lighting.glsl>

float SphereFunction(vec3 position)
{
    return sqrt(dot(position, position)) - 64;
}

vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)
{
    vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));
    r.y /= aspect_ratio;

    return normalize(r);
}

float SdRoundBox( vec3 p  )
{
    vec3 b = vec3(2, 2, 2);
    float r = 0.5;
    vec3 q = abs(p) - b;
    return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;
}

vec3 Gradient(vec3 point)
{
    const float epsilon = 0.0001;
    const float dx =
          SdBoxSphere(vec3(point.x + epsilon, point.y, point.z))
        - SdBoxSphere(vec3(point.x - epsilon, point.y, point.z));

    const float dy =
          SdBoxSphere(vec3(point.x, point.y + epsilon, point.z))
        - SdBoxSphere(vec3(point.x, point.y - epsilon, point.z));

    const float dz =
          SdBoxSphere(vec3(point.x, point.y, point.z  + epsilon))
        - SdBoxSphere(vec3(point.x, point.y, point.z  - epsilon));

    return vec3(dx, dy, dz);
}

vec4 BiplanarMapping( sampler2D sam, in vec3 p, in vec3 n, in float k )
{
    // grab coord derivatives for texturing
    vec3 dpdx = vec3(0.01);//dFdx(p);
    vec3 dpdy = vec3(0.01);//dFdy(p);
    n = abs(n);

    // determine major axis (in x; yz are following axis)
    ivec3 ma = (n.x>n.y && n.x>n.z) ? ivec3(0,1,2) :
               (n.y>n.z)            ? ivec3(1,2,0) :
                                      ivec3(2,0,1) ;
    // determine minor axis (in x; yz are following axis)
    ivec3 mi = (n.x<n.y && n.x<n.z) ? ivec3(0,1,2) :
               (n.y<n.z)            ? ivec3(1,2,0) :
                                      ivec3(2,0,1) ;
    // determine median axis (in x;  yz are following axis)
    ivec3 me = ivec3(3) - mi - ma;

    // project+fetch
    vec4 x = textureGrad( sam, vec2(   p[ma.y],   p[ma.z]),
                               vec2(dpdx[ma.y],dpdx[ma.z]),
                               vec2(dpdy[ma.y],dpdy[ma.z]) );
    vec4 y = textureGrad( sam, vec2(   p[me.y],   p[me.z]),
                               vec2(dpdx[me.y],dpdx[me.z]),
                               vec2(dpdy[me.y],dpdy[me.z]) );

    // blend factors
    vec2 w = vec2(n[ma.x],n[me.x]);
    // make local support
    w = clamp( (w-0.5773)/(1.0-0.5773), 0.0, 1.0 );
    // shape transition
    w = pow( w, vec2(k/8.0) );
    // blend and return
    return (x*w.x + y*w.y) / (w.x + w.y);
}

void main()
{
    const float aspect_ratio = float(display_width) / float(display_height);
    const float disp_x = gl_GlobalInvocationID.x;
    const float disp_y = gl_GlobalInvocationID.y;

    const float x = disp_x * 2 / display_width - 1;
    const float y = disp_y * 2 / display_height - 1;

    const vec3 r = (inverse(view) * vec4(GenerateRay(vec2(x, y), aspect_ratio, 45), 0)).xyz;
    const vec3 cam_pos = (inverse(view) * vec4(0, 0, 0, 1)).xyz;

    vec3 ray_pos = vec3(x, y, 0) + cam_pos;
    vec4 x_color = vec4(0);

    float last_distance = 0;
    for(uint i = 0; i < 100; i++)
    {
        float sphere_radius = SdRoundBoxray_pos);
        ray_pos += r * sphere_radius;
        last_distance = sphere_radius;
    }

    const vec3 normal = normalize(Gradient(ray_pos));
    vec3 albedo = BiplanarMapping( albedo, ray_pos, normal, 10 ).rgb;
    float test = min(min(mod(ray_pos.x, 1.f), mod(ray_pos.y, 1.f)), mod(ray_pos.z, 1.f));
    vec4 highlight = test <= 0.01 ? vec4(1, 0, 0, 1) : vec4(0);

    vec4 color = BlinnPhong(
        ray_pos,
        normal,
        cam_pos,
        albedo,
        vec3(100),
        normalize(vec3(1, 1, 1)) * 0.3,
        1)
        + highlight;

    x_color = color * int(last_distance < 0.01);

    imageStore(
        output_image,
        ivec2(disp_x, disp_y),
        x_color
    );
}

This image might make it more obvious:

enter image description here

Same scene raymarched:

enter image description here

$\endgroup$
18
  • $\begingroup$ This is not enough information to answer your question. $\endgroup$ – lightxbulb Jul 22 at 10:43
  • $\begingroup$ What additional information is needed? $\endgroup$ – Makogan Jul 22 at 19:00
  • $\begingroup$ Your highlight variable produces the red curves. $\endgroup$ – lightxbulb Jul 23 at 16:35
  • $\begingroup$ Yes, that is correct. $\endgroup$ – Makogan Jul 23 at 16:59
  • $\begingroup$ So are you not asking about the red curves? "but when my camera is close to the object I see curves" $\endgroup$ – lightxbulb Jul 23 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.