Alpha blending textures and primitives
我有两个纹理和一个三角形图元(其顶点的颜色由
纹理A看起来像这样:
纹理B看起来像这样:
三角形基元P看起来像这样:
当我渲染纹理A,然后渲染纹理B时,我得到了预期的结果,即矩形的中间是透明的。
但是,如果我渲染图元P,然后渲染纹理A,然后渲染纹理B,则会得到错误的颜色。 P不是纯红色,纹理颜色全部变为黑色。
如何解决此问题,以便保持适当的透明度和颜色。
纹理参数:
1 2 3 4 5 6 | GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); GLfloat debugColor[] = {1.0f, 0.0f, 1.0f, 1.0f}; GL_CALL(glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, debugColor)); |
融合功能:
1 2 | GL_CALL(glEnable(GL_BLEND)); GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); |
P,A和B的渲染:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | if(true) { // Render Primitive P GL_CALL(glBegin(GL_TRIANGLES)); GL_CALL(glColor4f(1.0f, 0.0f, 0.0f, 1.0f)); GL_CALL(glVertex2f(-0.5f, -0.5f)); GL_CALL(glColor4f(1.0f, 0.0f, 0.0f, 1.0f)); GL_CALL(glVertex2f(0.0f, 0.5f)); GL_CALL(glColor4f(1.0f, 0.0f, 0.0f, 1.0f)); GL_CALL(glVertex2f(0.5f, -0.5f)); glEnd(); } if(true) { // Render Texture A GL_CALL(glBindTexture(GL_TEXTURE_2D, textureId)); GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)); real32 screenPercentage = 0.25f; GL_CALL(glBegin(GL_TRIANGLES)); // Lower triangle GL_CALL(glTexCoord2f(0.0f, 0.0f)); GL_CALL(glVertex2f(-screenPercentage, screenPercentage)); GL_CALL(glTexCoord2f(1.0f, 0.0f)); GL_CALL(glVertex2f(screenPercentage, screenPercentage)); GL_CALL(glTexCoord2f(1.0f, 1.0f)); GL_CALL(glVertex2f(screenPercentage, -screenPercentage)); // Upper triangle GL_CALL(glTexCoord2f(0.0f, 0.0f)); GL_CALL(glVertex2f(-screenPercentage, screenPercentage)); GL_CALL(glTexCoord2f(1.0f, 1.0f)); GL_CALL(glVertex2f(screenPercentage, -screenPercentage)); GL_CALL(glTexCoord2f(0.0f, 1.0f)); GL_CALL(glVertex2f(-screenPercentage, -screenPercentage)); glEnd(); } if(true) { // Render Texture B GL_CALL(glBindTexture(GL_TEXTURE_2D, textureId)); GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, window[0].offscreenBuffer.width, window[0].offscreenBuffer.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, window[0].offscreenBuffer.data)); real32 screenPercentage = 1.0f; GL_CALL(glBegin(GL_TRIANGLES)); // Lower triangle GL_CALL(glTexCoord2f(0.0f, 0.0f)); GL_CALL(glVertex2f(-screenPercentage, screenPercentage)); GL_CALL(glTexCoord2f(1.0f, 0.0f)); GL_CALL(glVertex2f(screenPercentage, screenPercentage)); GL_CALL(glTexCoord2f(1.0f, 1.0f)); GL_CALL(glVertex2f(screenPercentage, -screenPercentage)); // Upper triangle GL_CALL(glTexCoord2f(0.0f, 0.0f)); GL_CALL(glVertex2f(-screenPercentage, screenPercentage)); GL_CALL(glTexCoord2f(1.0f, 1.0f)); GL_CALL(glVertex2f(screenPercentage, -screenPercentage)); GL_CALL(glTexCoord2f(0.0f, 1.0f)); GL_CALL(glVertex2f(-screenPercentage, -screenPercentage)); glEnd(); } |
编辑:尝试@ Rabbid76的解决方案后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); if(true) { // Render triangle with all vertices having color 1.0f, 0.0f, 0.0f, 1.0f } if(true) { // Render texture A with color set to 1.0f, 1.0f, 1.0f, 1.0f and the appropriate texture u,v coordinates } if(true) { // Render texture B with color set to 1.0f, 1.0f, 1.0f, 1.0f and the appropriate texture u,v coordinates } |
我得到以下结果:
即使所有三个实体的alpha为1.0f,而空心区域的alpha为0.0f,颜色仍然不正确
如果启用纹理,则默认情况下,纹理像素的颜色将乘以当前颜色,因为默认情况下纹理环境模式(
这导致纹理的纹理像素的颜色与
渲染纹理时,仍会设置三角形的红色,这将导致纹理变为红色。绿色和蓝色通道完全消失,并且由于纹理没有红色通道,因此剩下的一切都是黑色。
为了解决您的问题,必须在渲染纹理之前设置白色:
1 | glColor4f(1.0f, 1.0f, 1.0f, 1.0f); |
并在渲染三角形之前禁用
请注意,始终存在纹理绑定,没有"没有纹理"之类的东西,默认纹理对象0也是有效对象。
这将导致纹理查找呈现完全黑色,并与由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | glDisable( GL_TEXTURE_2D ); if( true ) { // Render Primitive P ..... } glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); glEnable( GL_TEXTURE_2D ); if ( true ) { // Render Texture A ..... } |