Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL
前面的文章主要是整理的Android 官方文档对OpenGL ES支持的介绍。通过之前的文章,我们基本上可以完成的基本的形状的绘制。
这是本人做的整理笔记: https://github.com/renhui/OpenGLES20Study
目前到这里第一阶段的学习,也就是基本的图形绘制,基本的交互的实现。
- 平面绘制:三角形、正方形、在相机视角下的三角形、彩色三角形
- 立体绘制:正方体、圆柱体、圆锥体、球体
- 基本交互:手绘点、旋转三角形
知道了基本的图形绘制,也知道了基本的交互的实现,现在可能大多数人还是对整个实现的流程有点懵,最主要的地方可能就是对顶点着色器和片元着色器了。前面的使用过程中,我们大概也对着色器语言有一定的了解了,但是在前面我们使用的着色器代码还是很简单的,做的事情也是很有限的,后面的开发过程中,我们用到的着色器会越来越复杂,So,这里我们想一下着色器语言GLSL。
我们知道,在OpenGL ES中着色器分为顶点着色器和片元着色器。顶点着色器是针对每个顶点执行一次,用于确定顶点的位置。片元着色器是针对每个片元,片元我们可以理解为每个像素,用于确定每个片元(像素)的颜色。
一、GLSL 简介
GLSL又叫OpenGL着色语言(OpenGL Shading Language),是用来在OpenGL中着色编程的语言,是一种面向过程的语言,基本的语法和C/C++基本相同,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器)。
在前面的学习中,我们基本上使用的都是非常简单的着色器,基本上没有使用过GLSL的内置函数,但是在后面我们完成其他的功能的时候应该就会用到这些内置函数了。
二、GLSL 基础
GLSL 虽然很类似于C/C++,但是它和C/C++还是有很大的不同的,比如,没有double,long等类型,没有union、enum、unsigned以及位运算等特性。
基本数据类型
GLSL中的数据类型主要分为标量、向量、矩阵、采样器、结构体、数组、空类型七种类型:
1. 标量:
标量表示的是只有大小没有方向的量,在GLSL中标量只有bool、int和float三种。对于int,和C一样,可以写为十进制(16)、八进制(020)或者十六进制(0x10)。对于标量的运算,我们最需要注意的是精度,防止溢出问题。
2. 向量:
向量我们可以看做是数组,在GLSL通常用于储存颜色、坐标等数据,针对维数,可分为二维、三维和四位向量。针对存储的标量类型,可以分为bool、int和float。共有vec2、vec3、vec4,ivec2、ivec3、ivec4、bvec2、bvec3和bvec4九种类型,数组代表维数、i表示int类型、b表示bool类型。需要注意的是,GLSL中的向量表示竖向量,所以与矩阵相乘进行变换时,矩阵在前,向量在后(与DirectX正好相反)。向量在GPU中由硬件支持运算,比CPU快的多。
- 作为颜色向量时,用rgba表示分量,就如同取数组的中具体数据的索引值。三维颜色向量就用rgb表示分量。比如对于颜色向量vec4 color,color[0]和color.r都表示color向量的第一个值,也就是红色的分量。其他相同。
- 作为位置向量时,用xyzw表示分量,xyz分别表示xyz坐标,w表示向量的模。三维坐标向量为xyz表示分量,二维向量为xy表示分量。
- 作为纹理向量时,用stpq表示分量,三维用stp表示分量,二维用st表示分量。
3. 矩阵:
在GLSL中矩阵拥有22、33、4*4三种类型的矩阵,分别用mat2、mat3、mat4表示。我们可以把矩阵看做是一个二维数组,也可以用二维数组下表的方式取里面具体位置的值。
4.采样器:
采样器是专门用来对纹理进行采样工作的,在GLSL中一般来说,一个采样器变量表示一副或者一套纹理贴图。所谓的纹理贴图可以理解为我们看到的物体上的皮肤。
5.结构体:
和C语言中的结构体相同,用struct来定义结构体,关于结构体参考C语言中的结构体。
6.数组:
数组知识也和C中相同,不同的是数组声明时可以不指定大小,但是建议在不必要的情况下,还是指定大小的好。
7.空类型:
空类型用void表示,仅用来声明不返回任何值得函数。
数据声明示例:
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中的运算符有(越靠前,运算优先级越高):
- 索引:[]
- 前缀自加和自减:++,–
- 一元非和逻辑非:~,!
- 加法和减法:+,-
- 等于和不等于:==,!=
- 逻辑异或:^^
- 三元运算符号,选择:?:
- 成员选择与混合:.
- 后缀自加和自减:++,–
- 乘法和除法:*,/
- 关系运算符:>,<,=,>=,<=,<>
- 逻辑与:&&
- 逻辑或:||
- 赋值预算:=,+=,-=,*=,/=
类型转换
GLSL的类型转换与C不同。在GLSL中类型不可以自动提升,比如float a=1;就是一种错误的写法,必须严格的写成float a=1.0,也不可以强制转换,即float a=(float)1;也是错误的写法,但是可以用内置函数来进行转换,如float a=float(1);还有float a=float(true);(true为1.0,false为0.0)等,值得注意的是,低精度的int不能转换为低精度的float。
限定符
在之前的博客中也提到了,GLSL中的限定符号主要有:
- attritude:一般用于各个顶点各不相同的量。如顶点颜色、坐标等。
- uniform:一般用于对于3D物体中所有顶点都相同的量。比如光源位置,统一变换矩阵等。
- varying:表示易变量,一般用于顶点着色器传递到片元着色器的量。
- const:常量。
限定符与java限定符类似,放在变量类型之前,并且只能用于全局变量。在GLSL中,没有默认限定符一说。
流程控制
GLSL中的流程控制与C中基本相同,主要有:
- if(){}、if(){}else{}、if(){}else if(){}else{}
- while(){}和do{}while()
- for(;
Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL的更多相关文章
- 着色器语言GLSL入门
着色器语言 GLSL (opengl-shader-language)入门大全 -- 转载自: https://github.com/wshxbqq/GLSL-Card
- OpenGLES2.0着色器语言glsl
OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...
- 着色器语言 GLSL (opengl-shader-language)入门大全
基本类型: 类型 说明 void 空类型,即不返回任何值 bool 布尔类型 true,false int 带符号的整数 signed integer float 带符号的浮点数 floating s ...
- OpenGL ES着色器语言之着色概览(官方文档)
OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...
- OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)
OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...
- OpenGL ES着色器语言之操作数(官方文档第五章)
OpenGL ES着色器语言之操作数(官方文档第五章) 5.1操作数 OpenGL ES着色器语言包含如下操作符. 5.2数组下标 数组元素通过数组下标操作符([ ])进行访问.这是操作数组的唯一操作 ...
- OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)
OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...
- OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围
OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章) 所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符. ...
- OpenGL ES着色器语言之静态使用(static use)和预处理
OpenGL ES着色器语言之静态使用(static use) 在OpenGL ES中有一个术语叫静态使用(static use),什么叫静态使用呢? 在写代码中,对于一个变量可能具有以下三种情况: ...
随机推荐
- NOI2009 二叉查找树 【区间dp】
[NOI2009]二叉查找树 [问题描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左子树结点的数据值大,而比它右子树结点的数据值小.另一方面,这棵查找树中每个结点都有 ...
- 2、flask之基础知识点
本篇导航: 路由系统 视图函数 请求与响应 模版语法 session 蓝图(blueprint).闪现 (flash) 扩展 一.路由系统 1.可传入参数: @app.route('/user/< ...
- 【深度学习系列】用PaddlePaddle进行车牌识别(一)
小伙伴们,终于到了实战部分了!今天给大家带来的项目是用PaddlePaddle进行车牌识别.车牌识别其实属于比较常见的图像识别的项目了,目前也属于比较成熟的应用,大多数老牌厂家能做到准确率99%+.传 ...
- spring boot 使用java9上传到github其他人clone后报错
错误原因: Java.lang.NoClassDefFoundError:javax/xml/bind/JAXBException jdk9存在版本兼容问题. 经过查找资料发现问题所在 大致意思是ja ...
- 用原生js实现一个new方法
首先写一个父类方法(包含参数name,age): function Person(name,age){ this.name = name; this.age = age; } new一个Person的 ...
- 概括一下nodejs
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js是事件驱动,非阻塞I/O的.所以它再处理高并发,I/O密集的场景下性能优势明显,如web. 对比 ...
- LVS-DR之VIP、DIP跨网段实例
在日常应用环境中,我们会遇到这样一种lvs部署环境,所有的dr以及的rs server都在一个局域网环境中,但只有一个公网ip,而又需要将应用发布到internet上,都知道lvs的最好的模式就是所有 ...
- hive:排序分析函数
基本排序函数 语法: rank()over([partition by col1] order by col2) dense_rank()over([partition by col1] order ...
- openstack-ocata-镜像服务3
一. 镜像服务概述 镜像服务(glance)使用户能够发现.登记,并检索虚拟机镜像.它提供了一个REST API,使您可以查询虚拟机镜像元数据和检索一个实际的形象.可以存储虚拟机镜像通过镜像服务在不同 ...
- Django使用模板后无法找到静态资源文件
Django使用模板后无法找到静态资源文件 环境配置 Django版本1.11 python版本3.6.2 前言 在编写Django网站的时候,在涉及模板方面,一些简单的例子都没有问题,但这些例子都有 ...