gpt4 book ai didi

OpenGL 从当前绑定(bind)到帧缓冲区的纹理单元读取

转载 作者:行者123 更新时间:2023-12-01 23:22:17 31 4
gpt4 key购买 nike

我在尝试从当前附加到绘制帧缓冲区的纹理单元读取数据时遇到问题。只要我在绘制调用之间使用 glTextureBarrier ,错误就会被消除。不过,我正在尝试消除绘制调用,因此这是一个不是最佳的解决方案。 OpenGL 4.5 规范(第 9.3 节“纹理和帧缓冲区之间的反馈循环”)指出

The mechanisms for attaching textures to a framebuffer object do not prevent a one- or two-dimensional texture level, a face of a cube map texture level, or a layer of a two-dimensional array or three-dimensional texture from being attached to the draw framebuffer while the same texture is bound to a texture unit. While this condition holds, texturing operations accessing that image will produce unde-fined results, as described at the end of section 8.14. ... Specifically, the values of rendered fragments are undefined if any shader stage fetches texels and the same texels are written via fragment shader outputs, even if the reads and writes are not in the same draw call, unless any of the following exceptions apply:

The reads and writes are from/to disjoint sets of texels (after accounting for texture filtering rules).

There is only a single read and write of each texel, and the read is in the fragment shader invocation that writes the same texel (e.g. using texelFetch2D(sampler, ivec2(gl_FragCoord.xy), 0);).

If a texel has been written, then in order to safely read the result a texel fetch must be in a subsequent draw call separated by the command void TextureBarrier( void ); TextureBarrier will guarantee that writes have completed and caches have been invalidated before subsequent draw calls are executed.

我对其他 4 个纹理执行此操作,没有出现任何问题。对于这些纹理,我仅从同一纹理元素进行一次读取和一次写入,因此它们被第二个异常(exception)覆盖。导致问题的纹理需要进行一些过滤,因此在写入之前我需要从不同的纹素进行多次读取。我认为这可以通过第一个异常(exception)来允许,所以我将它们放入一个数组纹理中,交替读取和写入哪个层。这个想法是,这将创建一个设置,其中读取和写入来自/到不相交的纹素集。这没有帮助。

我还尝试仅每隔一个绘制调用执行一次 glTextureBarrier,以查看是否是第三个绘制调用导致了问题。当我一直使用障碍和不使用障碍时,这给出了不同的(仍然是错误的)结果。

绘制调用正在 0,0,0 中绘制一个点,该点在几何着色器中分解为全屏四边形。

更新

我正在通过体积数据进行光线追踪。

帧缓冲区设置

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rayPositionTexture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, rayDirectionTexture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, IORTexture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, resultTexture, 0);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, rayOffsetTexture, 0, 0);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, rayOffsetTexture, 0, 1);

着色器

...
uniform sampler2D RayPositionTexture;
uniform sampler2D RayDirectionTexture;
uniform sampler2DArray RayOffsetTexture;
uniform sampler2D IORTexture;
uniform sampler2D ColorTexture;
...
flat in uint offsetIndex;
layout(location = 0) out vec4 outRayPosition;
layout(location = 1) out vec4 outRayDirection;
layout(location = 2) out float outIOR;
layout(location = 3) out vec4 outColor;
layout(location = 4) out vec4 outRayOffsetA;
layout(location = 5) out vec4 outRayOffsetB;
...
vec3 filteredOffset(ivec2 Pixel)
{
vec3 Offset = vec3(0.0);
float TotalWeight = 0.0;
for(int i = -KernelRadius; i <= KernelRadius; i++)
{
for (int j = -KernelRadius; j <= KernelRadius; j++)
{
ivec2 SampleOffset = ivec2(i,j);
ivec3 SampleLocation = ivec3(Pixel + SampleOffset, offsetIndex);
vec3 Sample = texelFetch(RayOffsetTexture, SampleLocation, 0).xyz;
float Weight = KernelRadius > 0 ? gauss(SampleOffset) : 1.0f;

Offset += Sample * Weight;
TotalWeight += Weight;
}
}
Offset = Offset / TotalWeight;
return Offset;
}
...
//if (offsetIndex == 1)
outRayOffsetA = vec4(RayDirection.xyz - RayDirectionNew, 0.0);
//else
outRayOffsetB = vec4(RayDirection.xyz - RayDirectionNew, 0.0);
outIOR = IOR;
} else {
// if (offsetIndex == 1)
outRayOffsetA = vec4(0.0);
// else
outRayOffsetB = vec4(0.0);
outIOR = PreviousIOR;
//imageStore(VolumeBackTexture, Pixel, vec4(1.0));
}
outColor = Color;
...

绘制调用

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 };
glDrawBuffers(6, drawBuffers);

// Run shader
glBindVertexArray(pointVAO);
float distance = 0.0f;
for (int i = 0; distance < 1.73205080757f; i++)
{
glTextureBarrier();
glDrawArrays(GL_POINTS, i, 1);
distance += fUnitStep;
}
glBindVertexArray(0);

上面没有纹理屏障的结果与

相同(错误的结果)
glBindVertexArray(pointVAO);
glDrawArrays(GL_POINTS, 0, int(std::ceil(1.73205080757f / fUnitStep)));
glBindVertexArray(0);

最佳答案

为了回答这个问题,这里需要TextureBarrier,因为我想从刚刚绘制的纹素中读取。只有在先前的绘制调用已完成且纹理缓存已失效的情况下才能安全地完成此操作,这正是 TextureBarrier 所保证的。

关于OpenGL 从当前绑定(bind)到帧缓冲区的纹理单元读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38534694/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com