在GLSL中实现射线行走表面

4
我一直在阅读关于GLSL着色器中光线行进的各种文章(例如这篇文章:http://www.iquilezles.org/www/articles/rmshadows/rmshadows.htm),这引发了我想要问的一些问题。
在我的应用程序中,我正在渲染一个带有几个网格的场景,并想尝试阴影。虽然我似乎有点理解光线行进的概念,但我不太明白如何在GLSL中正确实现它。我知道如何计算射线和平面的交点,但这该如何通过GLSL着色器处理?
根据这里的线程:(https://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work),它提到您正在测量光线起点和“表面”之间的距离。他所指的表面是指网格吗?我需要将组成网格的平面/点数组发送到着色器中以计算射线相交测试吗?我需要使用深度缓冲区来确定表面的距离吗?

关于最后一点,是的,阴影贴图对此非常有帮助。请看一下这个非常新的GDC'14演示文稿,大约在71-81页左右。虽然它的重点主要是使用镶嵌技术优化光线行进算法,但这些图表可能会在概念上帮助您。 - Andon M. Coleman
所以我想阴影贴图是实现这种效果的唯一方法。假设在我的着色器中,我从相机的视角获取帧缓冲图像和从光源视角获取深度缓冲,并且对于每个像素,从光线的起点到像素(在转换为3D空间坐标后)进行跟踪,并将其与帧缓冲区的像素进行比较。虽然这开始听起来更像是光线追踪而不是光线行进。 - Villsa
嗯,是的...但这并不是光线行进的好应用。如果你只想找到完全阻挡光线的第一个点的距离,那么你可以仅使用阴影图来完成。光线行进是设计用于使用有限数量的采样数据进行积分而不是解析方法;可以将其视为使用梯形法则和几个子区间下的面积近似计算曲线下的面积。它对于计算非均匀烟雾体积阻挡多少光线很有用,给定了几个点处的烟雾密度。 - Andon M. Coleman
那么似乎更适合像SSAO这样的东西,或者用于平滑阴影贴图? - Villsa
更或少,体积光和更多基于物理的光源,如面光,在射线行进中大量使用。请考虑此页面上的图表,并特别注意面光(太阳)与点光(在自然界中并不存在)之间的区别。 - Andon M. Coleman
2个回答

0

Raymarching的方式是iq/RGBA(Inigo Quilezles)所解释的,是对符号距离函数(“SDF”)进行的Raymarching。 这是一种完全数学化的方法来描述场景。

我们只渲染一个屏幕四分之一,整个要显示的世界都由片段着色器代码构成,该代码可以操纵空间,或计算到某个数学定义实体的符号距离,甚至组合不同物体的距离。

这样的简单示例可能是:

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
}

这段代码描述了一个环面在世界中的位置,该位置是由“world”函数中给定的旋转和平移对“p”进行修改得到的。请注意,我们像在相机空间中一样反向修改空间,因此要移动到空间中的某个点,我们必须从p中减去其向量。

无论如何,这就是纯分析方法中几何学的来源,iq提出了一个很好的进一步阅读:http://mercury.sexy/hg_sdf/


0

这取决于您的着色器与渲染引擎的功能。在纯演示着色器(例如shadertoy,参见其阴影示例)中,整个场景都编码在着色器中,因此除了性能问题外,没有问题发射次要光线或更多光线。

如果场景没有被你的着色器管理,则需要一些引擎的合作。至少在第一遍通行时生成一个阴影图(存在许多不同的算法)。 请注意,使用SVO表示,场景首先会转换为稀疏体素,然后可以由着色器进行次要光线的遍历。甚至可以用于主光线,但您可以在此处使用常规Z缓冲区,并使用体素锥追踪(例如)用于各种次要光线(请参见*使用体素锥追踪的交互式间接照明*,链接:http://gigavoxels.imag.fr/publications.html (好吧,在您的简单应用中可能会发现它过度强大)。有关软阴影和景深,请参阅里程碑式论文。请注意,树甚至可以是三角形的常规BSP,而不是体素的八叉树。但是,这样您将失去SVO的许多优势(性能,增加软阴影)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接