下采样和上采样纹理偏移,OpenGL GLSL

时间:2016-05-25 21:17:28

标签: opengl glsl textures

假设我想从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 = ...;
}

1 个答案:

答案 0 :(得分:1)

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

更有效的选择是使用textureGather扩展名中指定的ARB_texture_gather指令。当用于对纹理进行采样时,它将返回相同的四个纹素,用于过滤。它只返回每个纹素的单个组件以产生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));