zoukankan      html  css  js  c++  java
  • OpenGL 12.1

    图片显示到屏幕上由CPU/GPU 协作完成:

    CPU:计算视图 frame 、图片解码,需要绘制的图片通过数据总线交给 GPU。

    GPU:纹理混合、顶点变换与计算、像素点的填充计算、渲染到帧缓冲区。

    iOS双缓冲机制:2个帧缓冲区

    纹理图片滤镜处理,通过修改片元着色器实现滤镜效果。

    效果:

    一、灰度

    原理:对纹理RGB值权重修改并保持平衡,或只取绿色G值 --> 人眼对绿色是最敏感的,绿色值越大,眼睛看到图片越暗。

    1. 浮点算法: Gray = R*0.3+G*0.59+B*0.11
    2. 整数方法: Gray = (R*30+G*59+B*11)/100
    3. 移位方法: Gray = (R*76+G*151+B*28)>>8
    4. 平均值法: Gray = (R+G+B)/3
    5. 仅取绿色: Gray = G

    片元着色器代码:

     1 precision highp float;
     2 uniform sampler2D Texture;
     3 varying vec2 TextureCoordsVarying;
     4 const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);// 权重值取自GPUImage,RGB三值相加=1
     5 
     6 void main (void) {
     7     // 获取纹理图片当前纹理坐标下的 颜色值
     8     vec4 mask = texture2D(Texture, TextureCoordsVarying);
     9     float luminance = dot(mask.rgb, W);// 点乘 颜色 点乘 变换因子
    10     gl_FragColor = vec4(vec3(luminance), 1.0);// 将灰度值转化并填充到像素中(luminance,luminance,luminance,mask.a) 
    11    // gl_FragColor = vec4(vec3(mask.g), 1.0);// 只取绿色
    12 }

    翻转:

    OpenGL 十 - 002、GLSL案例-纹理图片绘制与翻转 中 第三节 图片倒立翻转问题。

    二、方形马赛克

    马赛克原理:⻢赛克效果就是把图片中的⼀个相对⼤小的区域(设置每个马赛克的大小范围)取⽤同⼀个点的颜⾊来表示。可以认为是⼤规模的降低图像的分辨率,⽽让图像的⼀些细节隐藏起来。

    每个小方块范围内取同一个色值,计算每个马赛克块的所在位置对应所取的色值 —>

    1.对纹理图片进行放大(400,400),纹理坐标(400*x,400*y)

    2.求出放大后纹理坐标下 对应的马赛克块(size:16,16)位置,向下取整 —> 400*x / 16 * 16 // 即:400*x  % 16

    3.对放大坐标进行复原,相应缩小,取出位置对应颜色

    —> 可理解为:纹理图片被分割成了N个小方块,每个小方块范围内取同一个色值填充,我们计算出方块应取得色值是什么即可。纹理大小除以方块大小得到个数,第n个方块取得色值都是(n,n)位置的色值。

    片元着色器代码:

    precision mediump float;
    
    varying vec2 TextureCoordsVarying;
    uniform sampler2D Texture;
    const vec2 TexSize = vec2(400.0, 400.0);
    const vec2 mosaicSize = vec2(16.0, 16.0);
    
    void main() {
        vec2 intXY = vec2(TextureCoordsVarying.x*TexSize.x, TextureCoordsVarying.y*TexSize.y);
        vec2 XYMosaic = vec2(floor(intXY.x/mosaicSize.x)*mosaicSize.x, floor(intXY.y/mosaicSize.y)*mosaicSize.y);
        vec2 UVMosaic = vec2(XYMosaic.x/TexSize.x, XYMosaic.y/TexSize.y);
        vec4 color = texture2D(Texture, UVMosaic);
        gl_FragColor = color;
    }

    三、正六边形马赛克

    1、目标:将 纹理图片 处理成 由 N 个六边形的图形马赛克 绘制而成。

    2、方式:纹理像素取值:每个六边形范围内,取六边形的中心位置的纹理坐标值。

    3、算法逻辑:每个六边形周边会有4个中心位置组成一个矩形。

    当纹理坐标传入时,根据纹理坐标计算出六边形中心点位置 --> 矩形顶点位置 --> 上图中黄绿原点。

    算法:

     

    1)给定六边形边长 length,矩形的长宽比 = 3*length : √3*length 

    2)上图 紫色位置处纹理坐标w(x,y),它所对应的矩形的位置 --> ( int(x / (3*length)),  int (y / (√3*length))

    3)计算中心点坐标

    3.1、六边形所在矩形分割成4个小矩形。

    a、当 w 位置是 偶行偶列 时,如下图 --> 计算 1、5 两个中心点:

    1:(3/2 * length * wx, √3/2 * length * wy)

    5:(3/2 * length * (wx + 1), √3/2 * length * (wy + 1)) 

    为何中心点5的 x、y 坐标值 +1 --> w 的位置对应计算出的值恰好是 1 的值,而 5 与 1 的跨度是一个小矩形的大小,所以坐标值需加 相应的宽高(矩形长宽)值。

     b、当 w 位置是 偶行奇列 时,如下图 --> 计算 2、5 两个中心点 -->

    5:(3/2 * length * wx, √3/2 * length * (wy + 1))

    2:(3/2 * length * (wx + 1), √3/2 * length * wy)

    --> w 计算出的值是左上角 --> 中心点 2 的 x 位置多了一个宽度,中心点 5 的 y 多了一个高度。

     

    c、当中心点位置是 奇行偶列 时,如下图 --> 4、5 两个中心点 -->

    4:(3/2 * length * wx, √3/2 * length * (wy + 1))

    5:(3/2 * length * (wx + 1), √3/2 * length * wy)

     

    d、当 w 位置是 奇行奇列 时,如下图 --> 计算 3、5 两个中心点:

    5:(3/2 * length * wx, √3/2 * length * wy)

    3:(3/2 * length * (wx + 1), √3/2 * length * (wy + 1)) 

     4)计算出当前纹理坐标 w(x, y) 位置距两个中心点 v1、v2 位置的远近

    s1 = √(v1.x-x)² + (v1.y-y)²)  s12 = √(v2.x-x)² + (v2.y-y)²)

    比较大小,取距离近的,即取小值。

    4、片元着色器代码

     1 precision highp float;
     2 uniform sampler2D Texture;
     3 varying vec2 TextureCoordsVarying;
     4 
     5 const float mosaicSize = 0.03;
     6 
     7 void main (void) {
     8     
     9     float length = mosaicSize;
    10     
    11     float TR = 0.866025;// √3/2
    12     float TB = 1.5;// 3/2
    13     
    14     float x = TextureCoordsVarying.x;
    15     float y = TextureCoordsVarying.y;
    16     
    17     int wx = int(x / (TB*length));
    18     int wy = int(y / (TR*length));
    19     vec2 v1, v2, vn;
    20     
    21     if (wx/2 * 2 == wx) {// wx % 2 == 0
    22         if (wy/2 * 2 == wy) {
    23             // (0,0),(1,1)
    24             v1 = vec2(length * TB * float(wx), length * TR * float(wy));
    25             v2 = vec2(length * TB * float(wx + 1), length * TR * float(wy + 1));
    26         } else {
    27             // (0,1),(1,0)
    28             v1 = vec2(length * TB * float(wx), length * TR * float(wy + 1));
    29             v2 = vec2(length * TB * float(wx + 1), length * TR * float(wy));
    30         }
    31     }else {
    32         if (wy/2 * 2 == wy) {
    33             // (0,1),(1,0)
    34             v1 = vec2(length * TB * float(wx), length * TR * float(wy + 1));
    35             v2 = vec2(length * TB * float(wx + 1), length * TR * float(wy));
    36         } else {
    37             // (0,0),(1,1)
    38             v1 = vec2(length * TB * float(wx), length * TR * float(wy));
    39             v2 = vec2(length * TB * float(wx + 1), length * TR * float(wy + 1));
    40         }
    41     }
    42     
    43     float s1 = sqrt(pow(v1.x - x, 2.0) + pow(v1.y - y, 2.0));
    44     float s2 = sqrt(pow(v2.x - x, 2.0) + pow(v2.y - y, 2.0));
    45     if (s1 < s2) {
    46         vn = v1;
    47     } else {
    48         vn = v2;
    49     }
    50     vec4 color = texture2D(Texture, vn);
    51     
    52     gl_FragColor = color;
    53     
    54 }

    四、三角形马赛克

     三角形马赛克算法原理:

    1、在正六边形算法的基础上,切割成三角形,计算每个三角形的弧度 --当前纹理坐标与正六边形中心点的夹角

    2、对比夹角所在位置处在1~6哪个三角形中,取对应三角形的中心位置点的颜色

    3、计算每个三角形的中心位置(此中心位置并非为准确的中心点,而是三角形中线的1/2,图中绿色线的1/2位置)

    片元着色器代码

     1 precision highp float;
     2 uniform sampler2D Texture;
     3 varying vec2 TextureCoordsVarying;
     4 
     5 float mosaicSize = 0.03;
     6 
     7 void main (void) {
     8     
     9     const float TR = 0.866025;
    10     const float PI6 = 0.523599;// π/6  30度
    11     
    12     float x = TextureCoordsVarying.x;
    13     float y = TextureCoordsVarying.y;
    14     
    15  
    16     int wx = int(x/(1.5 * mosaicSize));
    17     int wy = int(y/(TR * mosaicSize));
    18     
    19     vec2 v1, v2, vn;
    20     
    21     if (wx / 2 * 2 == wx) {
    22         if (wy/2 * 2 == wy) {
    23             v1 = vec2(mosaicSize * 1.5 * float(wx), mosaicSize * TR * float(wy));
    24             v2 = vec2(mosaicSize * 1.5 * float(wx + 1), mosaicSize * TR * float(wy + 1));
    25         } else {
    26             v1 = vec2(mosaicSize * 1.5 * float(wx), mosaicSize * TR * float(wy + 1));
    27             v2 = vec2(mosaicSize * 1.5 * float(wx + 1), mosaicSize * TR * float(wy));
    28         }
    29     } else {
    30         if (wy/2 * 2 == wy) {
    31             v1 = vec2(mosaicSize * 1.5 * float(wx), mosaicSize * TR * float(wy + 1));
    32             v2 = vec2(mosaicSize * 1.5 * float(wx+1), mosaicSize * TR * float(wy));
    33         } else {
    34             v1 = vec2(mosaicSize * 1.5 * float(wx), mosaicSize * TR * float(wy));
    35             v2 = vec2(mosaicSize * 1.5 * float(wx + 1), mosaicSize * TR * float(wy+1));
    36         }
    37     }
    38 
    39     float s1 = sqrt(pow(v1.x - x, 2.0) + pow(v1.y - y, 2.0));
    40     float s2 = sqrt(pow(v2.x - x, 2.0) + pow(v2.y - y, 2.0));
    41 
    42     if (s1 < s2) {
    43         vn = v1;
    44     } else {
    45         vn = v2;
    46     }
    47     
    48     // 三角形处理
    49     // 计算纹理坐标与六边形中心点夹角 - 
    50     // atan 计算出的范围(-180~180),对应的值 -PI~PI
    51     float a = atan((x - vn.x)/(y - vn.y));
    52 
    53     // 计算6个中心点位置
    54     vec2 area1 = vec2(vn.x, vn.y - mosaicSize * TR / 2.0);
    55     vec2 area2 = vec2(vn.x + mosaicSize / 2.0, vn.y - mosaicSize * TR / 2.0);
    56     vec2 area3 = vec2(vn.x + mosaicSize / 2.0, vn.y + mosaicSize * TR / 2.0);
    57     vec2 area4 = vec2(vn.x, vn.y + mosaicSize * TR / 2.0);
    58     vec2 area5 = vec2(vn.x - mosaicSize / 2.0, vn.y + mosaicSize * TR / 2.0);
    59     vec2 area6 = vec2(vn.x - mosaicSize / 2.0, vn.y - mosaicSize * TR / 2.0);
    60   
    61     if (a >= PI6 && a < PI6 * 3.0) {// 30~90
    62         vn = area1;
    63     } else if (a >= PI6 * 3.0 && a < PI6 * 5.0) {// 90~150
    64         vn = area2;
    65     } else if ((a >= PI6 * 5.0 && a <= PI6 * 6.0)|| (a<-PI6 * 5.0 && a>-PI6*6.0)) {// 150~180 -180~-150
    66         vn = area3;
    67     } else if (a < -PI6 * 3.0 && a >= -PI6 * 5.0) {// -150~-90
    68         vn = area4;
    69     } else if (a <= -PI6 && a> -PI6 * 3.0) {// -90~-30
    70         vn = area5;
    71     } else if (a > -PI6 && a < PI6) {// -30~30
    72         vn = area6;
    73     }
    74     
    75     vec4 color = texture2D(Texture, vn);
    76     gl_FragColor = color;
    77 }
  • 相关阅读:
    Postfix 邮件服务器搭建
    DER、CRT、CER、PEM格式的证书及转换
    Apache SSL 服务搭建
    scapy 中的ARP
    关于linux特殊含义的转义符33
    关于javascript中defineProperty的学习
    python QT 编程之路
    python socket编程制作后门木马(原创)
    mybatis学习——映射器(mappers)
    mybatis学习——properties属性实现引用配置文件
  • 原文地址:https://www.cnblogs.com/zhangzhang-y/p/13499360.html
Copyright © 2011-2022 走看看