如何在其他对象中以 3D space 渲染点精灵

How to render point sprites in 3D space among other objects

渲染混合点精灵和 3D 对象的最佳方式是什么?

例如,我想将 "space dust" 粒子建模为点精灵。在 space 我可以有大的小行星物体(为简单起见立方体)并且 space 尘埃颗粒可以在小行星立方体的前面或后面。

我遇到了两种情况:

  1. 我先渲染 space 尘点精灵,使用 gl_DepthMask(GL_TRUE) 然后渲染小行星立方体(space 灰尘总是 后面小行星)
  2. 我先渲染小行星立方体,使用gl_DepthMask(GL_FALSE),渲染space尘点精灵并设置gl_DepthMask(GL_TRUE)(space尘总是出现在小行星前面)

我目前正在使用单个粒子发射器顶点着色器,它在随机 (x,y,z) 位置绘制具有 gl_DrawArrays() 的粒子负载。

如何渲染大量粒子,使它们同时出现在小行星立方体的前后?

如果我的粒子是单个四边形,那么我可以对 Z 渲染的顺序进行排序,但我不知道如何使用 gl_DrawArrays()GL_POINTs 和我的顶点着色器实现此行为。

我是否应该将粒子拆分成数组集 - 例如,我是否必须这样做:

  1. 绘制所有小行星后面的粒子阵列
  2. 画最远的小行星
  3. 绘制另一个粒子阵列,这些粒子出现在上面的小行星前面但在下一个最近的小行星后面
  4. 绘制最前面的小行星

如果我有很多小行星,这不是非常低效吗?

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 是一个很好的参考。