OpenGL-ES-学习(2)-----OpenGL-ES-Shader-语言语法

142 阅读6分钟

#####Shader 举例 一个典型的简单的Shader 程序:

const char vShaderStr[] =
	"#version 300 es                            \n"
	"layout(location = 0) in vec4 a_position;   \n"
	"layout(location = 1) in vec4 a_color;      \n"
	"out vec4 v_color;                          \n"
	"void main()                                \n"
	"{                                          \n"
	"    v_color = a_color;                     \n"
	"    gl_Position = a_position;              \n"
	"}";

####Shader 语法 #####版本规范声明 定义在Shader 程序的第一行; Shader 版本规范 没有声明版本号的默认将会使用 1.0版本 3.0版本中显然定义了更多的功能 #####变量和定法方法

分类类型描述
浮点向量float、vec2、vec3、vec4有1,2,3,4 个分量的浮点向量类型
整数向量int, ivec2, ivec3, ivec4有1,2,3,4 个分量的整数向量类型
无符号整数向量uint, uvec2, uvec3, uvec4有1,2,3,4 个分量的无符号整数向量类型
布尔向量bool, bvec2, bvec3, bvec4有1,2,3,4 个分量基于bool的向量类型
矩阵mat2 mat2x3 mat2x4 mat3x2 mat3 mat3x4 mat4x2 mat42-2 2-3 2-4 等不同的向量类型

OpenGL ES 的变量只能赋值为同类型的其他变量 或者和同类型的其他变量进行运算 举例; float myFloat = 1.0 float myFloat2 = 1 定义错误,类型转换错误 bool myBool = true int myInt = 0 int myInt2 = 0.0 定义错误,类型转换错误 myFloat = float(myBool) 类型转换 bool -> float myFloat = float(myInt) 类型转换 int -> float myBool=bool(myInt) 类型转换 int -> bool

#####向量构造方法

定义方法含义
vec4 myVec4 = vec4(1.0)vec4 myVec4 = vec4{1.0, 1.0,1.0,1.0}
vec3 myVec3 = vec3(1.0,0.0,0.5)myVec3 = {1.0, 0.0, 0.5}
vec3 temp = vec3(myVec3)temp = myVec3
vec2 myVec2 = vec2(myVec3)myVec2 = {myVec3.x, myVec3.y}
myVec4 = vec4(myVec2, temp)myVec4 {myVec2.x, myVecy, temp.x, temp.y}
#####矩阵构造方法
矩阵的每个分量可以用**{r, g, b, a} {x, y, z, w} {s, t, p, q}**
  • 矩阵分量如果只设定为一个标量参数,那么该值将会被放置在对角线上
  • 矩阵可以从多个向量参数构造,mat2 可以用两个 vec2 构造
  • 矩阵可以从多个标量参数构造

#####结构,数组,函数定义 ######1. 结构 结构可以认为是C语言中的结构体的概念

struct {
    vec4 color;
    float start;
    float end;
} fogVar;

######2. 数组 数组与C语言类型 从0开始索引

float floatArray[4];
vec4 vecArray[2];

数组的构造初始化形式:

float floatArray[4] = float[](1.0, 2.0, 3.0,4.0);
float floatArray[4] = float[4](1.0, 2.0, 3.0,4.0);
vec2 c[2] = vec2[2](vec(1.0), vec2(1.0)))

######3. 函数 声明方法和C语言相同,如果函数在定义之前使用,那么必须要提供原型声明,区别在于参数的传递方法,Open-GL ES 中的限定符:

限定符描述
in没有指定时的默认限定符 这个限定值按照参数值传递,函数不能修改
inout这个限定符按照引用传入参数,在函数退出后会变化
out该变量不被传入函数,在函数返回时会被修改

函数不能递归

######内建函数 常用的内建函数都是有的,比如 sin,cos 等等

#####条件语句和运算符 举例: if(color.a < 0.25) 条件语句中测试的表达式必须是一个 bool 值

#####统一变量 统一变量是应用程序通过 Open-GL ES API传入的 Shader 的只读值,

	uniform mat4 viewProjMatrix;
	uniform mat4 viewMatrix;
	uniform vec3 lightPosition;

注意统一变量的命名空间在Vertex Shader和Pixel Shader都是共享的,也就是说,如果Vertex Shader和 Pixel Shader 一起链接到一个程序对象,它们就会共享同一组统一变量,如果在Vertex Shader 和 Pixel Shader 声明同一个同一变量,那么两个声明必须匹配

统一变量通常保存在硬件中,这个区域被叫做常量存储,是硬件中为存储常量值而分配的特殊空间,因为常量的大小一般是固定的,所以程序中可以使用统一变量数量受到限制,OpenGL ES 3.0 实现必须提供256 个顶点统一向量和224 个片段统一向量

#####统一变量块 统一变量缓冲区对象可以通过一个缓冲区对象支持统一变量数据的存储,具备下面的优势:

  • 统一变量的缓冲区数据可以在多个程序之间共享,但是只需要设置一次
  • 统一变量对象可以存储大量的统一变量数据
  • 在缓冲区对象之间切换比单独加载一个统一变量更加高效

#####Shader 输入输出 顶点输入变量用于指定 Vetex Shader每个顶点的输入,用 in 关键字指定;它们通常存储位置,法线,纹理坐标和颜色这样的数据。 顶点输入是为绘制的每个顶点指定的数据;本质上,应用程序会为每个顶点创建一个顶点数组,该数组包含位置和颜色。 底层硬件通常可以在输入Vertex shader 的数量上有限制,OpenGL ES 3.0 实现可支持的最小属性为 16个

#version 300 es
uniform mat4 u_matViewProjection;
layout(location  =  0) in vec4  a_position
layout(location  =  1) in vec4  a_color
out vec3  v_color
void main(void) {
gl_position = u_matViewProjection * a_position
	v_color = a_color;
}

#version 300 es
precision medium float

in vec3 v_color
layout(location = 0) out vec4 o_fragColor
void main()
{
	o_fragColor = vec4(v_color, 1.0)
}

#####插值限定符 OpenGL ES 支持两种插值

  • 线性插值,平滑着色
  • 平面着色 定义了顶点着色器在基本图元中的插值形式:

线性插值:

smooth out vec3 v_color
smooth in vec3 v_color

平面着色

flat out vec3 v_color
flat in vec3 v_color

#####预处理命令

#define
#undef
#if
#ifdef
#ifndef
#else
#elif
#endif
__LINE__
__FILE__
#version
GL_ES

#error
#extension
#pragma

#####打包方法 TBD #####精度限定符 精度限定符可以用作任何基于浮点数或者整数的变量的精度,关键字为 lowp,meidump,highp 示例:

highp vec4 position;
varying lowp vec4 color;
mediump float specularExp;

也可以对类型指定默认精度

presision highp float;
presision medium int;

为float 指定的精度将用作基于浮点值的变量的默认精度,

  • 在Vertex Shader ,没有指定默认精度,为 int 和 float 的值都是 highp;
  • 但是在Pixel Shader 没有默认的精度值,每个Pixel Shader 必须指定一个精度

#####不变性 OpenGL-ES 规定的 invariant 关键字可以用于任何可变顶点的Shader 输出; 在Shader 编译的时候,编译器进行优化,可能导致指令的重新排序; 这种指令的重排意味着两个 Shader 之间的等价计算不能保证产生完全相同的结果,这种不一致性在多变的Shader 特效的时候尤其会有可能产生问题,在这种情况下,相同的对象会用Alpha 混合绘制在自身上方,如果计算输出位置的数值的精度不完全一样,精度差异就会产生伪像。这个对象通常表现为深度冲突(Z fighting), 可以将变量定义为 invariant 变量,比如:

	invarient gl_position
	invarirent textCoord

一旦某个输出变量声明了不变性,编译器便保证相同的计算和 Shader 输入的条件下计算结果相同,

也可以用 #pragma 让所有的变量保持不变:

	#pragma STDGL   invarient(all)