http://www.pptjcw.com

ppt所有幻灯片切换效果设置:PPT 切换 - 纯 Shader 实现(下)

    下面的是PPT教程网给你带来的相关内容:

    ppt所有幻灯片切换效果设置:PPT 切换 - 纯 Shader 实现(下)

    此文是对PPT 切换 - 纯 实现(上) 的补充,至此,基本实现了所有的PPT切换效果(剩下几个倒不是没思路,只是暴力写出来太繁琐了)

    如下图所示,上文实现了红框的内容,本文补充绿框的内容:

    ppt所有幻灯片切换效果设置

    目录如下:

    ppt所有幻灯片切换效果设置

    下面这张 GIF 展示了 30 个切换效果,本文将介绍后半部分(后面有每个效果单独的高清 GIF)

    ppt所有幻灯片切换效果设置

    同样,除了两张转场图片外,没有用到其他纹理。所有形状都是 生成,并且没有开 FBO,保证单次 完成

    是用 GLSL 写的,之前跟着 网站和 的教程把 的 API 包了一下,下面这个链接可以获得相关的 和 代码:

    下面也同样 只给出片段着色器里面的函数部分,而关于 顶点着色器、着色器的输入输出、宏定义常量 都是一样的,可在上文和上述 链接找到,故省略

    二十、帘式

    ppt所有幻灯片切换效果设置

    现象:一张图片类似于窗帘往两边展开,随后切换到另一张图片

    要点:

    1、 模拟窗帘的布料,窗帘的形状主要用sin函数进行模拟ppt所有幻灯片切换效果设置:PPT 切换 - 纯 Shader 实现(下),加上一些噪声进行扰动,使之更自然

    2、 用关键帧的思想,实现“布料”的动画,在关键时间戳,定义好布料(纹理坐标)的变换,然后tent函数进行叠加,即进行线性插值

    代码:

    // tent 函数,用于不同关键帧的线性插值
    float triFun(float x, float l, float c, float r)
    {
     float y1 = x / (c - l) - l / (c - l);
     float y2 = x / (c - r) + r / (r - c);
     return min(clamp(y1, 0.0, 1.0), clamp(y2, 0.0, 1.0));
    }
    float random(vec2 st) {
     return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
    }
    vec3 hash33(vec3 p) {
     float n = sin(dot(p, vec3(7, 157, 113)));
     return fract(vec3(2097152, 262144, 32768) * n) * 2. - 1.;
    }
    float tetraNoise(in vec3 p)
    {
     vec3 i = floor(p + dot(p, vec3(0.333333))); p -= i - dot(i, vec3(0.166666));
     vec3 i1 = step(p.yzx, p), i2 = max(i1, 1.0 - i1.zxy); i1 = min(i1, 1.0 - i1.zxy);
     vec3 p1 = p - i1 + 0.166666, p2 = p - i2 + 0.333333, p3 = p - 0.5;
     vec4 v = max(0.5 - vec4(dot(p, p), dot(p1, p1), dot(p2, p2), dot(p3, p3)), 0.0);
     vec4 d = vec4(dot(p, hash33(i)), dot(p1, hash33(i + i1)), dot(p2, hash33(i + i2)), dot(p3, hash33(i + 1.)));
     return clamp(dot(d, v * v * v * 8.) * 1.732 + .5, 0., 1.); // Not sure if clamping is necessary. Might be overkill.
    }
    // 一个 transform 完成单边窗帘纹理坐标的变换,所以在 main 里面要对 0.5 左右分别调用
    vec3 transform(vec2 texCoord)
    {
     vec2 res = texCoord;
     // 变换的思想类似于:动画的关键帧,在关键时间点定义好变换形式,然后插值
     float t1 = 0.0, t2 = 0.5 / 6.0, t3 = 2.0 / 6.0, t4 = 3.0 / 6.0, t5 = 3.5 / 6.0, t6 = 4.5 / 6.0, t7 = 5.3 / 6.0, t8 = 1.0;
     // 对 x 坐标的关键帧变换表达式
     float fx1 = 0.0;
     float fx2 = 0.5 * pow(res.y, 2.0);
     float fx3 = 0.5;
     float fx4 = 0.5 + 0.25 * pow(1.0 - res.y, 2.0);
     float fx5 = 0.5;
     float fx6 = 0.5 - 0.25 * pow(1.0 - res.y, 2.0);
     float fx7 = 1.0 - 0.75 * pow(1.0 - res.y, 2.0);
     float fx8 = 1.0;
     // 对x的关键帧进行插值,使用 tent 函数
     float deltaX =
     triFun(u_ratio, t1, t1, t2) * (fx1)
     +triFun(u_ratio, t1, t2, t3) * (fx2)
     +triFun(u_ratio, t2, t3, t4) * (fx3)
     +triFun(u_ratio, t3, t4, t5) * (fx4)
     +triFun(u_ratio, t4, t5, t6) * (fx5)
     +triFun(u_ratio, t5, t6, t7) * (fx6)
     +triFun(u_ratio, t6, t7, t8) * (fx7)
     +triFun(u_ratio, t7, t8, t8) * (fx8);
     // 对 x 坐标进行变换:大幅度的窗帘拉动 and 细微的偏移
     res.x = (res.x - deltaX) / (1.0 + 0.2 * u_ratio - deltaX);
     res.x = res.x - 0.02 * cos(20.0 * PI * res.x) * deltaX;
     // 对 y 坐标的关键帧变换表达式
     float fy1 = 0.0;
     float fy2 = 0.2 * pow(1.0 - res.x, 2.0);
     float fy3 = 0.0;
     float fy4 = 0.05 * pow(1.0 - (res.x), 2.0);
     float fy5 = 0.0;
     float fy6 = 0.05 * pow(1.0 - (res.x), 2.0);
     float fy7 = 0.3 * pow(1.0 - (res.x), 2.0);
     float fy8 = 0.0;
     // 对 y 的关键帧进行插值,使用 tent 函数
     float deltaY =
     triFun(u_ratio, t1, t1, t2) * (fy1)
     +triFun(u_ratio, t1, t2, t3) * (fy2)
     +triFun(u_ratio, t2, t3, t4) * (fy3)
     +triFun(u_ratio, t3, t4, t5) * (fy4)
     +triFun(u_ratio, t4, t5, t6) * (fy5)
     +triFun(u_ratio, t5, t6, t7) * (fy6)
     +triFun(u_ratio, t6, t7, t8) * (fy7)
     +triFun(u_ratio, t7, t8, t8) * (fy8);
     // 对 y 坐标进行变换:大幅度的窗帘拉动 and 细微的偏移
     res.y = (res.y - 1.0) / (1.0 - deltaY) + 1.0;
     res.y = res.y + 0.05 * sin(20.0 * PI * res.x) * deltaX * (1.0 - res.y) * random(vec2(floor(res.x * 20.0), 1.0));
     float noise = tetraNoise(vec3(res * vec2(5.0, 0.2), u_ratio * 1.0));
     //res.x = res.x - clamp(0.2 * noise * pow(deltaX, 0.5),0.0,res.x);
     
     // 窗帘上形如三角函数的光影变化,和变换后的坐标一同返回
     float intensityOffset = 0.2 * cos(20.0 * PI * (res.x - clamp(0.2 * noise * pow(deltaX, 0.5), 0.0, res.x))) * deltaX;
     return vec3(res, intensityOffset);
    }
    void main()
    {
     vec4 resColor = vec4(1.0, 0.0, 0.0, 1.0);
     vec4 texColor2 = texture(u_ourTexture2, texCoord);
     // 对右半部分:从 0.5 -> 1.0 映射到 0.0 -> 1.0,经过 transform 后再映射回来
     if (texCoord.x > 0.5)
     {
     vec2 coord = vec2(texCoord.x * 2.0 - 1.0, texCoord.y);
     vec3 res = transform(coord);
     resColor = texture(u_ourTexture1, vec2(res.x * 0.5 + 0.5, res.y));
     resColor = resColor * (1.0 + res.z);
     // 对于上一张图超出 0-1 范围的地方,显示下一张图
     if (res.x < 0.0 || res.x > 1.0 || res.y < 0.0 || res.y > 1.0)
     resColor = texColor2;
     }
     // 对左半部分:从 0.0 -> 0.5 映射到 1.0 -> 0.0,经过 transform 后再映射回来
     if (texCoord.x <= 0.5)
     {
     vec2 coord = vec2(1.0 - texCoord.x * 2.0, texCoord.y);
     vec3 res = transform(coord);
     resColor = texture(u_ourTexture1, vec2(0.5 - res.x * 0.5, res.y));
     
     resColor = resColor * (1.0 + res.z);
     if (res.x < 0.0 || res.x > 1.0 || res.y < 0.0 || res.y > 1.0)
     resColor = texColor2;
     }
     FragColor = resColor;
    };

    二十一、悬挂 Drape

    ppt所有幻灯片切换效果设置

    现象:一张图片类似一块布从上往下掉落,完成切换

    要点:

    1、 布往下坠落的过程,需要显示布的背面,且需要选择合适的函数来对布料进行近似

    2、 布坠落到底部后,由于惯性,会有轻微的往里偏移ppt所有幻灯片切换效果设置,随后恢复

    代码:

    // tent 函数,用于不同关键帧的线性插值
    float triFun(float x, float l, float c, float r)
    {
     if (l == c) l = c - 0.0001;
     if (r == c) r = c + 0.0001;
     float y1 = (x - l) / (c - l);
     float y2 = (x - r) / (c - r);
     return min(clamp(y1, 0.0, 1.0), clamp(y2, 0.0, 1.0));
    }
    float random(vec2 st) {
     return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
    }
    vec3 transform(vec2 texCoord)
    {
     vec2 res = texCoord;
     float t1 = 0.5,t2 = 0.6,t3 = 0.7,t4 = 1.0;
     // 变换的思想类似于:动画的关键帧,在关键时间点定义好变换形式,然后插值
     // 对 x 坐标的关键帧变换表达式
     float fx1_left = 0.0;
     float fx2_left = 0.1 * res.y * (1.0 - res.y);
     float fx3_left = 0.1 * pow(1.0 - res.y, 2.0);
     float fx4_left = 0.0;
     float fx1_right = 1.0;
     float fx2_right = 1.0 - 0.05 * res.y * (1.0 - res.y);
     float fx3_right = 1.0 - 0.05 * pow(1.0 - res.y, 2.0);
     float fx4_right = 1.0;
     // 对x的关键帧进行插值,使用 tent 函数
     float deltaX_left =
     triFun(u_ratio, t1, t1, t2) * (fx1_left)
     +triFun(u_ratio, t1, t2, t3) * (fx2_left)
     +triFun(u_ratio, t2, t3, t4) * (fx3_left)
     +triFun(u_ratio, t3, t4, t4) * (fx4_left);
     float deltaX_right =
     triFun(u_ratio, t1, t1, t2) * (fx1_right)
     +triFun(u_ratio, t1, t2, t3) * (fx2_right)
     +triFun(u_ratio, t2, t3, t4) * (fx3_right)
     +triFun(u_ratio, t3, t4, t4) * (fx4_right);
     // 对 x 坐标进行变换
     res.x = (res.x - deltaX_left) / (deltaX_right - deltaX_left);
     // 对 y 坐标的关键帧变换表达式
     float fy1_down = 0.0;
     float fy2_down = 0.3 * ((0.2-0.3)*res.x + 0.2);
     float fy3_down = 0.5 * ((0.2 - 0.3) * res.x + 0.2);
     float fy4_down = 0.0;
     float fy1_top = 1.0;
     float fy2_top = 1.0;
     float fy3_top = 1.0;
     float fy4_top = 1.0;
     // 对y的关键帧进行插值,使用 tent 函数
     float deltaY_down =
     triFun(u_ratio, t1, t1, t2) * (fy1_down)
     +triFun(u_ratio, t1, t2, t3) * (fy2_down)
     +triFun(u_ratio, t2, t3, t4) * (fy3_down)
     +triFun(u_ratio, t3, t4, t4) * (fy4_down);
     float deltaY_top = 1.0;
     // 对 y 坐标进行变换
     res.y = (res.y - deltaY_down) / (deltaY_top - deltaY_down);
     // 光影变化,和变换后的坐标一同返回
     float intensityOffset = 0.0;
     return vec3(res, intensityOffset);
    }
    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);
     if (u_ratio < 0.5)
     {
     float R = pow(clamp(1.0 - u_ratio/0.5,0.0,1.0),2.0);
     // 转到画布真实的像素坐标系进行变换
     vec2 coord = texCoord;
     coord.y = 2.0*R - coord.y;
     // 添加光影变化
     float intensityOffset = -0.5+2.0*(texCoord.y - R) ;
     // 揭开的背面的部分
     resColor = texture(u_ourTexture1, coord)*(1.0 + intensityOffset);
     //resColor = vec4(1.0+intensityOffset,0.0,0.0,1.0);
     if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0)
     resColor = texColor1;
     if(texCoord.y < R)
     resColor = texColor2;
     }
     else
     {
     vec3 coord = transform(texCoord);
     resColor = texture(u_ourTexture1, coord.xy);
     if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0)
     resColor = texColor2;
     }
     FragColor = resColor;
    };

    二十二、上拉帷幕

    ppt所有幻灯片切换效果设置

    现象:一张图片像一张布一样被上拉,从而切换到另一张图

    要点:

    1、 选择合适的函数,模拟布料的扭曲,同时施加噪声,模拟布料的飘动

    代码:

    // tent 函数,用于不同关键帧的线性插值
    float triFun(float x, float l, float c, float r)
    {
     if (l == c) l = c - 0.0001;
     if (r == c) r = c + 0.0001;
     float y1 = (x - l) / (c - l);
     float y2 = (x - r) / (c - r);
     return min(clamp(y1, 0.0, 1.0), clamp(y2, 0.0, 1.0));
    }
    float random(vec2 st) {
     return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
    }
    vec3 hash33(vec3 p) {
     float n = sin(dot(p, vec3(7, 157, 113)));
     return fract(vec3(2097152, 262144, 32768) * n) * 2. - 1.;
    }
     
    float tetraNoise(in vec3 p)
    {
     vec3 i = floor(p + dot(p, vec3(0.333333))); p -= i - dot(i, vec3(0.166666));
     vec3 i1 = step(p.yzx, p), i2 = max(i1, 1.0 - i1.zxy); i1 = min(i1, 1.0 - i1.zxy);
     vec3 p1 = p - i1 + 0.166666, p2 = p - i2 + 0.333333, p3 = p - 0.5;
     vec4 v = max(0.5 - vec4(dot(p, p), dot(p1, p1), dot(p2, p2), dot(p3, p3)), 0.0);
     vec4 d = vec4(dot(p, hash33(i)), dot(p1, hash33(i + i1)), dot(p2, hash33(i + i2)), dot(p3, hash33(i + 1.)));
     return clamp(dot(d, v * v * v * 8.) * 1.732 + .5, 0., 1.); // Not sure if clamping is necessary. Might be overkill.
    }
    float polynomialFun(float x, float p1, float p2, float p3, float p4, float p5, float p6)
    {
     return p1 * pow(x, 5.0)
     + p2 * pow(x, 4.0)
     + p3 * pow(x, 3.0)
     + p4 * pow(x, 2.0)
     + p5 * pow(x, 1.0)
     + p6 * pow(x, 0.0);
    }
    vec3 transform(vec2 texCoord)
    {
     vec2 res = texCoord;
     float t1 = 0.0;
     float t2 = 0.35;
     float t3 = 1.0;
     res.y = res.y - clamp((u_ratio - t2) / (t3 - t2), 0.0, 1.0) - u_ratio * 0.1;
     // 加一个噪声函数,使之更有灵性
     float noise = tetraNoise(vec3(texCoord, u_ratio * 3.0));
     
     // 变换的思想类似于:动画的关键帧,在关键时间点定义好变换形式,然后插值
     // 对 x 坐标的关键帧变换表达式
     float fx1_left = 0.0;
     float fx2_left = 0.03 * pow(1.0 - res.y, 2.0);
     float fx3_left = 0.1 + 0.25 * pow(1.0 - res.y, 2.0);
     float fx1_right = 1.0;
     float fx2_right = 1.0 - 0.03 * (1.0 - res.y);
     float fx3_right = 0.9 - 0.3 * (1.0 - res.y);
     // 对x的关键帧进行插值,使用 tent 函数
     float deltaX_left = 0.0;
     deltaX_left =
     triFun(u_ratio, t1, t1, t2) * (fx1_left)
     +triFun(u_ratio, t1, t2, t3) * (fx2_left)
     +triFun(u_ratio, t2, t3, t3) * (fx3_left);
     float deltaX_right = 1.0;
     deltaX_right =
     triFun(u_ratio, t1, t1, t2) * (fx1_right)
     +triFun(u_ratio, t1, t2, t3) * (fx2_right)
     +triFun(u_ratio, t2, t3, t3) * (fx3_right);
     // 对 x 坐标进行变换
     res.x = (res.x - deltaX_left) / (deltaX_right - deltaX_left) - 0.04 * noise * pow(u_ratio, 0.5);
     // 对 y 坐标的关键帧变换表达式
     float polynomialValue = polynomialFun(res.x, -6.407, 18.57, -18.76, 7.581, -0.98, 0.017);
     float polynomialGrandientValue = polynomialFun(res.x, 0.0, -6.407 * 5.0, 18.57 * 4.0, -18.76 * 3.0, 7.581 * 2.0, -0.98 * 1.0);
     float fy1_down = 0.0;
     float fy2_down = 0.1 * res.x * (1.0 - res.x) + 0.2 * polynomialValue - 0.05;
     float fy3_down = 0.3 * res.x * (1.0 - res.x) + 1.0 * polynomialValue;
     float fy1_top = 1.0;
     float fy2_top = 1.0 + 1.5 * res.x * (1.0 - res.x) - 0.1;
     float fy3_top = 1.0 + 0.6 * res.x * (1.0 - res.x);
     // 对y的关键帧进行插值,使用 tent 函数
     float deltaY_down =
     triFun(u_ratio, t1, t1, t2) * (fy1_down)
     +triFun(u_ratio, t1, t2, t3) * (fy2_down)
     +triFun(u_ratio, t2, t3, t3) * (fy3_down);
     float deltaY_top =
     triFun(u_ratio, t1, t1, t2) * (fy1_top)
     +triFun(u_ratio, t1, t2, t3) * (fy2_top)
     +triFun(u_ratio, t2, t3, t3) * (fy3_top);
     // 对 y 坐标进行变换
     res.y = (res.y - deltaY_down) / (deltaY_top - deltaY_down);
     res.y = res.y - 0.3 * noise * pow(u_ratio, 0.5);
     // 光影变化,和变换后的坐标一同返回
     float intensityOffset = 1.5 * polynomialGrandientValue * pow((deltaX_left + 1.0 - deltaX_right), 0.5);
     return vec3(res, intensityOffset);
    }
    void main()
    {
     vec4 texColor2 = texture(u_ourTexture2, texCoord);
     vec3 res = transform(texCoord);// transform 返回变换后的 纹理坐标 和 光影调节值
     vec4 resColor = texture(u_ourTexture1, res.xy);
     resColor = resColor * (1.0 + res.z);
     if (res.x < 0.0 || res.x > 1.0 || res.y < 0.0 || res.y > 1.0)
     resColor = texColor2;
     FragColor = resColor;
    };

    二十三、剥离

    ppt所有幻灯片切换效果设置

    ppt所有幻灯片切换效果设置

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

    要点:

    1、 此实现类似于(十九-悬挂),假想有一根斜直线,如 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;
    };

    二十四、库

    ppt所有幻灯片切换效果设置

    现象:第一张图先向内旋转,同时另一张图推着进来,最后旋转回来

    要点:

    1、 近似实现图片的三维变换

    2、 实现镜像的效果

    代码:

    vec2 transform(vec2 texCoord, vec2 xyOffset, float zOffset, vec2 scaleCenter, float theta, vec2 thetaCenter)
    {
     vec2 res = texCoord;
     // xy 位移
     res = res - xyOffset;
     // z 位移,体现为缩放
     res = res - scaleCenter;
     res = res * (1.0 + zOffset);
     res = res + scaleCenter;
     // 旋转
     res = res - thetaCenter;
     res.x = res.x / (cos(theta) + 0.0001);
     res.y = res.y / (1.0 - res.x * sin(theta));
     res.x = res.x / (1.0 - res.x * sin(theta));
     res = res + thetaCenter;
     return res;
    }
    void main()
    {
     vec2 screenCenter = vec2(0.5);
     vec4 texColor1 = vec4(0.0);
     vec4 texColor2 = vec4(0.0);
     float intensityOffset = 0.0;
     vec2 thetaCenter = vec2(1.0, 0.5);
     float t1 = 0.4;
     float t2 = 0.7;
     if (u_ratio < t1)
     {
     float R1 = clamp((u_ratio - 0.0) / (t1 - 0.0), 0.0, 1.0);
     float zOffset1 = 0.0;
     vec2 screenCenter1 = vec2(0.5);
     vec2 xyOffset1 = vec2(0.0, 0.0);
     float theta1 = -R1 * PI * 0.06;
     vec2 coord1 = transform(texCoord, xyOffset1, zOffset1, screenCenter1, theta1, thetaCenter);
     if (coord1.y < 0.0)
     {
     // 倒影的实现
     coord1.y = -coord1.y - 0.01;
     intensityOffset = -coord1.y * 5.0 - 0.5;
     }
     texColor1 = texture(u_ourTexture1, coord1) * (1.0 + intensityOffset);
     }
     if (u_ratio >= t1 && u_ratio < t2)
     {
     float R2 = clamp((u_ratio - t1) / (t2 - t1), 0.0, 1.0);
     float zOffset1 = 0.2 * R2;
     vec2 xyOffset1 = vec2(-0.8 * R2, 0.0);
     float theta1 = -PI * 0.06;
     vec2 coord1 = transform(texCoord, xyOffset1, zOffset1, screenCenter, theta1, thetaCenter);
     if (coord1.y < 0.0)
     {
     coord1.y = -coord1.y - 0.01;
     intensityOffset = -coord1.y * 5.0 - 0.5;
     }
     texColor1 = texture(u_ourTexture1, coord1) * (1.0 + intensityOffset);
     
     float zOffset2 = -0.2 * (1.0 - R2);
     vec2 xyOffset2 = vec2(1.0 * (1.0 - R2), 0.0);
     float theta2 = -PI * 0.06;
     vec2 coord2 = transform(texCoord, xyOffset2, zOffset2, screenCenter, theta2, thetaCenter);
     if (coord2.y < 0.0)
     {
     coord2.y = -coord2.y - 0.01;
     intensityOffset = -coord2.y * 5.0 - 0.5;
     }
     texColor2 = texture(u_ourTexture2, coord2) * (1.0 + intensityOffset);
     }
     if (u_ratio > t2)
     {
     float R3 = clamp((u_ratio - t2) / (1.0 - t2), 0.0, 1.0);
     float zOffset1 = 0.2 * (1.0 - R3);
     vec2 xyOffset1 = vec2(-0.8 - 0.25 * R3, 0.0);
     float theta1 = -PI * 0.06 * (1.0 - R3);
     vec2 coord1 = transform(texCoord, xyOffset1, zOffset1, screenCenter, theta1, thetaCenter);
     if (coord1.y < 0.0)
     {
     coord1.y = -coord1.y - 0.01;
     intensityOffset = -coord1.y * 5.0 - 0.5;
     }
     texColor1 = texture(u_ourTexture1, coord1) * (1.0 + intensityOffset);
     
     float zOffset2 = 0.0;
     vec2 xyOffset2 = vec2(0.0, 0.0);
     float theta2 = -PI * 0.06 * (1.0 - R3);
     vec2 coord2 = transform(texCoord, xyOffset2, zOffset2, screenCenter, theta2, thetaCenter);
     if (coord2.y < 0.0)
     {
     coord2.y = -coord2.y - 0.01;
     intensityOffset = -coord2.y * 5.0 - 0.5;
     }
     texColor2 = texture(u_ourTexture2, coord2) * (1.0 + intensityOffset);
     }
     FragColor = texColor1 + texColor2;
    };

    二十五、立方体 Cube

    ppt所有幻灯片切换效果设置

    想象:类似立方体的两面进行旋转切换

    要点:

    1、 近似实现图片的三维变换。之所以是近似,是因为依我现在的水平来看,在 里面无法对纹理坐标实现和顶点一样的三维变换,特别是旋转和投影,只能是近似的剪切变换,所以会看上去有一些

    代码:

    vec2 transform(vec2 texCoord, vec2 xyOffset, float zOffset, vec2 scaleCenter, float theta, vec2 thetaCenter)
    {
     vec2 res = texCoord;
     // xy 位移
     res = res - xyOffset;
     // z 位移,体现为缩放
     res = res - scaleCenter;
     res = res * (1.0 + zOffset);
     res = res + scaleCenter;
     // 旋转
     res = res - thetaCenter;
     res.x = res.x / (cos(theta)+0.0001);
     res.y = res.y / (1.0 - res.x * sin(theta));
     res.x = res.x / (1.0 - res.x * sin(theta));
     res = res + thetaCenter;
     return res;
    }
    void main()
    {
     vec2 screenCenter = vec2(0.5);
     vec2 thetaCenter = vec2(0.5, 0.5);
     
     // 图片 1 从 (0.0,0.0,0.0) 移动到 (-0.5,0.0,0.5),且角度为 从 0 到 -PI/2
     float zOffset1 = 0.5 * u_ratio;
     vec2 xyOffset1 = vec2(-0.5 * u_ratio,0.0);
     float theta1 = -u_ratio * PI * 0.5;
     vec2 coord1 = transform(texCoord, xyOffset1, zOffset1, screenCenter, theta1, thetaCenter);
     vec4 texColor1 = texture(u_ourTexture1, coord1);
     
     // 图片 2 从 (0.5,0.0,0.5) 移动到 (0.0,0.0,0.0),且角度为 从 PI/2 到 0
     float zOffset2 = 0.5 * (1.0-u_ratio);
     vec2 xyOffset2 = vec2(0.5 * (1.0 - u_ratio), 0.0);
     float theta2 = (1.0-u_ratio) * PI * 0.5;
     vec2 coord2 = transform(texCoord, xyOffset2, zOffset2, screenCenter, theta2, thetaCenter);
     vec4 texColor2 = texture(u_ourTexture2, coord2);
     
     float R = 1.0 - u_ratio;
     if(texCoord.x > R)
     FragColor = texColor2;
     else
     FragColor = texColor1;
    };

    二十六、门 Door

    ppt所有幻灯片切换效果设置

    现象:第一张图像门一样打开,第二张图从小到大显示出来

    要点:

    1、 近似实现第一张图的旋转,第二张图的缩放,同时进行混合

    代码:

    vec2 transform(vec2 texCoord, vec2 xyOffset, float zOffset, vec2 scaleCenter, float theta, vec2 thetaCenter)
    {
     vec2 res = texCoord;
     res = res - scaleCenter;
     res = res * (1.0 + zOffset);
     res = res + scaleCenter;
     
     res = res - thetaCenter;
     res.x = res.x / cos(theta);
     res.y = res.y / (1.0 - res.x * sin(theta));
     res.x = res.x / (1.0 - res.x * sin(theta));
     res = res + thetaCenter;
     
     res = res - xyOffset;
     return res;
    }
    void main()
    {
     float zOffset1 = -1.0 * u_ratio;
     vec2 screenCenter = vec2(0.5);
     vec4 texColor1 = vec4(1.0, 0.0, 0.0, 1.0);
     if (texCoord.x < 0.5)
     {
     float theta = u_ratio * PI * 0.5;
     vec2 thetaCenter = vec2(0.0, 0.5);
     vec2 coord1 = transform(texCoord, vec2(0.0, 0.0), zOffset1, screenCenter, theta, thetaCenter);
     if (coord1.x > 0.5)
     coord1.x = 1.001;
     texColor1 = texture(u_ourTexture1, coord1);
     }
     else
     {
     float theta = -u_ratio * PI * 0.5;
     vec2 thetaCenter = vec2(1.0, 0.5);
     vec2 coord1 = transform(texCoord, vec2(0.0, 0.0), zOffset1, screenCenter, theta, thetaCenter);
     if (coord1.x < 0.5)
     coord1.x = -0.001;
     texColor1 = texture(u_ourTexture1, coord1);
     }
     float zOffset2 = 0.5 * (1.0 - u_ratio);// zOffset从 0.5 -> 0,类似缩放因子从 0.5 -> 1
     vec2 coord2 = transform(texCoord, vec2(0.0, 0.0), zOffset2, vec2(0.5), 0.0, vec2(0.0, 0.0));
     vec4 texColor2 = texture(u_ourTexture2, coord2);
     if (coord2.x < 0.0 || coord2.x > 1.0 || coord2.y < 0.0 || coord2.y > 1.0)
     {
     //texColor2 = vec4(1.0); // window
     texColor2 = vec4(0.0); // door
     }
     FragColor = mix(texColor1, texColor2, u_ratio);
    };

    二十七、框 Box

    ppt所有幻灯片切换效果设置

    现象:两张图片类似一个方形的框架进行旋转,切换到另一张图

    要点:

    1、 近似实现图片的三维旋转,思路大致和(二十四-立方体)相同

    代码:

    vec2 transform(vec2 texCoord, vec2 xyOffset, float zOffset, vec2 scaleCenter, float theta, vec2 thetaCenter)
    {
     vec2 res = texCoord;
     // xy 位移
     res = res - xyOffset;
     // z 位移,体现为缩放
     res = res - scaleCenter;
     res = res * (1.0 + zOffset);
     res = res + scaleCenter;
     // 旋转
     res = res - thetaCenter;
     res.x = res.x / (cos(theta) + 0.0001);
     res.y = res.y / (1.0 - res.x * sin(theta));
     res.x = res.x / (1.0 - res.x * sin(theta));
     res = res + thetaCenter;
     return res;
    }
    void main()
    {
     vec2 screenCenter = vec2(0.5);
     vec2 thetaCenter = vec2(0.5, 0.5);
     
     float zOffset1 = (-abs(u_ratio - 1.0 / 3.0) + 1.0 / 3.0) * 0.5;
     vec2 xyOffset1 = vec2(-0.5 * u_ratio, 0.0);
     float theta1 = u_ratio * PI * 0.5;
     vec2 coord1 = transform(texCoord, xyOffset1, zOffset1, screenCenter, theta1, thetaCenter);
     vec4 texColor1 = texture(u_ourTexture1, coord1);
     
     float zOffset2 = (-abs((1.0 - u_ratio) - 1.0 / 3.0) + 1.0 / 3.0) * 0.5;
     vec2 xyOffset2 = vec2(0.5 * (1.0 - u_ratio), 0.0);
     float theta2 = -(1.0 - u_ratio) * PI * 0.5;
     vec2 coord2 = transform(texCoord, xyOffset2, zOffset2, screenCenter, theta2, thetaCenter);
     vec4 texColor2 = texture(u_ourTexture2, coord2);
     
     FragColor = texColor1 + texColor2;
    };

    ppt所有幻灯片切换效果设置

    二十八、梳理 Comb

    ppt所有幻灯片切换效果设置

    现象:图像一条一条向左向右飞出,显示出另一张图片

    要点:比较简单的实现,纵向分条即可

    代码:

    void main()
    {
     vec4 resColor = vec4(u_ratio, 0.0, 0.0, 1.0);
     float halfCombNum = 3.0;
     float delay = floor(texCoord.y * halfCombNum * 2.0) / halfCombNum * 0.25; // 0-0.5
     float Ry = floor(fract(texCoord.y * halfCombNum) * 2.0);// 0-1-0-1-0-1
     float ratio = clamp(u_ratio * 2.0 - delay * 2.0, 0.0, 1.0);
     if (1.0 - Ry - ratio + (2.0 * Ry - 1.0) * texCoord.x > 0.0)
     resColor = texture(u_ourTexture1, vec2(texCoord.x + (1.0 - 2.0 * Ry) * ratio, texCoord.y));
     else
     resColor = texture(u_ourTexture2, vec2(texCoord.x, texCoord.y));
     FragColor = resColor;
    };

    二十九、缩放 Zoom

    ppt所有幻灯片切换效果设置

    现象:两张图片缩放,一张淡出,一张淡入,实现切换

    要点:

    1、 实现图片缩放,比较简单的实现

    代码:

    vec2 transform(vec2 texCoord, float zOffset)
    {
     vec2 coord = texCoord - vec2(0.5);
     coord = coord * (1 + zOffset); // zOffset 此处指z方向的偏移,实际上指代指缩放因子
     coord = coord + vec2(0.5);
     return coord;
    }
    void main()
    {
     float zOffset1 = -0.5 * u_ratio;// zOffset从 0 -> -0.5,类似缩放因子从 1 -> 1.5
     vec2 coord1 = transform(texCoord, zOffset1);
     vec4 texColor1 = texture(u_ourTexture1, coord1);
     float zOffset2 = 0.5 * (1.0 - u_ratio);// zOffset从 0.5 -> 0,类似缩放因子从 0.5 -> 1
     vec2 coord2 = transform(texCoord, zOffset2);
     vec4 texColor2 = texture(u_ourTexture2, coord2);
     FragColor = mix(texColor1, texColor2, u_ratio);
    };

    三十、碎片 Shred

    ppt所有幻灯片切换效果设置

    现象:第一张图被分割成多块碎片,分别往前往后迅速移动,在最远点瞬间切换为另一张图,随后恢复

    要点:

    1、 随机碎片的生成,使用简单的随机数进行生成,详见函数

    2、 近似实现碎片的三维变换

    代码:

    vec2 transform(vec2 texCoord, vec2 xyOffset, float zOffset, vec2 scaleCenter, float xTheta, vec2 xThetaCenter, float yTheta, vec2 yThetaCenter, float zTheta, vec2 zThetaCenter)
    {
     vec2 res = texCoord;
     float projectPar = 0.8;
     // 绕 x 轴旋转
     res = res - xThetaCenter;
     res.y = res.y / cos(xTheta);
     res.y = res.y / (1.0 - projectPar * res.y * sin(xTheta));
     res.x = res.x / (1.0 - projectPar * res.y * sin(xTheta));
     res = res + xThetaCenter;
     // 绕 y 轴旋转
     res = res - yThetaCenter;
     res.x = res.x / cos(yTheta);
     res.y = res.y / (1.0 - projectPar * res.x * sin(yTheta));
     res.x = res.x / (1.0 - projectPar * res.x * sin(yTheta));
     res = res + yThetaCenter;
     // 绕 z 轴旋转
     res = res - zThetaCenter;
     res = res * vec2(u_width, u_height);
     res = vec2(dot(vec2(cos(zTheta), sin(zTheta)), res), dot(vec2(-sin(zTheta), cos(zTheta)), res));
     res = res / vec2(u_width, u_height);
     res = res + zThetaCenter;
     // z 方向位移
     res = res - scaleCenter;
     res = res * (1.0 + zOffset);
     res = res + scaleCenter;
     // xy 方向位移
     res = res - xyOffset;
     return res;
    }
    float random(vec2 st) {
     return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
    }
    float random(float inV)
    {
     return random(vec2(inV));
    }
    float generateFrag(vec2 texCoord)
    {
     vec2 coord = texCoord;
     float num = 12.0;
     float v = ceil(fract(coord.x * num) * 2.0 - 1.0);
     float floorV = floor(coord.x * num * 2.0);
     coord.x = coord.x + random(floorV) / num * 0.5;
     if (coord.y < random(floor(coord.x * num * 2.0)))
     v = 1.0 - v;
     if (texCoord.x < 0.0 || texCoord.x > 1.0 || texCoord.y < 0.0 || texCoord.y > 1.0)
     v = 0.0;
     return v;
    }
    vec4 textureSelect(vec2 coord)
    {
     vec4 resColor = vec4(0.0);
     if (u_ratio < 0.5)
     resColor = texture(u_ourTexture1, coord);
     else
     resColor = texture(u_ourTexture2, coord);
     return resColor;
    }
    void main()
    {
     vec2 scaleCenter = vec2(0.5);
     vec2 xThetaCenter = vec2(0.5);
     vec2 yThetaCenter = vec2(0.5);
     vec2 zThetaCenter = vec2(0.5);
     vec4 resColor1 = vec4(0.0);
     vec4 resColor2 = vec4(0.0);
     vec2 res1 = texCoord;
     vec2 res2 = texCoord;
     
     float zOffset = 0.0;
     vec2 xyOffset = vec2(0.0);
     float xTheta = -PI * 0.05;
     float yTheta = PI * 0.1;
     float zTheta = 0.0;
     
     float t1 = 0.3;
     float t2 = 0.7;// 保证 t1 + t2 = 1.0,且都在 0-1 之间
     
     if (u_ratio < t1 || u_ratio >= t2)
     {
     float R1 = (-abs(u_ratio - 0.5) + 0.5) / t1;
     xTheta = -PI * 0.05 * R1;
     yTheta = PI * 0.1 * R1;
     {
     zOffset = (0.4) * R1;
     res1 = transform(texCoord, xyOffset, zOffset, scaleCenter, xTheta, xThetaCenter, yTheta, yThetaCenter, zTheta, zThetaCenter);
     float mask = generateFrag(res1);
     resColor1 = textureSelect(res1) * mask;
     }
     {
     zOffset = (0.6) * R1;
     res2 = transform(texCoord, xyOffset, zOffset, scaleCenter, xTheta, xThetaCenter, yTheta, yThetaCenter, zTheta, zThetaCenter);
     float mask = 1.0 - generateFrag(res2);
     resColor2 = textureSelect(res2) * mask;
     }
     FragColor = mix(resColor2, resColor1, resColor1.a);
     }
     if (u_ratio >= t1 && u_ratio < t2)
     {
     float R2 = 1.0 - abs((u_ratio - t1) / (t2 - t1) * 2.0 - 1.0);
     {
     zOffset = 0.4 - 1.5 * R2;
     xyOffset = vec2(0.7, 0.2) * R2;
     res1 = transform(texCoord, xyOffset, zOffset, scaleCenter, xTheta, xThetaCenter, yTheta, yThetaCenter, zTheta, zThetaCenter);
     float mask = generateFrag(res1);
     resColor1 = textureSelect(res1) * mask;
     }
     {
     zOffset = 0.6 + 5.0 * R2;
     xyOffset = vec2(-1.5, -0.2) * R2;
     res2 = transform(texCoord, xyOffset, zOffset, scaleCenter, xTheta, xThetaCenter, yTheta, yThetaCenter, zTheta, zThetaCenter);
     float mask = 1.0 - generateFrag(res2);
     resColor2 = textureSelect(res2) * mask;
     }
     FragColor = mix(resColor2, resColor1, resColor1.a);
     }
    };

    三十一、跌落 Fall

    ppt所有幻灯片切换效果设置

    现象:一张图片向里跌落,切换到另一张图片

    要点:

    1、 对纹理坐标进行扭曲,用多项式函数来近似边缘的扭曲

    2、 对图片施加旋转的同时,进行边缘扭曲

    代码:

    vec2 transform(vec2 texCoord, vec2 xyOffset, float zOffset, vec2 scaleCenter, float theta, vec2 rotateCenter)
    {
     vec2 res = texCoord;
     // 这个场景不需要 z 偏移,故可注去
     //res = res - scaleCenter;
     //res = res * (1.0 + zOffset);
     //res = res + scaleCenter;
     // 绕 x 轴旋转结合透视,体现为 x 轴方向的剪切,y轴方向的缩放和剪切,且添加了弯曲因素,使得图片看上去弯曲了
     res = res - rotateCenter;
     res.y = clamp(res.y / cos(theta), -0.5, 1.5);
     float yWrapFact = (0.3 * (1.0 - res.x) * u_ratio);// y 坐标的弯曲,与 x 呈线性变化,体现为左边低一些
     res.y = res.y * (1.0 + res.y * sin(theta) + yWrapFact);
     float xWrapFact = 0.2 * (1.1 - res.x) * u_ratio * sin((res.y + 0.2 * res.x + 0.1) * PI);// x 坐标的弯曲,用 sin 函数进行干扰
     res.x = res.x * (1.0 + (res.y * sin(theta) + xWrapFact));
     res = res + rotateCenter;
     // 这个场景不需要 xy 偏移,故可注去
     // res = res - xyOffset;
     return res;
    }
    void main()
    {
     vec4 resColor = vec4(1.0, 0.0, 0.0, 1.0);
     float zOffset1 = 0.0;
     vec2 screenCenter = vec2(0.5);
     vec2 xyOffset = vec2(0.0);
     vec2 rotateCenter = vec2(0.5, 0.0);
     // theta 是一个分段函数,用于控制坠落速度,先线性后三次函数
     float b = 0.001;
     float a = 0.2;
     float theta = b / a * u_ratio * PI * 0.5;
     if (u_ratio > a)
     theta = (pow((u_ratio - a) / (1.0 - a), 3.0) * (1.0 - b) + b) * PI * 0.5;
     vec2 coord1 = transform(texCoord, xyOffset, zOffset1, screenCenter, theta, rotateCenter);
     // 控制图片变暗的因子
     float fadeRatio = 1.0 - 0.5 * u_ratio;
     resColor = fadeRatio * texture(u_ourTexture1, coord1);
     // 坠落图片意外的区域,显示第二张图
     if (coord1.x < 0.0 || coord1.x > 1.0 || coord1.y < 0.0 || coord1.y > 1.0)
     resColor = texture(u_ourTexture2, texCoord);
     FragColor = resColor;
    };

    三十二、翻页

    ppt所有幻灯片切换效果设置

    现象:像书本翻页一样,进行图片切换

    要点:实现图片右半部分的顺时针旋转,这个本身不属于PPT切换的内容,本意是为了模拟“页面卷曲”然而卷曲效果不好实现,就做了这个翻页效果

    代码:

    vec2 transform(vec2 texCoord, float theta)
    {
     vec2 res = texCoord - vec2(0.5, 0.5);
     // 执行旋转和投影(投影本质上是剪切)
     res.x = res.x / cos(theta);
     res.y = res.y / (1.0 - res.x * sin(theta));
     res.x = res.x / (1.0 - res.x * sin(theta));
     res = res + vec2(0.5, 0.5);
     return res;
    }
    void main()
    {
     // 图片在z方向上的偏移量
     vec2 texCoordAfterTransform = transform(texCoord, -u_ratio * PI);
     
     if (u_ratio < 0.5)
     {
     if (texCoord.x < 0.5)
     FragColor = texture(u_ourTexture1, texCoord);
     else
     {
     if (texCoordAfterTransform.x > 1.0 || texCoordAfterTransform.x < 0.0 || texCoordAfterTransform.y < 0.0 || texCoordAfterTransform.y > 1.0)
     FragColor = texture(u_ourTexture2, texCoord);
     else
     FragColor = texture(u_ourTexture1, texCoordAfterTransform) * (1.0 - u_ratio);
     }
     }
     else
     {
     if (texCoord.x >= 0.5)
     FragColor = texture(u_ourTexture2, texCoord);
     else
     {
     if (texCoordAfterTransform.x > 1.0 || texCoordAfterTransform.x < 0.0 || texCoordAfterTransform.y < 0.0 || texCoordAfterTransform.y > 1.0)
     FragColor = texture(u_ourTexture1, texCoord);
     else
     FragColor = texture(u_ourTexture2, vec2(1.0 - texCoordAfterTransform.x, texCoordAfterTransform.y)) * (u_ratio);
     }
     }
    };

    感谢你支持pptjcw.com网,我们将努力持续给你带路更多优秀实用教程!

    提示:如果您觉得本文不错,请点击分享给您的好友!谢谢

    上一篇:ppt动画效果怎么设置全部出来:【实用小技能】用PPT制作好玩的动画图表! 下一篇:ppt整体动画效果在哪里设置:好绝!手把手教会你 7 种高级感 PPT 动画制作,一个比一个好看

    郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。