• OpenGL-GLES Shader


    渲染管线

    管线可以理解为渲染流水线。实际上可以理解为原始图形数据经过一个输送管道,期间经过各种变化处理最终出现在屏幕的过程。

    在OpenGL下渲染图形,就像流水线,每个任务类似流水线一样执行,任务之间有先后顺序。管线又可以分为两种,固定管线和可编程管线。固定管线简单理解就是在渲染图像这个过程中,只能通过调用固定管线效果实现一系列的着色器处理。而可编程管线在处理图形的过程,能够使用自定义顶点着色器和片元着色器。由于OpenGL的使用场景非常丰富,固定管线或者存储着色器无法完成每一个任务,这时将相关部分开放成可编程。

    将图形/图像数据转换成3D空间图像操作叫做渲染,下图中带阴影的部分就是管线的可编程阶段:

    顶点数组和顶点缓冲区

    在绘制一个图形时,它的顶点位置数据就是顶点,数据一般存在数组中或者将缓存到GPU内存中。

    在调用绘制方法的时候,若是顶点数据存储在内存当中,直接从内存传入顶点数据,被称为顶点数组。若是将顶点数据预先存储到显存中,这部分显存被称为顶点缓冲区。存储在显存中的性能更好一点。

    顶点着色器

    顶点着色器一般用来处理图形的顶点变换包括旋转、平移、投影等,可以操作的属性有:位置、颜色、纹理坐标,但是不能创建新的顶点,最终产生的位置、颜色、纹理坐标信息送往后续阶段。

    对每个顶点数据都会执行一次顶点着色器。并行执行,运算过程中无法访问其他的顶点数据。

    图元装配

    顶点组合成图元的过程叫做图元装配。OpenGL中的图像都是由图元组成,有3种类型:点、线和三角形。GLES中最基础且唯一的多边形就是三角形,所有更复杂的图形都是由三角形组成的。

    光栅化

    将图片转化为片段的过程叫做光栅化。其实是一种将几何图元变为二维图像的过程。

    纹理

    在渲染图形时为了使得场景更加逼真,需要在其编码填充图片,这里使用的图片,就是纹理。

    片段着色器

    片段着色器一般用来处理图形中每个像素点颜色计算和填充,每个片段的颜色等属性计算出来并送给后续阶段。

    片段着色器是逐像素运算的程序,每个像素都会执行一次片元着色器,并行执行。

    Shader 

    Shader是一段执行在GPU上的程序,来描述顶点或者像素的特性。

    常用的shader有两种:Vertex Shader和Fragment Shader。除此之外,还有几何着色器Geometry Shader、Compute Shader、Tessellation Shader等。

    OpenGL在处理shader时,通过编译、链接等步骤,生成了着色器程序glProgram,着色器程序同时包含顶点着色器和片元着色器的运算逻辑。在绘制的时候,首先由顶点着色器对传入的顶点数据进行运算。再通过图元装配,将顶点转换为图元。然后进行光栅化,将图元这种矢量图形,转换为栅格化数据。最后,将栅格化数据传入片元着色器中进行运算。片元着色器会对栅格化数据中的每一个像素进行运算,并决定像素的颜色。

     

    Vertex Shader

    VS的功能是把每个顶点在虚拟空间中的三维坐标变换为可以在屏幕上显示的二维坐标,可以操作位置、颜色、纹理坐标等属性,但是不能创建新的顶点。对于发送给GPU的每一个Vertex(顶点),都要执行一次VS。

    主要完成的工作包括基于点操作的矩阵乘法位置变换,根据光照公式计算每点的color值以及生成或者转换纹理坐标。

    输入:

    (1) Shader program:描述顶点上执行操作的顶点着色器程序源代码/可执行文件;

    (2) Attributes:用顶点数组提供的每个顶点的属性数据,如空间位置,纹理坐标,顶点颜色等,GLES 2.0规定了所有实现应该支持的最大属性个数不能少于 8 个;

    (3) Uniforms:顶点或者片元着⾊器使用的不变数据,保存着由应用程序传递给着色器的只读常量数据。在顶点着色器中,这些数据通常是变换矩阵、光照参数、颜色等。由uniform修饰符修饰的变量属于全局变量,该全局性对顶点着色器与片元着色器均可见。如果在这两个着色器中都声明了同名的uniform变量,要保证这对同名变量完全相同,因为它们实际是同一个变量。uniform变量存储在常量存储区,因此uniform变量的个数受到限制,GLES 2.0中规定实现应该支持的最大顶点着色器uniform变量个数不少于128个,最大的片元着色器uniform变量个数不能少于16个;

    (4) Samplers:用于呈现纹理,代表顶点着色器使用纹理的特殊统一变量类型,可用于顶点着色器和片元着色器;

    输出:

    (1) Varying:该变量用于存储顶点着色器的输出数据,也存储片元着色器的输入数据。顶点着色器中声明的varying变量都应在片元着色器中重新声明同名同类型的varying变量。GLES 2.0中规定所有实现应该支持的最大varying变量个数不能少于8个;

    (2) 在顶点着色器阶段至少应输出位置信息gl_Position,是每个点固有的Varying,表示点的空间位置。gl_FrontFacing 和 gl_PointSize是可选变量;

    // 定义顶点坐标属性
    attribute vec4 position;
    // 定义纹理坐标属性
    attribute vec4 coordinate; 
    // uniform变量
    uniform mat4 matrix; 
    varying mediump vec4 varytext; 
    void main()
    {
        varytext = coordinate; 
        vec4 vPosition = position;
        vPosition = vPosition * matrix; 
        gl_Position = vPosition;
    }
    View Code

    Fragment Shader

    FS负责计算每个像素的颜色和其它属性,通过应用光照值、阴影、半透明等处理来计算像素的颜色并输出。也可改变像素的深度或在多个渲染目标被激活的状态下输出多种颜色。FS只在一个像素上进行操作,不知道场景的几何形状。

    主要完成的工作包括计算颜色、获取纹理值以及往像素点中填充颜色值。

    输入:

    (1) Shader program:同VS,描述在片元上执行的操作;

    (2) Varyings:顶点着色器阶段输出的varying变量在光栅化阶段被线性插值计算之后输出到片元着色器中作为它的输入,GLES 2.0中规定了所有实现应该支持的最大varying变量个数不能少于 8 个;

    (3) Uniforms:用于FS的常量,比如说雾化、纹理参数等,GLES 2.0中规定了所有实现应该支持的最大的片元着色器uniform变量个数不能少于16个;

    (4) Samples:同VS,用于呈现纹理;

    输出:

    (1) 在顶点着色器阶段只有唯一的varying输出变量gl_FragColor;

    // 从顶点着色器传递过来的纹理坐标
    varying mediump vec4 varytext; 
    // 纹理采样 
    uniform sampler2D colorMap; 
    void main()
    {
        // texture2D: 纹理采样器获取纹理像素
        gl_FragColor = texture2D(colorMap, varytext); 
    }
    View Code

    Geometry Shader

    GS几何着色器是继VS和FS之后,引入的第三个着色器。它在OpengGL 2.0+中作为扩展使用,在OpenGL3.x中成为核心。它的输入为点、线和三角形,其输出是点、线带和三角形。GS在VS执行之后执行。

    在GS里,处理的单元是Primative,与VS相比,根本上都是顶点的处理,但是进入VS里的是一次一个的顶点,而进入GS的是一次一批的顶点,GS掌握着这些顶点所组成的图元的信息。它的处理阶段处于流水线的栅格化之前,也在视锥体裁剪和裁剪空间坐标归一化之前。

    精度相关

    着色器语言定义了三种精度分别是lowp、mediump、highp。可以直接在文件开头定义默认的精度,如下代码定义在float类型默认使用highp级别的精度:

    precision highp float;

    在VS里,int和float都默认为highp级别,在FS里,如果没有默认精度,那么就没有默认精度,必须在每个变量前放置精度描述符。GLES 2.0中没有强制要求所有实现在片元阶段都支持highp精度的。

    在VS和FS里,同样的计算可能会得到不同的结果。因此GLSL引入了invariant修饰符来修饰在两个着色阶段的同一变量,确保同样的计算会得到相同的值。

    GLSL基础

    GLSL是一种面向过程的语言,基本语法与C/C++基本相同,通过限定符操作来管理输入输出类型。

    GLSL基于C/C++,有C/C++有相似的地方,但也有很多的不同之处,比如在GLSL中没有double、long等类型,没有union、enum、unsigned以及位运算等特性。

    基本数据类型主要分为标量、向量、矩阵、采样器、结构体、数组、空类型七种类型。

    标量表示的是只有大小没有方向的量,在GLSL中标量只有bool、int和float三种。

    向量可以看做是数组,在GLSL通常用于储存颜色、坐标等数据,针对维数,可分为二维、三维和四维向量。针对存储的标量类型,可以分为bool、int和float。共有vec2、vec3、vec4,ivec2、ivec3、ivec4、bvec2、bvec3和bvec4九种类型。矩阵拥有2*2、3*3、4*4三种类型的矩阵,分别用mat2、mat3、mat4表示。

    采样器是专门用来对纹理进行采样工作的,一个采样器变量表示一副或者一套纹理贴图。

    GLSL的结构体和C语言中的结构体相同,用struct来定义结构体。数组也和C中相同。空类型用void表示,仅用来声明不返回任何值的函数。

    在GLSL中类型不可以自动提升,比如float a=1,这种写法错误,要写成float a=1.0。不可以强制转换,float a=(float)1,这种写法也错误。但是可以用内置函数来进行转换,如float a=float(1) 。

    GLSL中限定符有下述四个:

    attritude:一般用于各个顶点各不相同的量,如顶点颜色、坐标等。

    uniform:一般用于对于3D物体中所有顶点都相同的量,比如光源位置,统一变换矩阵等。

    varying:表示易变量,一般用于顶点着色器传递到片元着色器的量。

    const:常量。

    GLSL中可以定义函数,定义函数的方式也与C语言基本相同。函数的返回值可以是GLSL中的除了采样器的任意类型。对于GLSL中函数的参数,可以用参数用途修饰符来进行修饰,常用修饰符如下:

    in:输入参数,无修饰符时默认为此修饰符。

    out:输出参数。

    inout:既可以作为输入参数,又可以作为输出参数。

    GLSL的内建变量:

    在着色器中一般会声明变量来在程序中使用,但是着色器中还有一些特殊的变量,不声明也可以使用,这些变量叫做内建变量。內建变量相当于着色器硬件的输入和输出,在顶点着色器中的内建变量和片元着色器的内建变量是不相同的。

    顶点着色器的内建变量

    输入变量:gl_Position:顶点坐标;gl_PointSize:点的大小,没有赋值则为默认值1。

    片元着色器的内建变量

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

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

    常用内置函数

    常见函数

    常见函数:
    
    radians(x):角度转弧度
    
    degrees(x):弧度转角度
    
    sin(x):正弦函数,传入值为弧度,相同还有cos、tan、asin、acos、atan
    
    pow(x,y):xy
    
    exp(x):ex
    
    exp2(x):2x
    
    log(x):logex
    
    log2(x):log2x
    
    sqrt(x):x√
    
    abs(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):返回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之间平滑的插值
    
    dFdx(p):p在x方向上的偏导数
    
    dFdy(p):p在y方向上的偏导数
    
    几何函数:
    
    length(x):计算向量x的长度
    
    distance(x,y):返回向量xy之间的距离
    
    dot(x,y):返回向量xy的点积
    
    cross(x,y):返回向量xy的差积
    
    normalize(x):返回与x向量方向相同,长度为1的向量
    
    矩阵函数:
    
    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;
    
    
    
    
     
    View Code
    关山难越,谁悲失路之人; 萍水相逢,尽是他乡之客。
  • 相关阅读:
    js判断是否为数字
    MongoDB 复制集机制及原理
    MongoDB 聚合查询
    C#中时间相关知识点小结
    C#中的小数和百分数计算
    WPF使用VisualTreeHelper进行复杂命中测试
    WPF使用VisualTreeHelperj简单进行命中测试
    WPF Data Binding数据驱动
    WPF Binding中的RelativeSource属性
    WPF特效:流光动画效果
  • 原文地址:https://www.cnblogs.com/xue0708/p/15195909.html
Copyright © 2020-2023  润新知