着色器语言(GLSL)基础学习二

函数参数的限定符:

函数的参数默认是以拷贝的形式传递的,也就是值传递,任何传递给函数参数的变量,其值都会被复制一份,然后再交给函数内部进行处理。所以,可以为参数添加限定符来达到传递引用的目的。

限定符说明
< none:default >默认使用in限定符
in复制到函数中在函数中可读可写。默认限定符,最终真正传入函数形参的其实是实参的一份拷贝,在函数中,修改in修饰的形参不会影响到实参变量本身
out返回时从函数中复制出来。他的作用是想函数外部传递性质,out模式下传递进来的参数是write-only(可写不可读)的,在函数中,修改out修饰的形参回影响到实参本身
inout复制到函数中斌返回时复制出来。可读可写,在函数中,修改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,即可对该变量的精度声明。

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
    #endif

2.自定义宏:

#define NUM 100
#if NUM==100
#endif

内置的特殊变量

GLSL程序使用一些特殊的内置变量与硬件进行沟通。大致分为两种,一种是input类型,负责向硬件(渲染管线)发送数据,另一种是output类型,负责向程序回传数据,以便编程需要。
在vertex shader中:
output类型的内置变量:

变量说明单位
highp vec4 gl_Positiongl_Position放置顶点坐标信息vec4
mediump float gl_PointSizegl_PointSize需要绘制点的大小(只在gl.POINTS模式下有效)float

在fragment shader中:
input类型:

变量说明单位
mediump vec4 gl_FragCoord片元在framebuffer画面的相对位置vec4
bool gl_FrontFaceing标志当前图元是不是正面图元的一部分bool
mediump vec2 gl_PointCoord经过插值计算后的纹理坐标,点的范围是0.0~1.0vec2

output类型:

变量说明单位
mediump vec4 gl_FragColor设置当前片点的颜色vec4 RGBA color
mediump vec4 gl_FragData[n]设置当前片点的颜色,使用glDrawBuffers数据数组vec4 RGBA color
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值