在Vulkan GLSL计算着色器中能否向深度缓冲区写入深度值?
实现方案说明
你想到的替代方案是目前兼容性最好、应用最广泛的成熟实现方式,除此之外也有硬件支持前提下的更高效方案,具体实现细节如下:
方案1:兼容所有支持着色器存储图像的硬件的通用方案
- 不需要用普通RGBA彩色图像存储深度,直接创建单通道
R32F格式的浮点纹理作为光追深度存储载体,imageStore原生支持写入浮点格式纹理,你只需要在光追着色器中将对齐到光栅化管线深度范围的归一化深度值写入该纹理的R通道即可,相比占用RGBA通道的实现显存占用更低、读写效率更高。 - 后续的占位着色器阶段只需要绘制一个和屏幕分辨率匹配的全屏四边形,在片段着色器中采样你提前写入的光追深度纹理,直接赋值给内置变量
gl_FragDepth即可,这一步会把光追计算的深度值正式写入当前图形管线的深度缓冲区,后续绘制传统三角形时,硬件自动触发的深度测试会正确处理光追内容和光栅化内容的遮挡关系。 - 如果需要同时输出光追的颜色结果,可以在光追阶段并行写入颜色纹理和深度纹理,后续全屏Pass同时输出颜色值和设置
gl_FragDepth,一次性完成光追结果上屏和深度写入,不需要额外的性能开销。
方案2:高版本硬件/API支持的更高效方案
如果你的运行环境支持对应扩展(Vulkan的VK_EXT_shader_image_atomic_int64、OpenGL 4.2以上版本的GL_ARB_shader_image_load_store扩展),可以直接创建DEPTH_COMPONENT32F格式的存储图像,直接通过imageStore写入深度值,不需要额外的全屏绘制Pass,性能开销更低,但是该方案对硬件和API版本有要求,兼容性不如通用方案。
注意事项
- 必须统一光追阶段和光栅化阶段的深度坐标系:光追计算得到的视线深度需要转换到和光栅化管线完全一致的深度范围(比如正向深度的01范围、反向深度的10范围),否则会出现遮挡关系错位的问题。
内容的提问来源于stack exchange,提问作者Makogan
相关产品推荐
相关产品推荐

