<p>In raymarching, it's typical to change the direction of the ray according to the fragment coordinates, but leave the origin at vec3(0,0,0). In you code you add <code>r</code>, which is equivalent to vec3(x,y,1) to <code>ray_pos</code>, which starts at <code>vec3(x,y,0)</code>. You scale x and y properly to lie from 0 to 1. So lets consider the angle of the ray along the x coordinate. Lets say x=1 and y=0 for a given array. If x=1, y=0, and z=1,  then you get a 45 degree fov as desired. In your code, you would add an extra x=1 to your ray direction, leading to a ray direction of X=2, Y=0, and Z=1, which is an fov of 63 degrees. However, the problem is worse, since the &quot;effective fov&quot; will change as X and Y vary, leading to significant distortion. Try using <code>vec3 ray_pos = cam_pos;</code> and see if it fixes your problem.</p>
<p>Other than that</p>
<ol>
<li>Make sure to separate the tracing code from the shading code</li>
<li>Always check your normals</li>
<li>In your sphere tracing loop, make sure to add breaking conditions for when the ray intersects the surface (SDF&lt;0.0001 or similar epsilon), or exceeds some max distance (I like 2048.0). This can save you some unnecessary &quot;back and forth&quot; oscillation near the end of your march sequence.</li>
</ol>
<p>The following is my ray-marching code:
github.com/mikeandike523/SDFBuilder/blob/main/f1.frag.</p>
<p>Feel free to even lift code as long as you use it according to GNU GPL 3.0</p>
<p>Thanks,
Mike</p>

CC BY-SA 4.0
2021-08-14T03:37:15.337Z
Silly me you are right adding that pixel based offset was a mistake.
Makogan
CC BY-SA 4.0
2021-08-14T03:59:23.887Z
I am curious, did it work in the end? Also, take a look at these two youtube channels (art of code) https://www.youtube.com/channel/UCcAlTqd9zID6aNX3TzwxJXg, and Inigo Quilez,https://www.youtube.com/user/mari1234mari. Also, if you ever want to easily test a shader, use shadertoy.com.
Michael Sohnen
CC BY-SA 4.0
2021-08-14T19:09:10.017Z
Yes, it worked perfectly, I understand now the mistake I made : p
Makogan
CC BY-SA 4.0
2021-08-14T00:16:09.680Z
2021-08-14T00:16:09.680Z
Michael Sohnen
<p>Some curvature artifacts are normal when doing raymarching or ray-tracing. And if you are careful, you can even find curvature artifacts in some rastered scenes if the triangles are small enough.</p>
<p>It may be that your camera is too close with respect to the size of your cube.</p>
<p>In the following render, which uses raymarching, the greatest dimension of the box is about 3.2 units. The camera is 4.5 units away from the center of the scene. The fov is 45 degrees, which is the same as in your code:</p>
<p><a href="https://i.sstatic.net/rSKgt.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/rSKgt.png" alt="enter image description here" /></a></p>
<p>It is also important to mention, that in some cases, you won't notice this same distortion effect in raster rendering, since only the vertices of large triangles are distorted, but the edges are always straight.</p>
<p>Also I recommend testing your normal generation. You can do this by making the color of the material equal to the absolute value of the normal.</p>

CC BY-SA 4.0
2021-08-13T07:35:53.413Z
The normals in that first image are wrong, they are the normals of a sphere. It was mostly negligence on my end to change them.

What you are saying might make sense, although what is the underlying cause that creates the distortion? And is there a way to minimize it?
Makogan
CC BY-SA 4.0
2021-08-13T23:32:35.783Z
1 -- Can you list the exact coordinates of your box and camera?
Michael Sohnen
CC BY-SA 4.0
2021-08-13T23:39:25.573Z
the box is 2x2x2 centered at the origin.

The camera (I don't have a way print the values right now) is quite close to it about 0.1 - 0.5 units away from it.
Makogan
CC BY-SA 4.0
2021-08-13T23:56:21.690Z
When reviewing the question, I came across a MASSIVE FLAW in your program. In your main function, you type `vec3 ray_pos = vec3(x, y, 0) + cam_pos;`,  You should not add vec(x,y,0), since you later add r, which contains information about the screen. In raymarching and raytracing, you always trace from the origin.  I'm writing a new answer now describing why. Additionally, here is my implementation of raymarching: https://github.com/mikeandike523/SDFBuilder/blob/main/f1.frag. If you want to arrange a quick Zoom call to debug your code, comment here.
Michael Sohnen
CC BY-SA 4.0
2021-08-13T07:29:21.083Z
2021-08-13T07:29:21.083Z
Michael Sohnen
<p>I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:</p>
<p><a href="https://i.sstatic.net/TDJyE.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/TDJyE.png" alt="enter image description here" /></a></p>
<p>I am not entirely sure where they are coming from, as I am using nothing but linear operations to render this.</p>
<p>This is how I generate a ray:</p>
<pre><code>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);
}
</code></pre>
<p>And after that all I do is ray march until I am inside the volume.</p>
<p>This is the full shader:</p>
<pre><code>#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 &lt;phong_lighting.glsl&gt;

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&gt;n.y &amp;&amp; n.x&gt;n.z) ? ivec3(0,1,2) :
               (n.y&gt;n.z)            ? ivec3(1,2,0) :
                                      ivec3(2,0,1) ;
    // determine minor axis (in x; yz are following axis)
    ivec3 mi = (n.x&lt;n.y &amp;&amp; n.x&lt;n.z) ? ivec3(0,1,2) :
               (n.y&lt;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 &lt; 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 &lt;= 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 &lt; 0.01);

    imageStore(
        output_image,
        ivec2(disp_x, disp_y),
        x_color
    );
}
</code></pre>
<p>This image might make it more obvious:</p>
<p><a href="https://i.sstatic.net/YVnkX.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/YVnkX.png" alt="enter image description here" /></a></p>
<p>Same scene raymarched:</p>
<p><a href="https://i.sstatic.net/q3pqo.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/q3pqo.png" alt="enter image description here" /></a></p>

CC BY-SA 4.0
2021-07-22T10:43:46.820Z
This is not enough information to answer your question.
lightxbulb
CC BY-SA 4.0
2021-07-22T19:00:26.777Z
What additional information is needed?
Makogan
CC BY-SA 4.0
2021-07-23T16:35:41.503Z
Your `highlight` variable produces the red curves.
lightxbulb
CC BY-SA 4.0
2021-07-23T16:59:37.540Z
Yes, that is correct.
Makogan
CC BY-SA 4.0
2021-07-23T17:26:34.987Z
So are you not asking about the red curves? "but when my camera is close to the object I see curves"
lightxbulb
CC BY-SA 4.0
2021-07-23T18:03:10.570Z
The curves are in the entire object. I.e. the object is meant to be a cube with round edges, but if you look at the image, there is curvature along the entire object, as if it was being distorted (imagine applying a fish eye effect).

i.e. I am asking about some strange deformation that occurs only when the camera is clsoe to the object.
Makogan
CC BY-SA 4.0
2021-07-23T20:02:50.830Z
Perspective projection distortion? Intersection error distortion?
lightxbulb
CC BY-SA 4.0
2021-07-23T21:21:17.090Z
Ray volume intersection distortion I think.
Makogan
CC BY-SA 4.0
2021-07-25T23:29:05.293Z
@lightxbulb I added a new image that I think better shows what I mean by curvature. That;s a straight box frame.
Makogan
CC BY-SA 4.0
2021-07-26T09:08:23.533Z
What do you get with ray-tracing (not sphere tracing) for the last scene?
lightxbulb
CC BY-SA 4.0
2021-07-26T20:47:49.250Z
Pretty much the same at lower fps.
Makogan
CC BY-SA 4.0
2021-07-26T21:01:27.923Z
I assumed it was sphere tracing error, but since you've tested ray-tracing and the issue persists I have no more guesses. A perspective projection (equivalently ray-tracing) ought to produce straight lines, yet in your case it doesn't.
lightxbulb
CC BY-SA 4.0
2021-07-26T21:13:56.723Z
Someone mentioned to me it could be lack of fp precision.
Makogan
CC BY-SA 4.0
2021-07-26T21:22:21.600Z
Why do you get these seesaw like artifacts in the last image? Do you have the equivalent ray-traced version?
lightxbulb
CC BY-SA 4.0
2021-07-26T21:30:45.103Z
The seesaw artifacts are because I am just raymarching, so sometimes the ray walks through the thin part of the shape without detecting a collision.
Makogan
CC BY-SA 4.0
2021-07-26T22:24:13.640Z
So did you try ray-tracing with analytic intersections with the same shape?
lightxbulb
CC BY-SA 4.0
2021-07-26T22:31:33.667Z
I am not sure how to ray trace this shape in particular.
Makogan
CC BY-SA 4.0
2021-07-27T05:47:43.627Z
It's a shape made of elongated boxes. If you have a ray-box intersection routine you should be able to do it.
lightxbulb
CC BY-SA 4.0
2021-08-13T09:57:38.617Z
One issue I see is the ray marcher loop has no escape so it's possible to overshoot the surface due to rounding (this is the cause of the sawtooth pattern) . You should check that sphere_radius is below some epsilon and early escape the loop.
PaulHK
CC BY-SA 4.0
2021-08-13T19:08:08.143Z
@PaulHK with sphere tracing if you overshoot you start going backwards along the ray since the sphere radius is now negative so if you overshoot it it will be by just a little. The sawteeth pattern appears in the ray marched image not in the spre traced one. : p
Makogan
<raytracing><shader><artifacts><signed-distance-field>
How to avoid curvature artifact in raytracer?
Makogan
# How to avoid curvature artifact in raytracer?

(Asked by: username_0 on 2021-07-21)

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](https://i.sstatic.net/TDJyE.png)](https://i.sstatic.net/TDJyE.png)

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](https://i.sstatic.net/YVnkX.png)](https://i.sstatic.net/YVnkX.png)

Same scene raymarched:

[![enter image description here](https://i.sstatic.net/q3pqo.png)](https://i.sstatic.net/q3pqo.png)

**Tags:** raytracing, shader, artifacts, signed-distance-field

> **Comments:**
> **username_1**: This is not enough information to answer your question.  
> **username_0**: What additional information is needed?  
> **username_1**: Your `highlight` variable produces the red curves.  
> **username_0**: Yes, that is correct.  
> **username_1**: So are you not asking about the red curves? "but when my camera is close to the object I see curves"  
> **username_0**: The curves are in the entire object. I.e. the object is meant to be a cube with round edges, but if you look at the image, there is curvature along the entire object, as if it was being distorted (imagine applying a fish eye effect).  i.e. I am asking about some strange deformation that occurs only when the camera is clsoe to the object.  
> **username_1**: Perspective projection distortion? Intersection error distortion?  
> **username_0**: Ray volume intersection distortion I think.  
> **username_0**: @username_1 I added a new image that I think better shows what I mean by curvature. That;s a straight box frame.  
> **username_1**: What do you get with ray-tracing (not sphere tracing) for the last scene?  
> **username_0**: Pretty much the same at lower fps.  
> **username_1**: I assumed it was sphere tracing error, but since you've tested ray-tracing and the issue persists I have no more guesses. A perspective projection (equivalently ray-tracing) ought to produce straight lines, yet in your case it doesn't.  
> **username_0**: Someone mentioned to me it could be lack of fp precision.  
> **username_1**: Why do you get these seesaw like artifacts in the last image? Do you have the equivalent ray-traced version?  
> **username_0**: The seesaw artifacts are because I am just raymarching, so sometimes the ray walks through the thin part of the shape without detecting a collision.  
> **username_1**: So did you try ray-tracing with analytic intersections with the same shape?  
> **username_0**: I am not sure how to ray trace this shape in particular.  
> **username_1**: It's a shape made of elongated boxes. If you have a ray-box intersection routine you should be able to do it.  
> **username_2**: One issue I see is the ray marcher loop has no escape so it's possible to overshoot the surface due to rounding (this is the cause of the sawtooth pattern) . You should check that sphere_radius is below some epsilon and early escape the loop.  
> **username_0**: @username_2 with sphere tracing if you overshoot you start going backwards along the ray since the sphere radius is now negative so if you overshoot it it will be by just a little. The sawteeth pattern appears in the ray marched image not in the spre traced one. : p  

---

## 2 answers

### Answer by username_3 on 2021-08-14. Score: 2 | Accepted answer

In raymarching, it's typical to change the direction of the ray according to the fragment coordinates, but leave the origin at vec3(0,0,0). In you code you add `r`, which is equivalent to vec3(x,y,1) to `ray_pos`, which starts at `vec3(x,y,0)`. You scale x and y properly to lie from 0 to 1. So lets consider the angle of the ray along the x coordinate. Lets say x=1 and y=0 for a given array. If x=1, y=0, and z=1, then you get a 45 degree fov as desired. In your code, you would add an extra x=1 to your ray direction, leading to a ray direction of X=2, Y=0, and Z=1, which is an fov of 63 degrees. However, the problem is worse, since the "effective fov" will change as X and Y vary, leading to significant distortion. Try using `vec3 ray_pos = cam_pos;` and see if it fixes your problem.

Other than that

1. Make sure to separate the tracing code from the shading code
2. Always check your normals
3. In your sphere tracing loop, make sure to add breaking conditions for when the ray intersects the surface (SDF<0.0001 or similar epsilon), or exceeds some max distance (I like 2048.0). This can save you some unnecessary "back and forth" oscillation near the end of your march sequence.

The following is my ray-marching code:
github.com/mikeandike523/SDFBuilder/blob/main/f1.frag.

Feel free to even lift code as long as you use it according to GNU GPL 3.0

Thanks,
Mike

> **Comments:**
> **username_0**: Silly me you are right adding that pixel based offset was a mistake.  
> **username_3**: I am curious, did it work in the end? Also, take a look at these two youtube channels (art of code) https://www.youtube.com/channel/UCcAlTqd9zID6aNX3TzwxJXg, and Inigo Quilez,https://www.youtube.com/user/mari1234mari. Also, if you ever want to easily test a shader, use shadertoy.com.  
> **username_0**: Yes, it worked perfectly, I understand now the mistake I made : p  

---

### Answer by username_3 on 2021-08-13. Score: 1

Some curvature artifacts are normal when doing raymarching or ray-tracing. And if you are careful, you can even find curvature artifacts in some rastered scenes if the triangles are small enough.

It may be that your camera is too close with respect to the size of your cube.

In the following render, which uses raymarching, the greatest dimension of the box is about 3.2 units. The camera is 4.5 units away from the center of the scene. The fov is 45 degrees, which is the same as in your code:

[![enter image description here](https://i.sstatic.net/rSKgt.png)](https://i.sstatic.net/rSKgt.png)

It is also important to mention, that in some cases, you won't notice this same distortion effect in raster rendering, since only the vertices of large triangles are distorted, but the edges are always straight.

Also I recommend testing your normal generation. You can do this by making the color of the material equal to the absolute value of the normal.

> **Comments:**
> **username_0**: The normals in that first image are wrong, they are the normals of a sphere. It was mostly negligence on my end to change them.  What you are saying might make sense, although what is the underlying cause that creates the distortion? And is there a way to minimize it?  
> **username_3**: 1 -- Can you list the exact coordinates of your box and camera?  
> **username_0**: the box is 2x2x2 centered at the origin.  The camera (I don't have a way print the values right now) is quite close to it about 0.1 - 0.5 units away from it.  
> **username_3**: When reviewing the question, I came across a MASSIVE FLAW in your program. In your main function, you type `vec3 ray_pos = vec3(x, y, 0) + cam_pos;`,  You should not add vec(x,y,0), since you later add r, which contains information about the screen. In raymarching and raytracing, you always trace from the origin.  I'm writing a new answer now describing why. Additionally, here is my implementation of raymarching: https://github.com/mikeandike523/SDFBuilder/blob/main/f1.frag. If you want to arrange a quick Zoom call to debug your code, comment here.  

---

