点精灵介绍
是指在绘制时一个精灵用一个点来表示,通常将一个点的size变大,就变成了矩形,然后将纹理映射到点上
初步使用
glPointSize(10.0f);
....
glDrawArrays(GL_POINTS,0,cnt);
vertex sader
uniform mat4 mvp;
layout(location = 0) in vec4 position;
void main()
{
gl_Position = mvp * position;
}
fragment shader:
uniform sampler2D tex;
layout(location = 0) out vec4 color;
void main()
{
color = texture(tex, gl_PointCoord);
}
在粒子系统中的使用
每个粒子绘制成圆
fragment shader:
#version 330 core
in vec3 Fcolor;
layout(location = 0)out vec4 glcolor;
void main()
{
vec2 texCoord = gl_PointCoord*2 -vec2(1.0f);
float r2 = dot(texCoord,texCoord);
if(r2>1.0)
discard;
glcolor = vec4(Fcolor,1.0f);
}
把粒子渲染成球
需要求出法向量,加入光照,视觉上看起来像球,实际上还只是画了圆
fragment shader:
#version 330 core
in vec3 Fcolor;
layout(location = 0)out vec4 glcolor;
void main()
{
vec3 n;
n.xy = gl_PointCoord*2 -vec2(1.0f);
float r2 = dot(n.xy, n.xy);
if(r2>1.0)
discard;
n.z = sqrt(1-r2);
vec3 lightDir = vec3(0.0, 0.0, 3.0);
vec3 viewPos = vec3(.0 ,.0, 5.0);
vec3 half = normalize(lightDir + viewPos);
float diffuse = max(0.0, dot(lightDir,n));
float spec = pow(max(0,dot(half,n)),64);
glcolor = vec4( (diffuse)*Fcolor,1.0f)+spec;
}
粒子球之间的相互挤压效果
在并不需要如上面类型的两个球交叉时,交叉部分只会显示一种颜色,
表示完全遮挡,而不能表现出球之间的相互作用。
如果需要相互作用效果,像分子结构一样,就需要修改深度值,使得深度值是距离圆中心的距离相关的值,那么在交叉部分,像素的颜色会为距离
球中心近的颜色,效果如下:
在上面的fragment shader中加入一句即可
gl_FragDepth = r2;
粒子大小随着距离相机的远近变化
在vertex shader中算得距离相机的远近,设置gl_PointSize,
需要在程序中设置
glEnable(GL_PROGRAM_POINT_SIZE);
vertex shader:
void main()
{
Fcolor = color;
vec4 eyePos = modelView * vec4(position, 1.0);
vec4 projVoxel = proj * vec4(spriteSize, spriteSize, eyePos.z, eyePos.w);
vec2 projSize = screenSize * projVoxel.xy / projVoxel.w;
gl_PointSize = 0.25 * (projSize.x + projSize.y);
gl_Position = proj * eyePos;
}