c++ - 绕过经典的延迟着色光体积

标签 c++ opengl glsl deferred-rendering

我想“绕过”延迟光照的经典光体积方法。

通常,当您想影响点光源体积内的像素时,您可以简单地渲染一个球体网格。

我想尝试另一种方法来做到这一点,想法是渲染一个包含球体的立方体,立方体是球体的“外接点”,因此每个面的中心都是球体的点。然后,如果您改为渲染球体,您只需从您的角度知道哪个片段将成为圆(屏幕上的球体)的一部分。

所以主要的问题是要知道哪个片段必须被丢弃。 我该怎么做: 在片段着色器中,我有我的“相机”世界坐标、我的片段世界坐标、我的球体世界中心和我的球体半径。 因此,我有一条直线,其方向 vector 由相机片段世界点建模。 我可以建立我的球体方程。 最后我可以知道直线是否与球体相交。

这样说是正确的,从我的角度,如果直线与球体相交,则该片段必须被视为高亮片段(如果我而是渲染了一个球体)?

最佳答案

Thus the check "lenght(fragment - sphereCenter) <= sphereRadius" doesn't really mean something here because the fragment is not on the sphere.

那又怎样?

灯光的标准延迟着色解决方案是渲染全屏四边形。渲染球体的目的是避免对光源效果之外的片段进行大量的逐片段计算。这意味着该球体的中心是光源,其半径代表光源产生影响的最大距离。

因此,从片段(即从您的 g 缓冲区数据重建,而不是立方体生成的片段)到球体中心的长度非常相关。这是片段和光源之间的长度。如果它大于球体半径(又名:光的最大范围),那么您可以剔除片段。

或者您可以让您的光衰减计算完成相同的工作。毕竟,为了让灯光看起来不像被裁剪过,球体半径必须与某种形式的光衰减一起使用。也就是说,当片段位于该距离时,光的衰减必须为 0 或小到可以忽略不计。

因此...渲染球体、立方体或全屏四边形并不重要。您可以剔除片段或让光衰减完成它的工作。


但是,如果您希望在读取任何 g-buffer 之前丢弃片段以节省性能,您可以这样做。假设您可以访问 FS 中球体/立方体中心的相机空间位置:

  1. 将立方体片段的位置转换为相机空间。您可以通过反向转换 gl_FragCoord 来做到这一点,但将相机空间位置传递给片段着色器可能会更快。这不像您的 VS 正在做很多工作或其他任何事情。

  2. 因为相机空间位置在相机空间中,所以它已经表示从相机进入场景的方向。所以现在,使用这个方向来执行射线/球体相交的部分。也就是说,一旦计算出判别式就停止(以避免昂贵的平方根)。判别式为:

    float A = dot(cam_position, cam_position);
    float B = -2 * (dot(cam_position, cam_sphere_center);
    float C = (dot(cam_sphere_center, cam_sphere_center)) - (radius * radius)
    float Discriminant = (B * B) - 4 * A * C;
    

    如果判别式为负,则丢弃片段。否则,做你平常的事情。

关于c++ - 绕过经典的延迟着色光体积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37774163/

相关文章:

c++ - 复制调用功能

c++ - 如何暂停这个opengl程序?

c++ - OpenGL gluLookat 无法使用着色器

c++ - 列号 1 超出范围 0..-1

c++ - 如何在 Linux 上的 Flutter 插件中使用 CMake 正确链接 ffmpeg?

c++ - push_back 上的 STL 列表段错误

opengl - (gl_FragCoord.z/gl_FragCoord.w) 代表什么?

opengl - 透视除法 : Why use the w component?

matrix - 在顶点着色器中将 GLSL mat4 分解为原始 RTS 值以计算 View UV 偏移

c++ - opengl 3.1 纹理未加载