【发布时间】:2014-05-03 20:12:45
【问题描述】:
主要问题:
1) 仅当目标颜色不透明时,如何让片段着色器不将当前像素更新为透明像素?
2) gl_LastFragColor 是否适用于 android 2.3 OpenGL ES 2.0?
背景:
我正在尝试使用批量纹理使用 OpenGL ES 2.0 编写文本。片段着色器中的挑战是仅在目标像素颜色的 alpha 为 1 时才更新文本的像素颜色,我知道这意味着像素不属于文本。
文本图集的纹理存储在一个位图中:Bitmap.Config.ALPHA_8
几个小时后,我发现了三个问题:
第一个问题:不知何故,alpha 1 被用作不透明而 0 被用作透明。
第二个问题:假设我显示“Hi”。虽然我的 draworder 应该通过纹理 H,然后是 i 来绘制“Hi”,但它的做法是:“i”,然后是“H”。
我知道这一点,因为如果我手动将“Hi”的顶点顺序反转为从“i”开始,那么我会得到我的文本。由于问题 3,这是一个问题。
第三个问题:我相信这是主要问题。假设字母 H 的纹理框的宽度正好为 0.5,但我使用宽度为 1 的纹理,其中第一个 0.25 是白色,alpha 1,下一个 0.5 是白色,alpha 0,最后一个 0.25 是白色,alpha 1。同样为“我”。
当“i”首先被纹理化,然后“H”被纹理化后,宽度将相交(故意,例如“DD”和“dd”具有不同的组合宽度)。但是在“i”之后渲染“H”之后,它会将其宽度上的所有像素更新为透明,并且大部分字母 o 消失了。如果先渲染“i”然后渲染“H”并且禁用混合,则这是正确的行为。
所以我尝试在更新之前使用 gl_LastFragColor 检查前一个像素,但我得到:未声明的标识符。所以我被这个片段代码卡住了:
片段代码:
vec4 myTexture;
myTexture = texture2D(u_Texture, v_TexCoordinate);
if( myTexture[3] < 0.01){ // The texture is Bitmap.Config.ALPHA_8. If alpha is 0 . . .
gl_FragColor = vec4(0.0,0.0,0.0,0.0); // 0.0 is somehow transparent.
}
else{
gl_FragColor = vec4(1.0,1.0,1.0,1.0); // display text in white. Somehow 1.0 is opaque.
gl_FragColor = myTexture;
}
我称draw为:
GLES20.glEnable (GLES20.GL_BLEND);
GLES20.glBlendFunc (GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
// GLES20.glBlendFunc (GLES20.GL_ONE_MINUS_SRC_ALPHA, GLES20.GL_SRC_ALPHA); This makes alpha of 1 transparent!!
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrderLength, GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glDisable (GLES20.GL_BLEND);
附:如果我将 alpha 从 1 切换到 0,或者等效的技巧,我会遇到同样的问题,透明度倒置。
【问题讨论】: