7

我正在尝试使用点精灵用 OpenGL 3+ 渲染一些粒子。我刚刚意识到我的观点存在重大问题。它们的大小会根据相机距离自动增加。结果如下:

靠近粒子发射器:

科尔斯

而在远处,一切都显得模糊而臃肿:

远的

在旧版本中,似乎可以使用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;
}
4

2 回答 2

14

所以事实证明我的问题是由于我对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;
}
于 2014-10-15T18:56:44.243 回答
5

将 GLSL 与 three.js 一起使用时遇到了同样的问题。根据 glampert 的回答解决了这个问题,但首先,three.js 需要使用某些预定义的变量名

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 首先应用于粒子位置,然后计算到该位置的距离。因为如果您对粒子系统对象应用变换,您的粒子位于不等于全局坐标的对象坐标中。所以我计算视图坐标中的距离(相机总是在原点)。

于 2016-01-19T15:51:57.680 回答