c++ - 为 Sprite 混合设置 alpha 上限

标签 c++ opengl glfw opengl-3

在现代 OpenGL 中,我正在绘制一系列相邻的 Sprite ,为每个 Sprite 使用带纹理的四边形(如笔触)。在不累积 alpha 值的情况下,我可以使用什么技术来绘制 Sprite ?

为了清楚起见,让我举个例子。

假设我的 Sprite 是一个半透明的圆圈,这样:
enter image description here

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

这很正常,但我想得到的是:
enter image description here

其中结果的 alpha 值是源和目标的 alpha 的最大值,就好像它们是同一可视层的一部分。

我想这涉及到我的 blend function . 目前是:

 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

我可以使用哪种混合函数或其他技术来获得所需的结果?

最佳答案

(Ab)使用模板缓冲区:

  1. 清除模板缓冲区为 0xff
  2. 对于每个圆圈,只写入(和混合)模板缓冲区为 0xff 的颜色和模板缓冲区。如果模板和深度测试成功,则将片段的模板值设置为零。

通过这种方式,您只能一次写入(和混合)一个颜色像素,直到您再次清除模板缓冲区。

示例:

#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;
}

关于c++ - 为 Sprite 混合设置 alpha 上限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31613675/

相关文章:

c++ - 如何使用函数对象作为回调来调用对象中的成员函数(处理程序)?

c++ - MOVAPS 访问未对齐的地址

c++ - 动态分配数据类型 C++

c++ - 如何共享 OpenGL 上下文或数据?

c++ - glTexImage2D 在 OpenGL 3 及更高版本的 GLUT/FreeType 示例中失败

java - 使用 glfw 删除最小化和最大化按钮

c++ - GLFW 错误 - GLFWwindow* 未被识别为有效参数

c++ - "error: sizeof ' x' 的原因在 C++ 中未知或为零?

c++ - 为什么我不能在 for 循环的第一条语句中包含 2 个变量

java - 为什么深度测试在选色离屏渲染中不起作用?