我正在尝试实现“用于实时全局照明的基于八叉树的稀疏体素化”的一部分。
基本上只是体素化,我已经完成了。
还有“Voxel-fragment list”构造,它基本上是几个预先分配的体素位置和属性的缓冲区。
使用原子计数器和 atomic-comp-swap 或 atomic-add 创建位置缓冲区非常容易,以确保它仅由一个线程写入
layout(r32ui, binding = 0) uniform coherent volatile uimage3D Voxels;
layout(r32ui, binding = 1) uniform coherent volatile uimageBuffer positionBuffer;
void writeVoxels(ivec3 coord)
{
uint voxelVal = imageAtomicCompSwap(Voxels, coord, 0, 1);
if(voxelVal == 0)
{
int index = 3*int(atomicCounterIncrement(voxelCounter));
imageStore(positionBuffer, index+0, uvec4(coord.x));
imageStore(positionBuffer, index+1, uvec4(coord.y));
imageStore(positionBuffer, index+2, uvec4(coord.z));
}
}
但是,在多个线程写入相同体素位置的情况下,如何确保所有线程都获得适当的索引?如上所示,正确的索引仅对 1 个线程有效。
像下面的东西
#extension GL_NV_shader_atomic_float : require
layout(r32ui, binding = 0) uniform coherent volatile uimage3D Voxels;
layout(r32ui, binding = 1) uniform coherent volatile uimageBuffer positionBuffer;
layout(r32f, binding = 2) uniform coherent volatile imageBuffer colorBuffer;
void writeVoxels(ivec3 coord, vec3 color)
{
uint voxelVal = imageAtomicAdd(Voxels, coord, 1);
int index;
if(voxelVal == 0) //This ensure that only 1 thread performs the
{ //atomicCounterIncrement
index = 3*int(atomicCounterIncrement(voxelCounter));
imageStore(positionBuffer, index+0, uvec4(coord.x));
imageStore(positionBuffer, index+1, uvec4(coord.y));
imageStore(positionBuffer, index+2, uvec4(coord.z));
}
//Need index to be valid here
imageAtomicAdd(colorBuffer, index+0, color.x);
imageAtomicAdd(colorBuffer, index+1, color.y);
imageAtomicAdd(colorBuffer, index+2, color.z);
}
我已经尝试了很多不同的方法。论文中唯一的提示是
为了管理(体素片段)列表,我们将下一个可用条目的索引(也是列表中体素片段数量的计数器)存储为另一个缓冲区对象中的单个 32 位值。
听起来它只是描述原子计数器的缓冲区对象。为了保持简单(目前),我没有计算运行平均值(如论文中所述),只是在渲染时将颜色相加并除以访问计数。