OpenGL Shader-分镜特效实现

·  阅读 306

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

前言

在了解如何展示图片纹理之后就可以考虑如何在纹理上实现一些效果。比如下面要说的分镜效果:一张图片内容画布对半切分,左右展示原图片居中内容。因为纹理绘制由图片信息和坐标组成,所以只需要对绘制纹理坐标进行修改即可实现内容切分效果,可以直接通过代码来了解具体实现方式。

实现

二分镜

x轴二分镜效果。判断uv的x大小,若x大于0.5则减去0.5。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    if(uv.x >= 0.5){
        uv.x -=0.5;
    }
    gl_FragColor = texture(iChannel2,uv);
}
复制代码

y轴二分镜效果。判断uv的y大小,若y大于0.5则减去0.5。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    if(uv.y >= 0.5){
        uv.y -=0.5;
    }
    gl_FragColor = texture(iChannel2,uv);
}
复制代码
原图y轴二分镜x轴二分镜
image.pngimage.pngimage.png

三分镜

三分镜实现和二分镜实现效果原理是一样的,只是将二分判断逻辑改成三分而已。当uv.y小于1/3或者大于2/3时,分别加上1/3和减去1/3实现只展示居中部分内容。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    float three = 1.0 / 3.0;
    if(uv.y <= three){
        uv.y = (uv.y + three);
    }else if(uv.y >= three * 2.0){ 
        uv.y -= three;
    }
    gl_FragColor = texture(iChannel2,uv);
}
复制代码

实现三分镜效果之后,可以在三分镜效果基础上添加新效果。比如对uv做除法计算将显示内容放大并增加位移,每个分镜的内容有所偏差达到意外效果。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    float three = 1.0 / 3.0;
    if(uv.y <= three){
        uv.y = (uv.y + three) / 2.0 + 0.25;
        uv.x =  uv.x / 2.0;
    }else if(uv.y >= three * 2.0){ 
        uv.y -= three;
    }else{
        uv.x = uv.x / 1.5 + 0.3;
        uv.y = uv.y / 1.5 + 0.2;
    }
    gl_FragColor = texture(iChannel2,uv);
}
复制代码
原图三分镜三分镜错位
image.pngimage.pngimage.png

分割线

分割线可以使用smoothstep内置函数实现。smoothstep(min,max,x)有三个入参,minmax表示区间,x表示入参值,函数输出值在minmax之间。可以简单理解smoothstep是从minmax平滑过渡的函数。

不过本次实现不采用smoothstep方式而采用简单方法实现。通过判断y值是否在绘制分割线范围内,若y值在分割线范围内就将line值设置为1.0,表示绘制分割线。最终通过mix函数将纹理图片和绘制分割线vec4向量混合,mix函数最后一个入参是line值表示透明度。只有line值大于0时才会在纹理图片上混合分割线vec4。实现方法中line值只有0和1的情况,所以就实现了分割线效果。

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    float three = 1.0 / 3.0;
    float line = 0.0;
    float lineSize = 0.005;
    if(uv.y >= three - lineSize && uv.y <= three + lineSize){ 
     //在1/3处绘制分割线 混合透明度为1.0
       line = 1.0;
    }else if(uv.y >= (three * 2.0 - lineSize) && uv.y <= (three * 2.0 + lineSize)){  
     //在2/3处绘制分割线 混合透明度为1.0
       line = 1.0;
    }
    if(uv.y <= three){
        uv.y += three;
    }else if(uv.y >= three * 2.0){ 
        uv.y -= three;
    }
    gl_FragColor = mix(texture(iChannel2,uv),vec4(0.0,0.0,0.0,1.0),line);
}
复制代码
原图效果
image.pngimage.png
分类:
Android
标签:
分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改