如何在其他对象中以 3D space 渲染点精灵
How to render point sprites in 3D space among other objects
渲染混合点精灵和 3D 对象的最佳方式是什么?
例如,我想将 "space dust" 粒子建模为点精灵。在 space 我可以有大的小行星物体(为简单起见立方体)并且 space 尘埃颗粒可以在小行星立方体的前面或后面。
我遇到了两种情况:
- 我先渲染 space 尘点精灵,使用
gl_DepthMask(GL_TRUE)
然后渲染小行星立方体(space 灰尘总是 在 后面小行星)
- 我先渲染小行星立方体,使用
gl_DepthMask(GL_FALSE)
,渲染space尘点精灵并设置gl_DepthMask(GL_TRUE)
(space尘总是出现在小行星前面)
我目前正在使用单个粒子发射器顶点着色器,它在随机 (x,y,z) 位置绘制具有 gl_DrawArrays()
的粒子负载。
如何渲染大量粒子,使它们同时出现在小行星立方体的前后?
如果我的粒子是单个四边形,那么我可以对 Z 渲染的顺序进行排序,但我不知道如何使用 gl_DrawArrays()
、GL_POINT
s 和我的顶点着色器实现此行为。
我是否应该将粒子拆分成数组集 - 例如,我是否必须这样做:
- 绘制所有小行星后面的粒子阵列
- 画最远的小行星
- 绘制另一个粒子阵列,这些粒子出现在上面的小行星前面但在下一个最近的小行星后面
- 绘制最前面的小行星
如果我有很多小行星,这不是非常低效吗?
OpenGL 肯定有比我上面建议的更好的方法来实现这个目标吗?
更新:尝试 Thomas 的建议:
我的立方体和粒子是通过以下 blend/depth 调用渲染的:
// First render opaque object(s)
glEnable( GL_DEPTH_TEST );
glDepthMask( true );
g_ObjCube1.Render();
// Now render sprites with particle emitter - sprites should appear
// behind and in front of above cube
glEnable( GL_POINT_SPRITE );
// Stop overlapping particles from interfering with each other
//glDisable( GL_DEPTH_TEST ); <- NO! Must leave depth test enabled
glDepthMask( false );
glEnable( GL_BLEND );
//glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glBlendFunc( GL_SRC_ALPHA, GL_ONE ); // Doing the same as above
glBlendEquation( GL_FUNC_ADD );
...
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
...
glDepthMask( true );
我假设你的粒子有一定的透明度,否则不会有问题。
然后答案与所有透明对象相同。首先首先渲染不透明物体(小行星)(使用深度缓冲,以任何顺序)。然后按从后到前的顺序渲染所有透明对象。此排序将(据我所知)需要在 CPU.
上完成
或者,根据您的目标效果,您可以对粒子使用附加混合 (glBlendFunc(GL_SRC_ALPHA, GL_ONE)
)。然后渲染顺序无关紧要,因为加法是可交换的。请务必为此禁用深度写入。
作为另一种选择,使用 alpha 测试 (true/false) 而不是 alpha 混合可以让您以任何顺序渲染粒子。在这种情况下,完全透明的像素不会写入深度缓冲区。但是,使用此技术时,不能有部分透明区域。
This article 是一个很好的参考。
渲染混合点精灵和 3D 对象的最佳方式是什么?
例如,我想将 "space dust" 粒子建模为点精灵。在 space 我可以有大的小行星物体(为简单起见立方体)并且 space 尘埃颗粒可以在小行星立方体的前面或后面。
我遇到了两种情况:
- 我先渲染 space 尘点精灵,使用
gl_DepthMask(GL_TRUE)
然后渲染小行星立方体(space 灰尘总是 在 后面小行星) - 我先渲染小行星立方体,使用
gl_DepthMask(GL_FALSE)
,渲染space尘点精灵并设置gl_DepthMask(GL_TRUE)
(space尘总是出现在小行星前面)
我目前正在使用单个粒子发射器顶点着色器,它在随机 (x,y,z) 位置绘制具有 gl_DrawArrays()
的粒子负载。
如何渲染大量粒子,使它们同时出现在小行星立方体的前后?
如果我的粒子是单个四边形,那么我可以对 Z 渲染的顺序进行排序,但我不知道如何使用 gl_DrawArrays()
、GL_POINT
s 和我的顶点着色器实现此行为。
我是否应该将粒子拆分成数组集 - 例如,我是否必须这样做:
- 绘制所有小行星后面的粒子阵列
- 画最远的小行星
- 绘制另一个粒子阵列,这些粒子出现在上面的小行星前面但在下一个最近的小行星后面
- 绘制最前面的小行星
如果我有很多小行星,这不是非常低效吗?
OpenGL 肯定有比我上面建议的更好的方法来实现这个目标吗?
更新:尝试 Thomas 的建议:
我的立方体和粒子是通过以下 blend/depth 调用渲染的:
// First render opaque object(s)
glEnable( GL_DEPTH_TEST );
glDepthMask( true );
g_ObjCube1.Render();
// Now render sprites with particle emitter - sprites should appear
// behind and in front of above cube
glEnable( GL_POINT_SPRITE );
// Stop overlapping particles from interfering with each other
//glDisable( GL_DEPTH_TEST ); <- NO! Must leave depth test enabled
glDepthMask( false );
glEnable( GL_BLEND );
//glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glBlendFunc( GL_SRC_ALPHA, GL_ONE ); // Doing the same as above
glBlendEquation( GL_FUNC_ADD );
...
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
...
glDepthMask( true );
我假设你的粒子有一定的透明度,否则不会有问题。
然后答案与所有透明对象相同。首先首先渲染不透明物体(小行星)(使用深度缓冲,以任何顺序)。然后按从后到前的顺序渲染所有透明对象。此排序将(据我所知)需要在 CPU.
上完成或者,根据您的目标效果,您可以对粒子使用附加混合 (glBlendFunc(GL_SRC_ALPHA, GL_ONE)
)。然后渲染顺序无关紧要,因为加法是可交换的。请务必为此禁用深度写入。
作为另一种选择,使用 alpha 测试 (true/false) 而不是 alpha 混合可以让您以任何顺序渲染粒子。在这种情况下,完全透明的像素不会写入深度缓冲区。但是,使用此技术时,不能有部分透明区域。
This article 是一个很好的参考。