Metal与图形渲染十一:分屏滤镜

作者: 肠粉白粥_Hoben | 来源:发表于2021-10-19 21:12 被阅读0次

    零. 前言

    分屏滤镜是指在一个有限的区域内,将内容分割为若干个部分,应用在一些剪辑或者连麦展示效果上,做了个小demo,效果如下:

    一. 分屏原理

    分屏滤镜修改的是片段着色器,对于同一个渲染内容,可以分成若干个模块,对于某个模块来说,需要对原纹理进行采样,采样可以选择保持原比例不裁剪,或者居中裁剪。

    但是如果该模块比例发生变化的话,保持比例裁剪就会产生压缩问题,比如上面的二分屏和三分屏。

    下面分别给出了将x或y坐标二等分或三等分的方法,

    二等分不裁剪:左半边将坐标 * 2,由[0, 0.5]区间变为[0, 1];右半边由[0.5, 1],变为[0, 1]。

    二等分裁剪:左右半边均变为[0.25, 0.75]。

    三等分不裁剪:和二等分类似,直接 * 3变为[0, 1]。

    三等分裁剪:均变为[1 / 3, 2 / 3]。

    float splitTwoCoor(float coor, bool centerCrop) {
        float res;
        
        if (centerCrop) {
            if (coor < 0.5) {
                res = coor + 0.25;
            }
            else {
                res = coor - 0.25;
            }
        } else {
            if (coor < 0.5) {
                res = coor * 2.0;
            }
            else {
                res = (coor - 0.5) * 2.0;
            }
        }
        
        return res;
    }
    
    float splitThreeCoor(float coor, bool centerCrop) {
        float res;
        
        if (centerCrop) {
            if (coor < 1.0 / 3) {
                res = coor + 1.0 / 3;
            }
            else if (coor > 2.0 / 3) {
                res = coor - 1.0 / 3;
            }
            else {
                res = coor;
            }
        } else {
            if (coor < 1.0 / 3) {
                res = coor * 3.0;
            }
            else if (coor < 2.0 / 3) {
                res = (coor - 1.0 / 3) * 3.0;
            }
            else {
                res = (coor - 2.0 / 3) * 3.0;
            }
        }
        
        return res;
    }
    

    二. 各等分的调用

    二等分:将y坐标二等分

    fragment float4
    twoScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
                           constant bool &centerCrop [[ buffer(0) ]],
                           texture2d<float> texture [[ texture(0) ]]) {
        float currentY = input.textureCoordinate.y;
    
        float sampleY = splitTwoCoor(currentY, centerCrop);
    
        constexpr sampler s;
        
        float4 color = texture.sample(s, float2(input.textureCoordinate.x, sampleY));
    
        return color;
    }
    

    三等分:将y坐标三等分

    fragment float4
    threeScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
                             constant bool &centerCrop [[ buffer(0) ]],
                             texture2d<float> texture [[ texture(0) ]]) {
        float currentY = input.textureCoordinate.y;
    
        float sampleY = splitThreeCoor(currentY, centerCrop);
    
        constexpr sampler s;
        
        float4 color = texture.sample(s, float2(input.textureCoordinate.x, sampleY));
        
        return color;
    }
    

    四等分:将x、y坐标二等分

    fragment float4
    fourScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
                            constant bool &centerCrop [[ buffer(0) ]],
                            texture2d<float> texture [[ texture(0) ]]) {
        float currentX = input.textureCoordinate.x;
        float currentY = input.textureCoordinate.y;
        
        float sampleX = splitTwoCoor(currentX, centerCrop);
        float sampleY = splitTwoCoor(currentY, centerCrop);
        
        constexpr sampler s;
        
        float4 color = texture.sample(s, float2(sampleX, sampleY));
        
        return color;
    }
    

    九等分:将x、y坐标三等分

    fragment float4
    nineScreenSplitFragment(SingleInputVertexIO input [[ stage_in ]],
                            constant bool &centerCrop [[ buffer(0) ]],
                            texture2d<float> texture [[ texture(0) ]]) {
        float currentX = input.textureCoordinate.x;
        float currentY = input.textureCoordinate.y;
    
        float sampleX = splitThreeCoor(currentX, centerCrop);
        float sampleY = splitThreeCoor(currentY, centerCrop);
        
        constexpr sampler s;
        
        float4 color = texture.sample(s, float2(sampleX, sampleY));
        
        return color;
    }
    

    三. 总结

    本文主要介绍了分屏滤镜的原理,在业务的分屏滤镜中,可能有各种各样的样式要求,比如左半边展示一个大头像,右半边再四等分...这些都是可以通过修改片段着色器来实现的,其原理是在特定的区域按取样公式对整个纹理进行采样,从而达到分屏的效果。

    四. 参考文章

    OpenGL ES(九)-自定义滤镜(分屏滤镜)

    相关文章

      网友评论

        本文标题:Metal与图形渲染十一:分屏滤镜

        本文链接:https://www.haomeiwen.com/subject/ekxzoltx.html