我有像Source这样的图片:
我的目标是像结果一样显示它:
颜色必须是可变的。
是否可以使用glEnable/glBlendFunc/glBlendFuncSeparate/glBlendEquationSeparate
执行此操作?
或者我必须使用着色器(glsl)?这个着色器怎么样?
答案 0 :(得分:0)
要创建这样的绘图,我仍然建议您使用着色器,但如果没有,仍有很多方法可以绘制它,但它需要您至少进行2次绘制调用。
所以问我最好的方法是将所有这些绘图仅绘制到alpha通道。这意味着只有alpha会被绘制,而颜色将保持不变。为此,您需要先将alpha清除为零,这样当清除颜色缓冲区时,请确保将alpha分量设置为零glClearColor(0,0,0,0)
。在停止绘制之前,使用颜色蒙版仅启用alpha:glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE)
。现在使用glBlendFuncSeparate( GL_ZERO, GL_ONE, GL_ONE, GL_ONE)
绘制图像。这意味着忽略纹理的颜色(它的RGB部分)并使用之前缓冲区上的任何颜色,这意味着使用纹理中的alpha并将其加到缓冲区中已有的任何颜色上(最后一个值更有意义)是GL_ZERO
,但这会阻止重叠)。现在可以根据需要绘制尽可能多的纹理。您可能只有一个,但它应该适用于任何数量。
所以此时你的缓冲区到处都会有alpha零,但是你已经绘制了纹理并且纹理具有非零alpha。所以是时候绘制实际的颜色了。我们需要重新启用颜色蒙版以绘制颜色,以便glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
(alpha部分可以设置为false,但我们也可以重置那个)。现在绘制我们需要覆盖具有alpha的部分的实际颜色,让我们将混合设置为glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ZERO)
。这意味着我们将根据缓冲区上的当前alpha状态应用颜色。如果状态为1,那么将应用全颜色,如果alpha为0,则相同的颜色将保持不变,如果为0.5,它将先前在缓冲区上的颜色与新颜色混合,这意味着如果如果您有白色背景,可能需要将颜色清除为(1,1,1,0)
。然后,alpha将被覆盖到颜色中将设置为新alpha的任何内容。
现在要么重新绘制一个带有禁用纹理的全屏矩形,并将颜色设置为目标颜色应该是什么(紫罗兰色),你就完成了。或者,您只能在绘制图像的任何位置重绘矩形。
不够容易?怎么样:
glClearColor(violet.r, violet.g, violet.b, 0.0)
将alpha保持为零glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE)
glBlend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
注意:此最后一个步骤仅在您的视图/屏幕/画布启用了混合时才有效。如果没有,则在大多数情况下仅显示RGB部分,这将导致整个屏幕具有纯色。