我有一个应用程序可以在有或没有多重采样的情况下运行。我正在从着色器中先前渲染的多重采样纹理中获取样本。是否有必要编译不同版本的着色器,使用sampler2D或sampler2DMS来访问纹理,具体取决于它是否是多重采样纹理?
我尝试通过sampler2DMS从非多重采样纹理中获取并且它可以工作,但我不知道这是否是根据规范未定义的行为,或者我可以在多大程度上依赖它来工作。
有谁知道这是否是正确定义的行为?
您创建的每个纹理对象都有与之关联的目标。当您第一次将该对象绑定到上下文时,您传递了
glBindTexture
一个特定的目标枚举。 GL_TEXTURE_2D
、GL_TEXTURE_CUBE_MAP
等。您在第一次绑定调用中使用的目标与纹理对象有着千丝万缕的联系;如果您尝试将其与不同的目标绑定,glBindTexture
将会失败。
GL_TEXTURE_2D
和 GL_TEXTURE_2D_MULTISAMPLE
是不同的目标。如果您使用 glBindTexture(GL_TEXTURE_2D, obj)
绑定新创建的纹理对象,则以后不能将其与 GL_TEXTURE_2D_MULTISAMPLE
绑定。反之亦然。
您可能已经注意到,GLSL 采样器类型带有后缀。那么,这些后缀表示特定采样器类型所使用的纹理类型。
sampler2D
是一个浮点采样器,可与 GL_TEXTURE_2D
纹理配合使用。因此,它只会找到具有相应目标的纹理。
如果您设置
sampler2D
统一以使用纹理单元 0,并将某些东西绑定到 GL_TEXTURE_2D_MULTISAMPLE
,则采样器 将看不到它。它只会寻找绑定到该采样器的 GL_TEXTURE_2D
。
现在,您可能听说过“查看纹理”。这些纹理与其他纹理共享存储。但视图可以有不同的尺寸,甚至纹理目标。您可以将 2D 数组纹理中的单个图层视为 2D 纹理。等等。 您
不能执行的转换是将多重采样纹理视为非多重采样纹理。反之亦然。 因此,如果您所描述的有效,那么这是未定义的行为。你不能依赖它。
话虽这么说:
是否需要编译不同版本的shader
one不;你只是不能使用
变量。拥有两个不同类型的采样器变量并有条件地决定对其中一个与另一个进行采样是完全有效的。如果条件是动态一致的(对于 GL 4.x),您甚至不会丢失隐式导数 您唯一要做的就是让它们使用
不同的纹理单元。不要尝试玩游戏时为它们分配相同的纹理单元并让它根据您绑定的内容决定使用哪个。它不起作用(或者如果起作用,那就是 UB)。
GL_TEXTURE_2D_MULTISAMPLE
不会在正在查看该纹理槽的制服上看到
解决此问题的唯一方法似乎是将 MSAA FBO 位图传输到屏幕,或另一个(非多重采样)纹理(然后您可以在该常规纹理上执行 PP 操作)要传输 FBO:
glBindFramebuffer( GL_READ_FRAMEBUFFER, srcFBO );
// If destFBO is 0, you blit to the screen
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, destFBO );
glBlitFramebuffer( 0, 0, wSrc, hSrc, 0, 0, wDst, hDst, GL_COLOR_BUFFER_BIT, GL_LINEAR );
// Restore original states just in case
glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );