使用现代OpenGL点精灵大小衰减

时间:2014-10-15 16:42:02

标签: opengl glsl particle-system point-sprites

我尝试使用点精灵渲染OpenGL 3+的粒子。我刚刚意识到我的问题存在重大问题。它们相对于相机距离自动增大。导致以下结果:

靠近粒子发射器:

colse

远在外,一切看起来都模糊不清:

far

在旧版本中,似乎可以使用glPointParameter调整磅值比例。该功能仍可在新的3+ OpenGL中使用,但它仅支持两个参数。 GL_POINT_FADE_THRESHOLD_SIZE似乎就像我需要的那样,但我已经尝试过没有结果。我还使用glEnable(GL_PROGRAM_POINT_SIZE);

任何其他方式我可以避免根据相机距离自动缩放点数?我宁愿不必更改代码来使用由三角形组成的标准广告牌。

目前还不确定是否相关,但这是我使用的顶点着色器:

layout(location = 0) in vec4 a_position_size; // Point size in w coord
layout(location = 1) in vec4 a_color;         // RGBA color modulated with texture

layout(location = 0) out vec4 v_color;

uniform mat4 u_MVPMatrix;

void main()
{
    gl_Position  = u_MVPMatrix * vec4(a_position_size.xyz, 1.0);
    gl_PointSize = a_position_size.w;
    v_color      = a_color;
}

2 个答案:

答案 0 :(得分:12)

事实证明我的问题是由于我对gl_PointSize的误解。正如评论中所述并在文档中明确说明的那样,gl_PointSize 包含栅格化点的大小(以像素为单位)。因此,一旦我们离开它们,点精灵就会变得更大,但不是因为它们被缩放,而是因为它们仍然占据相同的屏幕空间,而3D场景的其余部分根据透视投影按比例缩小。

我通过对顶点着色器进行一些调整来修复问题,以根据距观察者的距离实际缩放点大小:

uniform mat4 u_MVPMatrix;
uniform vec3 u_cameraPos;

// Constants (tweakable):
const float minPointScale = 0.1;
const float maxPointScale = 0.7;
const float maxDistance   = 100.0;

void main()
{
    // Calculate point scale based on distance from the viewer
    // to compensate for the fact that gl_PointSize is the point
    // size in rasterized points / pixels.
    float cameraDist = distance(a_position_size.xyz, u_cameraPos);
    float pointScale = 1.0 - (cameraDist / maxDistance);
    pointScale = max(pointScale, minPointScale);
    pointScale = min(pointScale, maxPointScale);

    // Set GL globals and forward the color:
    gl_Position  = u_MVPMatrix * vec4(a_position_size.xyz, 1.0);
    gl_PointSize = a_position_size.w * pointScale;
    v_color      = a_color;
}

答案 1 :(得分:4)

使用带有three.js的GLSL时遇到同样的问题。根据glampert的答案解决了这个问题,但首先要解决这三个问题。需要使用某些predefined variable names

uniform vec4 origin;

void main() {
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    float cameraDist = distance( mvPosition, origin );
    gl_PointSize = 200.0 / cameraDist;
    gl_Position = projectionMatrix * mvPosition;
}

其次请注意,modelViewMatrix首先应用于粒子位置,然后计算距离到该位置。因为如果将变换应用于粒子系统对象,则粒子位于不等于全局坐标的对象坐标中。因此,我计算视图坐标中的距离(相机始终位于原点)。