【问题标题】:Using alpha from texture to draw solid color使用纹理中的 alpha 绘制纯色
【发布时间】:2010-11-14 01:39:20
【问题描述】:

如何使用 OpenGLES 1.1 (iPhone) 绘制纹理,但只使用 alpha 绘制一些颜色?

结果应该是与原始纹理完全相同的 alpha 蒙版,内部使用单一纯色而不是原始颜色。

我将glDrawArraysglCoordPointerglVertexPointer 一起使用。

我认为要进行两次传递,一次使用纹理,另一次使用纯色。我似乎找不到 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); 的反转。

编辑:经过一番环顾后,我认为这应该可以使用glTexEnvf 来实现。这只是找到正确论点的问题。

【问题讨论】:

  • 我希望那是与 python 相关的,我现在会有无数的答案。

标签: iphone opengl-es cocos2d-iphone


【解决方案1】:

如前所述,glTexEnv 是要走的路。

要替换纹理的 RGB 组件并保持其 alpha 不变,您可以尝试这样的操作(此代码使用红色作为替换颜色):

glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );

glActiveTexture( GL_TEXTURE_0 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, spriteTexture);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);

// ... draw as usual

这里有一些解释。

使用 GL_COMBINE 时,您可以完全控制不同纹理阶段的输入/输出如何组合在一起。在这种情况下,我们指定我们想用来自前一阶段 (GL_PREVIOUS) 的纹理替换 (GL_REPLACE) 纹理阶段 0 的 RGB 组件,在这种情况下是单一颜色(使用 glColor4f 设置)。

我们没有为 alpha 组件设置任何特殊的东西,因为我们想要常规行为。 添加以下行会产生与不包含相同的效果(默认行为):

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);   
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);

【讨论】:

  • 感谢您提供的信息丰富的答案!我必须将GL_TEXTURE_0 更改为GL_TEXTURE0 以使其编译,并在绘图后添加glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 以使其余的渲染工作。现在形状已正确绘制,但始终使用白色作为颜色。可能与我所做的更改有关?
  • 我认为您的更改不是问题的原因,是的,您必须添加 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);绘制后返回默认纹理模式。我不清楚您为什么会得到白色结果...您是否按照示例中的说明正确添加了 glColor4f()?
  • 是的,glColor4f 的调用位置与您的代码示例完全相同。
  • 嗯...您可能想通过调用 glActiveTexture( GL_TEXTURE1 ); 来检查纹理单元 1 是否被正确禁用; glDisable(GL_TEXTURE_2D);还要检查您是否启用了混合,并且混合功能设置如下:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  • 谢谢!如果您找到得到白色结果的原因,请告诉我们……我真的很好奇。
【解决方案2】:

如果您可以使用 OpenGL ES 2.0,您可以使用自定义片段着色器来完成此操作。如果您使用的是基于 1.1 构建的框架或针对不支持 2.0 的设备,这将没有多大帮助。但如果可以的话,你可以这样做:

uniform lowp sampler2D sampler; // which texture unit to use
uniform lowp vec4 solidColor;

varying highp vec2 fragmentTexCoord;

void main()
{
    // Get the color with an alpha of zero
    vec4 color = vec4(1,1,1,0) * solidColor;
    // Get the alpha from the texture, zero the r,g,b components
    vec4 alpha = vec4(0,0,0,1) * texture2D(sampler, fragmentTexCoord);
    // their sum is the solid color with the alpha mask of the texture
    gl_FragColor = color + alpha;
}

如果您可以确保 solidColor 的 alpha 为零,则可以跳过乘法步骤。

【讨论】:

  • 感谢您的建议。我不太确定是否可以使用着色器。没有办法使用 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); 的倒数吗?这样做?
  • 这个答案说 OpenGLES 1.1 不支持自定义着色器:stackoverflow.com/questions/543948/opengl-es-1-x-shaders/….
  • 对不起,我会编辑答案,即使它对你没有用,可能值得保留给其他人搜索。
【解决方案3】:

glBlendFunc(source_factor, dest_factor) 转换为:

dest= source*source_factor + dest*dest_factor

所以glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA) 是:

dest= source*0 + dest*(1 - source.alpha)

第二遍(不是相反的)应该是glBlendFunc(GL_SRC_ALPHA, GL_ONE)

dest= source*source.alpha + dest

因为您已经在第一遍中应用了 Alpha 蒙版。尽管您仍然需要弄清楚如何使用 alpha 而不是源纹理应用恒定颜色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    相关资源
    最近更新 更多