用于精灵混合的封顶alpha

时间:2015-07-24 14:53:53

标签: c++ opengl glfw opengl-3

在现代OpenGL中,我使用每个精灵的纹理四边形绘制一系列相邻的精灵(如画笔笔划)。我可以使用什么技术绘制精灵而不会累积alpha值?

要说清楚,让我举个例子。

假设我的精灵是一个半透明的圆圈,如下:
enter image description here

如果我绘制两个相邻的精灵,我会得到这个:
enter image description here

这是非常正常的,虽然我想得到的是这个:
enter image description here

其中结果的alpha值是source和dest的alpha的最大值,就好像它们是同一视觉图层的一部分一样。

我认为这涉及我的blend function。 目前它是:

 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

我可以使用哪种混合功能或其他技术来达到预期效果?

2 个答案:

答案 0 :(得分:2)

(Ab)使用模板缓冲区:

  1. 将模板缓冲区清除为0xff
  2. Foreach圈,只能写入(和混合)颜色和&模板缓冲区,其中模板缓冲区为0xff。如果模板&深度测试成功将片段的模板值设置为零。
  3. 这样,您只能在中写入(并混合)一个彩色像素,直到再次清除模板缓冲区为止。

    示例:

    #include <GL/glut.h>
    
    void quad()
    {
        glBegin( GL_QUADS );
        glVertex2i( -1, -1 );
        glVertex2i(  1, -1 );
        glVertex2i(  1,  1 );
        glVertex2i( -1,  1 );
        glEnd();
    }
    
    void display()
    {
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glOrtho( -2, 2, -2, 2, -1, 1 );
    
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
    
        // clear stencil buffer to all 1s
        glClearStencil( 0xff );
        glClear( GL_STENCIL_BUFFER_BIT );
    
        // turn on stencil testing & make sure we don't mask out any bits
        glEnable( GL_STENCIL_TEST );
        glStencilMask( 0xff );
    
        // only allow fragments through to the color/depth buffers if
        // the stencil buffer at that point is 0xff
        glStencilFunc( GL_EQUAL, 0xff, 0xff );
    
        // if the stencil/depth tests succeed for a fragment, 
        // zero out the stencil buffer at that point;
        // that way you can only write to a color buffer pixel once
        glStencilOp( GL_KEEP, GL_KEEP, GL_ZERO );
    
        glEnable( GL_BLEND );
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        glPushMatrix();
        glTranslatef( -0.5, -0.5, 0 );
        glColor4ub( 255, 0, 0, 128 );
        quad();
        glPopMatrix();
    
        glPushMatrix();
        glTranslatef( 0.5, 0.5, 0 );
        glColor4ub( 255, 0, 0, 128 );
        quad();
        glPopMatrix();
    
        glutSwapBuffers();
    }
    
    int main( int argc, char **argv )
    {
        glutInit( &argc, argv );
        glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_STENCIL );
        glutInitWindowSize( 600, 600 );
        glutCreateWindow( "GLUT" );
        glutDisplayFunc( display );
        glutMainLoop();
        return 0;
    }
    

答案 1 :(得分:1)

这就是我最终要做的事情。很难称之为答案,因为我已经改变了问题的参数,但我想我会为后人提及它。

我使用完全不透明的精灵,而不是使用透明的精灵。

然后我将这些渲染到纹理,然后使用所需的不透明度绘制该纹理。