美文网首页SurfaceView
《OpenGL从入门到放弃05》着色器语言

《OpenGL从入门到放弃05》着色器语言

作者: 蓝师傅_Android | 来源:发表于2019-04-27 09:56 被阅读0次

    之前文章:

    《OpenGL从入门到放弃01 》一些基本概念
    《OpenGL从入门到放弃02 》GLSurfaceView和Renderer
    《OpenGL从入门到放弃03 》相机和视图
    《OpenGL从入门到放弃04 》画一个长方形

    通过前面几篇文章,相信大家已经掌握了使用OpenGL绘制三角形和长方形,还有一些看起来复杂一点的圆柱、圆锥,就不再介绍了,大家有兴趣的话自己去发挥一些。
    有疑问的点应该是着色器语言,所以有了这篇文章。

    着色器语言

    数据类型

    GLSL中的数据类型主要分为标量、向量、矩阵、采样器、结构体、数组、空类型七种类型:

    • 标量:相当于java的基本数据类型,在GLSL中标量只有bool、int和float三种。我们最需要注意的是精度,防止溢出问题。

    • 向量:向量我们可以看做是数组,在GLSL通常用于储存颜色、坐标等数据,针对维数,可分为二维、三维和四维向量。针对存储的标量类型,可以分为bool、int和float。共有vec2、vec3、vec4,ivec2、ivec3、ivec4、bvec2、bvec3和bvec4九种类型,数字代表维数、i表示int类型、b表示bool类型。需要注意的是,GLSL中的向量表示竖向量,所以与矩阵相乘进行变换时,矩阵在前,向量在后(与DirectX正好相反)。向量在GPU中由硬件支持运算,比CPU快的多。

      1. 作为颜色向量时,用rgba表示分量,就如同取数组的中具体数据的索引值。三维颜色向量就用rgb表示分量。比如对于颜色向量vec4 color,color[0]和color.r都表示color向量的第一个值,也就是红色的分量。其他相同。
      2. 作为位置向量时,用xyzw表示分量,xyz分别表示xyz坐标,w表示向量的模。三维坐标向量为xyz表示分量,二维向量为xy表示分量。
      3. 作为纹理向量时,用stpq表示分量,三维用stp表示分量,二维用st表示分量。
    • 矩阵:在GLSL中矩阵拥有22、33、4*4三种类型的矩阵,分别用mat2、mat3、mat4表示。我们可以把矩阵看做是一个二维数组,也可以用二维数组下标的方式取里面具体位置的值。

    • 采样器:sampler2D,采样器是专门用来对纹理进行采样工作的,一般来说,一个采样器变量表示一副或者一套纹理贴图。所谓的纹理贴图可以理解为我们看到的物体上的皮肤。

    • 结构体:和C语言中的结构体相同,用struct来定义结构体,关于结构体参考C语言中的结构体。

    • 数组:跟C、Java中的数组基本相同

    变量声明示例:

    float a=1.0;
    int b=1;
    bool c=true;
    vec2 d=vec2(1.0,2.0);
    vec3 e=vec3(1.0,2.0,3.0)
    vec4 f=vec4(vec3,1.2);
    vec4 g=vec4(0.2);  //相当于vec(0.2,0.2,0.2,0.2)
    vec4 h=vec4(a,a,1.3,a);
    mat2 i=mat2(0.1,0.5,1.2,2.4);
    mat2 j=mat2(0.8);   //相当于mat2(0.8,0.8,0.8,0.8)
    mat3 k=mat3(e,e,1.2,1.6,1.8);
    

    运算符

    GLSL中的运算符有(越靠前,运算优先级越高):

    1. 索引:[]
    2. 前缀自加和自减:++,–
    3. 一元非和逻辑非:~,!
    4. 加法和减法:+,-
    5. 等于和不等于:==,!=
    6. 逻辑异或:^^
    7. 三元运算符号,选择:?:
    8. 成员选择与混合:.
    9. 后缀自加和自减:++,–
    10. 乘法和除法:*,/
    11. 关系运算符:>,<,=,>=,<=,<>
    12. 逻辑与:&&
    13. 逻辑或:||
    14. 赋值预算:=,+=,-=,*=,/=

    基本和其它语言一致。

    限定符

    attritude:一般用于各个顶点各不相同的量。如顶点颜色、坐标等。
    uniform:一般用于对于3D物体中所有顶点都相同的量。比如光源位置,统一变换矩阵等。
    varying:表示易变量,一般用于顶点着色器传递到片元着色器的量。
    const:常量。
    看下例子:

        // 顶点着色器的脚本
        String vertexShaderCode =
                        "uniform mat4 uMVPMatrix;" +    /接收传入的转换矩阵
                        "attribute vec4 vPosition;" +      //接收传入的顶点
                        "attribute vec2 aTexCoord;" +       //接收传入的顶点纹理位置
                        "varying vec2 vTextureCoord;" +     //增加用于传递给片元着色器的纹理位置变量
                        "void main() {" +
                            "gl_Position = uMVPMatrix * vPosition;" +  //矩阵变换计算之后的位置
                            "vTextureCoord = aTexCoord;" +
                        " }";
    
    

    浮点精度

    与顶点着色器不同的是,在片元着色器中使用浮点型时,必须指定浮点类型的精度,否则编译会报错。精度有三种,分别为:

    lowp:低精度。8位。
    mediump:中精度。10位。
    highp:高精度。16位。

    不仅仅是float可以制定精度,其他(除了bool相关)类型也同样可以,但是int、采样器类型并不一定要求指定精度。加精度的定义如下:

    uniform lowp float a=1.0;
    varying mediump vec4 c;
    

    也可以直接在片元着色器第一行声明

    precision mediump float;  // 声明float类型的精度为中等(精度越高越耗资源)
    

    内建变量

    顶点着色器的内建变量

    输入变量

    1. gl_Position:顶点坐标
      在上面代码段可以看到,直接使用gl_Position,不需要定义或者声明,
    2. gl_PointSize:点的大小,没有赋值则为默认值1,通常设置绘图为点绘制才有意义。

    片元着色器的内建变量

    输入变量

    1. gl_FragCoord:当前片元相对窗口位置所处的坐标。
    2. gl_FragFacing:bool型,表示是否为属于光栅化生成此片元的对应图元的正面。

    加粗是我们常用的内建变量

    输出变量

    1. gl_FragColor:当前片元颜色
    2. gl_FragData:vec4类型的数组。向其写入的信息,供渲染管线的后继过程使用。

    函数

    常见函数

    • radians(x):角度转弧度
    • degrees(x):弧度转角度
    • sin(x):正弦函数,传入值为弧度。相同的还有cos余弦函数、tan正切函数、asin反正弦、acos反余弦、atan反正切
    • pow(x,y):[Math Processing Error]xy
    • exp(x):[Math Processing Error]ex
    • exp2(x):[Math Processing Error]2x
    • log(x):[Math Processing Error]logex
    • log2(x):[Math Processing Error]log2x
    • sqrt(x):[Math Processing Error]x
    • inversesqr(x):[Math Processing Error]1x
    • abs(x):取x的绝对值
    • sign(x):x>0返回1.0,x<0返回-1.0,否则返回0.0
    • ceil(x):返回大于或者等于x的整数
    • floor(x):返回小于或者等于x的整数
    • fract(x):返回x-floor(x)的值
    • mod(x,y):取模(求余)
    • min(x,y):获取xy中小的那个
    • max(x,y):获取xy中大的那个
    • mix(x,y,a):返回[Math Processing Error]x∗(1−a)+y∗a
    • step(x,a):x< a返回0.0,否则返回1.0
    • smoothstep(x,y,a):a < x返回0.0,a>y返回1.0,否则返回0.0-1.0之间平滑的Hermite插值。
    • dFdx(p):p在x方向上的偏导数
    • dFdy(p):p在y方向上的偏导数
    • fwidth(p):p在x和y方向上的偏导数的绝对值之和

    函数目前基本没怎么用到过,所以没有加粗,后面用到再回来查一下即可

    几何函数

    • length(x):计算向量x的长度
    • distance(x,y):返回向量xy之间的距离
    • dot(x,y):返回向量xy的点积
    • cross(x,y):返回向量xy的差积
    • normalize(x):返回与x向量方向相同,长度为1的向量

    ps:distance 函数在后面做滤镜的时候可能会用到

    矩阵函数

    • matrixCompMult(x,y):将矩阵相乘
    • lessThan(x,y):返回向量xy的各个分量执行x< y的结果,类似的有greaterThan,equal,notEqual
    • lessThanEqual(x,y):返回向量xy的各个分量执行x<= y的结果,类似的有类似的有greaterThanEqual
    • any(bvec x):x有一个元素为true,则为true
    • all(bvec x):x所有元素为true,则返回true,否则返回false
    • not(bvec x):x所有分量执行逻辑非运算

    纹理采样函数

    • 纹理采样函数有
    • texture2D
    • texture2DProj、
    • texture2DLod、
    • texture2DProjLod、
    • textureCube、
    • textureCubeLod
    • texture3D、
    • texture3DProj、
    • texture3DLod、
    • texture3DProjLod等。

    texture表示纹理采样,2D表示对2D纹理采样,3D表示对3D纹理采样
    Lod后缀,只适用于顶点着色器采样 Proj表示纹理坐标st会除以q

    texture2D 有2个参数, 第一个参数表示纹理采样器,(纹理采样器是片元着色器的内置变量)。 第二个参数表示纹理坐标,可以是二维、三维、或者四维(我们需要把纹理坐标传过去)

    认真阅读,可以发现着色器语言并不复杂,我们只要掌握几个常用的,然后其他等需要的时候再查一下即可。

    下一篇开始我们将学习比较有意思的纹理和图片处理,敬请期待吧!

    相关文章

      网友评论

        本文标题:《OpenGL从入门到放弃05》着色器语言

        本文链接:https://www.haomeiwen.com/subject/fjatnqtx.html