【问题标题】:Downsample and upsample texture offsets, OpenGL GLSL下采样和上采样纹理偏移,OpenGL GLSL
【发布时间】:2016-06-02 20:27:01
【问题描述】:

假设我想从 4x4 纹理像素下采样到 2x2 纹理,做一些花哨的事情,然后再从 2x2 上采样到 4x4。如何计算正确的相邻纹素偏移?我不能使用双线性过滤或最近过滤。我需要为每个片段执行选择 4 个样本,并在下采样之前选择最大的一个。上采样过程也是如此,即我需要为每个片段执行选择 4 个样本。

我是否正确计算了邻居偏移(我使用的是全屏四边形)?

//Downsample: 1.0 / 2.0, Upsample: 1.0 / 4.0.
vec2 texelSize = vec2(1.0 / textureWidth, 1.0 / textureHeight);

const vec2 DOWNSAMPLE_OFFSETS[4] = vec2[]
(
    vec2(-0.5, -0.5) * texelSize,
    vec2(-0.5, 0.5) * texelSize,
    vec2(0.5, -0.5) * texelSize,
    vec2(0.5, 0.5) * texelSize
);

const vec2 UPSAMPLE_OFFSETS[4] = vec2[]
(
    vec2(-1.0, -1.0) * texelSize,
    vec2(-1.0, 1.0) * texelSize,
    vec2(1.0, -1.0) * texelSize,
    vec2(1.0, 1.0) * texelSize
);

//Fragment shader.
#version 400 core

uniform sampler2D mainTexture;
in vec2 texCoord;
out vec4 fragColor;

void main(void) 
{
    #if defined(DOWNSAMPLE)
    vec2 uv0 = texCoord + DOWNSAMPLE_OFFSETS[0];
    vec2 uv1 = texCoord + DOWNSAMPLE_OFFSETS[1];
    vec2 uv2 = texCoord + DOWNSAMPLE_OFFSETS[2];
    vec2 uv3 = texCoord + DOWNSAMPLE_OFFSETS[3];
    #else
    vec2 uv0 = texCoord + UPSAMPLE_OFFSETS[0];
    vec2 uv1 = texCoord + UPSAMPLE_OFFSETS[1];
    vec2 uv2 = texCoord + UPSAMPLE_OFFSETS[2];
    vec2 uv3 = texCoord + UPSAMPLE_OFFSETS[3];
    #endif

    float val0 = texture(mainTexture, uv0).r;
    float val1 = texture(mainTexture, uv1).r;
    float val2 = texture(mainTexture, uv2).r;
    float val3 = texture(mainTexture, uv3).r;

    //Do some stuff...

    fragColor = ...;
}

【问题讨论】:

  • 您可以使用 fbo 和 reder 对具有不同样本数的 multisampleTexture 进行多重采样(如果您可以使用默认多重采样)
  • 在我的情况下这是不可能的,因为我需要对深度纹理进行下采样并对另一个纹理进行上采样以避免像素出血。因此,我必须手动比较一个双线性邻域。

标签: opengl glsl textures


【解决方案1】:

假设 texelSize 在这两种情况下都是渲染目标的 texel 大小,偏移看起来是正确的。也就是说,下采样通道的大小是上采样通道的两倍。在上采样的情况下,您并没有准确地击中源纹素中心,而是足够接近,以至于最近邻过滤将它们捕捉到预期的结果。

更有效的选择是使用textureGather 指令,在ARB_texture_gather 扩展中指定。当用于对纹理进行采样时,它返回相同的四个纹素,用于过滤。它只返回每个 texel 的单个组件来生成 vec4,但鉴于您只关心红色组件,如果扩展可用,它是一个理想的解决方案。下采样和上采样的代码将是相同的:

#define GATHER_RED_COMPONENT 0
vec4 vals = textureGather(mainTexture, texcoord, GATHER_RED_COMPONENT);

// Output the maximum value
fragColor = max(max(vals.x, vals.y), max(vals.z, vals.w));

【讨论】:

  • 感谢您的确认!我正在使用 OpenGL 4.0,textureGather 需要它而不需要扩展。我去试试,再次感谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 2021-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-10-25
相关资源
最近更新 更多