gpt4 book ai didi

c++ - OpenGL 4 和 ES 3.0 与 packHalf2x16/unpackHalf2x16 的差异

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:48:08 24 4
gpt4 key购买 nike

我非常希望问一个简洁的问题,可以得到明确的答案,但我担心有太多关于 FBO 初始化的小事情我不完全理解,我需要澄清。我正在编写一个针对 OpenGL 4.3 和 OpenGL ES 3.0 的延迟着色器,前者的行为完全符合我的预期,但后者给了我一些我无法确定其来源的问题。

首先,我将描述我对为 GL 4.2 和 ES 3.0 设置 MRT FBO 的理解/困惑,并希望有人能够纠正任何误解。

  • OpenGL ES 3.0 规范说它支持“四个或更多渲染目标”,但没有提到(我能找到)这些渲染目标的规范。关于这些渲染目标的大小,可以安全地假设什么?我可以简单地假设它可以具有 RGBA32F 的内部格式吗? (四个 32 位浮点 channel )?在我看来,对于写入 RT 的着色器来说,这是一个至关重要的假设/知识。常见的程序是:尝试创建具有特定规范的 FBO,然后测试 FBO 完整性?如果失败:减少要求并使用替代着色器来补偿减少的位深度?
  • 据说精度限定符“有助于 OpenGL ES 的代码可移植性,而对常规 OpenGL 没有影响”,但我发现很难理解这些 highp 究竟是什么, mediump , lowp ,用于以及它们如何与渲染目标的位深度一起播放。首先,我假设渲染目标的位深度是在FBO中确定和配置的,并且精度限定符自动匹配这个,这让我想到high , mediumlow32有某种关系, 16 , 8位深度。我查看了OpenGL ES 3.0 specs ,而且这还不是很清楚。
  • FBO 的纹理附件使用 glTexStorage2D 配置(与 target=GL_TEXTURE_2Dlevels=1 ),我认为在这里使用比 glTexImage2D 更正确,因为只有 internalformat应该很重要。
  • 然后将 (3.) 中配置的纹理附加到 FBO COLOR_ATTACHMENT使用 glFramebufferTexture2D .


  • 它变得奇怪的地方( packHalf2x16/ unpackHalf2x16 ):

    假设我设置了带有两个颜色附件的 FBO,第一个( RT1 )具有内部格式 GL_RGBA32UI ,第二个( RT2 )与 GL_RGBA32F .对象分两次渲染。第一个到 FBO 的 RT,然后是两个由默认帧缓冲区处理的全屏四边形。

    为简化起见,我将只关注在两个阶段之间传递 RGB 颜色数据。我试图以三种不同的方式这样做:
  • [适用于 GL 和 ES] 使用 RT2 ,定期将颜色数据存储为浮点数,将其读取为浮点纹理并将其输出到默认帧缓冲区。
  • [适用于 GL 和 ES] 使用 RT1 ,存储转换为uint的颜色数据(每个 channel 在 [0,..,255] 中),读作 uint纹理,将其转换为 float [0,1]并将其输出到默认帧缓冲区。
  • [仅适用于 GL] 使用 RT1 , 使用 packHalf2x16 将颜色数据打包到一个半 channel 中.阅读它作为 uint纹理,并使用 unpackHalf2x16 将其转换回 float .


  • 不确定代码细节的相关性/重要性(我会快速跟进任何请求)。我正在使用 highp两者都适用 floatint .第一遍的渲染目标定义为:
    layout (location = 0) out uvec4 fs_rt1;
    layout (location = 1) out vec4 fs_rt2;

    在第二遍中,作为纹理访问:
    uniform highp usampler2D RT1;
    uniform highp sampler2D RT2;
    ...

    // in main():
    uvec4 rt1 = texelFetch(RT1, ivec2(gl_FragCoord.xy), 0);
    vec4 rt2 = texelFetch(RT2, ivec2(gl_FragCoord.xy), 0);

    方法 1. :
    // in first pass:
    fs_rt2.rgb = decal.rgb;

    // in second pass:
    color = vec4(rt2.rgb, 1.0);

    方法 2. :
    // in first pass:
    fs_rt1.rgb = uvec3(decal.xyz * 256.0f);

    // in second pass:
    color = vec4(vec3(rt1.xyz)/256.0f, 1);

    方法 3. :
    // in first pass:
    fs_rt1.x = packHalf2x16(decal.xy);
    fs_rt1.y = packHalf2x16(vec2(decal.z, 0.0f));

    // in second pass:
    vec2 tmp = unpackHalf2x16(rt1.y);
    color = vec4(vec3(unpackHalf2x16(rt1.x), tmp.x), 1);

    在方法中 1 , 2 , 和 3 ,桌面 GL 输出如下所示:
    Desktop OpenGL 4.3 output

    在 Nexus 5 上,方法 12 OpenGL ES 3.0 输出如下所示:

    Nexus 5 OpenGL ES 3.0 output

    方法 3然而,在 nexus 5 上看起来像这样:

    Nexus 5 OpenGL ES 3.0 bad output

    我无法弄清楚为什么第三种方法在 OpenGL ES 3.0 上失败。任何帮助或建议将不胜感激。我不反对阅读文档,所以如果你只想给我指出正确的方向,那也会有帮助。

    最佳答案

    对于前几个问题:

  • 您可以查询GL_MAX_COLOR_ATTACHMENTS获取您可以附加到 FBO 的颜色附件的数量。对于 ES 3.0,这保证 > 4。这是无关 颜色附件的格式(无论是渲染缓冲区还是纹理)。但是,您可以渲染的格式有限制。查看表 glTexStorage2D特别是在“可渲染颜色”列中。这让您知道可以附加到 FBO 的格式。代码 需要测试 FBO 完整性,但不是因为有多种颜色附件。 glCheckFramebufferStatus检查所有附件是否具有相同数量的样本和其他供应商特定的东西,如深度/模板附件。
  • GLES 中有精度限定符来帮助优化。当您知道您正在处理某个范围内的数字时,某些算术运算在低精度下会更快或更有效,请参阅 section 4.5.1 GLSL ES 规范。请注意,这些是最小精度值,即使您请求 lowp,一些供应商也会为您提供 highp。这些精度限定符仅在 GLSL 着色语言中有效。它影响渲染目标的格式。您可能想要做的一些优化,例如对lowp中的颜色值进行操作:值从0.0f到1.0f。这允许 GPU 使用更少的能量,因为它使用的是专为低精度操作而设计的 ALU,例如 PowerVR .我会说,当您的应用程序运行缓慢或作为优化传递时,应该保留使用除 highp 以外的任何内容。您无需从一开始就担心。
  • 使用 glTexStorage2D 和 glTexImage2D 之间存在差异。当您使用 glTexStorage2D 时,它会提示驱动程序此纹理格式不会改变。它变得不可变。这意味着当您使用此纹理时,驱动程序可以执行优化。总是更喜欢 glTexStorage2D。 :)
  • 是的。再次检查 GL_MAX_COLOR_ATTACHMENTS查看您可以附加到 FBO 的数量。您可以使用 GL_COLOR_ATTACHMENT0GL_COLOR_ATTACHMENT0 + maxColourAttachments .

  • 至于您的问题,我看不到您的代码中有任何错误,但是我担心您正在使用的 GPU 驱动程序中可能存在错误。我之前在使用 uint 时遇到过类似的问题某些 GPU 上的变量。我建议您在具有不同供应商 GPU 的手机上尝试该应用程序,看看是否会出现相同的错误。

    您也可以尝试使用不同的打包方法来避免该问题,请参阅 this answer .这不使用 uint s 存储信息,但 float 渲染目标,因此可以绕过错误。

    我希望这回答了你的问题。 :)

    关于c++ - OpenGL 4 和 ES 3.0 与 packHalf2x16/unpackHalf2x16 的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24922668/

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