我正在尝试在 GLSL 片段着色器中渲染 raymarched 场景。我能够在不使用 MVP 矩阵时成功绘制场景,而只是从指定的摄像机位置沿用固定视图渲染的方向场景行进光线,但是当我尝试更改代码以使用模型视图投影矩阵时(到请允许我使用合适的相机在场景中移动)我只是得到一个黑屏。我正在按照使用模型的说明,从这里查看带有光线行进的投影矩阵
不使用模型视图投影时我的顶点着色器
#version 330 core
layout (location = 0) in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
不使用模型视图投影时我的片段着色器
#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);
}
但是,当我尝试使用模型视图投影矩阵来转换场景时,我得到的只是一个空白屏幕。
这是我将矩阵传递给着色器的方法:
...
glm::mat4 mvp = camera.GetProjMatrix(width, height) * camera.GetViewMatrix() * octree.getTransform();
auto inverseMatrix = glm::inverse(mvp);
raymarchShader.setMat4("mvp", mvp);
raymarchShader.setMat4("inverseMatrix", inverseMatrix);
我的模型视图投影矩阵顶点着色器
#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));
}
这是更新的片段着色器
...
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);
}
这是最终结果我到底做错了什么?如何使用模型视图投影矩阵计算光线行进的光线原点和方向?