我希望可以不使用帧缓冲区或着色器,只需直接使用glBlendFunc或glBlendFuncSeparate。
我正在使用标准混合模式正常渲染场景:
glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
在那个场景的场景中,我想绘制一个被其他纹理遮盖的纹理。这些是在任意位置绘制的(不一定是矩形,不一定是彼此相同的大小/位置)。
订单是;渲染蒙面纹理,然后蒙版纹理。
蒙面纹理是带有alpha的常规图像。
掩码纹理为黑色RGBA(0,0,0,255)或透明RGBA(0,0,0,0)
我想要黑色不接触的任何东西,看不见。基本上,最终结果应该是:
RGBA(masked.r, masked.g, masked.b, masked.a * mask.a)
以下是订购图片,以解释我的意思。我真的在寻找一种解决方案,以避免使用不同的着色器或将东西粘在帧缓冲器上。如果绝对不可能,请告诉我。
答案 0 :(得分:1)
我将解释为什么这是不可能的。使用混合进行遮罩需要三次通过,因为它有三个部分:目标,源和遮罩。无论你做什么,你必须将源和掩码混合到帧缓冲区中,然后渲染到目的地。
然而,模板缓冲区内置于默认窗口帧缓冲区中,前提是您告诉OpenGL提供它(就像您将使用深度缓冲区),并且看起来完全符合您的要求。作为GLUT调用,在双缓冲窗口中,如下所示在窗口中初始化模板缓冲区以及启用alpha的颜色和深度缓冲区:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL);
模板缓冲区能够完全按照您的需要进行操作 - 您可以在其中绘制一个形状,并选择性地告诉它丢弃或保留该形状内的像素。这是一个如何使用它的例子,修改自OpenGL红皮书:
GLdouble dRadius = 0.1; // Initial radius of spiral
GLdouble dAngle; // Looping variable
// Use 0 for clear stencil, enable stencil test
glClearStencil(0);
glEnable(GL_STENCIL_TEST);
// Clear stencil buffer
glClear(GL_STENCIL_BUFFER_BIT);
// All drawing commands fail the stencil test, and are not
// drawn, but increment the value in the stencil buffer.
// glStencilFunc takes three arguments: the stencil function, the reference value, and the mask value. Whenever the stencil function is tested (for example GL_LESS), both the reference and the stencil value being tested from the buffer is bitwise ANDed with the mask: GL_LESS returns true if (ref & mask) < (stencil & mask).
glStencilFunc(GL_NEVER, 0x0, 0x0);
// glStencilOp takes three arguments: the stencil operation to call when the stencil test fails, the stencil operation to call when the stencil test passes but the depth test fails, and the stenciloperation to call when the stencil test passes AND the depth test passes (or depth test is disabled or no depth buffer is allocated).
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
// Spiral pattern will create stencil pattern
// Draw the spiral pattern with white lines. We
// make the lines white to demonstrate that the
// stencil function prevents them from being drawn
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
for(dAngle = 0; dAngle < 400.0; dAngle += 0.1)
{
glVertex2d(dRadius * cos(dAngle), dRadius * sin(dAngle));
dRadius *= 1.002;
}
glEnd();
// Now, allow drawing, except where the stencil pattern is 0x1
// and do not make any further changes to the stencil buffer
glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Now draw red square
glColor3f(0.0f, 1.0f, 0.0f);
glRectf(0, 0, 200, 200);
此绘图代码的输出为红色正方形,横跨它,从(1,1)开始。螺旋由废弃的像素组成,因此与清除的颜色缓冲区的颜色相同。如果您要将此代码用于您的目的,您将绘制正方形,您希望纹理位于编写螺旋代码的位置,然后使用GL_EQUAL作为模板函数,绘制蒙版纹理,绘制红色正方形。有关模板缓冲区的更多信息可以在here找到。