函数参数的限定符:
函数的参数默认是以拷贝的形式传递的,也就是值传递,任何传递给函数参数的变量,其值都会被复制一份,然后再交给函数内部进行处理。所以,可以为参数添加限定符来达到传递引用的目的。
限定符 | 说明 | none:default | 默认使用in限定符 | in/centroid in | 复制到函数中在函数中可读可写。默认限定符,最终真正传入函数形参的其实是实参的一份拷贝,在函数中,修改in修饰的形参不会影响到实参变量本身。centroid in 变量于插值类型有关 | out/centroid out | 返回时从函数中复制出来。他的作用是想函数外部传递性质,out模式下传递进来的参数是write-only(可写不可读)的,在函数中,修改out修饰的形参回影响到实参本身。centroid out 变量于插值类型有关 | ninout | 复制到函数中斌返回时复制出来。可读可写,在函数中,修改inout修饰的形参会影响到实参本身 |
---|
GLSL的函数:
glsl允许在程序的最外部声明函数。函数不能嵌套,不能递归调用,且必须声明返回值类型(无返回值时声明为void).
vec4 getPosition(){
vec4 v4=vec4(0.0,0.0,0.0,1.0);
return v4;
}
void doubleSize(inout float size){
size=size*2.0;
}
void main(){
float psize= 10.0;
doubleSize(psize);
gl_Position = getPosition();
gl_PointSize = psize;
}
构造函数:
glsl中变量可以在声明的时候初始化,也可以先声明再在需要时赋值。而聚合类型对象,如(向量,举证,数组,结构),需要使用其构造函数来进行初始化。
//一般类型
float pSize=10.0;
float pSize1;
pSize1=10.0;
//复合类型,如向量
vec4 color=vec4(0.0,1.0,0.0,1.0);
vec4 color1;
color1=vec4(0.0,1.0,0.0,1.0);
//结构
struct light{
float intensity;
vec3 position;
}
light lightVar=light(3.0,vec3(1.0,2.0,3.0));
//数组
const float c[3]=float[3](5.0,7.2,1.1);
精度限定:
glsl在进行光栅化着色的时候,会产生大量的浮点数运算,这些运算可能会超出当前设备的承受能力,所以glsl提供了三种浮点数精度。在变量前面加上highp 、mediump 、lowp,即可对该变量的精度声明。
- highp (-2的16次方, 2的16次方);
- mediump (-2的10次方, 2的10次方);
- lowp (-2的8次方, 2的8次方);
lowp float color;
varying mediump vec2 Coord;
lowp ivec2 foo(lowp mat3);
highp mat4 m
确定精度:
变量的精度首先都是由精度限定符确定的,如果没有精度限定符,则要寻找右侧表达式中已经确定精度的变量,一旦找到,那么整个表达式都将在该精度下运行。如果找到多个,则选择精度较高的,如果未找到,则会使用默认或者更大的精度类型。
uniform highp float h1;
highp float h2=2.3*4.7;//运算过程和结果都会使用高精度
mediump float m;
m=3.7*h1*h2;//运算过程是高精度
h2=m*h1;//运算过程是高精度
h2=m+m//运算过程和结果都是中精度
//形参p是高精度,传入的3.3是高精度
void f(highp float p);
f(3.3);
invariant
关键: 由于shader在编译时会进行一些内部优化,可能会导致同样的运算在不同shader里结果不一定精确相等,这会引起一些问题,尤其是vertex shader向fragment shader传值的时候。所以需要使用invariant关键字来显示要求计算结果必须精确一直。当然也可以使用#pragma STDGL invariant(all)来命令所有输出变量必须精确一致,但这样会限制编译器优化程度,降低性能。
#pragma STDGL invariant(all) //所有输出变量为
invariant invariant varying texCoord; //varying在传递数据的时候声明为invariant
限定符的顺序:
当需要用到多个限定符的是要遵循以下顺序:
1.在一般变量中: invariant > storage > precision
2.在参数中: storage > parameter > precision
预编译指令
以#开头的是预编译指令,常用的有: #define 、 #undef 、 #if 、 #ifdef 、#ifndef 、#else、#elif、 #endif 、#error 、#pragma 、#extension、#version 、#line 比如#version 100,表示规定当前shader使用GLSL ES 1.00标准进行编译,如果使用该指令,则必须出现在程序最开始的位置。
内置的宏: LINE:当前源码中的行号。 VERSION:一个整数,指示当前的GLSL版本。 GL_ES:如果当前是在OpenGL ES环境中运行则GL_ES被设置成1,一般用来检查当前环境是不是OpenGL ES. GL_FRAGMENT_PRECISION_HIGH:如果当前系统glsl的片元着色器支持高浮点精度,则设置为1,一般用来检查着色器的精度。
实例: 1.如何通过判断系统环境,来选择合适的精度:
#ifdef GL_ES //
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
2.自定义宏:
#define NUM 100
#if NUM==100
#endif
内置的特殊变量
GLSL程序使用一些特殊的内置变量与硬件进行沟通。大致分为两种,一种是input类型,负责向硬件(渲染管线)发送数据,另一种是output类型,负责向程序回传数据,以便编程需要。
在vertex shader中:
output类型的内置变量:
变量 | 说明 | 单位 | highp vec4 gl_Position | gl_Position放置顶点坐标信息 | vec4 | mediump float gl_PointSize | gl_PointSize需要绘制点的大小(只在gl.POINTS模式下有效) | float |
---|
在fragment shader中:
input类型:
变量 | 说明 | 单位 | mediump vec4 gl_FragCoord | 片元在framebuffer画面的相对位置 | vec4 | bool gl_FrontFaceing | 标志当前图元是不是正面图元的一部分 | bool | mediump vec2 gl_PointCoord | 经过插值计算后的纹理坐标,点的范围是0.0~1.0 | vec2 |
---|
output类型:
变量 | 说明 | 单位 | mediump vec4 gl_FragColor | 设置当前片点的颜色 | vec4 RGBA color | mediump vec4 gl_FragData[n] | 设置当前片点的颜色,使用glDrawBuffers数据数组 | vec4 RGBA color |
---|
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!