1

I am trying to render a raymarched scene in a GLSL fragment shader. I am able to draw the scene successfully when not using a MVP matrix and just marching a ray from a specified camera position in a direction Scene rendered with fixed view, however when I try and change my code to use a model view projection matrix (to allow me to use a proper camera to move around the scene) I simply get a black screen. I'm following the instructions for using the model, view projection matrices with ray marching from here

My vertex shader when not using model view projection

#version 330 core
layout (location = 0) in vec2 position;


void main() {
    gl_Position = vec4(position, 0.0, 1.0);
}

My fragment shader when not using model view projection

#version 330 core
#define MAX_VOXELS 128
#define MAX_STEPS 100
#define MAX_DIST 100.
#define SURF_DIST .001

uniform float iTime;
uniform vec2 iResolution;

uniform vec3 camPosition;
uniform vec3 camDirection;

uniform vec3 voxelPositions[MAX_VOXELS];
uniform float voxelSizes[MAX_VOXELS];
uniform int voxelCount;
out vec4 fragColor;

float sdBoundingBox( vec3 p, vec3 b, float e )
{
    p = abs(p  )-b;
    vec3 q = abs(p+e)-e;

    return min(min(
    length(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),
    length(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),
    length(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));
}

float GetDist(vec3 point) {
    float planeDist = point.y;
    float d = 10000.0;
    for(int i = 0; i < voxelCount; i++)
    {
        vec3 voxelSize = vec3(voxelSizes[i],voxelSizes[i],voxelSizes[i]);
        float vox = sdBoundingBox(point-voxelPositions[i], voxelSize, 0.015);
        d = min(d, vox);
    }

    return d;
}

float RayMarch(vec3 rayOrigin, vec3 rayDir) {
    float dO=0.;

    for(int i=0; i<MAX_STEPS; i++) {
        vec3 p = rayOrigin + rayDir*dO;
        float dS = GetDist(p);
        dO += dS;
        if(dO>MAX_DIST || dS<SURF_DIST) break;
    }

    return dO;
}

vec3 GetNormal(vec3 p) {
    float d = GetDist(p);
    vec2 e = vec2(.001, 0);

    vec3 n = d - vec3(
    GetDist(p-e.xyy),
    GetDist(p-e.yxy),
    GetDist(p-e.yyx));

    return normalize(n);
}


float GetLight(vec3 p) {
    vec3 lightPos = vec3(0, 5, 0);
    lightPos.xz += vec2(sin(iTime), cos(iTime))*2.;
    vec3 l = normalize(lightPos-p);
    vec3 n = GetNormal(p);

    float dif = clamp(dot(n, l), 0., 1.);
    float d = RayMarch(p+n*SURF_DIST*2., l);
    if(d<length(lightPos-p)) dif *= .1;

    return dif;
}

void main()
{
    vec2 uv = (gl_FragCoord.xy-.5*iResolution.xy)/iResolution.y;
    vec3 col = vec3(0);
    vec3 rayOrigin = camPosition;
    vec3 rayDir = normalize(vec3(uv.x, uv.y, 1));
    float d = RayMarch(rayOrigin, rayDir);
    vec3 p = rayOrigin + rayDir * d;

    float dif = GetLight(p);
    col = vec3(dif);
    col = pow(col, vec3(.4545));    // gamma correction

    fragColor = vec4(col,1.0);
}

However when I try to use a model view projection matrix to transform the scene I get nothing but a blank screen.

Here's how I pass my matrices to the shader:

...
glm::mat4 mvp = camera.GetProjMatrix(width, height) * camera.GetViewMatrix() * octree.getTransform();
auto inverseMatrix = glm::inverse(mvp);
raymarchShader.setMat4("mvp", mvp);
raymarchShader.setMat4("inverseMatrix", inverseMatrix);

My model view projection matrix vertex shader

#version 330 core
layout (location = 0) in vec2 position;

out vec4 near_4;
out vec4 far_4;

uniform mat4 mvp;
uniform mat4 inverseMatrix;

void main() {
    gl_Position = mvp * vec4(position, 0.0, 1.0);
    vec2 pos = gl_Position.xy/gl_Position.w;

    near_4 = inverseMatrix * (vec4(pos, -1.0, 1.0));
    far_4  = inverseMatrix * (vec4(pos, 1.0, 1.0));

}

And here's the updated fragment shader

...
in vec4 near_4;    //for computing rays in fragment shader
in vec4 far_4;
...
void main()
{
    vec2 uv = (gl_FragCoord.xy-.5*iResolution.xy)/iResolution.y;

    vec3 col = vec3(0);
    vec3 rayOrigin = near_4.xyz/near_4.w;
    vec3 far3 = far_4.xyz/far_4.w;
    vec3 rayDir = far3- rayOrigin;
    rayDir = normalize(rayDir);

    float d = RayMarch(rayOrigin, rayDir);

    vec3 p = rayOrigin + rayDir * d;

    float dif = GetLight(p);
    col = vec3(dif);
    col = pow(col, vec3(.4545));    // gamma correction

    fragColor = vec4(col,1.0);
}

This is the final resultWhat exactly am I doing wrong here? How do I compute ray origin and direction for raymarching using a model view projection matrix?

0x003
  • 65
  • 9
  • 1
    see https://stackoverflow.com/a/45140313/2521214 and https://stackoverflow.com/a/48092685/2521214 check the vertex shaders on how the ray position and direction is computed (however the second link is deleted and you are too low rep to view it it contains voxel back raytracer using 3D texture which is more or less what you trying to do) – Spektre Aug 17 '21 at 09:02
  • 1
    Thanks @Spektre, I found the second link helpful (used archive.org to view it) While adapting the code got something visible, I'm still struggling with allowing rotations (rotating just skews my perspective, not rotating around the target object). I need to improve my understanding of transforms and the coordinate systems – 0x003 Aug 20 '21 at 00:21
  • maybe this [Understanding 4x4 homogenous transform matrices](https://stackoverflow.com/a/28084380/2521214) will help a bit ... – Spektre Aug 20 '21 at 06:35

0 Answers0