干货分享 | Shader 实现 PPT 转场效果(附源码)

音视频开发进阶

共 3768字,需浏览 8分钟

 ·

2021-08-18 04:58

知乎上看到一位大佬用 Shader 实现了 PPT 里面的转场效果,转载大佬的文章,一起围观膜拜一下。

原文分为上下两篇,详细阐述了每个效果的实现。

上篇:https://zhuanlan.zhihu.com/p/378967288

下篇:https://zhuanlan.zhihu.com/p/380968758

两篇文章实现了 PPT 里面大部分切换效果,如下图所示:

并且还提供了源码,除了两张转场图片之外,没有用到其他纹理,所有形状都是 shader 生成,并且没有开 FBO,保证单次 drawcall 完成。

源码地址如下:

https://github.com/ydc258ttbaby/PPT_transtions_with_shader

摘录了几个效果供大家参考:

擦除效果

现象:从右往左将上面一张图片擦除。

思路:主要还是依赖于 mix 函数进行混合,只不过在边缘处实现渐变,渐变的实现可简单用线性插值实现,如下图所示:

从右往左的擦除就好比将一条斜线从右往左移动,随后 clamp 就成为了透明度 alpha 。

代码:

void main()
{
 vec4 texColor1 = texture(u_ourTexture1, texCoord);
 vec4 texColor2 = texture(u_ourTexture2, texCoord);
 float w = 0.5;
 float alpha = clamp(-1.0 / w * texCoord.x + (1.0 + w) / w + u_ratio * (-(1.0 + w) / w), 0.01.0);
 FragColor = mix(texColor1, texColor2, alpha);
};

剥离效果

现象:一张图片像一张纸一样被揭开,显示出另一张图 。

要点:此实现类似于(十九-悬挂),假想有一根斜直线,如 y = x – 1,图片背面通过镜像得到,直线右边显示底图,左边显示上面的图。

代码实现:

// 斜直线对于 x 的表达式
float fx(float x)
{
 return x - u_width + u_ratio * (u_height + u_width + 100.0);
}
// 斜直线对于 y 的表达式
float gy(float y)
{
 return y + u_width - u_ratio * (u_height + u_width + 100.0);
}
void main()
{
 vec4 resColor = vec4(u_ratio, 0.0, 0.0, 1.0);
 vec4 texColor1 = texture(u_ourTexture1, texCoord);
 vec4 texColor2 = texture(u_ourTexture2, texCoord);
 
 // 转到画布真实的像素坐标系进行变换
 vec2 coordRealScale = texCoord * vec2(u_width, u_height);
 
 // 用二次函数,对揭开的边缘添加偏移
 float xNor = (coordRealScale.x - gy(0.0)) / (u_width - gy(0.0));
 float yNor = (coordRealScale.y - 0.0) / (fx(u_width) - 0.0);
 if (coordRealScale.x > gy(0.0) && coordRealScale.x < u_width)
 coordRealScale.y = coordRealScale.y + 70.0 * xNor * (1.0 - xNor);
 if (coordRealScale.y > 0.0 && coordRealScale.y < fx(u_width))
 coordRealScale.x = coordRealScale.x - 70.0 * yNor * (1.0 - yNor);
 
 // 沿 y = f(x) 翻转
 coordRealScale = vec2(gy(coordRealScale.y), fx(coordRealScale.x));
 vec2 coord = coordRealScale / vec2(u_width, u_height);
 // 添加光影变化
 float intensityOffset = (1.0 - (1.0 - coord.x) * u_width / u_height - coord.y) + 2.0 * u_ratio - 0.1;
 // 揭开的背面的部分
 resColor = texture(u_ourTexture1, coord) * intensityOffset;
 if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0)
 resColor = texColor1;
 if (coordRealScale.y > fx(coordRealScale.x))
 resColor = texColor2;
 FragColor = resColor;
};

这种剥离效果在其他地方也是可以用到的,很有参考意义。

关于其他更多的效果,欢迎到原作者的文章上去看,有着详细代码讲解和技术总结,受益匪浅~~



技术交流,欢迎加我微信:ezglumes ,拉你入技术交流群。

推荐阅读:

音视频面试基础题

OpenGL ES 学习资源分享

开通专辑 | 细数那些年写过的技术文章专辑

NDK 学习进阶免费视频来了

推荐几个堪称教科书级别的 Android 音视频入门项目

觉得不错,点个在看呗~


浏览 20
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报