【问题标题】:OpenGL 2D: glColor4 has no effect - what have I missed?OpenGL 2D:glColor4 没有效果 - 我错过了什么?
【发布时间】:2026-01-28 21:50:01
【问题描述】:

我正在将游戏从 WP7 XNA 移植到 Android;使用 Canvas 一切正常,但速度太慢,所以我按照 Replica Island 和 SpriteMethodTest 的示例切换到 OpenGL ES。

我的问题是,当我在绘制纹理之前立即设置 glColor 时,我的纹理没有被着色或透明 - 它被完全忽略并且纹理在加载状态下被绘制。纹理本身固有的所有颜色和透明度信息都已正确应用。我还使用 setPixels 以编程方式生成了一些位图,在那里我遇到了完全相同的问题。

我仍处于“OpenGL 只是魔法”的理解阶段 :-( 这使得遵循现有文档,这似乎是针对中级或高级编码人员,相当令人沮丧。我希望从这些样本中复制/粘贴会起作用,但我一定错过了一些东西,我无法弄清楚它是什么。我已经到了代码盲区,无法分辨它们之间的区别代码和我的。

glColor4 显然适用于 Replica Island,当我在同一个模拟器中运行它时,所有文本都会在不透明度发生变化时淡入淡出,就像它应该的那样。但它在我的代码中不起作用:-(

这是我的 GL 初始化代码:

surfaceCreated:

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
    gl.glShadeModel(GL10.GL_FLAT);
    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glEnable(GL10.GL_TEXTURE_2D);
    // gl.glDisable(GL10.GL_DITHER);
    // gl.glDisable(GL10.GL_LIGHTING);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

sizeChanged:

    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrthof(0.0f, width, 0.0f, height, 0.0f, 1.0f);
    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glShadeModel(GL10.GL_FLAT);
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    gl.glEnable(GL10.GL_TEXTURE_2D);

我注释掉了禁用抖动和照明,以防万一……但不是。没有区别。

位图是从资源中加载的:

    gl.glGenTextures(1, mTextureNameWorkspace, 0);
    textureName = mTextureNameWorkspace[0];
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
    gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, srcBitmap, 0);

最后是我的绘制代码:

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    ((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop(src), 0);
    gl.glColor4f(tint.R(), tint.G(), tint.B(), tint.A());
    ((GL11Ext) gl).glDrawTexfOES(dst.left, screenHeight - dst.bottom, 0.0f, dst.width(), dst.height());

色调成员的范围应该是 0.0..1.0。如果我设置了无效的纹理:

    gl.glBindTexture(GL10.GL_TEXTURE_2D, -1);

...然后 OpenGL 会在正确的位置绘制具有正确阴影和不透明度的矩形。

我一定已经尝试了 glBlendFunc 可能参数的所有组合 - 其中一些会部分影响透明度,但它们都不能正常工作,而且它们都不会导致 glColor 色调产生任何影响。

我要做的只是相当于:

    PorterDuff.Mode mode = PorterDuff.Mode.MULTIPLY;
    if (tint.A() < 1.0f && tint.R() == 1.0 && tint.G() == 1.0
            && tint.B() == 1.0)
        mode = PorterDuff.Mode.DST_IN;
    Paint paint = new Paint();
    PorterDuffColorFilter cf = new PorterDuffColorFilter(tint, mode);
    paint.setColorFilter(cf);
    canvas.drawBitmap(texture.bitmap, srcRect, dstRect, Paint(tint));

【问题讨论】:

    标签: android opengl-es transparency textures opengl-es-2.0


    【解决方案1】:

    不要使用GL_REPLACE,而是将glTexEnvf() 函数的第三个参数更改为GL_MODULATE

    从今天开始,我会参考我的earlier answer

    【讨论】:

    • 非常感谢。我知道它必须是非常简单的东西,但我只是不知道从哪里开始寻找。这似乎工作得很好。现在你已经指出了,我什至可以在 Replica Island 源代码中看到他们已经做出了确切的更改。我只是忙着查看渲染时代码,没想到要对纹理加载代码进行三次检查。
    最近更新 更多