【发布时间】:2019-05-01 00:21:59
【问题描述】:
我在 CUDA 中对有符号距离场进行 raymarching,我正在渲染的场景包含数千个球体(球体的位置存储在设备缓冲区中,因此我的 SDF 函数会遍历 所有 球体每个像素)。
目前,我计算到球体表面的距离为:
sqrtf( dot( pos - sphere_center, pos - sphere_center ) ) - sphere_radius
使用sqrt() 函数,我的场景渲染大约需要 250 毫秒。然而,当我移除对sqrt() 的调用并只留下dot( pos - sphere_center, pos - sphere_center ) - sphere_radius 时,渲染时间下降到17 毫秒(并渲染黑色图像)。
sqrt() 函数似乎是瓶颈,所以我想问一下是否有办法可以改善我的渲染时间(通过使用不使用平方根的不同公式或不同的渲染方法)?
我已经在使用-use-fast-math。
编辑:我尝试了Nico Schertler 建议的公式,但它在我的渲染器中不起作用。 Link to M(n)WE on Shadertoy.
【问题讨论】:
-
如果只需要零水平集,可以使用
dot( pos - sphere_center, pos - sphere_center ) - sphere_radius * sphere_radius字段。 -
如果
currDst不是实际距离,@wlcezarcurrPt += rd * currDst;显然是行不通的……但即使是这样,这也可能无法达到你想要的效果……除非你的光线击中正好是球心,这里你沿射线移动的距离不是沿射线测量的距离…… -
以防万一:如果您只想与球体相交,则无需使用距离场。球体和射线的交集可以直接计算出来……
-
也许您可以将平方距离的使用“传播”到其余的计算中。至少你可以这样做:
min(squared_distance_to_closest_sphere, distance_to_the_closest_object_in_the_rest_of_the_scene^2)- 对吧? -
--use-fast-math在sqrt()AFAIK 上有no effect。如果您使用sqrt()(即不是sqrtf()),如果您可以切换到例如,您可能会获得一些好处。__fsqrt_rn()
标签: math optimization cuda render