opengl纹理坐标与像素对应关系,glsl模拟linear插值

文章介绍了如何在Shadertoy中通过Linear插值和预乘alpha处理解决纹理偏色问题,提供了my_texture2D函数实现,以及未预乘alpha的线性插值导致的边缘偏白效果对比。
摘要由CSDN通过智能技术生成

推荐一个网页:Shader - Shadertoy BETA

在网页中测试发现了如下关系:

测试过程很简单,纹理图使用Linear,然后texture2D,限定pos位置,如果得出的颜色不是插值出来的颜色,则说明找对了。

大致关系如上图,由于纹理坐标是[0,1],乘上宽高之后,等于 分别为[0,width] 和 [0,height]

一张宽为width的图片,实际一行是width个像素,序号从0到width-1,而[0,width]有width+1个像素,所以,每个实际的像素偏移了0.5,即对应关系为:

        texture2D((0.5*(i+1)/width,0.5*(j+1)/height)) == rgba[i][j]

如果是Nearest,就是floor(xy) + 0.5

如果是Linear,需要找四个邻近点,进行线性插值

由于非预乘的纹理,进行二次线性插值时,会有偏色的问题,通过模拟二次线性插值,可解决(仅供学习,实际操作还是尽可能对纹理进行预乘alpha的好

vec4 premul(vec4 c){
    return vec4(c.rgb * c.a,c.a);
}
vec4 nopremul(vec4 c){
    if(c.a == .0)
        return vec4(0,0,0,0);
    return vec4(clamp(c.rgb / c.a,.0,1.0),c.a);
}

vec4 my_texture2D(sampler2D tex,vec2 size,vec2 pos){
    vec2 ixy = (pos * size) - .5;
    vec2 i_base = floor(ixy) + .5;
    vec2 xy_base0 = i_base / size;
    vec2 xy_base1 = vec2(i_base.x + 1.0,i_base.y) / size;
    vec2 xy_base2 = vec2(i_base.x,i_base.y+1.0) / size;
    vec2 xy_base3 = (i_base + 1.0) / size;
    vec2 xy_fract = fract(ixy);
    
    vec4 c_base0 = premul(texture2D(tex,xy_base0));
    vec4 c_base1 = premul(texture2D(tex,xy_base1));
    vec4 c_base2 = premul(texture2D(tex,xy_base2));
    vec4 c_base3 = premul(texture2D(tex,xy_base3));
    vec4 ret0 = mix(c_base0,c_base1,xy_fract.x);
    vec4 ret1 = mix(c_base2,c_base3,xy_fract.x);
    vec4 ret = mix(ret0,ret1,xy_fract.y);
    return nopremul(ret);
    
    
    return texture2D(tex,pos);
}

测试main函数如下:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    
    vec4 c = my_texture2D(iChannel1,iChannelResolution[1].xy,uv);

    // Time varying pixel color
    vec3 col = c.rgb;
    if(c.a < 0.5)
        c = vec4(1,0,0,1);

    // Output to screen
    fragColor = c;
}

对比未预乘的线性插值效果:

未预乘alpha的图片边缘效果明显偏白。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值