AGLKPointParticleShader.vsh
//顶点着色器。
// VERTEX ATTRIBUTES
attribute vec3 a_emissionPosition; //位置
attribute vec3 a_emissionVelocity; //速度
attribute vec3 a_emissionForce; //受力
attribute vec2 a_size; //大小 和 Fade持续时间 size = GLKVector2Make(aSize, aDuration);
attribute vec2 a_emissionAndDeathTimes; //发射时间 和 消失时间
//一般用attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。
// UNIFORMS
uniform highp mat4 u_mvpMatrix; //变换矩阵
uniform sampler2D u_samplers2D[1]; //纹理
uniform highp vec3 u_gravity; //重力
uniform highp float u_elapsedSeconds; //当前时间
//uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。
// Varyings
varying lowp float v_particleOpacity; //粒子 不透明度
//varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,
//然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。application不能使用此变量。
void main()
{
highp float elapsedTime = u_elapsedSeconds - a_emissionAndDeathTimes.x; //流逝时间
// 质量假设是1.0 加速度 = 力 (a = f/m)
// v = v0 + at : v 是当前速度; v0 是初速度;
// a 是加速度; t 是时间
highp vec3 velocity = a_emissionVelocity +
((a_emissionForce + u_gravity) * elapsedTime);
// s = s0 + 0.5 * (v0 + v) * t : s 当前位置
// s0 初始位置
// v0 初始速度
// v 当前速度
// t 是时间
// 运算是对向量运算,相当于分别求出x、y、z的位置,再综合
highp vec3 untransformedPosition = a_emissionPosition +
0.5 * (a_emissionVelocity + velocity) * elapsedTime;
//得出点的位置
gl_Position = u_mvpMatrix * vec4(untransformedPosition, 1.0);
gl_PointSize = a_size.x / gl_Position.w;
// 消失时间减去当前时间,得到当前的寿命; 除以Fade持续时间,当剩余时间小于Fade时间后,得到一个从1到0变化的值
// 如果这个值小于0,则取0
v_particleOpacity = max(0.0, min(1.0,
(a_emissionAndDeathTimes.y - u_elapsedSeconds) /
max(a_size.y, 0.00001)));
}
/*******************************************************************
顶点着色器的扩展知识点:
Vertex shader – 在你的场景中,每个顶点都需要调用的程序,称为“顶点着色器”。假如你在渲染一个简单的场景:一个长方形,每个角只有一个顶点。于是vertex shader 会被调用四次。它负责执行:诸如灯光、几何变换等等的计算。得出最终的顶点位置后,为下面的片段着色器提供必须的数据。
vertex shader可通过可编程的方式实现对顶点的操作,如坐标空间转换,颜色及纹理坐标。最简单的Vertex shader如下
attribute vec4 Position;
void main(Void) {
gl_Position = Position; // must set gl_Position for vertex shader
}
1、attribute声明vertex shader接收的变量,针对每一个顶点的数据。属性可理解为针对每一个顶点的输入数据,只有在vertex shader中才有,在fragment shader中没有。vec4表示由4部分组成的矢量。这里的Position用来传入顶点vertex的位置数据。
2、main是shader脚本的入口。
3、gl_Position是vertex shader内建的输出变量,传递给fragment shader,必须设置。这里将Position直接传递给fragment shader(片元着色器)。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Vertex shader接收多个参数
上边的vertex shader仅接收顶点的位置信息,因此像素颜色都是在fragment shader中写固定的(红色)。而在下边的vertex shader中,通过SourceColor传递像素颜色。
attribute vec4 Position; // position of vertex
attribute vec4 SourceColor; // color of vertex
varying vec4 DestinationColor; // will pass out to fragment shader
void main(void) {
DestinationColor = SourceColor;
gl_Position = Position;
}
1、未声明为attribute的变量即为输出变量(如DestinationColor),将传递给fragment shader。
2、varying表示依据两个顶点的颜色,平滑地计算出顶点之间每个像素的颜色。
对应的fragment shader为:
varying lowp vec4 DestinationColor;
void main(void) {
gl_FragColor = DestinationColor;
}
这里,fragment shader接收来自vertex shader的变量DestinationColor,赋值给gl_FragColor,再输出至OpenGLES。即每个像素的颜色由DestinationColor决定,这样可在代码中精确控制每个像素的颜色。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
內建特殊变量
gl_VertexID是一个输入变量,用于保存顶点的整数索引.
这个整数型变量用highp精度限定符声明.
gl_InstanceID是一个输入变量,用于保存实例化绘图调用中图元的示例编号.
对于常规的绘图调用,该值为0.
gl_InstanceID是一个整数型变量,用highp精度限定符声明.
gl_Position用于输出顶点位置的裁剪坐标.
该值在裁剪和视窗阶段用于执行相应的图元裁剪以及从裁剪坐标到屏幕坐标的顶点位置转换.
如果顶点着色器未写入gl_Position.则该值未定义.
gl_Position是一个浮点变量,用highp精度限定符声明.
gl_PointSize用于写入以像素表示的点精灵尺寸,在渲染点精灵时使用.
顶点着色器输出的gl_PointSize值被限定在OpenGL ES 3.0实现支持的非平滑点大小范围之内.
该值是一个浮点变量,用highp精度限定符声明.
gl_FrontFacing是一个特殊变量,但不是由顶点着色器直接写入的,而是根据顶点着色器生成的位置和渲染的图元类型生成的.
该值是一个布尔变量
內建常量
const mediump int gl_maxVertexAttribs = 16
const mediump int gl_maxVertexUniformVectors = 256
const mediump int gl_maxVertexOutputVectors = 16
const mediump int gl_maxVertexTextureImageUnits = 16
const mediump int gl_maxCombindedTextureImageUnits = 32
gl_maxVertexAttribs : 是可以指定的顶点属性的最大数量.
gl_maxVertexUniformVectors : 顶点着色器可以使用的vec4统一变量项目的最大数量
gl_maxVertexOutputVectors : 输出向量的最大数量
gl_maxVertexTextureImageUnits : 顶点着色器中可用的纹理单元的最大数量.
gl_maxCombindedTextureImageUnits : 顶点和片段着色器中可用纹理单元最大数量的总和.
********************************************************************/
AGLKPointParticleShader.fsh
// UNIFORMS
//片段着色器
//mat4 4*4维矩阵
uniform highp mat4 u_mvpMatrix;
uniform sampler2D u_samplers2D[1];
uniform highp vec3 u_gravity;
uniform highp float u_elapsedSeconds;
// Varyings
varying lowp float v_particleOpacity;
void main()
{
lowp vec4 textureColor = texture2D(u_samplers2D[0],
gl_PointCoord);
textureColor.a = textureColor.a * v_particleOpacity;
gl_FragColor = textureColor;
}
/*******************************************************************
片元着色器的扩展知识点:
Fragment shader – 在你的场景中,大概每个像素都会调用的程序,称为“片段着色器”。在一个简单的场景,也是刚刚说到的长方形。这个长方形所覆盖到的每一个像素,都会调用一次fragment shader。片段着色器的责任是计算灯光,以及更重要的是计算出每个像素的最终颜色
Fragment是可以被渲染到屏幕上的像素点,fragment shader即用于计算每个像素的颜色等属性。最简单的Fragment shader如下
precision mediump float;
void main(void) {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // must set gl_FragColor for fragment shader
}
1、precision mediump float设置float的精度为mediump,还可设置为lowp和highp,主要是出于性能考虑。
2、gl_FragColor是fragment shader唯一的内建输出变量,设置像素的颜色。这里设置所有像素均为红色。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Vertex shader与Fragment shader的差异
1、shader脚本中有三种级别的精度:lowp,mediump,highp。如precision highp float; 。在vertex shader中,int和float都默认为highp级别。而fragment shader中没有默认精度,必须设置精度描述符,一般设为mediump即可。
2、attribute只作用于vertex shader中,表示接收的变量。在vertex shader中,若没有attribute则为输出变量(输出至fragment shader)。
3、vertex shader的默认输出变量至少应该有gl_Position,另外有两个可选的gl_FrontFacing和gl_PointSize。而fragment shader只有唯一的varying输出变量gl_FragColor。
4、Uniform是全局变量,可用于vertex shader和fragment shader。在vertex shader中通常是变换矩阵、光照参数、颜色等,。在fragment shader中通常是雾化参数、纹理参数等。OpenGLES 2.0规定所有实现应该支持的最大vertex shader的uniform变量个数不能少于128个,而最大fragment shader的uniform变量个数不能少于16个。
5、simpler是一种特殊的uniform,用于呈现纹理,可用于vertex shader和fragment shader.
内建特殊变量:
gl_FragCoord —— 片段着色器中的只读变量。保存片段的窗口相对坐标
gl_FrontFacing —— 片段着色器中的一个只读变量。表示片段是否是正面图片的一部分
gl_PointCoord —— 只读变量,渲染点时使用。
gl_FragDepth —— 只写输出变量,在片段着色器中写入时,覆盖片段的固定功能深度值。慎用,因为可能会导致GPU深度优化禁用,即“Early-Z”功能被禁用。“Early-Z”会使得不能通过深度测试的片段不会被着色。
********************************************************************/