2010-11-14 142 views
8

如何使用OpenGLES 1.1(iPhone)绘制纹理,但仅使用Alpha绘制某种颜色?从纹理使用alpha绘制纯色

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

我使用glDrawArraysglCoordPointerglVertexPointer

我认为要做两遍,一次是纹理,另一次是纯色。我似乎无法找到glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);的反转。

编辑:经过一些更多的环顾四周,我认为这应该有可能实现使用glTexEnvf。这只是找到正确的论点。

+0

我想这是蟒蛇的关系,我现在有一个极大的答案。 – sharvey 2010-11-14 22:59:00

回答

8

正如所提到的,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); 
+0

感谢您提供真正丰富的答案!我必须将'GL_TEXTURE_0'改为'GL_TEXTURE0'来编译,并在绘图之后添加'glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);'以完成其余的绘制工作。现在形状被正确绘制,但总是使用白色作为颜色。可能与我所做的改变有关? – sharvey 2010-12-04 20:02:43

+0

我不认为你的改变是你的问题的原因,是的,你必须添加glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);绘图后返回默认的纹理模式。我不清楚为什么你会得到白色的结果...你有没有正确地添加glColor4f()如在示例中所述? – Ozirus 2010-12-05 00:47:09

+0

是的,glColor4f在与代码示例中完全相同的位置被调用。 – sharvey 2010-12-05 17:13:06

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具有零阿尔法您可以跳过乘步骤。

+0

感谢您的建议。我不太确定我是否可以使用着色器。没有办法使用glBlendFunc的反函数(GL_ZERO,GL_ONE_MINUS_SRC_ALPHA);去做这个? – sharvey 2010-11-14 21:02:57

+0

回答说OpenGLES 1.1不支持自定义着色器:http://stackoverflow.com/questions/543948/opengl-es-1-x-shaders/544022#544022。 – sharvey 2010-11-14 21:45:54

+1

对不起,我会编辑答案,即使它对你没有用处,也值得为其他人做搜索。 – benzado 2010-11-15 20:07:32

0

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而不是源纹理应用常量颜色。