3

我有一个 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);

现在我的问题是我想要一个 mipmapped 版本而不使用 opengl 函数,因为我注意到它非常慢。所以我正在考虑同时在所有级别写入 3D 纹理,例如,最大分辨率为 512^3,当我在该 3dtex 中写入 1 voxel VALUE 时,我还为 256^3 写入 0.125*VALUE voxel 和 0.015625*VALUE 用于 126^3 等。由于我使用 imageStore,它使用原子性,所有值都将被写入并使用这些权重我会自动获得平均值(不完全像插值,但我可能会得到一个令人愉快的结果反正)。所以我的问题是,拥有多个 3dtexture 并同时写入所有这些的最佳方法是什么?

4

1 回答 1

2

我相信硬件 mipmapping 的速度和你能得到的一样快。我一直认为尝试自定义 mipmapping 会更慢,因为您必须依次手动绑定和光栅化到每个图层。Atomics 会引起巨大的争论,而且速度会非常慢。即使没有原子,你也会否定 mipmap 的 O(log n) 构造。

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

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

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


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

于 2014-06-26T13:12:56.350 回答