OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

4.5精度和精度修饰符

4.5.1范围和精度

用于存储和展示浮点数、整数变量的范围和精度依赖于数值的源(varying,uniform,纹理查找,等等),是不是顶点或者片元着色器,还有其他一些底层实现的细节。最低存储需要通过精度修饰符来声明。典型地,精度操作必须要保留变量包含的精度存储。仅有的例外是需要大量复杂计算的内建函数,如atan(),返回值的精度低于声明的精度。

强烈建议顶点语言提供一种匹配IEEE单精度浮点数或更高精度的浮点数的浮点范围和精度。这就需要顶点语言提供浮点变量的范围至少是(-2^62,  2^62),精度至少是65536。

顶点语言必须提供一种至少16位,加上一个符号位的整数精度。

片元语言提供与顶点着色器相同的浮点数范围和精度是很有必要的,但不是必须的。这就需要片元语言提供的浮点数的范围至少是(-16384,+16384),精度至少是1024。

片元语言必须提供一种至少10为,加上一个符号位的整数精度。

4.5.2精度修饰符

任何浮点数或者整数声明前面都可以添加如下精度修饰符:

举例:

lowp float color;

varying mediump vec2 Coord;

lowp ivec2 foo(lowp mat3);

highp mat4 m; 

精度修饰符声明了底层实现存储这些变量必须要使用的最小范围和精度。实现可能会使用比要求更大的范围和精度,但绝对不会比要求少。

一下是精度修饰符要求的最低范围和精度:

Floating Point Magnitude Range是非零值量级的范围。对于Floating Point Precision,relative意思是任何度量的值的精度都是相对于这个值的。对于所有的精度级别,0必须被精确的表示出来。任何不能提供着色器存储变量所声明的精度的实现都会引起一个编译或链接错误。

对于高精度和中级精度,整型范围必须可以准确地转化成相应的相同精度修饰符所表示的float型。这样的话,highp int 可以被转换成highp float, mediump int 可以被转换成mediump float,但是lowp int 不能转换成相应的lowp float。

顶点语言要求编译和链接任何lowp, mediump和highp应用都不能出现错误。

片元语言要求编译和链接任何lowp, mediump应用都不能出现错误。但是highp支持是可选的。

字符常量和布尔型没有精度修饰符.当浮点数和整数构造器不含带有精度修饰符的参数时也不需要精度修饰符。

在这段文档中,操作包含运算符,内建函数和构造器,操作数包含函数参数和构造器参数。

对于精度没有定义的常量表达式或子表达式,评估的精度结果是所有操作数中的最高精度(mediump或者highp) 。带评估的常量表达式必须是固定不变的,并且在编译期进行。

另外,对于没有精度修饰符的操作数,精度将来自于其他操作数。如果所有的操作数都没有精度,那么接着看使用计算结果的其他表达式。这个操作是递归的,直到找到一个有精度的操作符为止。如果必要,这个操作也包含赋值运算的左值,初始化声明的变量,函数形参,函数返回值.如果这样依然不能决定精度,如果组成表达式的所有操作数都没有精度,如果结果没有被赋值,也没有当作参数传进函数,那么将使用默认或更大的类型.当这种情况出现在片元着色器中,默认的精度必须被定义.

比如:

uniform highp float h1;

highp float h2 = 2.3*4.7;操作和结果都是高精度

mediump float m;

m = 3.7*h1*h2;//所有操作都是高精度

h2 = m * h1;//操作是高精度

m = h2 - h1;//操作是高精度

h2 = m + m;//加法和结果都是mediump精度

void f(highp p);

f(3.3);//3.3将作为高精度值传入函数

4.5.3默认精度修饰符

precision precision-qualifier type;

precision可以用来确定默认精度修饰符。type可以是int或float或采样器类型,precision-qualifier可以是lowp, mediump, 或者highp。任何其他类型和修饰符都会引起错误。如果type是float类型,那么该精度(precision-qualifier)将适用于所有无精度修饰符的浮点数声明(标量,向量,矩阵)。如果type是int类型,那么该精度(precision-qualifier)将适用于所有无精度修饰符的整型数声明(标量,向量)。包括全局变量声明,函数返回值声明,函数参数声明,和本地变量声明等。没有声明精度修饰符的变量将使用和它最近的precision语句中的精度。

在顶点语言中有如下预定义的全局默认精度语句:

precision highp float;

precision highp int;

precision lowp sampler2D;

precision lowp samplerCube;

在片元语言中有如下预定义的全局默认精度语句:

precision mediump int;

precision lowp sampler2D;

precision lowp samplerCube;

片元语言没有默认的浮点数精度修饰符。因此,对于浮点数,浮点数向量和矩阵变量声明,要么声明必须包含一个精度修饰符,要不默认的精度修饰符在之前已经被声明过了。

4.5.4可用的精度修饰符

内建宏GL_FRAGMENT_PRECISION_HIGH在支持highp精度的片元语言中是定义过的,但在不支持的系统中是未定义的。一旦定义以后,在顶点和片元语言中都可以使用。

#defien GL_FRAGMENT_PRECISION_HIGH 1;

4.6变异和invariant修饰符

在这部分中,变异是指在不同的着色器中的相同语句返回不同的值的可能性.举个例子,两个顶点着色器都使用相同的表达式来设置gl_Position,并且当着色器执行时传进表达式的值也是一样的.完全有可能,由于两个着色器独立的编译环境,当着色器运行时赋给gl_Position的值不一定会相同.在这个例子中,会引起多路算法的几何对齐问题.

通常,着色器之间的这种变异是允许的.如果想避免这种变异的发生,变量可以使用invariant来声明.

4.6.1invariant修饰符

   为确保一个特定的输出变量是不变的,可以使用invariant修饰符.它可以修饰之前已经定义过的变量,如:

invariant gl_Position;

也可以用在变量的声明当中:

invariant varying mediump vec3 Color;

仅如下变量可以声明为invariant:

(1)顶点着色器中内建的特定输出变量

(2)顶点着色器中输出varying变量

(3)片元着色器中特定的输入变量

(4)片元着色器中的输入varying变量

(5)片元着色器中内建的输出变量

invariant后面还可以跟一个用逗号隔开的之前声明的标识符列表.

为了确保两个着色器中特定的输出变量不发生变异.还应遵循以下规则:

(1)顶点和片元着色器中的输出变量都声明为invariant

(2)相同的值必须输入到赋给输出变量的表达式或控制流的所有着色器输入变量.

(3)输出变量上的任何纹理函数调用在使用纹理格式,纹理像素值和纹理过滤时都需要设置成相同的方式.

(4)所有的输入变量都以相同的方式操作.

初始时,默认的所有输出变量被允许变异.如果想强制所有输出变量都不可变,那么在着色器所有的变量声明之前使用

#pragma STDGL invariant(all)

4.6.2着色器中的不变体

当一个值被存到一个变量中,我们通常假设它是一个常量,除非显示的去更改它的值.然而,在优化处理期间,编译期可能会重新计算一个值而不是将它存到寄存器中.因为操作的精度没有被完全指定(如,低精度的操作会被转成中等精度或高精度),重新计算的值有可能就和原来的值不一致.

在着色器中变体是允许的.如果要避免变体,可以使用invariant修饰符或invariant pragma.

precision mediump;

vec4 col;

vec2 a = ...;

........

col = texture2D(tex, a);//此时a的值假设为a1

..............

col = texture2D(tex, a);//此时a的值假设为a2,但是有可能a1不等于a2

如果强制成常量,可以使用:

#pragma STDGL invariant(all)

例子二:

vec2 m = ...;

vec2 n = ...;

vec2 a = m + n;

vec2 b = m + n;//没法保证a和b完全相等

4.6.3常量表达式的不变体

常量表达式必须要保证是不变体.一个特定的表达式在相同的还是不同的着色器中都必须有相同的结果.这包括同一个表达式出现在同一个顶点和片元着色器中,或出现在不同的顶点和片元着色器中.

如果满足以下条件,常量表达式必须得出相同的值:

(1)表达式的输入值相同

(2)执行的操作相同并且顺序也相同

(3)所有操作均以相同的精度执行

4.6.4不变体和链接装置

在顶点和片元着色器中声明的不变体varying变量必须要匹配.对于内建的特定变量,当且仅当gl_Position被声明为invariant时,gl_FragCoord才可以被声明为invariant.同样的,当且仅当gl_PositionSize被声明为invariant时,gl_PointCoord才可以被声明为invariant.将gl_FrontFacing声明为invariant是错误的.gl_FrontFacing的不变体和gl_Position的不变体是一样的.

4.7修饰顺序

当需要使用多个修饰时,它们必须遵循严格的顺序:

(1)invariant-qualifier   storage-qualifier   precision-qualifier

(2)storage-qualifier    parameter-qualifier    precision-qualifier

 

OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)的更多相关文章

  1. OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围

    OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)   所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符. ...

  2. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  3. OpenGL ES着色器语言之操作数(官方文档第五章)

    OpenGL ES着色器语言之操作数(官方文档第五章) 5.1操作数 OpenGL ES着色器语言包含如下操作符. 5.2数组下标 数组元素通过数组下标操作符([ ])进行访问.这是操作数组的唯一操作 ...

  4. OpenGL ES着色器语言之静态使用(static use)和预处理

    OpenGL ES着色器语言之静态使用(static use) 在OpenGL ES中有一个术语叫静态使用(static use),什么叫静态使用呢? 在写代码中,对于一个变量可能具有以下三种情况: ...

  5. OpenGL ES着色器语言之着色概览(官方文档)

    OpenGL ES着色器语言之着色概览(官方文档第二章) 事实上,OpenGL ES着色语言是两种紧密关联的语言.这些语言用来在OpenGL ES处理管线的可编程处理器创建着色器. 在本文档中,除非另 ...

  6. Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL

    前面的文章主要是整理的Android 官方文档对OpenGL ES支持的介绍.通过之前的文章,我们基本上可以完成的基本的形状的绘制. 这是本人做的整理笔记: https://github.com/re ...

  7. OpenGL官方教程——着色器语言概述

    OpenGL官方教程——着色器语言概述 OpenGL官方教程——着色器语言概述 可编程图形硬件管线(流水线) 可编程顶点处理器 可编程几何处理器 可编程片元处理器 语言 可编程图形硬件管线(流水线) ...

  8. OpenGLES2.0着色器语言glsl

    OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...

  9. Axiom3D:手动创建ManualObject与Mesh,以及如何使用Cg着色器语言

    在开始正文前,先说下Axiom3D里遇到的二个BUG. 1.在启动axiom生成的程序中,我发现输出里总是有一些如"billboard_type","billboard_ ...

随机推荐

  1. 戏说HTML5(转)

    如果有非技术人员问你,HTML5是什么,你会怎么回答? 新的HTML规范... 给浏览器提供了牛逼能力,干以前不能干的事...(确切地说应该是给浏览器规定了许多新的接口标准,要求浏览器实现牛逼的功能. ...

  2. GlusterFS缺点分析[转]

    原文:http://blog.sina.com.cn/s/blog_6b89db7a0101gbcy.html GlusterFS(GNU ClusterFile System)是一个开源的分布式文件 ...

  3. ggplot2 坐标系相关设置(coord)

    在ggplot中,未来更好的数据可视化效果,我们有时候可能要用到一些坐标转换的操作,比如要画横向条形图或者蜘蛛图等. coord_cartesian(xlim = NULL, ylim = NULL) ...

  4. C++对象模型笔记之程序设计模型

    C++程序设计模型支持三种程序设计模型 1.程序模型(procedural model) 可以理解为过程化模型,就像C一样 2.抽象数据类型模型(ADT) 数据结构教材里有说过,查了下资料也不是很明确 ...

  5. 洛谷-哥德巴赫猜想(升级版)-BOSS战-入门综合练习1

    题目背景 Background 1742年6月7日哥德巴赫写信给当时的大数学家欧拉,正式提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和.质数是指除了1和本身之外没有其他约数的数,如2和 ...

  6. Scala Tuple类型

    Tuple可以作为集合存储不同类型的数据,初始化实例如下: val tuple = (1,3,3.14,"aa") val third = tuple._3 Tuple 下标访问从 ...

  7. matlab里的nargin

    nargin是用来判断输入变量个数的函数,这样就可以针对不同的情况执行不同的功能.

  8. js 中null 和 undifined

    1.一个重要问题 null == undifined (true) ; null === undefined (false) 为什么是这样的呢? undifined是未赋值的基本数据类型,未定义: n ...

  9. Windows 小端存储

    小端->高高低低(高位存在高地址,低位存在低地址)

  10. asp脱离源代码管理

    当项目中出现“未能找到与此解决方案关联的源代码管理提供程序.项目将视为不受源代码管理” 解决方法:1.vs2013打开项目, 2.提示“您正在打开的解决方案已绑定到以下Team Foundation ...