首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >干货分享 | Shader 实现 PPT 转场效果(附源码)

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

作者头像
音视频开发进阶
发布2021-09-03 14:53:22
5500
发布2021-09-03 14:53:22
举报

知乎上看到一位大佬用 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.0, 1.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;
};

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 音视频开发进阶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 擦除效果
  • 剥离效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档