在片段着色器OpenGL中写入多个3d纹理

时间:2014-06-26 12:58:32

标签: c++ opengl voxels 3d-texture image-unit

我有一个3D纹理,我在这里编写数据,并以这种方式将其用作片段着色器中的体素:

#extension GL_ARB_shader_image_size : enable
...
layout (binding = 0, rgba8) coherent uniform image3D volumeTexture;
...
void main(){
vec4 fragmentColor = ...
vec3 coords = ...
imageStore(volumeTexture, ivec3(coords), fragmentColor);
}

并且以这种方式定义纹理

glGenTextures(1, &volumeTexture);
glBindTexture(GL_TEXTURE_3D, volumeTexture);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, volumeDimensions, volumeDimensions, volumeDimensions, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

然后我必须使用它

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, volumeTexture);

现在我的问题是我希望有一个mipmap版本的这个并且不使用opengl函数,因为我注意到它非常慢。所以我想在同一时间在所有级别的3D纹理中进行编写,例如,最大分辨率为512 ^ 3,当我在3dtex中写入1个体素值时,我也为256 ^ 3写入0.125 * VALUE体素和0.015625 *值为126 ^ 3等。由于我使用的是使用原子性的imageStore,所有的值都将被写入并使用这些权重我会自动得到平均值(不完全像插值但我可能得到一个令人满意的结果无论如何)。 所以我的问题是,有多个3dtexture并同时写入所有这些文本的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

我相信硬件mipmapping的速度和你一样快。我总是假设尝试自定义mipmapping会变慢,因为你必须依次手动绑定和栅格化每个图层。原子论将给予巨大的争论,而且它会非常缓慢。即使没有原子,你也可以否定mipmap的漂亮O(log n)结构。

对于访问顺序和缓存,您必须非常小心imageStore。我从这里开始尝试一些不同的索引(例如行/列与列/行)。

您可以尝试使用旧版方式绘制纹理,方法是将其绑定到FBO并使用glDrawElementsInstanced绘制一个全屏三角形(覆盖视口的大三角形)。在几何着色器中,将gl_Layer设置为实例ID。光栅化器为x / y创建片段,图层给出z。

最后,即使按今天的标准,512 ^ 3也只是一个巨大的质地。也许找出你的理论最大gpu带宽,以了解你有多远。例如。假设您的GPU可以达到200GB / s。无论如何,你可能只会在一个好的情况下得到100。你的512 ^ 3纹理是512MB所以你可以在~5ms内写入它(imo这看起来非常快,也许我犯了一个错误)。期望管道的其余部分产生一些开销和延迟,产生并执行线程等。如果你正在编写复杂的东西,那么内存带宽不是瓶颈,我的估计就会消失。所以试着先写零。然后尝试更改coords xyz订单。


更新:不是使用片段着色器来创建线程,而是可以使用顶点着色器,理论上可以避免光栅化器开销,尽管我已经看到它也没有表现出来的情况。您glEnable(GL_RASTERIZER_DISCARD)glDrawArrays(GL_POINTS, 0, numThreads)并使用gl_VertexID作为主题索引。