在上一篇文章之前,我已经遇到过尝试对事物进行哈希处理的问题:SSBO hash table, missing values我认为问题已解决,但并没有完全解决。
目标很简单,使用哈希表将3D纹理压缩到线性空间中。
我正在丢失一些数据,所以我试图进行调查:
(先前图像中的黑色区域缺少体素)。
我的散列函数可以创建整数,因为碰撞超过10个的任何东西都将被丢弃,因此要调查是否是这种情况,我做了以下函数:
int a_size = 100000;
void insert(vec3 pos, Voxel value)
{
ivec3 discretized = ivec3(pos / v_size);
int index = int(discretized.x * 73 + discretized.y * 169 + discretized.z * 8349) % a_size;
index = (a_size + index) % a_size;
for(int i=0; i<10; i++)
{
if(atomicCompSwap(voxels[index].filled, 0, 1) == 0)
{
if(value.position != ivec4(discretized, 1))
{
Voxel c_voxel = voxels[index];
value.position = ivec4(discretized, 1);
voxels[index] = value;
if(i==0) {
voxels[index].color = vec4(1,0,0,1);
}
if(i==1) {
voxels[index].color = vec4(0,1,0,1);
}
if(i==2) {
voxels[index].color = vec4(0,0,1,1);
}
if(i==3) {
voxels[index].color = vec4(1,0,1,1);
}
if(i>=4) {
voxels[index].color = vec4(1,0,1,1);
}
break;
}
}
index = (index * index + 7) % a_size;
}
}
因此所有没有碰撞的体素都是红色的,有1个碰撞的体素是绿色的...
如果一个体素发生9次或更多碰撞,它将变成白色。
在另一个着色器中,我继续读取以下值:
int a_size = 100000;
vec4 fetch(vec3 pos)
{
ivec3 discretized = ivec3(pos / v_size);
int index = int(discretized.x * 73 + discretized.y * 169 + discretized.z * 8349) % a_size;
index = (a_size + index) % a_size;
for(int i=0; i<10; i++)
{
Voxel c_voxel = voxels[index];
if(i>=1) {
return vec4(1);
}
if(ivec4(discretized,1) == voxels[index].position)
return voxels[index].color;
if(voxels[index].filled == 0) return vec4(0);
index = (index * index + 7) % a_size;
}
}
基于此函数的逻辑,所有返回的非空值应为红色或白色。发生了多次碰撞的白色体素发生。
结果是:
如您所见,有几个绿色体素,没有白色体素。
在我看来,这似乎表明我的检索哈希函数实际上与存储哈希函数并不相同。如果它们是相同的,则期望没有绿色像素可见,因为这些像素对应于发生1次碰撞的体素,而这些像素将被白色覆盖。因此,要返回绿色,该函数将在第一个哈希值上返回。
两个着色器中的体素和ssbo结构的声明为:
struct Voxel
{
int filled;
int pad1;
int pad2;
int pad3;
ivec4 position;
vec4 normal;
vec4 color;
};
layout(std430, binding = 0) buffer voxel_buffer
{
uint index;
Voxel voxels[];
};
两个散列函数对我来说似乎都是相同的。更改a_size参数也会更改丢失的匹配的比例,尽管没有特定的数字。一百万提供了最佳结果,但是90万提供了比110万更好的结果
1: