Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用粒子和更深的对象处理OpenGL加法混合和深度测试_C++_C_Opengl_Shader_Particle System - Fatal编程技术网

C++ 如何使用粒子和更深的对象处理OpenGL加法混合和深度测试

C++ 如何使用粒子和更深的对象处理OpenGL加法混合和深度测试,c++,c,opengl,shader,particle-system,C++,C,Opengl,Shader,Particle System,我有一个用OpenGL和glut制作的小精灵粒子系统,使用纹理绘制基本火焰。火焰对称地再现,以说明它在小盒子/场景中的行为。如下图所示,存在两个问题: 1-为了产生一个看起来不错的火焰效果,我想使用添加剂混合我的粒子,但混合也考虑到更深的青色面板的颜色,并产生白色火焰 2.1-此外,为了实现添加剂混合的正确实施,我必须在绘制颗粒时禁用深度测试,但这样做可以绘制颗粒,即使它们应该“隐藏” 2.2-如果我在绘制粒子时启用深度测试,下面是它的外观 如果有帮助的话,下面是我应用到粒子上的纹理 vo

我有一个用OpenGL和glut制作的小精灵粒子系统,使用纹理绘制基本火焰。火焰对称地再现,以说明它在小盒子/场景中的行为。如下图所示,存在两个问题:

1-为了产生一个看起来不错的火焰效果,我想使用添加剂混合我的粒子,但混合也考虑到更深的青色面板的颜色,并产生白色火焰

2.1-此外,为了实现添加剂混合的正确实施,我必须在绘制颗粒时禁用深度测试,但这样做可以绘制颗粒,即使它们应该“隐藏”

2.2-如果我在绘制粒子时启用深度测试,下面是它的外观

如果有帮助的话,下面是我应用到粒子上的纹理

void drawParticles()
{
   glPushAttrib(GL_ALL_ATTRIB_BITS);
   glDisable(GL_LIGHTING);
   glDisable(GL_DEPTH_TEST);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA,GL_ONE);
   glBindTexture(GL_TEXTURE_2D,explosionTexture[0]);
   glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);

   for (int i = 0; i < particlesNumber; ++i) 
   {
    glPointSize(50.0f);
        glBegin(GL_POINTS);
            glColor4f(particlesArray[i].color[0],particlesArray[i].color[1],particlesArray[i].color[2],0.5f);
            glVertex3f(particlesArray[i].position[0],particlesArray[i].position[1],particlesArray[i].position[2]);
       glEnd();
   }
   glBindTexture(GL_TEXTURE_2D, 0);
   glDisable( GL_BLEND );
   glEnable( GL_DEPTH_TEST );
   glPopAttrib();
}

void drawScene()
{
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
   gluPerspective( 60.0f, (GLdouble) g_width / (GLdouble) g_height, 0.1f, 300.0f );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();

   gluLookAt( dist*sin(phi)*sin(theta), dist*cos(phi), dist*sin(phi)*cos(theta), 0, 0, 0, 0, 1, 0 );

   glEnable( GL_DEPTH_TEST );
   glDisable( GL_BLEND );

   glBegin( GL_LINES );

      glColor3f( 1.0f, 0.0f, 0.0f );
      glVertex3f( 0.0f, 0.0f, 0.0f );
      glVertex3f( 0.5f, 0.0f, 0.0f );

      glColor3f( 0.0f, 1.0f, 0.0f );
      glVertex3f( 0.0f, 0.0f, 0.0f );
      glVertex3f( 0.0f, 0.5f, 0.0f );

      glColor3f( 0.0f, 0.0f, 1.0f );
      glVertex3f( 0.0f, 0.0f, 0.0f );
      glVertex3f( 0.0f, 0.0f, 0.5f );

   glEnd();

   glBegin( GL_QUADS );

      glColor4f( 1.0f, 1.0f, 1.0f , 0.0f);
      glVertex3f( -1.0f,  -0.2f,  1.0f );
      glVertex3f(  1.0f,  -0.2f,  1.0f );
      glVertex3f(  1.0f,  -0.2f, -1.0f );
      glVertex3f( -1.0f,  -0.2f, -1.0f );

      glColor4f( 1.0f, 1.0f, 0.0f , 0.0f );
      glVertex3f(  1.0f, -2.0f,  1.0f );
      glVertex3f(  1.0f, -2.0f, -1.0f );
      glVertex3f(  1.0f, -0.2f, -1.0f );
      glVertex3f(  1.0f, -0.2f,  1.0f );

      glColor4f( 1.0f, 0.0f, 1.0f , 0.0f );
      glVertex3f( -1.0f, -2.0f,  1.0f );
      glVertex3f( -1.0f, -2.0f, -1.0f );
      glVertex3f( -1.0f, -0.2f, -1.0f );
      glVertex3f( -1.0f, -0.2f,  1.0f );

      glColor4f( 0.0f, 1.0f, 1.0f , 1.0f );
      glVertex3f(  1.0f, -2.0f, -1.0f );
      glVertex3f( -1.0f, -2.0f, -1.0f );
      glVertex3f( -1.0f, -0.2f, -1.0f );
      glVertex3f(  1.0f, -0.2f, -1.0f );

   glEnd();

   glPushMatrix();
      drawParticles();
      glScalef(1.0f, -1.0f, 1.0f);
      drawParticles();
   glPopMatrix();


   glutSwapBuffers();
}

以下是显示场景和粒子的相关代码

void drawParticles()
{
   glPushAttrib(GL_ALL_ATTRIB_BITS);
   glDisable(GL_LIGHTING);
   glDisable(GL_DEPTH_TEST);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA,GL_ONE);
   glBindTexture(GL_TEXTURE_2D,explosionTexture[0]);
   glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);

   for (int i = 0; i < particlesNumber; ++i) 
   {
    glPointSize(50.0f);
        glBegin(GL_POINTS);
            glColor4f(particlesArray[i].color[0],particlesArray[i].color[1],particlesArray[i].color[2],0.5f);
            glVertex3f(particlesArray[i].position[0],particlesArray[i].position[1],particlesArray[i].position[2]);
       glEnd();
   }
   glBindTexture(GL_TEXTURE_2D, 0);
   glDisable( GL_BLEND );
   glEnable( GL_DEPTH_TEST );
   glPopAttrib();
}

void drawScene()
{
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
   gluPerspective( 60.0f, (GLdouble) g_width / (GLdouble) g_height, 0.1f, 300.0f );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();

   gluLookAt( dist*sin(phi)*sin(theta), dist*cos(phi), dist*sin(phi)*cos(theta), 0, 0, 0, 0, 1, 0 );

   glEnable( GL_DEPTH_TEST );
   glDisable( GL_BLEND );

   glBegin( GL_LINES );

      glColor3f( 1.0f, 0.0f, 0.0f );
      glVertex3f( 0.0f, 0.0f, 0.0f );
      glVertex3f( 0.5f, 0.0f, 0.0f );

      glColor3f( 0.0f, 1.0f, 0.0f );
      glVertex3f( 0.0f, 0.0f, 0.0f );
      glVertex3f( 0.0f, 0.5f, 0.0f );

      glColor3f( 0.0f, 0.0f, 1.0f );
      glVertex3f( 0.0f, 0.0f, 0.0f );
      glVertex3f( 0.0f, 0.0f, 0.5f );

   glEnd();

   glBegin( GL_QUADS );

      glColor4f( 1.0f, 1.0f, 1.0f , 0.0f);
      glVertex3f( -1.0f,  -0.2f,  1.0f );
      glVertex3f(  1.0f,  -0.2f,  1.0f );
      glVertex3f(  1.0f,  -0.2f, -1.0f );
      glVertex3f( -1.0f,  -0.2f, -1.0f );

      glColor4f( 1.0f, 1.0f, 0.0f , 0.0f );
      glVertex3f(  1.0f, -2.0f,  1.0f );
      glVertex3f(  1.0f, -2.0f, -1.0f );
      glVertex3f(  1.0f, -0.2f, -1.0f );
      glVertex3f(  1.0f, -0.2f,  1.0f );

      glColor4f( 1.0f, 0.0f, 1.0f , 0.0f );
      glVertex3f( -1.0f, -2.0f,  1.0f );
      glVertex3f( -1.0f, -2.0f, -1.0f );
      glVertex3f( -1.0f, -0.2f, -1.0f );
      glVertex3f( -1.0f, -0.2f,  1.0f );

      glColor4f( 0.0f, 1.0f, 1.0f , 1.0f );
      glVertex3f(  1.0f, -2.0f, -1.0f );
      glVertex3f( -1.0f, -2.0f, -1.0f );
      glVertex3f( -1.0f, -0.2f, -1.0f );
      glVertex3f(  1.0f, -0.2f, -1.0f );

   glEnd();

   glPushMatrix();
      drawParticles();
      glScalef(1.0f, -1.0f, 1.0f);
      drawParticles();
   glPopMatrix();


   glutSwapBuffers();
}
void drawParticles()
{
glPushAttrib(GLU所有属性位);
glDisable(GLU照明);
glDisable(GLU深度测试);
glEnable(GL_纹理_2D);
glEnable(GL_混合物);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glBindTexture(GL_TEXTURE_2D,explosionTexture[0]);
glTexEnvi(GL_POINT_SPRITE,GL_COORD_REPLACE,GL_TRUE);
for(int i=0;i
我愿意接受任何类型的建议,甚至包括着色器(但我想知道是否可以只使用普通OpenGL)

更新

也许我不清楚,我不一定对严格固定的管道解决方案感兴趣,我想知道如何在场景中管理加法混合,即使这意味着将着色器代码添加到我的项目中

现在,正如Columbo指出的,启用深度测试和禁用深度写入解决了我的第二个问题。现在关于添加剂混合问题,我仍然不知道如何在场景中管理添加剂混合。尽管场景中可能没有这样的基本颜色,但问题仍然存在,因为火焰仍然是白色的,我愿意知道如何使用建议的像素着色器

  • 对于添加剂混合问题,这可能不是问题。在真实场景中,你永远不会有一块青色。然而,如果你真的需要一个解决方案,你可以尝试一个预乘alpha混合(glBlendFunc(GL_ONE,GL_ONE_减去SRC_alpha),然后你就有了更多的控制。在像素着色器中,可以手动将输出RGB乘以源alpha,然后选择输出alpha。输出alpha为零会产生一种与当前相同的加法混合。输出完整的alpha值(顶点alpha*纹理alpha)将提供标准的调制alpha混合。你可能会在这两个极端之间找到一些值,它会使背景变暗,使你的火焰在青色背景下看起来也是黄色的,而不会让它看起来像垃圾。如果你不使用像素着色器,我相信在加载纹理的过程中,通过操纵你的纹理,使用固定的函数管道是可能的。这一切都相当微妙,我认为这不值得去做,因为在一个完成的、明亮的场景中,你不会有这样的原色。更正确的解决方案是使用HDR和色调映射,但这涉及到一些相当先进的渲染技术

  • 解决深度问题很简单。您需要为flame启用深度测试,但禁用深度写入。glEnable(GL_DEPTH_TEST)和glDepthMask(GL_FALSE)是相关命令

  • “仅使用普通OpenGL”:OpenGL 2.1+编写着色器是普通OpenGL。@CoffeeandCode I