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

时间:2018-04-13 08:18:43

标签: opengl fragment-shader vertex-shader glm-math geometry-shader

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

比方说,我想建模"太空尘埃"粒子作为点精灵。在太空中,我可能有大型小行星物体(简单的立方体),空间尘埃粒子可能位于小行星立方体的前面或后面。

我遇到了两种情况:

  1. 我首先渲染空间尘点精灵,使用gl_DepthMask(GL_TRUE)然后渲染小行星立方体(太空尘埃总是小行星后面)
  2. 我首先渲染小行星立方体,使用gl_DepthMask(GL_FALSE),渲染空间尘点精灵并设置gl_DepthMask(GL_TRUE)(空间尘埃总是出现在小行星前面)
  3. 我目前正在使用单个粒子发射器顶点着色器,它在随机(x,y,z)位置绘制带有gl_DrawArrays()的粒子负载。

    如何渲染一堆粒子,使它们出现在小行星立方体的前面和后面?

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

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

    1. 绘制一系列位于所有小行星后面的粒子
    2. 画得最小的小行星
    3. 画出另一个出现在上述小行星前面的粒子阵列,但是在下一个最近的小行星后面
    4. 画出最前面的小行星
    5. 如果我有很多小行星,这不是非常低效吗?

      当然,OpenGL有一种更好的方法来达到这个目的吗?

      更新:尝试托马斯'建议:

      我的立方体和粒子使用以下混合/深度调用进行渲染:

        // 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 );
      

1 个答案:

答案 0 :(得分:1)

我假设你的粒子有一定的透明度,否则不会有问题。

然后答案与所有​​透明对象的答案相同。首先渲染不透明物体(小行星)(使用深度缓冲,以任何顺序)。然后按照从前到后的顺序渲染所有透明对象。这个排序(据我所知)需要在CPU上完成。

或者,根据您的目标效果,您可以对粒子使用添加剂混合(glBlendFunc(GL_SRC_ALPHA, GL_ONE))。然后渲染顺序无关紧要,因为加法是可交换的。请务必禁用此深度书写。

作为另一种选择,使用alpha测试(true / false)而不是alpha混合可以让你以任何顺序渲染粒子。在这种情况下,完全透明的像素不会写入深度缓冲区。使用此技术时,您不能拥有部分透明的区域。

This article是一个很好的参考。