~~~~我的生活,我的点点滴滴!!
GLSL: OpenGL着色语言(GLSL――OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义
程序,他们是在图形卡的GPU(Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分。比如:视图转换、
投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),
有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量
进行传递。
在(vertex和fragment)shader程序内部,uniform变量就像是C语言里面的常量(const ),它不能被shader程序修改(shader只能用,不能改),
如果uniform变量在vertex和fragment两者之间声明方式完全一样,则它可以在vertex和fragment共享使用(相当于一个被vertex和fragment shader
共享的全局变量)。
uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。
以下是例子:
uniform mat4 viewProjMatrix; //投影+视图矩阵 uniform mat4 viewMatrix; //视图矩阵 uniform vec3 lightPosition; //光源位置
attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。在外部程序中,一般用函数glBindAttribLocation()来绑定
每个attribute变量的位置,然后用函数glVertexAttribPointer()为每个attribute变量赋值。
以下是例子:
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; }
varying变量是vertex和fragment shader之间做数据传递用的,一般vertex shader修改varying变量的值,然后fragment shader使用
该varying变量的值,因此varying变量在vertex和fragment shader二者之间的声明必须是一致的,application(外部程序)不能使用
此种变量。
以下是例子:
// Vertex shader 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; } // Fragment shader precision mediump float; varying vec2 v_texCoord; // 可易变量在片段着色器中 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); }
此图,显示了显卡渲染图形的过程,每次调用像drawArrays这样的函数,openGL都要处理先前以属性(如顶点的缓冲区)和统一变量(其用于
投影矩阵和模型视图矩阵)的形式提交给它的数据,并将其传入到顶点渲染器。
对每个顶点调用一次顶点渲染器,每次都为该顶点设置合适的属性。同时,将统一变量(uniform)传入到顶点渲染器。但是,统一变量(uniform)
正如它们的名字,在调用的过程中并不发生改变。一旦顶点渲染器完成其工作,openGL就会从这些可变变量中将三维图像转化为二维图像,接着它
在图像中为每一个像素调用一次片段渲染器(由于这个原因,在一些三维图像系统中片段渲染器被认作为像素渲染器。)当然,这意味着片段渲染器
用于那些没有顶点的像素——即,顶点结束的像素之间的像素。对于组成三角形的顶点位置,openGL将通过线性插值的方法在两个顶点间填充一些像
素。线性插值处理填充了组成可见三角形的顶点分隔的空间。片段渲染器的作用是返回每一个插值点的颜色,它在gl_FragColor可变变量中返回这个
颜色值。
一旦片段渲染器处理完成,openGL对其结果稍作混合,再将其放入帧缓冲区(frame buffer),此即屏幕上最终显示的东西。
我们所采用的方法是基于如下事实:我们能从顶点渲染器中传出可变变量(而不是位置信息),然后我们可以在片段渲染器中重新获得它们。因
此,我们把颜色信息传入到顶点渲染器,然后顶点渲染器直接将该信息置入一个可以在片段渲染器中获得的可变变量中。 这种方法很方便地为我们提
供了颜色的渐变,且不花费任何代价。当在顶点间生成片段时,除了位置信息,所有顶点渲染器设置的可变变量都是线性插值的。顶点间的线性颜色
插值为我们提供了平滑渐变。