Question

What I have is a set of 9 squares in a 3x3 grid being rendered for testing this blending function. Here's the idea.

On Pass 1:

  • Bind texture1 (dirt)
  • Render the squares using tex1 = Dirt

On Pass 2:

  • Bind texture2 (letter)
  • Render the same squares using tex2 = Letter W

This is for an in-game editor. We want to be able to change the color of letters from a text atlas as they are typed. The shader is supposed to check the alpha value of the fragment from the texture. Anything that is not equal to 0 (i.e. Visible) should be changed to the desired color that is passed into the shader as an attribute.

//Draw all Squares

glBindTexture(GL_TEXTURE_2D, textureID1);   //Dirt Texture

for (int Index = 0; Index < 9; Index++)
{
//Pass in Vertex Positions...
//Pass in UV's...
glDrawArrays(GL_TRIANGLES, 0, 6); // From index 0 to 6 -> 2 triangle
}

//Redraw Squares with letter texture bound.

glBindTexture(GL_TEXTURE_2D, textureID2);  //Letter Texture

glVertexAttrib3f(2,255,0,0);  //Desired Color of letter, passed to shaders.

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.05f);  //Anything with alpha < 0.05 is discarded.

//Draw all Squares
for (int Index = 0; Index < 9; Index++)
{
   //Pass in Vertex Positions...
   //Pass in UV's...
glDrawArrays(GL_TRIANGLES, 0, 6); // From index 0 to 6 -> 2 triangle
}

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_ALPHA_TEST);

//Draw blue vertex dots...etc...

Here's a picture showing the source images, and the output of 2 slightly different Fragment shaders. Along with the desired result.

Image Sources, with Frag Shaders and Desired Result

The textures are loaded, both have alpha channels (GL_BGRA, Targas). I'm using GL_NEAREST as MIN/MAG FILTERS.

The odd thing is, this shader works for me if I use 99% white (i.e. 254) in the alpha channel of the LETTER TEXTURE and fails when I use full white (i.e. 255).

I've tried enabling GL_BLEND and using various BlendFunc's, but they don't seem to work.

I guess the question is. Without using a multitexture shader, and without rendering to an FBO, is this the right way to do this sort of blending?

Was it helpful?

Solution

Turns out this was one of those situations where the shader was behaving just as I expected it to but I misinterpreted exactly what that meant.

In this case I was using the same shader to render both the initial background texture and the overlaying text texture. Because the alpha channel on the background texture is a solid 1.0 (white) all the way across it was rendering the dirt texture as a solid red. Then on the second pass it would render the text properly, but I couldn't see it because it was also being rendered as red.

I fixed my problem in this situation by instead drawing the letter in the alpha channel of the letter texture with black (i.e. Transparent) and then in the shader doing alpha testing and inverting where necessary. The key with this method is to Enable blending before the letter is rendered, and to disable it after.

In the end the shader works something like this.

  • If fragment alpha < 1
    Then, Color = vec4(in_color,(tex_color.a = (tex.color.a) ? (1.0 - tex_color.a) : 1.0));

  • Else, (Alpha = 1) invert the alpha channel
    tex_color.a = 0;
    Color = tex_color;

This makes it so that whatever is drawn in black in the alpha channel while blending is enabled will come out colored instead of transparent.

In the end, multitexturing is probably the way to go, but in my case I wanted to try to do it with only 1 texture enabled at a time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top