前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ - OpenGLES3.0 - ] 第三集 主线 - shader着色器与图片特效

[ - OpenGLES3.0 - ] 第三集 主线 - shader着色器与图片特效

作者头像
张风捷特烈
发布2020-04-30 11:14:55
1.5K0
发布2020-04-30 11:14:55
举报
文章被收录于专栏:Android知识点总结

问:学OpenGL能干嘛? 答: 为所欲为。

说起OpenGLES,大家可能都敬而远之,其实它并没有想象中的那么可怕,当然也并没有那么容易 都0202年了,本系列使用OpenGLES3.0,这是一次有预谋的计划:

  • [- 多媒体 -] OpenGLES3.0 接入视频实现特效 - 引言
  • [ - OpenGLES3.0 - ] 第一集 主线 - 打开新世界的大门
  • [ - OpenGLES3.0 - ] 第二集 主线 - 绘制面与图片贴图
  • [ - OpenGLES3.0 - ] 第三集 主线 - shader着色器与图片特效
  • [ - OpenGLES3.0 - ] 第四集 支线1 - 相机接入OpenGLES3.0实现特效
  • [ - OpenGLES3.0 - ] 第五集 支线1 - 视频接入OpenGLES3.0实现特效
  • [ - OpenGLES3.0 - ] 第六集 主线 - OpenGL视口详解与矩阵变换(上篇)
  • [ - OpenGLES3.0 - ] 第七集 主线 - OpenGL视口详解与矩阵变换(下篇)
  • [ - OpenGLES3.0 - ] 第八集 支线2 - 复杂面的绘制
  • [ - OpenGLES3.0 - ] 第九集 支线2 - 立体图形的绘制
  • [ - OpenGLES3.0 - ] 第十集 支线2 - OpenGLES展现建模软件3D模型

本篇主要介绍着色器的代码的使用,并据此完成特效图片的自定义组件 到现在你应该可以贴个图在GLSerfaceView中了,如果还不会,出门左转第二集


1.纹理贴图着色器代码

先从这张贴图开始说起吧


1.1 顶点着色器:texture.vsh

#version 300 es 声明版本为OpenGL ES 3.00规范 in表示输入量,java --> glsl vec3表示三维向量,vec2表示二维向量, out 表示输出量,此处 vsh--> fsh gl_Position表示顶点的位置,

代码语言:javascript
复制
---->[texture.vsh]----
#version 300 es
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTexCoord;

out vec2 vTexCoord;

void main(){
    gl_Position = vec4(aPosition.x, aPosition.y, aPosition.z, 1.0);
    vTexCoord = aTexCoord;
}
复制代码

layout (location = 0) 表示aPosition句柄为0, 如下java代码入参时根据0为aPosition赋值, aTexCoord同理 注意目前模拟器对layout支持不太好,需从0开始。建议真机测试,随意指定,对应即可

代码语言:javascript
复制
---->[GLTextureDrawer.java]----
    private int aPosition = 0;//位置的句柄
    private int aTexCoord = 1;//贴图坐标句柄

什么的顶点着色代码是说,需要传入两个变量,aPosition和aTexCoord 其中gl_Position是一个四维向量,确定渲染时顶点位置,其x,y,z使用aPosition分量, vTexCoord作为输出量传递给片段着色器,其值为aTexCoord


1.2 片段着色器:texture.fsh

precision 表示精度 lowp低、mediump中、highp高 很容易想到,精度越↑,效果越↑,但着色器速度↓ in vec2 vTexCoord; 表示接受顶点的输入的vTexCoord变量 uniform 统一变量,在着色器执行期间它的值是不变的 sampler2D 类型:2D纹理

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

void main(){
    outColor = texture(sTexture, vTexCoord);
}
复制代码

片段的out标识的变量就是输出的色值,sTexture承载纹理,vTexCoord承载坐标 通过texture函数获取值像素的色值,作为输出量。就相当于图片拓印到了"纸"上


2. 着色器颜色效果处理

着色器提供了一个绝佳的可能性,让我们能够操作像素, 通过rgba,理论上我们可以创造一切视觉体验,更不用说so easy的图片特效 下面就由简入难,分析几个常见的图片效果。


2.1 灰度图片特效

texture函数返回一个四维向量,是一个颜色的rgba四个分量值 我们只要轻轻的将outColor的rgb都改为g值即可

代码语言:javascript
复制
---->[gray.fsh]----
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

void main(){
    vec4 color= texture(sTexture, vTexCoord);
    outColor = vec4(color.g, color.g, color.g, 1.0);
}
复制代码

2.2 纯黑白图片特效

还有一种灰度计算方式35911(左一):g = r * 0.3 + g * 0.59 + b * 0.11; 变灰之后,根据灰值可以获取纯黑白色的图片,即像素值大于阈值为黑,小于为白 通过阈值的更改可以控制颜色的通量,阈值↓,通量↓。阈值=0,不通,白色 通过阈值的控制,颜色不太复杂的图就可以变成线稿(左三)。

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

const float threshold = 0.3;//阈值

void main(){
    vec4 color= texture(sTexture, vTexCoord);
    float r = color.r;
    float g = color.g;
    float b = color.b;

    g = r * 0.3 + g * 0.59 + b * 0.11;
    g= g <= threshold ? 0.0 : 1.0;

    outColor = vec4(g, g, g, 1.0);
}
复制代码

2.3 向着色器中传参控制

threshold如果只能写死在着色器代码里,未免有些鸡肋。 如何将它放入程序中进行动态控制呢? 比如下面的效果:

代码语言:javascript
复制
---->[black_white.fsh]----
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

uniform float uThreshold;//uniform入参

void main(){
    vec4 color= texture(sTexture, vTexCoord);
    float r = color.r;
    float g = color.g;
    float b = color.b;

    g = r * 0.3 + g * 0.59 + b * 0.11;
    g= g <= uThreshold ? 0.0 : 1.0;

    outColor = vec4(g, g, g, 1.0);
}
复制代码

其实和前面的顶点入参差不多,在绘制的代码里找到uThreshold句柄再赋值即可 之后就是setThreshold方法设置值,外部通过一个Slider进行控制

代码语言:javascript
复制
//寻找句柄
uThreshold= GLES30.glGetUniformLocation(program, "uThreshold");

public void draw() {
    //...
    GLES30.glUseProgram(program);
    GLES30.glUniform1f(uThreshold, threshold); //赋值
复制代码

这样你是不是对着色器有了那么一丢丢的感觉,不过别急着惊讶,这仅仅是个开始。


2.4 负片、怀旧、冷调

负片是将rgb色值用1去减,获取相对的颜色 怀旧是将图片变成偏黄的暖调, 冷调中只是将r和b的色值进行对调,就能达到相反的效果

代码语言:javascript
复制
---->[负片]----
r = 1.0 - color.r;
g = 1.0 - color.g;
b = 1.0 - color.b;

---->[怀旧]----
r = 0.393* r + 0.769 * g + 0.189* b;
g = 0.349 * r + 0.686 * g + 0.168 * b;
b = 0.272 * r + 0.534 * g + 0.131 * b;

---->[冷调]----
b = 0.393* r + 0.769 * g + 0.189* b;
g = 0.349 * r + 0.686 * g + 0.168 * b;
r = 0.272 * r + 0.534 * g + 0.131 * b;

其他的代码都是类似的,核心是色值的算法。 当然你也可以通过变量来控制这些系数,就可以成为简单的图片编辑器。


4.5. 流年效果

主要是对b值进行处理,arg越大,越发蓝

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

void main(){
    float arg = 3.0;
    
    vec4 color= texture(sTexture, vTexCoord);

    float r = color.r;
    float g = color.g;
    float b = color.b;

    b = sqrt(b)*arg;
    if (b>1.0) b = 1.0;

    outColor = vec4(r, g, b, 1.0);
}
复制代码

3. 着色器坐标效果处理

除了色值,还有一个非常重要的可用数据就是贴图坐标 可以通过坐标值进行一些位置上的处理,比如对称,旋转,缩放,分屏等

3.1 图片x,y反向

现在不要把它对称一张图片,而是一个个像素拼组成的对象 现在vTexCoord记录着这些像素的位置,改动vTexCoord就可以改变像素的位置 宽为1.0,如果仅是拿1.0- pos.x,就相当于右边的像素跑到左边了(下图2),其他同理

代码语言:javascript
复制
---->[x反]---
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){

    vec2 pos = vTexCoord.xy;
    pos.x= 1.0- pos.x;
    outColor = texture(sTexture, pos);
}

---->[y反]---
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord.xy;
    pos.y= 1.0- pos.y;
    outColor = texture(sTexture, pos);
}

---->[x,y反]---
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord.xy;
    pos.x= 1.0- pos.x;
    pos.y= 1.0- pos.y;
    outColor = texture(sTexture, pos);
}
复制代码

3.2 分屏

分屏也就是根据像素位置判断,去修改读取纹理的位置坐标,从而影响渲染 比如二分,当y大于0.5是,读取的位置是pos.y - 0.5,相当于还是渲染上面部分 你也可以调整0.5这个参数,达到不等分分屏。

  • 二分
代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;


void main(){

    vec2 pos = vTexCoord.xy;
    if (pos.y<= 0.5) {
        pos.y = pos.y ;
    }else{
        pos.y = pos.y - 0.5;
    }
    outColor = texture(sTexture, pos);

}
复制代码

也可以左右分镜:

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord;
    if (pos.x > 0.5) {
        pos.x = 1.0 - pos.x;
    }
    outColor = texture(sTexture, pos);
}
复制代码

  • 三分
代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord.xy;
    if (pos.y<= 1.0/3.0) {
        pos.y = pos.y * 1.0;
    }else if(pos.y<= 2.0/3.0){
        pos.y = (pos.y - 1.0/3.0) * 1.0;
    }else{
        pos.y = (pos.y - 2.0/3.0) * 1.0;
    }
    outColor = texture(sTexture, pos);
}
复制代码

  • 四分
代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord.xy;
    if(pos.x <= 0.5){
        pos.x = pos.x ;
    }else{
        pos.x = pos.x - 0.5;
    }

    if (pos.y<= 0.5) {
        pos.y = pos.y ;
    }else{
        pos.y = pos.y - 0.5;
    }
    outColor = texture(sTexture, pos);
}
复制代码

也许你觉得四分屏时填满多好啊(图中), 如果每个分镜可以处理不同效果那就更棒了(图右)

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord.xy;
    if(pos.x <= 0.5){
        pos.x = pos.x * 2.0;
    }else{
        pos.x = (pos.x - 0.5) * 2.0;
    }

    if (pos.y<= 0.5) {
        pos.y = pos.y * 2.0;
    }else{
        pos.y = (pos.y - 0.5) * 2.0;
    }
    outColor = texture(sTexture, pos);
}
复制代码

四分特效其实也很简单,可就是分成四块去判断,分别处理罢了 核心的算法都是上面介绍过的。是不是感觉自己不知不觉就会写些复杂的对象了?

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    vec2 pos = vTexCoord.xy;
    vec4 result;
    if(pos.x <= 0.5 && pos.y<= 0.5){ //左上
        pos.x = pos.x * 2.0;
        pos.y = pos.y * 2.0;
        vec4 color = texture(sTexture, pos);
        result = vec4(color.g, color.g, color.g, 1.0);
    }else if (pos.x >= 0.5 && pos.y<= 0.5){//右上
        pos.x = (pos.x - 0.5) * 2.0;
        pos.y = (pos.y - 0.5) * 2.0;
        vec4 color= texture(sTexture, pos);
        float r = color.r;
        float g = color.g;
        float b = color.b;
        g = r * 0.3 + g * 0.59 + b * 0.11;
        g= g <= 0.4 ? 0.0 : 1.0;
        result = vec4(g, g, g, 1.0);
    }else if (pos.y> 0.5 && pos.x < 0.5) {//左下
        pos.y = pos.y * 2.0;
        pos.x = pos.x * 2.0;
        vec4 color= texture(sTexture, pos);
        float r = color.r;
        float g = color.g;
        float b = color.b;
        r = 0.393* r + 0.769 * g + 0.189* b;
        g = 0.349 * r + 0.686 * g + 0.168 * b;
        b = 0.272 * r + 0.534 * g + 0.131 * b;
        result = vec4(r, g, b, 1.0);
    }else  if (pos.y> 0.5 && pos.x > 0.5){//右下
        pos.y = (pos.y - 0.5) * 2.0;
        pos.x = (pos.x - 0.5) * 2.0;
        vec4 color= texture(sTexture, pos);
        float r = color.r;
        float g = color.g;
        float b = color.b;
        b = 0.393* r + 0.769 * g + 0.189* b;
        g = 0.349 * r + 0.686 * g + 0.168 * b;
        r = 0.272 * r + 0.534 * g + 0.131 * b;
        result = vec4(r, g, b, 1.0);
    }
    outColor = result;
}
复制代码

3.3. 局部效果

可以控制位置量后,我们就可以做些有意思的事,比如,局部特效 可以通过区域的判断,来指定部分区域进行操作,比如(椭)圆

原来很简单,通过到指定点的距离判断,就可以截获区域

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){

    float centerX =0.4;
    float centerY =0.8;
    float raduius =0.3;

    vec2 pos = vTexCoord.xy;

    vec4 color= texture(sTexture, vTexCoord);
    float r = color.r;
    float g = color.g;
    float b = color.b;
    
    if((pos.x-centerX)*(pos.x-centerX)+(pos.y-centerY)*(pos.y-centerY)<raduius*raduius){//表示在圆的区域内
        outColor = vec4(g, g, g, 1.0);
    }else{
        outColor = vec4(r, g, b, 1.0);
    }
}
复制代码

注意,由于宽高不同,而最大值都是1.0,所以量纲是不同的 区域是椭圆也不用惊讶,解决方法很简单,传入一个宽高比校正即可 下面的rate可以提成变量,由java代码传入,java的Bitmap可以获取宽高 如果有闲情逸致,其他三个量也能提出来,就是一个灰图的探照灯 如果还有闲情逸致,可以定义多个特效效果,通过变量控制一下 就能变成特效探照灯,照到哪里,哪里就特效。

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    float rate= 1000.0/1369.0;
    float centerX =0.5;
    float centerY =0.5/rate;
    float raduius =0.25;

    vec2 pos;
    pos.x = vTexCoord.x;
    pos.y= vTexCoord.y/rate;
    vec4 color= texture(sTexture, vTexCoord);
    float r = color.r;
    float g = color.g;
    float b = color.b;

    if ((pos.x-centerX)*(pos.x-centerX)+(pos.y-centerY)*(pos.y-centerY)<raduius*raduius){ //表示在圆的区域内
        outColor = vec4(g, g, g, 1.0);
    } else {
        outColor = vec4(r, g, b, 1.0);
    }
}
复制代码

3.4. 光照效果

根据上面的效果,实现一下局部的光照效果

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    float rate= 1000.0/1369.0;
    float centerX =0.5;
    float centerY =0.5/rate;
    float radius =0.6;
    float strength = 150.0/255.0;//#设置光照强度

    vec2 pos;
    pos.x = vTexCoord.x;
    pos.y= vTexCoord.y/rate;
    vec4 color= texture(sTexture, vTexCoord);
    float r = color.r;
    float g = color.g;
    float b = color.b;

    float distance = sqrt((pos.x-centerX)*(pos.x-centerX)+(pos.y-centerY)*(pos.y-centerY));

    if (distance<radius){ //表示在圆的区域内
        //按照距离大小计算增强的光照值
       float result = strength*( 1.0 - distance / radius );
        r =  r+result;
        g =  g+result;
        b =  b+result;
        outColor = vec4(r, g, b, 1.0);
    } else {
        outColor = vec4(r, g, b, 1.0);
    }
}
复制代码

3.5 矩形马赛克

马赛克需要指定一行的个数,以及多少个占一块 比如100块,5*5,也就是一行20个小块。这些参数都可以提出去玩

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

void main(){
    float rate= 1000.0/1369.0;
    float cellX= 5.0;
    float cellY= 5.0;
    float rowCount=100.0;

    vec2 pos = vTexCoord;
    pos.x = pos.x*rowCount;
    pos.y = pos.y*rowCount/rate;
    
    pos = vec2(floor(pos.x/cellX)*cellX/rowCount, floor(pos.y/cellY)*cellY/(rowCount/rate))+ 0.5/rowCount*vec2(cellX, cellY);
    outColor = texture(sTexture, pos);
}
复制代码

局部特效以及会了,马赛克也ok了,局部马赛克还远吗?


局部马赛克

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    float rate= 1000.0/1369.0;
    float centerX =0.4;
    float centerY =0.3/rate;
    float radius =0.15;

    float cellX= 1.0;
    float cellY=1.0;
    float rowCount=100.0;

    vec2 pos;
    pos.x = vTexCoord.x;
    pos.y= vTexCoord.y/rate;

    float distance = sqrt((pos.x-centerX)*(pos.x-centerX)+(pos.y-centerY)*(pos.y-centerY));

    if (distance<radius){ //表示在圆的区域内
        vec2 pos = vTexCoord;
        pos.x = pos.x*rowCount;
        pos.y = pos.y*rowCount/rate;

        pos = vec2(floor(pos.x/cellX)*cellX/rowCount, floor(pos.y/cellY)*cellY/(rowCount/rate))+ 0.5/rowCount*vec2(cellX, cellY);
        outColor = texture(sTexture, pos);
    } else {
        outColor = texture(sTexture, vTexCoord);
    }
}
复制代码

3.6 图片点阵

和矩形马赛克类似,将图片分成若干个块,当在cell半径之内, 绘制UVMosaic点的像素值,否则,绘制白色

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;
in vec2 vTexCoord;
uniform sampler2D sTexture;

void main(){
    float rate= 1000.0/1369.0;
    float cellX= 3.0;
    float cellY=3.0;
    float rowCount=100.0;

    vec2 sizeFmt=vec2(rowCount, rowCount/rate);
    vec2 sizeMsk=vec2(cellX, cellY/rate);
    vec2 posFmt = vec2(vTexCoord.x*sizeFmt.x, vTexCoord.y*sizeFmt.y);
    vec2 posMsk = vec2(floor(posFmt.x/sizeMsk.x)*sizeMsk.x, floor(posFmt.y/sizeMsk.y)*sizeMsk.y)+ 0.5*sizeMsk;
    
    float del = length(posMsk - posFmt);

    vec2 UVMosaic = vec2(posMsk.x/sizeFmt.x, posMsk.y/sizeFmt.y);

    vec4 result;
    if (del< cellX/2.0)
    result = texture(sTexture, UVMosaic);
    else
    result = vec4(1.0,1.0,1.0,0.0);
    outColor = result;
}
复制代码

基于此很容易实现圆形的马赛克

代码语言:javascript
复制
#version 300 es
//英雄所见...

void main(){
    //英雄所见...
    else
    result = texture(sTexture, vTexCoord);
    outColor = result;
}
复制代码

3.7 图片加点

这个特效让我赚了一顿午饭钱,需求是将图片变灰加点,本来毫无头绪 聪明的我灵机一动,这不就是小版的马赛克,载把马赛克区域涂黑吗?

代码语言:javascript
复制
#version 300 es
precision mediump float;
out vec4 outColor;

in vec2 vTexCoord;

uniform sampler2D sTexture;

void main(){
    float rate= 1000.0/1369.0;
    float cellX= 1.0;
    float cellY=1.0;
    float rowCount=100.0;
    float space =4.0;

    vec2 sizeFmt=vec2(rowCount, rowCount/rate);
    vec2 sizeMsk=vec2(cellX, cellY/rate);
    vec2 posFmt = vec2(vTexCoord.x*sizeFmt.x, vTexCoord.y*sizeFmt.y);
    vec2 posMsk = vec2(floor(posFmt.x/sizeMsk.x)*sizeMsk.x, floor(posFmt.y/sizeMsk.y)*sizeMsk.y)+ 0.5*sizeMsk;

    float del = length(posMsk - posFmt);
    vec2 UVMosaic = vec2(posMsk.x/sizeFmt.x, posMsk.y/sizeFmt.y);

    vec4 result;
    if (del< cellX/space)
    result=vec4(0.2,0.2,0.2,0.1);
    else
    result = texture(sTexture, vTexCoord);
    outColor = vec4(result.g,result.g,result.g,1.0);
}
复制代码

3.8 灵魂出窍

核心是周期性的获取一个逐渐放大,逐渐透明的图片和原图进行叠合

代码语言:javascript
复制
#version 300 es
precision highp float;
in vec2 vTexCoord;
out vec4 outColor;
uniform sampler2D sTexture;
//传递进来的时间
uniform float uProgress;

void main () {
  float t = 0.7; //周期
  float maxAlpha = 0.4;//第二图最大透明度
  float maxScale = 1.8;//第二图放大最大比率
  //进度
  float progress = mod(uProgress, t) / t; // 0~1
  //当前的透明度
  float alpha = maxAlpha * (1.0 - progress);
  //当前的放大比例
  float scale = 1.0 + (maxScale - 1.0) * progress;
  //根据放大比例获取新的图层纹理坐标
  vec2 weakPos = vec2(0.5 + (vTexCoord.x - 0.5) / scale, 0.5 + (vTexCoord.y - 0.5) / scale);

  //新图层纹理坐标对应的纹理像素值
  vec4 weakMask = texture(sTexture, weakPos);
  vec4 mask = texture(sTexture, vTexCoord);

  //纹理像素值的混合公式,获得混合后的实际颜色
  outColor = mask * (1.0 - alpha) + weakMask * alpha;
}
复制代码

这里我将uProgress提出变量,方便颜色动态效果


本篇到这就差不多了,你应该对shader着色器多了那么一丢丢的理解 其次,这些特效都可以用在相机和视频播放之中,这也是OpenGL的强大之处。 本篇已经很长了,还有一些特效,留在相机和视频支线篇再说,敬请期待。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020年01月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.纹理贴图着色器代码
    • 1.1 顶点着色器:texture.vsh
      • 1.2 片段着色器:texture.fsh
      • 2. 着色器颜色效果处理
        • 2.1 灰度图片特效
          • 2.2 纯黑白图片特效
            • 2.3 向着色器中传参控制
              • 2.4 负片、怀旧、冷调
                • 4.5. 流年效果
                • 3. 着色器坐标效果处理
                  • 3.1 图片x,y反向
                    • 3.2 分屏
                      • 3.3. 局部效果
                        • 3.4. 光照效果
                          • 3.5 矩形马赛克
                            • 3.6 图片点阵
                              • 3.7 图片加点
                                • 3.8 灵魂出窍
                                相关产品与服务
                                图片处理
                                图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档