OpenGL:如何通过通道,通过采样和渲染到相同的纹理来写入纹理通道

时间:2014-11-25 23:51:15

标签: opengl textures fragment-shader

情景是: 我有一个纹理A. 有3个循环。每个循环将一个通道写入纹理A. 在3个循环之后,A中的所有3个通道都会更新。

着色器就像:

vec3 tmpVec3 = texture(inputTexture0, vUV).rgb; // inputTexture0 is texture A tmpVec3[channelIndex_P] = texture(inputTexture1, vUV).r;  // write one channel from inputTexture1

color = vec4(tmpVec3, 1.0);

渲染到纹理A,即inputTexture0。 通过这种方式渲染和采样相同的纹理,我可以通过一个纹理来节省内存。

然而,结果并不理想。

我阅读了文章“Sampling and Rendering to the Same Texture”。 它说:

  

“意思是它可以做你想要的,采样器可能会获得旧数据,   采样器可能会获得一半和一半的新数据,或者它可能会变成垃圾   数据。任何这些都是可能的结果。“

但是由于特定像素的写入数据总是在获取特定像素的数据后发生,为什么不可能呢?

另一篇文章“Sampling from and rendering to the same texture and parallel sorting / hashing” 它说:

  

“但是如果每个帧缓冲像素中的结果都是值   写入该像素而不是组合的片段之一   来自多个片段的值,此功能仍然是   对于在glsl中实现的并行排序/散列算法很有用。“

我不明白上面的话。是否说在某些情况下可以使用“采样和渲染到相同纹理”并定义结果。那怎么办呢?如何解决我目前的情况,因为我想保存一个纹理变量。

1 个答案:

答案 0 :(得分:1)

  

那么请你解释为什么我的情况无法解决,因为兴趣流程的写作和阅读不是同时进行的。

它们绝对是在同一时间处理的,我认为你不了解如何在GPU上安排着色器。片段着色器不会串行运行,并且在并行调用读取相同纹理之前,您不必完成写入纹理的尝试(也不保证纹理内存不会被缓存;对内存的更改不可见)

这就是你需要障碍的原因。纹理屏障(NV特定扩展)或通用内存屏障将导致着色器调用在屏障处停止,直到着色器的每个实例完成读取或写入,然后继续。这样可以防止导致读取错误数据的数据危险。

要在GL3类实现中执行此操作,纹理障碍可能是您唯一的选择。在GL4.2 +中,图像加载/存储将是首选方法,而一些较旧的实现通过GL_ARB_shader_image_load_store扩展支持此功能。

但是,如果没有这些东西,你现在要做的就是调用未定义的行为。您需要某种同步构造才能正确执行此操作,这就是障碍的来源。