点精灵的粒子系统 [英] Point Sprites for particle system

查看:243
本文介绍了点精灵的粒子系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是点精灵建立一个粒子系统的最佳选择?

Are point sprites the best choice to build a particle system?

在OpenGL和最新的显卡驱动程序的更新版本点精灵present?或者我应该做的VBO使用GLSL以及它?

Are point sprites present in the newer versions of OpenGL and drivers of the latest graphics cards? Or should I do it using vbo and glsl?

推荐答案

点精灵的确是非常适合粒子系统。但是,他们没有任何与维也纳组织和GLSL,这意味着它们是完全正交特性。不,如果你使用点精灵与否,你总是需要使用驻国际中心组织上传的几何形状的事,是他们只是指出,pre-制作精灵或什么的,你总是有通过一组着色器把这个几何体(当然,在现代的OpenGL)。

Point sprites are indeed well suited for particle systems. But they don't have anything to do with VBOs and GLSL, meaning they are a completely orthogonal feature. No matter if you use point sprites or not, you always have to use VBOs for uploading the geometry, be they just points, pre-made sprites or whatever, and you always have to put this geometry through a set of shaders (in modern OpenGL of course).

话虽这么说点精灵在现代的OpenGL很好的支持,只是没有自动与老固定功能的方法。什么是不支持是一点衰减功能,让您缩放根据相机它的距离点的大小,您必须手动做到这一点的顶点着色器内。以同样的方式,你必须做手工点的纹理以适当的片段着色器,使用特殊的输入变量 gl_PointCoord (也称凡在[0,1]整点的当前片段是 - 方)。例如,一个基本点精灵管道可能看起来是这样的:

That being said point sprites are very well supported in modern OpenGL, just not that automatically as with the old fixed-function approach. What is not supported are the point attenuation features that let you scale a point's size based on it's distance to the camera, you have to do this manually inside the vertex shader. In the same way you have to do the texturing of the point manually in an appropriate fragment shader, using the special input variable gl_PointCoord (that says where in the [0,1]-square of the whole point the current fragment is). For example a basic point sprite pipeline could look this way:

...
glPointSize(whatever);              //specify size of points in pixels
glDrawArrays(GL_POINTS, 0, count);  //draw the points

顶点着色器:

uniform mat4 mvp;

layout(location = 0) in vec4 position;

void main()
{
    gl_Position = mvp * position;
}

片段着色器:

uniform sampler2D tex;

layout(location = 0) out vec4 color;

void main()
{
    color = texture(tex, gl_PointCoord);
}

而这一切。当然这些着色只是做纹理精灵的最基本的绘图,但对于进一步的特征的起点。例如根据其与相机的距离(也许为了给它一个固定的世界空间大小)计算精灵的大小,你必须过glEnable(GL_PROGRAM_POINT_SIZE)和写在顶点着色器的特殊输出变量 gl_PointSize

And that's all. Of course those shaders just do the most basic drawing of textured sprites, but are a starting point for further features. For example to compute the sprite's size based on its distance to the camera (maybe in order to give it a fixed world-space size), you have to glEnable(GL_PROGRAM_POINT_SIZE) and write to the special output variable gl_PointSize in the vertex shader:

uniform mat4 modelview;
uniform mat4 projection;
uniform vec2 screenSize;
uniform float spriteSize;

layout(location = 0) in vec4 position;

void main()
{
    vec4 eyePos = modelview * position;
    vec4 projVoxel = projection * vec4(spriteSize,spriteSize,eyePos.z,eyePos.w);
    vec2 projSize = screenSize * projVoxel.xy / projVoxel.w;
    gl_PointSize = 0.25 * (projSize.x+projSize.y);
    gl_Position = projection * eyePos;
}

这将使所有的点精灵具有相同的世界空间的大小(因而不同的屏幕空间的大小以像素为单位)。

This would make all point sprites have the same world-space size (and thus a different screen-space size in pixels).

不过,点精灵同时仍然在现代OpenGL的完美支持也有缺点。其中最大的缺点之一是其裁剪的行为。点在其中心裁剪坐标(因为削波光栅化之前完成,因此前点被放大)。因此,如果在点的中心是在屏幕的外部,它可能仍然伸入观看区的其余部分未示出,所以在最坏的情况,一旦点是中途退出的屏幕上,它会突然消失。然而,这仅仅是noticable(或annyoing)如点精灵太大。如果他们不支付超过几个像素,每个像素反正多非常小的粒子,那么这将不会是太大的问题,我会仍然把粒子系统规范的用例为点精灵,只是不它们用于大型广告牌。

But point sprites while still being perfectly supported in modern OpenGL have their disadvantages. One of the biggest disadvantages is their clipping behaviour. Points are clipped at their center coordinate (because clipping is done before rasterization and thus before the point gets "enlarged"). So if the center of the point is outside of the screen, the rest of it that might still reach into the viewing area is not shown, so at the worst once the point is half-way out of the screen, it will suddenly disappear. This is however only noticable (or annyoing) if the point sprites are too large. If they are very small particles that don't cover much more than a few pixels each anyway, then this won't be much of a problem and I would still regard particle systems the canonical use-case for point sprites, just don't use them for large billboards.

但是,如果这是一个问题,那么现代的OpenGL提供了许多其他的方式来实现点精灵,除了建筑对所有精灵的CPU上四条线$ P $天真的方式。您仍然可以使它们就像一个满点(并因此他们很可能来自你的基于GPU的粒子引擎的方式)缓冲器。要真正产生四几何图形的话,你可以用几何着色器,它可以让你从单个点四。首先你做的顶点着色器内只有模型视图转换:

But if this is a problem, then modern OpenGL offers many other ways to implement point sprites, apart from the naive way of pre-building all the sprites as individual quads on the CPU. You can still render them just as a buffer full of points (and thus in the way they are likely to come out of your GPU-based particle engine). To actually generate the quad geometry then, you can use the geometry shader, which lets you generate a quad from a single point. First you do only the modelview transformation inside the vertex shader:

uniform mat4 modelview;

layout(location = 0) in vec4 position;

void main()
{
    gl_Position = modelview * position;
}

然后,几何着色器做的工作休息。它结合了4个角落的通用[0,1] -quad点位置,并完成转换成裁剪空间:

Then the geometry shader does the rest of the work. It combines the point position with the 4 corners of a generic [0,1]-quad and completes the transformation into clip-space:

const vec2 corners[4] = { 
    vec2(0.0, 1.0), vec2(0.0, 0.0), vec2(1.0, 1.0), vec2(1.0, 0.0) };

layout(points) in;
layout(triangle_strip, max_vertices = 4) out;

uniform mat4 projection;
uniform float spriteSize;

out vec2 texCoord;

void main()
{
    for(int i=0; i<4; ++i)
    {
        vec4 eyePos = gl_in[0].gl_Position;           //start with point position
        eyePos.xy += spriteSize * (corners[i] - vec2(0.5)); //add corner position
        gl_Position = projection * eyePos;             //complete transformation
        texCoord = corners[i];                         //use corner as texCoord
        EmitVertex();
    }
}

在片段着色器,你会那么当然使用自定义的 texCoord ,而不是不同的 gl_PointCoord 为纹理,因为我们不再绘制实际点。

In the fragment shader you would then of course use the custom texCoord varying instead of gl_PointCoord for texturing, since we're no longer drawing actual points.

或者另一种可能性(也许更快,因为我记得有对正在缓慢的声誉几何着色器)是使用实例化的渲染。这样,您有一个包含顶点额外VBO的只是一个普通的二维四的(即[0,1] - 方),并只包含点位置的好老VBO。那么,什么你要做的就是画这个单四极杆多次(实例化),而从点VBO采购的单个实例的位置:

Or another possibility (and maybe faster, since I remember geometry shaders having a reputation for being slow) would be to use instanced rendering. This way you have an additional VBO containing the vertices of just a single generic 2D quad (i.e. the [0,1]-square) and your good old VBO containing just the point positions. What you then do is draw this single quad multiple times (instanced), while sourcing the individual instances' positions from the point VBO:

glVertexAttribPointer(0, ...points...);
glVertexAttribPointer(1, ...quad...);
glVertexAttribDivisor(0, 1);            //advance only once per instance
...
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);  //draw #count quads

和在顶点着色器,你再组装与实际转角/四位置的每个点的位置(这也是顶点的纹理坐标):

And in the vertex shader you then assemble the per-point position with the actual corner/quad-position (which is also the texture coordinate of that vertex):

uniform mat4 modelview;
uniform mat4 projection;
uniform float spriteSize;

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 corner;

out vec2 texCoord;

void main()
{
    vec4 eyePos = modelview * position;            //transform to eye-space
    eyePos.xy += spriteSize * (corner - vec2(0.5)); //add corner position
    gl_Position = projection * eyePos;             //complete transformation
    texCoord = corner;
}

此实现相同几何着色器为基础的方法,具有一致世界空间大小适当-裁剪点精灵。如果你真的想致力于模拟实际点精灵的屏幕空间像素大小,你需要把更多的计算工作到它。但是,这是留给作为一个练习,并会从点精灵着色世界到屏幕的转型相当oppisite。

This achieves the same as the geometry shader based approach, properly-clipped point sprites with a consistent world-space size. If you actually want to mimick the screen-space pixel size of actual point sprites, you need to put some more computational effort into it. But this is left as an exercise and would be quite the oppisite of the world-to-screen transformation from the the point sprite shader.

这篇关于点精灵的粒子系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆