问题描述
我正在尝试使用点精灵在OpenGL 3+中渲染一些粒子.我刚刚意识到我在这些要点上存在重大问题.它们的尺寸会根据相机距离自动增加.结果如下:
靠近粒子发射器:
当距离很远时,一切看起来都变得模糊和肿胀:
在旧版本中,似乎可以使用 glPointParameter
.该功能在新的3+ OpenGL中仍然可用,但仅支持两个参数. GL_POINT_FADE_THRESHOLD_SIZE
看起来像什么我需要,但我没有尝试过.我也在使用 glEnable(GL_PROGRAM_POINT_SIZE);
还有其他方法可以避免根据相机距离自动缩放点吗?我宁愿不必更改代码以使用由三角形制成的标准广告牌.
不确定当前是否相关,但这是我正在使用的顶点着色器:
vec4 a_position_size中的 layout(location = 0);//w坐标中的点大小vec4 a_color中的layout(location = 1);//通过纹理调制的RGBA颜色布局(位置= 0)出vec4 v_color;统一的mat4 u_MVPMatrix;无效main(){gl_Position = u_MVPMatrix * vec4(a_position_size.xyz,1.0);gl_PointSize = a_position_size.w;v_color = a_color;}
所以事实证明,我的问题是由于对 gl_PointSize
的误解.正如评论中指出的和文档中明确指出的那样, gl_PointSize
包含光栅化点的大小(以像素为单位).因此,一旦我们远离它们,点精灵就会看起来更大,但这不是因为它们正在缩放,而是因为当3D场景的其余部分根据透视投影进行缩放时,它们仍然占据相同的屏幕空间.>
我对顶点着色器进行了一些调整,以根据与查看器的距离实际缩放点的大小来解决该问题:
统一的mat4 u_MVPMatrix;统一vec3 u_cameraPos;//常数(可调整):const float minPointScale = 0.1;const float maxPointScale = 0.7;const float maxDistance = 100.0;无效main(){//根据与观看者的距离计算点比例//补偿gl_PointSize是点的事实//尺寸(以栅格化点/像素为单位).浮动cameraDist =距离(a_position_size.xyz,u_cameraPos);浮点数比例= 1.0-(cameraDist/maxDistance);pointScale = max(pointScale,minPointScale);pointScale = min(pointScale,maxPointScale);//设置GL全局变量并转发颜色:gl_Position = u_MVPMatrix * vec4(a_position_size.xyz,1.0);gl_PointSize = a_position_size.w * pointScale;v_color = a_color;}
I'm trying to render some particles with OpenGL 3+ using point sprites. I've just realized that I have a major issue with the points. They increase in size automatically with respect to the camera distance. Resulting in the following:
Close to the particle emitter:
And when far away, everything looks blurry and bloated:
In older versions it seems one could adjust the point size scales with glPointParameter
. The function is still available in new 3+ OpenGL, but it only supports two parameters. GL_POINT_FADE_THRESHOLD_SIZE
seemed like what I need, but I've tried it with no results. I'm also using glEnable(GL_PROGRAM_POINT_SIZE);
Any other way I could avoid this automatic scaling of the points based on camera distance? I would rather not have to change to code to use standard billboards made of triangles.
Not sure if relevant at the moment, but this is vertex shader I'm using:
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;
}
So it turns out my problem was due to my misunderstanding of gl_PointSize
. As was noted in the comments and clearly stated in the documentation, gl_PointSize
contains size of rasterized points, in pixels. Hence the point sprites look larger once we move away from them, but not because they are being scaled, but because they still occupy the same screen space while the rest of the 3D scene is being scaled-down according to the perspective projection.
I fixed the problem with a few adjustments to the vertex shader to actually scale the point size according to the distance from the viewer:
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;
}
这篇关于使用现代OpenGL的点精灵大小衰减的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!