OpenGL ES 变量、结构体、语句、函数、精度
老
孟
一个
有态度
的程序员
变量
void
表示空,用于无返回值的函数。比如顶点shader中main函数:
void main() {
gl_Position = vPosition;
}
float、int、bool
分别代表浮点型,整型,布尔型。定义各类型变量如下:
float f = 1.0;
int i =0;
bool b = true;
vec2、vec3、vec4
分别包含2、3、4个float类型的向量。定义变量如下:
vec2 v2 = vec2(1.0, 0.0);
vec3 v3 = vec3(1.0, 0.0, 0.5);
vec4 v4 = vec4(1.0, 0.0, 0.5,0.5);
如果只给一个参数,则向量中其他值也会使用此值,比如给vec4一个1.0的值:
vec4 v5 = vec4(1.0);
等价于:
vec4 v5 = vec4(1.0,1.0,1.0,1.0);
注意:提供给向量的参数只能是1个或者对应向量个数,比如vec4类型不能提供2个参数:
vec4 v6 = vec4(1.0,1.0);
上面给vec4提供2个参数的写法是错误的。
经常使用的内置变量gl_Position和gl_FragColor是vec4类型,在片段shader中设置颜色:
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
ivec2, ivec3, ivec4和vec2、vec3、vec4用法一样,区别就是ivec的参数是int类型。
bvec2, bvec3, bvec4和vec2、vec3、vec4用法一样,区别就是bvec的参数是bool类型。
向量分量
获取向量分量有2种方式:
- 通过 “.” 符号获取,向量分量为{x, y, z, w} , {r, g, b, a} 或 {s, t, r, q} , {x, y, z, w}是位置相关的分量,{r, g, b, a}是颜色相关的分量,{s, t, r, q}是纹理坐标相关的分量,但是(x,y,z,w)、(r,g,b,a)和(s,t,r,q)不能混合使用。
- 通过数组下标获取,例如v2[0]。
用法如下:
vec4 v4 = vec4(1.0, 0.0, 0.5,0.5);
float a = v4.x;
vec2 v2 = v4.xy;
vec4 v5 = vec4(v4.x,v4.y,v4.z,v4.w);
vec4 color = vec4(v4.r,v4.g,v4.b,v4.a);
mat2, mat3, mat4
分别表示2x2,3x3,4x4浮点型矩阵。如果只提供一个参数,则该值做为矩阵对角线的值,也就是单位矩阵,比如mat4(1.0),就是4x4单位矩阵。
也可以按照如下方式定义矩阵:
mat3 m3 = mat3(1.0, 0.0, 0.0, // 第一列
0.0, 1.0, 0.0, // 第二列
0.0, 1.0, 1.0); // 第三列
sampler2D、samplerCube、samplerExternalOES
- sampler2D:2D纹理,可以用于绘制图片。
- amplerCube:立方体纹理。
- samplerExternalOES:Android端用于绘制视频或者相机预览,使用samplerExternalOES需要在shader头部添加 #extension GL_OES_EGL_image_external : require。
用法如下:
#extension GL_OES_EGL_image_external : require
uniform samplerExternalOES u_Texture;
结构体
在GLSL中允许声明结构体,和c语言类型,声明如下:
struct myStruct
{
vec4 color;
vec4 position;
} myVertex;
声明了一个myStruct类型的变量myVertex。初始化如下:
myVertex = myStruct(vec4(0.0, 1.0, 0.0, 0.0),vec4(0.5, 0.5,0.5, 0.5));
类型要和结构体中一一对应。
获取结构体值的方式如下:
vec4 color = myVertex.color;
vec4 position = myVertex.position;
基本语句
if-else
if-else 是条件判断语句,用法如下:
if (color.a < 0.25) {
gl_FragColor = vec4(1,0,0,1);
} else {
gl_FragColor = vec4(1,0,0,color.a);
}
for 循环
使用for循环时,循环变量必须是编译时已知,用法如下:
float sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
第一种典型的错误用法:
float myArr[4];
float sum = 0;
for (int i = 0; i < 3; i++) {
sum += myArr[i];
}
[ ]中只能为常量或 uniform 变量,不能为整数量变量(如:i,j,k)。
第二种典型的错误用法:
uniform int loopIter;
for (int i = 0; i < loopIter; i++) {
sum += i;
}
上面的用法是错误的,循环变量 loopIter 的值必须是编译时已知。
函数
函数的用法和C语言基本相同,在GLSL中不能递归调用且必须声明返回值类型,如果没有返回值则使用void。用法如下:
vec4 getPosition(float a){
return vec4(0.0,0.0,0.0,a);
}
void main(){
}
精度限定符
在GLSL中精度限定符分为低(lowp)、中(mediump)、高(highp)精度。当使用低精度时可以更加高效的运行,如果精度不合理可能会出现失真的问题,曾经在项目中遇到过拍照黑边的问题就是精度的问题引起的。
指定默认精度方式如下:
precision mediump float;
如果未使用的精度限定符的变量将会使用此默认值,用法如下:
//指定精度
highp vec4 position;
//默认精度
vec4 color;
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- LeetCode 392. 判断子序列
- LeetCode 5473. 灯泡开关 IV
- LeetCode 5472. 重新排列字符串
- BootStrap 导航栏实现下滑消失,上滑出现
- 七日Python之路--第六天
- 超性感的React Hooks(六)自定义hooks的思维方式
- 七日Python之路--第五天(之找点乐子)
- 超性感的React Hooks(七)useReducer
- 七日Python之路--第四天(之Django官方文档)
- 六、setTimeout与循环闭包经典面试题详解
- 七日Python之路--第四天
- 七、this
- 七日Python之路--第四天(之多线程)
- 超性感的React Hooks(八)useContext
- 七日Python之路--第三天(之不安分 wxPython)