OpenGL ES 3.0之Shading Language(八)
每个OpenGL ES 3.0程序要求一个顶点着色器和一个片段着色器去渲染一个图形。着色器概念是API 的中心,本篇将介绍着色器语言部分包含下面几项
1、变量和变量类型
2、矢量和矩阵创建及选择
3、常量
4、结构和阵列
5、运算符、流控制和函数
6、属性、只读变量和变量
7、预处理和指令
8、只读变量和变量压缩
9、精度控制和不变性
一、变量和变量类型
计算机图形学中,转换有两种基本的数据类型:矢量和矩阵。下图是OpenGL ES 着色器编程语言数据类型
变量可以在声明时初始化,或以后初始化,初始化是通过构造函数进行,也可做类型转换。
float myFloat = 1.0;
float myFloat2 = ; // ERROR: invalid type conversion
bool myBool = true;
int myInt = ;
int myInt2 = 0.0; // ERROR: invalid type conversion
myFloat = float(myBool); // Convert from bool -> float
myFloat = float(myInt); // Convert from int -> float
myBool = bool(myInt); // Convert from int -> bool
矢量同样可以转换
vec4 myVec4 = vec4(1.0); // myVec4 = {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,
// myVec2.y,
// temp.x, temp.y}
矩阵转换
mat3 myMat3 = mat3(1.0, 0.0, 0.0, // First column
0.0, 1.0, 0.0, // Second column
0.0, 1.0, 1.0); // Third column
二、矢量和矩阵元素
矩阵元素能够通过两种方式获取,使用“.”操作符或者数组下标。依据被给的元素的组成,每个被给的矩阵都能使用{x, y, z, w}, {r, g, b, a},或{s, t, r, q}表示。使用三种不同的命名表是因为有三种坐标顶点、颜色和贴图。x, r, 或s 表示矩阵里的第一个元素,不同的命名方式仅仅是为了使用方便。或者说你可以使用矩阵时混合使用矩阵命名方式,(但不能使用.xgr,只能一次使用一种命名规则)。当使用“.”时,你也可以重新排列一个矩阵。例如,
vec3 myVec3 = vec3(0.0, 1.0, 2.0); // myVec3 = {0.0, 1.0, 2.0}
vec3 temp;
temp = myVec3.xyz; // temp = {0.0, 1.0, 2.0}
temp = myVec3.xxx; // temp = {0.0, 0.0, 0.0}
temp = myVec3.zyx; // temp = {2.0, 1.0, 0.0}
矩阵也可以使用[]操作符,在这种下标模式[0]代表x, [1]代表y。矩阵被认为是多个矢量组成的,例如mat2 被考虑是两个vec2s,mat3 是3 个vec3s。对矩阵,单独的列被使用列下标[]选中。下面是例子:
mat4 myMat4 = mat4(1.0); // Initialize diagonal to 1.0
(identity)
vec4 colO = myMat4[]; // Get colO vector out of the matrix
float ml_l = myMat4[][]; // Get element at [1][1] in matrix
float m2_2 = myMat4[].z; // Get element at [2][2] in matrix
三、常量
常量是在着色器中不可改变的数据类型。使用const修饰,必须在声明时初始化。
const float zero = 0.0;
const float pi = 3.14159;
const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
const mat4 identity = mat4(1.0);
四、结构和数组
结构
像C 语言一样,可以集合几种变量成为结构。在OpenGL ES 结构如下:
struct fogStruct
{
vec4 color;
float start;
float end;
} fogVar;
这将产生新的变量类型fogStruct,和新的变量名fogVar。使用能够初始化构造函数变量。定义一个结构类型,定义一个结构,一个同名的构造函数也被定义,必须是一对一的。上面的结构能够被使用下面的语法初始化:
fogVar = fogStruct(vec4(0.0, 1.0, 0.0, 0.0), // color
0.5, // start
2.0); // end
结构的构造基于结构的类型,它把每个成员做输入参数。访问结构中的元素和C 语言相同。
vec4 color = fogVar.color;
float start = fogVar.start;
float end = fogVar.end;
数组
OpenGL ES 数组语法和C 语言非常类似,索引以0 开始。下面是创建数组的例子:
float floatArray[];
vec4 vecArray[]; float a[4] = float[](1.0, 2.0, 3.0, 4.0);
float b[4] = float[4](1.0, 2.0, 3.0, 4.0);
vec2 c[2] = vec2[2](vec2(1.0), vec2(1.0));
五、操作符
这些运算符使用和C 语言非常类似。但OpenGL ES 语法有严格的语法限制,执行运算符的变量必须有相同的类型,二进制运算符(*, /, +, -)必须是浮点变量或者是整型变量。乘运算符能够在浮点、矢量、矩阵的组合中运行。例如:
float myFloat;
vec4 myVec4;
mat4 myMat4;
myVec4 = myVec4 * myFloat; // Multiplies each component of myVec4
// by a scalar myFloat
myVec4 = myVec4 * myVec4; // Multiplies each component of myVec4
// together (e.g., myVec4 ^ 2 )
myVec4 = myMat4 * myVec4; // Does a matrix * vector multiply of
// myMat4 * myVec4
myMat4 = myMat4 * myMat4; // Does a matrix * matrix multiply of
// myMat4 * myMat4
myMat4 = myMat4 * myFloat; // Multiplies each matrix component by
// the scalar myFloat
比较运算符(==, !=, <, etc.)仅能够执行标量,矢量有专门的比较函数
六、函数
函数声明和C 语言一样,函数使用前,必须定义,它的原型必须给出。使用时非常类似C 语言。不同是参数使用上,提供特殊的变量限定词,指示变量是否能够被函数修改。那些限定词如下表:
使用如下:
vec4 myFunc(inout float myFloat, // inout parameter
out vec4 myVec4, // out parameter
mat4 myMat4); // in parameter (default)
散射光计算函数。
vec4 diffuse(vec3 normal,
vec3 light,
vec4 baseColor)
{
return baseColor * dot(normal, light);
}
OpenGL ES 函数不能递归,原因是一些编译工具执行这个函数时,这会让这个函数在线执行,最后使GPU 产生问题。
着色器语言也提供了内置函数。下面的例子是,在片段着色器中计算基本反射光的着色器代码。
float nDotL = dot(normal , light);
float rDotV = dot(viewDir, (2.0 * normal) * nDotL C light);
float specular = specularColor * pow(rDotV, specularPower);
七、流控制声明
控制语句语法和C 类似,if-then-else 逻辑也被使用,例如:
if(color.a < 0.25)
{
color *= color.a;
}
else
{
color = vec4(0.0);
}
条件表达式的结果必须是布尔值。或者说表达式基于布尔值计算,或者计算结果是布尔值(例如比较运算)。
八、Uniforms
Uniform
是变量类型的一种修饰符。。uniform 是OpenGL ES 中被输入着色器的只读值。。uniform被使用存储各种着色器需要的数据,例如:转换矩阵、光照参数或者颜色。基本上各种输入着色器的常量参数像顶点和片段(但在编译时并不知道)应该是uniform。uniform 应该使用修饰词被声明为全局变量,如下:
uniform mat4 viewProjMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
uniform 的空间被顶点着色器和片段着色器分享。也就是说顶点着色器和片段着色器被链接到一起进入项目,它们分享同样的uniform。因此一个在顶点着色器中声明的uniform,相当于在片段着色器中也声明过了。当应用程序装载uniform 时,它的值在顶点着色器和片段着色器都可用。
另一个需要注意的是,uniform 被存储在硬件被称为常量存储,这是一种分配在硬件上的存储常量值的空间。因为这种存储需要的空间是固定的,在程序中这种uniform 的数量是受限的。这个限制能通过读gl_MaxVertexUniformVectors 和gl_MaxFragmentUniformVectors编译变量得出。( 或者用GL_MAX_VERTEX_UNIFORM_VECTORS 或GL_MAX_FRAGMENT_UNIFORM_ VECTORS 为参数调用glGetIntegerv)OpenGL ES 3.0必须至少提供256 个顶点着色器uniform 和224个片段着色器uniform。但可以更多,
Uniform Blocks
uniform TransformBlock
{
mat4 matViewProj;
mat3 matNormal;
mat3 matTexGen;
};
layout(location = ) in vec4 a_position;
void main()
{
gl_Position = matViewProj * a_position;
}
九、属性
OpenGL ES 着色器语言的另一个变量是属性。属性变量仅仅在顶点着色器中被使用,逐顶点的指定顶点着色器的输入。典型的被用来储存位置、法线、贴图坐标和颜色数据。关键是懂得属性是每个顶点被绘制的详细数据。它实际上是着色器的使用者决定什么数据是属性。
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord;
void main(void)
{
gl_Position = u_matViewProjection * a_position;
v_texCoord = a_texCoord0;
}
像uniform 一样,硬件对顶点着色器的属性变量数量有限制。最大的属性数通过工具编译支持gl_MaxVertexAttribs 确定。(或者使用GL_MAX_VERTEX_ATTRIBS 为参数调用glGetIntegerv 查询)最小数是8。如果为确保你的程序能在任何OpenGL ES 2.0 工具上编译,确保你的属性不超过8。
变量被用来存储顶点着色器的输出和片段着色器的输入。基本上每个顶点着色器把输出数据转变成一个或更多片段着色器的输入。那些变量也被片段着色器声明(类型需匹配),并且在光栅化阶段被线性插补变成图元。
varying vec2 texCoord;
varying vec4 color;
变量也有数量的限制(硬件上它们被用来做插补)。工具支持的最大数目是gl_MaxVaryingVectors ( 使用GL_MAX_VARYING_VECTORS 为参数调用glGetIntegerv 查询)。最大数目是8.
下面是顶点着色器和片段着色器的变量如何匹配的声明
// Vertex shader
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord; // Varying in vertex shader
void main(void)
{
gl_Position = u_matViewProjection * a_position;
v_texCoord = a_texCoord0;
}
// Fragment shader
precision mediump float;
varying vec2 v_texCoord; // Varying in fragment shader
uniform sampler2D s_baseMap;
uniform sampler2D s_lightMap;
void main()
{
vec4 baseColor;
vec4 lightColor;
baseColor = texture2D(s_baseMap, v_texCoord);
lightColor = texture2D(s_lightMap, v_texCoord);
gl_FragColor = baseColor * (lightColor + 0.25);
}
十、预处理指令
#define
#undef
#if
#ifdef
#ifndef
#else
#elif
#endif
__LINE__ // 被着色器当前的行数取代
__FILE__ // 在 OpenGL ES 中总是0
__VERSION__ // OpenGL ES 着色器语言版本 (e.g., 100)
GL_ES // 被 ES 着色器定义为值1
其他
精度控制符,lowp,highp,mediump.对所有基于浮点的变量默认的精度是浮点值,基于整型的变量默认的精度是整型。在着色器中, 如果没有定义指定精度,默认对int 和float 的精度都是高。换句话说在顶点着色器中没有指定进度控制的变量将是高质量。而片段着色器规则却不同。对浮点值没有默认的精度控制。每个着色器必须声明默认的着色器浮点精度或指定每个浮点变量的精度。即OpenGL ES 2.0 不要求片段着色器支持高精度。决定是否高精度被支持是片段着色器是否定义了GL_FRAGMENT_PRECISION_HIGH 宏(和工具输出OES_fragment_precision_high 扩展字符串)。
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
最后要讨论的题目是不变性。在OpenGL ES 着色器编程语言里,invariant 是被用于任何顶点着色器的变量输出的关键字。它意味着什么和为什么需要他呢。着色器被编译时可能进行优化,一些指令被重新整理。指令重新整理意味着两个着色器之间平等的计算不保证产生相同的结果。这是个问题在多通道着色器特殊情况下,依稀物体使用透明混合来绘制时。如果精度被使用来计算输出位置是不准确一样,精度的不同将导致artifacts。这在Z fighting情况下经常发生。每个像素很小的Z 精度不同引起了不同的反光。下面的例子显示了进行多通道渲染时invariance 对得到正确的结果是非常重要的。下面的圆环被绘制用两种方式。片段着色器先计算镜面反射光,再计算环境光和散射光。顶点着色器不使用invariance,因此小的精度不同引起了Z 光在图
invariant gl_Position;
invariant varying texCoord;
一旦输出被宣布为invariance,同样的计算输入相同,编译器保证输出结果相同。例如你有两个顶点着色器使用多通道图像投射矩阵依据输入计算输出。你能保证那些位置是invariance。
uniform mat4 u_viewProjMatrix;
attribute vec4 a_vertex;
invariant gl_Position;
void main
{
//
gl_Position = u_viewProjMatrix * a_vertex; // Will be the same
// value in all
// shaders with the
// same viewProjMatrix
// and vertex
}
OpenGL ES 3.0之Shading Language(八)的更多相关文章
- (OpenGL ES 2.0 Shading Language) attribute 、uniform 和 varying
一:attribute .uniform 和 varying 都是glsl的变量的内存指示器(storage qualifiers),指明变量的内存特性 二:attribute attribute 是 ...
- OpenGL ES 3.0之顶点缓冲
所谓顶点缓冲就是直接将顶点数据存储在gpu的一段缓冲区,不需要从cpu拷贝到gpu.提高了程序的运行效率. 操作步骤 1.创建顶点缓冲对象 GLuint vertexBufferID; 2.分配空间 ...
- 梳理 Opengl ES 3.0 (二)剖析一个GLSL程序
OpenGL ES shading language 3.0 也被称作 GLSL,是个 C风格的编程语言. Opengl ES 3.0内部有两种可编程处理单元,即Vertex processor和Fr ...
- Beginning OpenGL ES 2.0 with GLKit Part 1
Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, ...
- 利用JNI技术在Android中调用C++形式的OpenGL ES 2.0函数
1. 打开Eclipse,File-->New-->Project…-->Android-->AndroidApplication Projec ...
- OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型
OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...
- OpenGL ES 3.0顶点着色器(二)
#version es uniform mat4 u_mvpMatrix; in vec4 a_position; in vec4 a_color;out vec4 v_color;void main ...
- 【C++ OpenGL ES 2.0编程笔记】8: 使用VBO和IBO绘制立方体 【转】
http://blog.csdn.net/kesalin/article/details/8351935 前言 本文介绍了OpenGL ES 2.0 中的顶点缓冲对象(VBO: Vertex Buff ...
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
随机推荐
- 《Go学习笔记 . 雨痕》类型
一.基本类型 清晰完备的预定义基础类型,使得开发跨平台应用时无须过多考虑符合和长度差异. 类型 长度 默认值 说明 bool 1 false byte 1 0 uint8 int, uint 4, ...
- Delphi 设置快捷键
= 'Repeat %s(&' + #32 + ')'; //设置快捷键 这个是设置空格的 如果设置字符, 就可以这样写= 'Repeat %s(&H)‘ const SRep ...
- In-Place upgrade to Team Foundation Server (TFS) 2015 from TFS 2013Team Foundation Server TFS TFS 2015 TFS upgrade TFS with Sharepoint
This upgrade document gives detailed step by step procedure for the In-Place upgrade from TFS 2013 t ...
- Modbus读写模拟量寄存器具体解释
读可读写模拟量寄存器: 发送命令(主机向从机)格式: [设备地址] [命令号03] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高 ...
- BootStrap中的button使用
原文地址:http://www.phloxblog.in/bootstrap-buttons/#.U5xYso2fclm 站点中事件的触发往往依赖于button或者超链接.因此,button能够觉得是 ...
- 用GridLayout实现计算器的布局
GridLayout是一个表格视图,我们一般定义它的列数和行数来设置好这个控件. 下面的布局文件先定义了一个TextView和一个Button,设置他们的属性为横跨4列.这样就可以独自占据一行了.然后 ...
- MARQUEE 字符滚动条效果
<MARQUEE scrolldelay =“100” direction=“up " > 滚动文字或图像 </MARQUEE> 说明: – scrolldelay: ...
- JAVAWEB开发之HttpServletResponse和HttpServletRequest详解(下)(各种乱码、验证码、重定向和转发)
HttpServletRequest获取请求头信息 (1)获取客户机请求头 String getHeader(String name) Enumeration<String> getHe ...
- java 常用集合list与Set、Map区别及适用场景总结
转载请备注出自于:http://blog.csdn.net/qq_22118507/article/details/51576319 list与Set.Map区别及 ...
- Sutherland-Hodgeman多边形裁剪
原文地址:http://course.cug.edu.cn/cugFirst/computer_graphics/class/course/3-3-1-a.htm