 # Infinite Loop when Raymarching a Cube

#1

I’m not sure this is the right place to ask this, because this is my first post.

I’m working on a simple ray-marcher in OpenGL. The ray marching is done in the fragment shader of a full-screen quad. The shader code is as follows:

``````#version 460 core

in vec3 ray_view;

uniform mat4 viewMatrixInv;

vec3 rayDirection_world;
vec3 rayOrigin_world;
vec3 marchPoint;
vec3 normal;
vec3 toEye;
vec3 lightDirection = vec3(3, -1, -1);
vec3 toLight;
vec3 sdfVector;
float sdfValue;

out vec3 color;

const vec3 sphereCenter_world = vec3(0, 0, 0);
const float sphereRadius = 1.0f;

const vec3 cubeCenter_world = vec3(2, 0, 0);
const vec3 cubeDimensions = vec3(1, 1, 1);

vec3 deformationRepeat4(vec3 wp){
return vec3(
mod(wp.x + 2, 4) - 2,
mod(wp.y + 2, 4) - 2,
mod(wp.z + 2, 4) - 2
);
}

vec3 reflectAcrossPlane(vec3 n, float offsetFromOrigin, vec3 p) {
if(dot(n, p) - offsetFromOrigin < 0)
return p - 2 * n * (dot(normalize(n), p) - offsetFromOrigin);
return p;
}

float sdfCube(vec3 p) {
vec3 d = abs(p) - cubeDimensions;
return length(max(d,0.0))
+ min(max(d.x,max(d.y,d.z)),0.0) - .01;
}

float sdfSphere(vec3 p) {
return length(abs(p - cubeCenter_world)) - sphereRadius;
}

vec3 deformation(vec3 wp) {
return wp;
}

float distanceToNearest(vec3 p){
//First, applies the deformation
vec3 pDeformed = deformation(p);
//Then gets the actual sdf of the shape
return sdfCube(pDeformed - cubeCenter_world);
}

void main() {
//while(true);

rayDirection_world = (vec3(viewMatrixInv * vec4(normalize(ray_view), 0)));
rayOrigin_world = vec3(viewMatrixInv * vec4(0, 0, 0, 1));

marchPoint = rayOrigin_world;
while(true){

sdfValue = distanceToNearest(marchPoint);

//If the ray has hit the sphere
if(sdfValue < 0.001){
//Draw the sphere's color
//Finds the cube normal
//vec3 normal = vec3(
//	(distanceToNearest(vec3(marchPoint.x + 0.001, marchPoint.y, marchPoint.z)) - sdfValue) / 0.001,
//	(distanceToNearest(vec3(marchPoint.x, marchPoint.y + 0.001, marchPoint.z)) - sdfValue) / 0.001,
//	(distanceToNearest(vec3(marchPoint.x, marchPoint.y, marchPoint.z + 0.001)) - sdfValue) / 0.001
//);
toLight = -normalize(lightDirection);
toEye = normalize(rayOrigin_world - marchPoint);

color = vec3(1, 0, 0);// * clamp(dot(normal, toLight), 0, 1) + vec3(1, 1, 1) * pow(clamp(dot(normalize(toLight + toEye), normal), 0, 1), 7);
return;
}

//If the ray is beyond the distance from the camera
if(length(marchPoint - rayOrigin_world) > 1000){
//Draw the background color
color = vec3(0, 0.5, 0.2);
return;
}

//March the ray forward
marchPoint += rayDirection_world * sdfValue;
}

//color = vec3(distanceToNearest(rayOrigin_world + rayDirection_world) / 15, 0, 0);
}
``````

I compile and run the whole program using Visual Studio 2017. Everything compiles fine and starts to run, but after a few seconds Visual Studio breaks and shows an error message that reads, “Unhandled exception at 0x69CA9C29 (nvoglv32.dll) in GravelMarcher.exe: Fatal program exit requested.”

This is the same error I get when the shader can’t exit and loops forever, but I cannot for the life of me figure out why the shader code would be looping forever. Any input would be greatly appreciated, and I am happy to post whatever extra code I need to.

Thank you in advance for your help!

#2

I found out some more information what might cause the error:

When the line

``````while(true){
``````

to

``````for(unsigned int i = 0; i < 1000; i++)
``````

, everything works fine. But when I add a line to the end of the shader outside of the for loop to run if the loop is ever finished to draw white instead of the background color or red, I see no white pixels. This seems to mean that the loop is never finished, but somehow having everything wrapped in a loop changes its behavior?

The plot thickens further. When I change

``````i < 1000
``````

to

``````true
``````

so the for loop runs forever, the same problem as with the while loop happens. I have no idea what this all means. Maybe somehow the code is compiled differently? I really don’t know.

Also, this problem seems to be specific to the cube. When I change to the sphere SDF, it works fine.

One more also, this problem seems to only happen when the ‘lowest corner’ of the cube has coordinates above 0. I have no idea how this plays into it.

Any insight is greatly appreciated.