让我们从定义您要寻找的混合类型开始。听起来你想让你的缓冲器从白色开始,让你的颜色混合服从
subtractive color model
. 最简单的方法是定义混合的结果
C
刷
结束
C
DST
AS:
C
=
C
刷
γ
C
DST
注意,使用这个方程,混合黄色(1,1,0)和青色(0,1,1)的结果是绿色(0,1,0),这是您所期望的。
拥有一把边缘会褪色的刷子会使事情稍微复杂一些。假设您现在有一个画笔不透明度值
一
刷
在哪里
一
刷
是1,你希望你的画笔颜色充分混合,在哪里
一
刷
为0,您希望保留原始颜色。现在你要找的是:
C
=(
C
刷
γ
C
DST
)
一
刷
+
C
DST
(1)
一
刷
)
因为在OpenGL ES中混合计算结果
C
=
C
SRC
γ
S
+
C
DST
γ
D
如果我们进行以下替换,我们可以得到我们想要的:
C
SRC
=
C
刷
γ
一
刷
一
SRC
=
一
刷
S
=
C
DST
D
=(1)
一
刷
)
现在让我们来看看在OpenGLES中设置它需要什么。这里有4个步骤:
-
将背景色更改为白色。
-
将画笔纹理更改为alpha纹理。
默认情况下,glpaint使用在rgb通道中绘制的画笔形状将其画笔纹理创建为rgba纹理,这有点不直观。出于您稍后将看到的原因,将画笔形状改为alpha通道非常有用。最好的方法是用CG绘制画笔形状,并将纹理创建为
GL_ALPHA
而是:
CGColorSpaceRef brushColorSpace = CGColorSpaceCreateDeviceGray();
brushData = (GLubyte *) calloc(width * height, sizeof(GLubyte));
brushContext = CGBitmapContextCreate(brushData, width, width, 8, width, brushColorSpace, kCGImageAlphaNone);
CGColorSpaceRelease(brushColorSpace);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, brushData);
-
设置
C
SRC
,
一
SRC
,
S
和
D
.
切换到alpha纹理后,假设仍通过
glColor4f
,您将发现默认的OpenGL ES纹理环境将为您提供:
C
SRC
=
C
刷
一
SRC
=
一
刷
为了得到额外的乘法
一
刷
对于
C
SRC
,您需要在纹理环境中设置自定义组合器函数,如下所示(您可以在
PaintingView
):
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
改变
GL_TEXTURE_ENV_MODE
到
GL_COMBINE
给你
C
刷
_0(要了解为什么会出现这种情况,请阅读
OpenGL ES 1.1 specification
)改变
GL_OPERAND0_RGB
到
GL_SRC_ALPHA
把乘法中的第二项改成我们想要的。
设立
S
和
D
,您只需更改混合因子(可以在之前设置了混合因子的情况下进行此操作):
glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
-
确保对
一
刷
画笔纹理的外部在其他通道上反射。
对纹理环境的上述修改只考虑来自画笔纹理的画笔不透明度部分。如果在其他地方修改alpha通道中的画笔不透明度(即通过缩放它,如
AppController
)必须确保对其他三个通道进行相同的修改:
glColor4f(components[0] * kBrushOpacity, components[1] * kBrushOpacity, components[2] * kBrushOpacity, kBrushOpacity);
请注意,使用减色模型实现画笔的缺点是颜色只能变暗,如果颜色不是主要减色颜色(青色、洋红或黄色)之一,则反复在其自身上绘制相同的颜色最终会导致颜色偏移。如果在执行此操作后,发现颜色偏移是不可接受的,请尝试将画笔纹理更改为步骤2中的alpha纹理,并按以下方式更改混合因子:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
这将给你简单的绘画你的画笔颜色超过白色,但没有实际的颜色混合(画笔颜色最终会覆盖背景)。