I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:
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:
Same scene raymarched:
highlight
variable produces the red curves. $\endgroup$