【发布时间】:2017-03-06 19:10:07
【问题描述】:
我在使用 SDF 函数在 GLSL 中进行球体追踪/光线行进时遇到了一些问题:
我的主程序(C++,使用 Vulkan)生成一个屏幕四边形,并为顶点着色器提供每个顶点 inPosition。顶点着色器可以访问窗口分辨率、投影矩阵和视图矩阵。使用glm::perspective(45.0, 1920/1080, 0.1, 100.0);生成投影矩阵。
在顶点着色器中,我尝试计算从vec4(0.0, 0.0, 0.0, 1.0) 的原点穿过图像平面的光线(使用齐次坐标的位置和方向)。我很困惑在哪里放置图像平面并选择 vec4(inPosition.xy, -5.0, 1.0) 现在沿着负 z 轴查看。
以下代码代表我的顶点着色器:
#version 450
#extension GL_ARB_separate_shader_objects : enable
struct Ray
{
vec4 pos;
vec4 dir;
};
layout(binding = 0) uniform UniformBufferObject {
vec3 res;
mat4 projection;
mat4 view;
} ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 0) out vec3 iResolution;
layout(location = 1) out Ray iRay;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
fragCoord = vec2(
((inPosition.x+1)/2) * (ubo.res.x-1),
((inPosition.y+1)/2) * (ubo.res.y-1)
);
iResolution = ubo.res;
gl_Position = vec4(inPosition, 1.0);
vec4 direction = inverse(ubo.projection) * vec4(inPosition.xy, -5.0, 1.0);
iRay.dir = direction;
iRay.pos = vec4(direction.xy, 0.0, 1.0);
}
我使用投影矩阵将方向转换为世界空间并将单位立方体扭曲为窗口分辨率。但是,在我的片段着色器中,SDF 函数和交叉点无法正常工作。如果我为距离和半径设置相同的值,我只能看到一个球体。查看片段着色器:
#version 450
#extension GL_ARB_separate_shader_objects : enable
struct Ray
{
vec4 pos;
vec4 dir;
};
layout(location = 0) in vec3 iResolution;
layout(location = 1) in Ray iRay;
layout(location = 0) out vec4 outColor;
float sdfSphere(vec3 p, float r)
{
return length(p) - r;
}
bool intersect(Ray ray)
{
for(int i = 0; i < 100; i++) {
float hit = sdfSphere((ray.pos.xyz + vec3(0.0, 0.0, -11.0)), 11.0);
ray.pos += hit * ray.dir;
if (hit < 0.001) {
return true;
}
}
return false;
}
void main()
{
bool result = intersect(iRay);
if(result == false) {
outColor = vec4(0.0, 0.0, 0.0, 1.0);
} else {
outColor = vec4(1.0, 0.0, 0.0, 1.0);
}
}
我的问题是:如何正确应用投影矩阵?如果它已经正确应用,为什么我不能为 SDF 球体设置不同的位置/半径?
【问题讨论】:
-
如果你使用 Vulkan,你应该这样标记它,而不是使用 OpenGL 标记。
标签: c++ matrix glsl raycasting vulkan