3

我正在尝试实现“用于实时全局照明的基于八叉树的稀疏体素化”的一部分。

基本上只是体素化,我已经完成了。

还有“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 位值。

听起来它只是描述原子计数器的缓冲区对象。为了保持简单(目前),我没有计算运行平均值(如论文中所述),只是在渲染时将颜色相加并除以访问计数。

4

1 回答 1

3

我不确定,但我认为您不必使用 imageAtomicAdd 将具有相同坐标的体素存储到同一个体素片段中。这意味着一些不同的体素片段可能具有相同的 3d 坐标。

这是我的代码。

const uint VOXEL_FRAGMENT_SIZE = 3;
layout(r32ui, binding = 0) uniform coherent volatile writeonly uimageBuffer voxelFragmentBuffer;
layout(binding=0, offset=0) uniform atomic_uint voxelIndexCounter;
// ...
int voxelIndex = int(atomicCounterIncrement( voxelIndexCounter ))* VOXEL_FRAGMENT_SIZE;
imageStore( voxelFragmentBuffer, voxelIndex+0, uvec4( convIVec3ToR32UI( voxelPosition ) ) );
imageStore( voxelFragmentBuffer, voxelIndex+1, uvec4( convVec4ToRGBA8( vec4( normal*127, 2.0 ) ) ) );
imageStore( voxelFragmentBuffer, voxelIndex+2, uvec4( convVec4ToRGBA8( color*255 ) ) );

我还没有完成实现,我可能是错的,但我认为具有相同坐标的体素将在 22.5.4 节点细分中的下一个过程中合并。

我想知道您提交此主题后是否有任何进展。

于 2012-10-30T17:19:29.807 回答