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

标签 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);

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

最佳答案

我相信硬件 mipmap 的速度与您所能达到的差不多。我一直认为尝试自定义 mipmap 会比较慢,因为您必须依次手动绑定(bind)和光栅化到每个层。原子将引起巨大的争论,而且速度会非常慢。即使没有原子,您也会否定 mipmap 的 O(log n) 构造。

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

您可以尝试以旧方式绘制纹理,方法是将其绑定(bind)到 FBO 并使用 glDrawElementsInstanced 绘制全屏三角形(覆盖视口(viewport)的大三角形)。在几何着色器中,将 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 作为您的线程索引。

关于c++ - 在片段着色器 OpenGL 中写入多个 3d 纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24431205/

相关文章:

c++ - 编译 Google Test 时出现 g++ fatal error

c++ - 如何在opencv中进行一对 multimap 像匹配?

objective-c - 在mac上学习openGL : GLUT or native windowing system?

optimization - 体素引擎和优化

c++ - Visual Studio 2012 - 在单独的文件中使用 OpenGL(GLU、GLUT)的删除功能

c++ - Qt转换unicode实体

c - OpenGL 中的位图渲染方法?

opengl - OpenGL Pixel Shader:如何在每个像素上生成0和1的随机矩阵?

graphics - 什么是稀疏体素八叉树?

programming-languages - 体素 3d "grid"