这个问题困扰了我一段时间,但我正忙于其他事情。如果不解决它,我就无法完成我的GI技术(特别是遮挡步骤)。

我单遍制作了二进制场景体素。结果存储在RGBA32UI 3D纹理中。这是三种方式,因此我分别为X,Y,Z方向设置了三个正交矩阵。这些矩阵在相机位置居中,并形成为圆锥形的视锥。在几何着色器中,选择基于三角形法线的轴。

首先,有效的方法-不进行二进制体素化(但这是对VRAM的浪费)。 br />
//gridDim - gridDimensions in voxels
ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;
ivec3 texcoord[3];

//correction of texture coord based on chosen axis and ortho matrix 
//(f_axis - 0, 1 or 2 from geometry shader)
texcoord[0] = temp;

texcoord[1].x = int(gridDim.z) - temp.x;
texcoord[1].y = temp.z;
texcoord[1].z = temp.y;

texcoord[2].x = temp.z;
texcoord[2].y = temp.y;
texcoord[2].z = int(gridDim.z) - temp.x;

imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));


绘制过程是通过使用实例化多维数据集来完成的。体素很大,因为更多的体素会导致大幅降低帧率:
但是如果我将其更改为二进制版本:

//vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader
vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);
geomCoords.xyz /= geomCoords.w;
geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;

ivec3 index = ivec3(geomCoords.xyz * gridDim);

uvec4 voxel2 = texelFetch(geometryTexture, index, 0);
if(voxel2.r == 0u)
    discard;

normalColor = vec4(normal0, 1.0);
fragColor = vec4(1.0, 0.0, 0.0, 1.0);


并阅读: >结果:



正如您在二进制版本中看到的那样,它闪烁,并且我未能找出背后的逻辑(尚未)。但是,体素位置似乎很好。我也可以通过在纹理上进行光线散布来渲染这些体素,并且也可以闪烁。 X方向(那么它是不正确的,但无论如何),并且仅将值存储在第一个切片中(我的gridDim小于128,因此适合),并且仍然闪烁: >

#1 楼

在二进制版本中,您正在同一纹理上执行imageLoadimageStore对其进行修改。这是一个经典的竞争条件:GPU并行执行着色器的多个线程,并且不能保证这些加载-修改-存储序列是原子发生的。可以交错来自不同线程的操作,导致存储错误的数据。

要解决此问题,应使用imageAtomicOr将要写入的位与缓冲区中已有的位合并,而不会出现竞争条件。有关更多信息,请参见此OpenGL Wiki页面。

评论


$ \ begingroup $
谢谢,我会尝试的。是的,我知道使用此操作时会出现这种情况。但是我认为这是正或(加)运算,因此无论顺序如何,这些运算都会将结果组合为相同的值。就像2 + 3 + 4 == 4 + 3 + 2。
$ \ endgroup $
–narthex
16 Dec 16'在10:45

$ \ begingroup $
在设置中,位占据位置。
$ \ endgroup $
–narthex
16 Dec 16'在13:47

$ \ begingroup $
@narthex是的,这是一个可交换的操作,但这不是问题所在-问题是,可以对来自不同线程的读写进行交织。例如:线程1将初始值读入局部变量,线程2将相同的初始值读入其局部变量,线程1写入修改后的值,然后线程2写入自己的不包括线程位的修改值1已经设定。因此线程1的贡献最终会丢失。
$ \ endgroup $
–内森·里德(Nathan Reed)
16 Dec 16 '18:13