我目前正在开发一个游戏引擎,该引擎使用带符号的距离场作为渲染技术来显示平滑的过程几何体(现在通过简单的图元(如您的链接中的图元生成)生成,希望将来实现Julia和IFS分形。由于我的引擎专注于过程生成,并且必须以使它们对光线行进者友好的方式定义图形,因此我认为我是回答这个问题的好地方:P。
关于流传输,简单的解决方案是使用某种类型的缓冲区,并在需要进行光线行进时将其扔到GPU上。缓冲区的每个元素都是复杂的类型(例如,C / C ++中的结构),并且每个类型都包含定义您应使用哪些函数来表示它,其位置,旋转度,比例等以及平均颜色的元素。然后,该过程简化为:
- 将场景划分为可管理的子集(请注意,无论如何,视锥细胞剔除和遮挡剔除部分还是由光线行进算法自动执行的)
- 将子集传递到渲染输入缓冲区
- 将缓冲区传递给GPU(如果尚不存在),然后使用普通的传统光线行进渲染场景。您将需要执行某种按步搜索,以评估光线行进器的每次迭代,输入缓冲区中哪个项最接近每个光线,并且您需要对这两个光线进行转换(在这种情况下)您需要在图形旋转到达GPU之前对其进行反转)或距离函数本身(移动函数原点以进行位置更改,例如调整立方边的长度以进行比例更改等)。最简单的方法是在您将它们传递给实际的核心距离函数。
关于图形颜色,请记住,着色器允许您定义复杂的类型以及图元;)。这样,您就可以将所有内容都放入C样式的结构中,然后将这些结构从distance函数中传回。
在我的引擎中,每个结构都包含一个距离,一个颜色以及一个将其与输入缓冲区中相应图形定义相关联的ID。每个ID都是从相关距离函数的周围环境中推断出来的(由于我的映射函数遍历了输入缓冲区以查找与每一步最接近的光线图形,因此当调用每个SDF时,我可以安全地处理循环计数器的值作为该功能的图形ID),而距离值是使用任意核心SDF定义的(例如point - figure.pos
颜色)是根据图形缓冲区中相应元素的平均颜色(因此,为什么保持图形ID有用)来定义颜色,也可以通过对存储的平均值加权的过程颜色来定义颜色(一个例子可能是在Mandelbulb上某个点的迭代计数,将您的“平均颜色”从FP颜色空间映射到整数颜色空间,然后通过对迭代计数进行异或运算,将映射的颜色用作调色板。
程序纹理是另一种方法,但是我从未亲自使用它们。iq在该领域进行了大量研究,并在Shadertoy上发布了一些有趣的演示,因此这可能是收集一些额外信息的一种方式。
无论每个图形的颜色是静态的,是通过程序生成的还是从程序纹理中神奇地采样的,基本逻辑都是相同的:将抽象图形转换为某种中间复杂类型(例如,结构),既存储局部距离又存储局部颜色,然后再将复杂类型作为距离函数的返回值进行传递。然后,根据您的实现,输出颜色可以直接传递到屏幕,或跟随碰撞点进入照明代码。
我不知道上面的内容是否足够清楚,所以不必担心是否有任何不合理的地方。因为我正在使用HLSL和计算阴影,所以我真的不能给出任何GLSL /像素阴影代码示例,但是我很乐意尝试并解决所有我最初未正确编写的内容:)。