我正在尝试使用点精灵来使用OpenGL 3进行粒子系统。
我使用带有GL_STREAM_DRAW的VBO,其中我放置了每个粒子的坐标。 在每个帧期间,我用新的粒子坐标更新VBO。使用GL_VERTEX_PROGRAM_POINT_SIZE简单地使用GL_POINTS渲染粒子。
我注意到有些颗粒被其他颗粒覆盖,尽管它们应该更靠近相机。
点精灵实际上是按绘制调用的顺序而不是深度绘制的,这会产生如下情况:
这里首先绘制最远的粒子,然后绘制闭粒子。正如预期的那样,衣柜颗粒完全覆盖了它背后的那个。
此处,绘制顺序相反,导致最远的粒子可见。
我尝试使用
进行OpenGL深度测试getInstance
但这只会导致没有被吸引。
据我所知,解决这个问题的一种方法是按深度重新排序粒子,但是对于许多粒子来说这个解决方案在CPU上会非常昂贵,所以有没有办法对GPU上的点精灵进行适当的深度测试?
用于绘制粒子的顶点着色器如下:
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.f, 1.f);
glEnable(GL_DEPTH_CLAMP);
片段着色器:
#version 330
layout(location = 0) in vec4 position;
uniform float time;
uniform mat4 camera;
smooth out float dist;
void main()
{
vec4 cameraPos = position + vec4(0.0, 0.0, -1.0, 0.0);
gl_Position = camera * cameraPos;
dist = sqrt(dot(camera * cameraPos, position));
gl_PointSize = 15.0/dist;
}
完整代码(减去一些样板代码):
#version 330
out vec4 colour;
uniform float time;
smooth in float dist;
float map(float value, float inMin, float inMax, float outMin, float outMax) {
return outMin + (outMax - outMin) * (value - inMin) / (inMax - inMin);
}
void main()
{
// colour = vec4(pos.x, pos.y, 1.0, 1.0);
if(dot(gl_PointCoord-0.5,gl_PointCoord-0.5)>0.25)
discard;
else {
float g = (dot(gl_PointCoord-0.5,gl_PointCoord-0.5) > 0.22 ? 0.6 : map(dot(gl_PointCoord-0.5,gl_PointCoord-0.5), 0.0, 0.21, 0.0, 0.6));
colour = vec4(g, g*sin(time)*sin(time)*cos(time), sin(dist), 1.0);
}
}
答案 0 :(得分:0)
这个问题实际上与2个问题有关:
1 - 深度缓冲区从未被清除,因为评论中提到了用户derhass。
2 - 顶点缓冲区中的点大小以错误的方式计算。透视矩阵仅应用于摄像机位置,而不应用于顶点位置。它应该是dist = distance(cameraPos, position));
而不是dist = sqrt(dot(camera * cameraPos, position));