How do I compute ray origin and direction for raymarching using a model view projection matrix?

1.1k Views Asked by At

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?

0

There are 0 best solutions below