在顶点颜色中使用 GL_MODULATE 和 alpha 时,GLKit 不显示纹理

GLKit does not display texture when using GL_MODULATE with alpha in vertex color

我有一张与 GLKit 一起使用的纹理图像。如果我在纹理上使用 GL_MODULATE 并具有顶点 RGBA (1.0, 1.0, 1.0, 1.0),那么纹理将完全显示为它在 GL_REPLACE 中的表现。完全不透明。 然后,如果我对顶点 RGB 使用红色 (1.0, 0.0, 0.0, 1.0),则纹理再次显示为红色调制纹理。 到目前为止,一切都很好。 但是,当我更改顶点颜色的透明度并使用 RGBA(1.0, 0.0, 0.0, 0.5) 时,只能看到浅红色并且看不到纹理,因此颜色将完全替换纹理。 纹理本身没有alpha,是RGB565纹理。
我将 GLKit 与 GLKTextureEnvModeModulate 结合使用。

self.effect.texture2d0.envMode = GLKTextureEnvModeModulate;

关于为什么在我指定 alpha 时纹理会消失的任何帮助?

添加快照:


这是原始纹理


RGBA (1.0, 1.0, 1.0, 1.0) - 白色,无预乘,不透明,纹理可见


RGBA (1.0, 1.0, 1.0, 0.5) - 白色,无预乘,alpha = 0.5,纹理丢失[​​=20=]


RGBA (1.0, 0, 0, 1.0) - 红色,无预乘,不透明,纹理可见


RGBA (1.0, 0, 0, 0.5) - 红色,无预乘,alpha = 0.5,纹理丢失[​​=20=]


RGBA (0.5, 0, 0, 0.5) - 红色,预乘,alpha = 0.5 每个@andon,纹理可见,但你可能需要放大才能看到它


RGBA (0.1, 0, 0, 0.1) - 红色,预乘,alpha = 0.1 每@andon,纹理丢失,可能是因为没有足够的对比度


RGBA (0.9, 0, 0, 0.9) - 红色,预乘,alpha = 0.9 每@andon,纹理可见,但你可能需要放大才能看到它

The texture itself has no alpha, it is RGB565 texture

RGB565 隐式具有常量 alpha(不透明 -> 1.0)。 这听起来可能不重要,但是用纹理颜色调制顶点颜色会进行分量乘法运算,如果 alpha 不是 1.0.[=42,那根本行不通=]

My blend function is for pre-multiplied - One, One - Src.

这需要用 A 分量预乘顶点颜色的 RGB 分量。 所有 颜色必须预乘,这包括纹素和顶点颜色。

您可以在下面看到原因:

Vtx = (1.0, 0.0, 0.0, 0.5)
Tex = (R,   G,   B,   1.0)

// Modulate Vertex and Tex
Src = Vtx * Tex = (R, 0, 0, 0.5)

// Pre-multiplied Alpha Blending (done incorrectly)
Blend_RGB = Src * 1    +  (1 - Src.a) * Dst
          = Src        +          Dst / 2.0
          = (R, 0, 0)  +          Dst / 2.0

唯一要做的就是将目标颜色除以 2,然后将未更改的源颜色添加到其中。 假设类似于线性插值(a * c + (1 - c) * b).

正确的混合应该是这样的:

// Traditional Blending
Blend_RGB = Src * Src.a   +  (1 - Src.a) * Dst
          = (0.5R, 0, 0)  +          Dst / 2.0

如果将顶点颜色的 RGB 部分乘以 A,则可以使用原始混合函数来完成此操作。

修正预乘alpha混合(通过预乘顶点颜色):

Vtx = (0.5, 0.0, 0.0, 0.5) // Pre-multiply: RGB *= A
Tex = (R,   G,   B,   1.0)

// Modulate Vertex and Tex
Src = Vtx * Tex = (0.5R, 0, 0, 0.5)

// Pre-multiplied Alpha Blending (done correctly)
Blend_RGB = Src * 1       +  (1 - Src.a) * Dst
          = (0.5R, 0, 0)  +          Dst / 2.0