WebGL中的OpenGL着色器语言
在webgl中,调用了OpenGL-ES-2.0的API,而在OpenGL-ES专为嵌入式设备设计,其和其它设备一样,都是使用GLSL(GL Shading Language)来编写片段程序并执行于GPU的着色器上,来完成对对象的渲染。GLSL在其中起着相当重要的作用,所以要玩好webgl,我们就得把GLSL搞懂,本文主要介绍shader的基础使用及组成。
整个管线处理过程:
1.指定几何对象
- 顶点数组(直接将顶点数据传送至shader里)
- 顶点索引(将顶点数据保存于缓冲区中,用索引来从缓冲区获取数据传入shader)
2.逐个顶点操作
3.图元组装
根据指定的图元组装方式将若干顶点组成一个图元,OpenGL支持的几何图元有点、线、不闭合折线、闭合折线、多边形、三角形、线型连续填充三角形、扇形连续填充三角形、四边形以及连续填充四边形。
而webgl支持的图元为POINTS(点), LINE_STRIP(不闭合折线), LINE_LOOP(闭合折线), LINES(独立的线段), TRIANGLE_STRIP(顶点按顺序相连的三角形), TRIANGLE_FAN(扇形顺序组合三角形), TRIANGLES(每三个顶点组合成一个三角形)。
绘制三角形序列的三种方式解释了三种三角形绘制方法之间的不同。
4.图元处理
5.栅格化(生成片元fragment)
6.片元处理
7.逐个片元操作
8.帧缓冲区操作
在这八个步骤中,我们最重要的是对顶点和片元的操作,在整个管线中,我们可以加入的自己程序的部分则是顶点着色器和片元着色器部分。
着色器
顶点着色器:
操作的是顶点值和其关联的数据,它可完成下面这些操作:
- 顶点变换
- 法线变换以及规格化
- 纹理坐标生成
- 纹理坐标变换
- 光照
- 彩色材质应用
顶点着色器必须计算坐标在裁剪空间中的齐次位置并将结果存储在特殊的输出变量gl_Position中,它还有特殊的输出变量gl_ClipVertex,gl_PointSize。
顶点处理器的输出将被发送到后续的处理阶段,即:图元组装,用户裁剪,平截裁剪,透视划分,视口贴图,多边形偏移,多边形模式,阴影模式,消隐等。
片元着色器:
处理片元值及其相关联数据,它可执行传统的图形操作,如:
在插值等到的值上的操作
- 访问纹理
- 应用纹理
- 雾化
- 颜色汇总
片元着色器其有特殊的输入变量gl_FragCoord(片元的窗口相对坐标)和gl_FrontFacing(正面图元为true,反之为false),经过计算颜色和深度将这些值写入特殊的输出变量gl_FragColor和gl_FragDepth中,或者完全丢弃(使用discard关键字)片元。
片元处理器的一大优点是它可以任意多次地访问纹理内存,并可以任意方式结合所读取的值,一次纹理访问的结果可作为执行另一次纹理访问的基础。
有三个精度可选择:lowp highp mediump
精度可指定于变量或设置默认精度
顶点着色器中的float和init默认精度为highp
片元着色器中float没有默认精度,所以必须为其指定默认精度,如:precision mediump float;
着色器多个执行是可并行发生的,针对每个顶点都会执行一次顶点着色器,针对每个片元都会执行一次片元着色器。
限定符
我们要向着色器中传入数据,则要了解其里面变量的组成和输入方式
属性变量(attribute):
这些变量代表了非常频繁地从应用程序传递到顶点处理器的值,只应用于程序中定义顶点数据,所以只允许作为顶点着色器的一部分,该值可以像每个顶点那样经常变动
一致变量(uniform):
用来将数据值从应用程序传递到顶点处理器或片元处理器,一致变量通常用来提供不频繁变动的值。
易变变量(varying):
定义了从顶点处理器传递到片元处理器的数据。
常量变量(const):
如C中的常量变量
数据类型
标量:
支持使用浮点数(float)、整数(int)和布尔值(bool)
矢量:
浮点数矢量:
vec2 (2个浮点数的矢量)
vec3 (3个浮点数的矢量)
vec4 (4个浮点数的矢量)
整数矢量:
ivec2 (2个整数的矢量)
ivec3 (3个整数的矢量)
ivec4 (4个整数的矢量)
布尔矢量:
bvec2 (2个布尔值的矢量)
bvec3 (3个布尔值的矢量)
bvec4 (4个布尔值的矢量)
矩阵:
mat2 (2×2的浮点数矩阵)
mat3 (3×3的浮点数矩阵)
mat4 (4×4的浮点数矩阵)
mat矩阵就像是一个vec数组,它也可以使用数组来进行访问。
取样器:
sampler1D (访问一个一维纹理)
sampler2D (访问一个二维纹理)
sampler3D (访问一个三维纹理)
samplerCube (访问一个立方贴图纹理)
sampler1DShadow (访问一个带对比的一维深度纹理)
sampler2DShadow (访问一个带对比的二维深度纹理)
只能通过uniform限定的取样器从应用程序接收取样器
使用时: uniform sampler2D texture;
操作
如果要对矢量进行部分操作,则可用访问矢量中的部分来使用,在shader中,共有三组组合供使用:
- x y z w
- s t p q
- r g b a
这四个值只是分别读取矢量中的第一个、第二个、第三个、第四个值,只是为了编写方便,语义化了三组组合,分别为坐标、纹理、颜色,但是使用它们去读取出来的值是一样的,如:
vec4 values = vec4(1.0,2.0,3.0,4.0);
values.z; //3.0
values.p; //3.0
values.b; //3.0
values[2]; //3.0
这三组使用时必须成组出现,不能混组出现,如:
vec4 values = vec4(1.0,2.0,3.0,4.0);
vec2 combination1 = values.xy; //同一组,正确
vec3 combination2 = values.rgb; //同一组,正确
vec3 combination3 = values.xt; //不同组,不正确
对矩阵的读取可以像数组一样:
vec2 x,y;
mat2 matrix;
x = matrix[];
y = matrix[];
运算
对于矢量的计算:
vec3 v,u,w;
w = v + u; //计算过程等价于 w.x = v.x + u.x;
w.y = v.y + u.y;
w.z = v.z + w.z;
对于矩阵和矢量的计算:
//该过程遵守线性代数中的计算规定,即做点乘的两个矩阵,前一个矩阵的行数等于后一个矩阵的列数 vec4 v,u;
mat4 m;
v * m; //行矢量与矩阵相乘
m * v; //矩阵与列矢量相乘
m * m; //矩阵与矩阵相乘
运算顺序:
//当多个矩阵同时施加加顶点矢量上时,则要以相反的顺序矩阵相乘
//如想实现先Ma再Mb的运算 vec4 v,u;
mat4 Ma,Mb; u = Mb * (Ma * v);
//即
u = (Mb * Ma) * v;
//即
u = Mb * Ma * v;
与C和C++差异
着色语言作为一种处理数字的语言,而不是处理字符或字符串数据的语言,在其中没有包含对指针、字符串、字符或基于这些类型的任何操作支持。
并且为了使编译器和图形硬件的实现负担更小,该语言不支持双精度浮点数、字节、短整数、长整数或者这些类型的无符号变化形式。
其包括了C++的一些重要语言特性:支持函数重载,支持基本类型bool。
注:
在向顶点着色器中进行传值时,顶点着色器会从缓存中依次读取每个顶点,如果使用的是顶点数组方法:
如传入:new Float32Array([1.0,1.0,1.0,0.0,
0.5,0.5,0.5,0.0]);
那么在shader中,假设有attribute vec4 position;
会从缓存中依次读取四个数来作为position进行处理,则总共执行了两次顶点着色器,共两个顶点。
如果在shader中有attribute vec2 position;
则会从缓存中依次读取两个数来作为position进行处理,共四个顶点,顶点着色器执行四次。
附:
WebGL-1.0参考卡片:http://files.cnblogs.com/files/zhiyishou/webgl-reference-card-1_0.pdf
OpenGL-ES-2.0参考卡片:http://files.cnblogs.com/files/zhiyishou/OpenGL-ES-2_0-Reference-card.pdf
The end.
WebGL中的OpenGL着色器语言的更多相关文章
- unity中使用的着色器语言
在unity中,着色器编程使用了一列列的HLSL语言变种(也叫作Cg,但是大部分实际上两者都是一样的). 目前,为了在不同平台下保持最好的跨平台性, 取样贴图时,最好使用DX9风格 的HLSL. 着色 ...
- OpenGL官方教程——着色器语言概述
OpenGL官方教程——着色器语言概述 OpenGL官方教程——着色器语言概述 可编程图形硬件管线(流水线) 可编程顶点处理器 可编程几何处理器 可编程片元处理器 语言 可编程图形硬件管线(流水线) ...
- 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),什么叫静态使用呢? 在写代码中,对于一个变量可能具有以下三种情况: ...
- OpenGL ES着色器语言之着色概览(官方文档)
OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...
- Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL
前面的文章主要是整理的Android 官方文档对OpenGL ES支持的介绍.通过之前的文章,我们基本上可以完成的基本的形状的绘制. 这是本人做的整理笔记: https://github.com/re ...
随机推荐
- 转: Linux网络编程 【8】五种I/O 模式
五种I/O 模式:[1] 阻塞 I/O (Linux下的I/O操作默认是阻塞I/O,即open和socket创建的I/O都是阻塞I/O)[2] 非阻塞 ...
- PHP-数据库长连接mysql_pconnect的细节
PHP的MySQL持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之.这到底是为啥么.近距离观察后发现,这家伙也不容易啊,要看Apache的脸色,还得听MySQL指挥. 对于作为Apache模 ...
- `libsass` bindings not found. Try reinstalling `node-sass`?
本篇文章由:http://xinpure.com/libsass-bindings-not-found-try-reinstalling-node-sass/ 坑一记 `libsass` bindin ...
- 使用CXF实现基于Rest方式的WebService
本文介绍使用CXF实现基于Rest方式的WebService(CXF的版本是3.0.0) 一. 前言 Java有三种WebService规范:Jax-WS,Jax-RS,Jaxm 1. Jax-WS( ...
- [HNOI2002]营业额统计 Splay tree
Splay tree入门题,学好代码风格,学习HH大牛的,传送门.. #include <functional> #include <algorithm> #include & ...
- C#指南,重温基础,展望远方!(9)C#接口
接口定义了可由类和结构实现的协定. 接口可以包含方法.属性.事件和索引器. 接口不提供所定义的成员的实现代码,仅指定必须由实现接口的类或结构提供的成员. 接口可以采用多重继承. 在以下示例中,接口 I ...
- int.TryParse非预期执行引发的思考 ASP.NET -- WebForm -- 给图片添加水印标记 Windows -- 使用批处理文件.bat删除旧文件
int.TryParse非预期执行引发的思考 问题出现 这天在写一个页面,想谨慎些就用了int.TryParse,结果出问题了. 代码如下: Copy int id = 1000; //Reque ...
- HDU 4280Island Transport(网络流之最大流)
题目地址:pid=4280">http://acm.hdu.edu.cn/showproblem.php? pid=4280 这个题是一个纯最大流模板题..就是用来卡时间的.. 还好我 ...
- VS2010/MFC编程入门之四十四:定时器Timer
前面一节鸡啄米讲了CTime类和CTimeSpan类的使用,本节继续讲与时间有关的定时器.定时器并不是一个类,主要考虑到,提起时间的话就不能不说定时器,所以就把它放到CTime和CTimeSpan之后 ...
- python 读取文件时报错: UnicodeDecodeError: 'gbk' codec can't decode byte 0xa4 in position 127: illegal multibyte sequence
UnicodeDecodeError: 'gbk' codec can't decode byte 0xa4 in position 127: illegal multibyte sequence p ...