光线行进曲面在GLSL中的实现

Implementation of raymarching surfaces in GLSL

本文关键字:GLSL 实现 曲面      更新时间:2023-10-16

我已经阅读了很多关于GLSL着色器中光线行进的文章(比如这篇文章:http://www.iquilezles.org/www/articles/rmshadows/rmshadows.htm)它提出了一些我想问的问题。

在我的应用程序中,我正在用几个网格渲染一个场景,我想尝试阴影。虽然我似乎有点理解raymarching如何工作的概念,但我不太明白如何在GLSL中正确实现这一点。我知道如何计算光线和平面的交点,但如何通过GLSL着色器处理?

根据这里的线索:(https://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work)它提到你正在测量光线的起点和"表面"之间的距离。他所指的表面是网格吗?为了计算光线相交测试,我是否需要将组成网格的平面/点阵列发送到着色器?我需要使用深度缓冲区来确定曲面的距离吗?

这取决于着色器的作用与渲染引擎的作用。在像shadertoy这样的纯演示着色器中(请参见其阴影示例),整个场景都在着色器中编码,因此拍摄二次光线或更多光线(除了perfs)没有问题。

如果场景不是由着色器管理的,则需要引擎进行一些协作。至少,第一次生成阴影贴图(存在许多不同的算法)。请注意,使用SVO表示,场景首先被转换为稀疏体素,然后可以由着色器进行二次光线的行进。甚至可以用于主光线,但您可以在此处使用常规Z缓冲区,并对所有类型的次光线使用体素圆锥体跟踪(例如)(请参见此处的*使用体素锥体跟踪的交互式间接照明*:http://gigavoxels.imag.fr/publications.html(好吧,在您的简单应用程序中,您可能会发现它有些过头了)。有关软阴影和景深,请参阅开创性论文GigaVoxels:Ray Guided Streaming For Efficient and Detailed Voxel Rendering。请注意,该树甚至可能是三角形的规则BSP,而不是体素的八叉树。但随后你失去了SVO的许多优势(性能,为柔和的阴影增加)。

iq/RGBA(Inigo Quilezles)解释的光线行进方式是符号距离函数("SDF"s)的光线行进。这是一种描述场景的完全数学方法。

我们只渲染一个屏幕四边形,要显示的整个世界由片段着色器代码组成,这些代码要么操纵空间,要么计算到某个数学定义实体的符号距离,甚至组合不同对象的距离。

例如:

float fTorus(vec3 p, float smallRadius, float largeRadius)
{
    return length(vec2(length(p.xz) - largeRadius, p.y)) - smallRadius;
}
vec2 pR( inout vec2 p, in float radians )
{   
    p = cos( radians ) * p + sin( radians ) * vec2( p.y, -p.x ) );
    return p;
}
vec2 world( in vec3 p )
{
    pR( p.xz, radians( -45 ) );   // manipulate Space - rotate around Y
    p -= vec3( 0.0, 0.0, 10.0 ); // manipulate Space - move (after rot)
    return vec2( fTorus( p ), float( 1 ) );
    // finally return distance to torus in x and the material number in y
}

这个世界代码描述了在世界中的一个位置上的环面,该环面是由给定的旋转和平移产生的;p〃;在";世界;作用注意,我们反向修改空间,就像在相机空间中一样,所以要移动到空间中的一个点,我们必须从p中减去它的矢量。

无论如何,这就是iq提出的纯分析方法中几何的来源。也许可以进一步阅读:http://mercury.sexy/hg_sdf/