函数的参数默认是以拷贝的形式传递的,也就是值传递,任何传递给函数参数的变量,其值都会被复制一份,然后再交给函数内部进行处理。所以,可以为参数添加限定符来达到传递引用的目的。
限定符说明< none:default >默认使用in限定符in复制到函数中在函数中可读可写。默认限定符,最终真正传入函数形参的其实是实参的一份拷贝,在函数中,修改in修饰的形参不会影响到实参变量本身out返回时从函数中复制出来。他的作用是想函数外部传递性质,out模式下传递进来的参数是write-only(可写不可读)的,在函数中,修改out修饰的形参回影响到实参本身inout复制到函数中斌返回时复制出来。可读可写,在函数中,修改inout修饰的形参会影响到实参本身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,即可对该变量的精度声明。
lowp float color; varying mediump vec2 Coord; lowp ivec2 foo(lowp mat3); highp mat4 m一般在片元着色器(fragment shader)最开始的地方加上precison mediump float,设定默认精度,这样所有没有显示声明精度的变量都会按照这个精度来处理。
确定精度: 变量的精度首先都是由精度限定符确定的,如果没有精度限定符,则要寻找右侧表达式中已经确定精度的变量,一旦找到,那么整个表达式都将在改精度下运行。如果找到多个,则选择精度较高的,如果未找到,则会使用默认或者更大的精度类型。
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
invariant varying lowp float color; // invariant > storage > precision void doubleSize(const in lowp float s){ //storage > parameter > precision float s1=s; }以#开头的是预编译指令,常用的有: #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 #endif2.自定义宏:
#define NUM 100 #if NUM==100 #endifGLSL程序使用一些特殊的内置变量与硬件进行沟通。大致分为两种,一种是input类型,负责向硬件(渲染管线)发送数据,另一种是output类型,负责向程序回传数据,以便编程需要。 在vertex shader中: output类型的内置变量:
变量说明单位highp vec4 gl_Positiongl_Position放置顶点坐标信息vec4mediump float gl_PointSizegl_PointSize需要绘制点的大小(只在gl.POINTS模式下有效)float在fragment shader中: input类型:
变量说明单位mediump vec4 gl_FragCoord片元在framebuffer画面的相对位置vec4bool gl_FrontFaceing标志当前图元是不是正面图元的一部分boolmediump vec2 gl_PointCoord经过插值计算后的纹理坐标,点的范围是0.0~1.0vec2output类型:
变量说明单位mediump vec4 gl_FragColor设置当前片点的颜色vec4 RGBA colormediump vec4 gl_FragData[n]设置当前片点的颜色,使用glDrawBuffers数据数组vec4 RGBA color