Fade in/out using texture

Member
Posts: 93
Joined: 2008.11
Post: #1
Hello fellows,

I surely understand that this has been discussed already. I just had 3 hours of googling and trying things out before I finally gave up and came to drop a post here.

I have this code to do fade in/out:

...
double a = calculatedAlphaValueFromTimeDelta;
glColor4f(a, a, a, a);
[t_Blank drawInRect: bounds]; // bounds is full screen
glColor4f(1, 1, 1, 1);
...

Tried with and without this code in my gl init:
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f);
...

The t_Blank is a Texture2D which is a 2x2 fully transparent texture.
Texture2D is the same class from the CrashLanding example.

I have also tested a lot off glBlendFunc combinations. Neither works as expected.

It doesn't work for that 2x2 texture, nor does it work for a 320x480 texture (fully transparent, white or black).
Now the most fun stuff: If I just use my background texture instead of the t_Blank - It works. But of course I get a fade to background instead of fade to black.

What the hell can be wrong here? Can someone show me some working code? I bet you guys have transitions in your games and I bet that some of them are fade in/out ones.

Thanks in advance!
Alex
Quote this message in a reply
Moderator
Posts: 3,574
Joined: 2003.06
Post: #2
Don't use alpha test, use GL_BLEND.

BTW, for best performance, when using GL_BLEND, turn it on only for the stuff that needs blending. IOW, don't enable it in your init and leave it on the whole time if you can avoid it.

Also, if you're just drawing a black cover quad to fade out, there is no need for texturing. For color, you'll probably want to do something like: glColor4f(0.0f, 0.0f, 0.0f, opacity); And for your blend func this will probably work with either ONE, ONE_MINUS_SRC_ALPHA or SRC_ALPHA, ONE_MINUS_SRC_ALPHA

However, if you're going to texture with Texture2D, then use glColor4f(opacity, opacity, opacity, opacity); and a blend func of ONE, ONE_MINUS_SRC_ALPHA

Also, glColor4f takes floats as parameters, not doubles, as denoted by the "f" suffix.

Also, as I recall, small textures (like less than 64x64) require a small modification to using calloc instead of malloc in Texture2D's loading code (I don't remember where exactly but it's with the CoreGraphics stuff) or else garbage can show up with transparancy.
Quote this message in a reply
Member
Posts: 93
Joined: 2008.11
Post: #3
Thanks for the info!
I will give it another try. I already fixed it like this and I guess that's far not the best way to get this done... but it works:

1) disabled GL_ALPHA_TEST. Indeed, alpha testing made things only worse. They look awful and the rendering is getting jumpy.. probably because of the cost.

2) in the rendering:
Code:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // This seems to create a very nice fade effect. better than with GL_REPLACE
glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);

glColor4f...;
[t_Blank draw...]; // The texture is now 2x2 opaque black png

...restore gl states...;

I will definitely try your suggestion concerning GL_BLEND, however I don't really understand how this can help performance? I would even expect it to slow down (read "more calls - less speed"). Can you explain?

Thanks again!
Alex

TapMania - iPhone StepMania // Human knowledge belongs to the world!
Quote this message in a reply
Moderator
Posts: 3,574
Joined: 2003.06
Post: #4
godexsoft Wrote:I will definitely try your suggestion concerning GL_BLEND, however I don't really understand how this can help performance? I would even expect it to slow down (read "more calls - less speed"). Can you explain?

Yes, it is backwards on iPhone: alpha test is slow, blend is faster.

By the way, glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); is default, so you don't need to explicitly set it.

Also, by the way, glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); is the "multiply" blend mode (like using multiply in Photoshop), when using premultiplied textures (FYI, Texture2D loads textures as premultiplied). Using multiply will work, but it might not behave exactly as you might expect. Best to stick to either of the two blend functions I suggested earlier for predictable results... unless you actually *want* to use the multiply blend mode, hehe.
Quote this message in a reply
Member
Posts: 93
Joined: 2008.11
Post: #5
I gave it a shot and it failed. Both the specified blend functions Smile
Maybe I do the drawing in some bad way... I tried to do glDrawArrays(GL_TRIANGLES, 0, 4); I suppose that should give me two triangles filled with colors/alpha I specified using glColor, right?

So when I use GL_ONE, GL_ONE_MINUS_SRC_ALPHA and glColor4f(a, a, a, a) I get a blank fade to white Smile That's understood because we use color components, not only the alpha. But if I set colors to 0.0f and use only the alpha I get no results.

Ideas?

TIA,
Alex

TapMania - iPhone StepMania // Human knowledge belongs to the world!
Quote this message in a reply
Moderator
Posts: 3,574
Joined: 2003.06
Post: #6
Why it would work in multiply blend mode and not the others, I am not sure, but it sounds funky. You mentioned earlier that you're using a "fully transparent texture". What is the purpose of that? You shouldn't use texturing if you aren't going to show something, since that is a waste.

For a quad, I usually use a triangle strip. Here's an example (this assumes you've disabled texturing and you're using a viewport set to the size of the screen):

Code:
void DrawCoverQuad(float opacity)
{
    GLfloat        quadVerts[8];
    GLfloat        halfWidth, halfHeight;
    
    if (orientation == ORIENTATION_PORTRAIT)
    {
        halfWidth = 160.0f;
        halfHeight = 240.0f;
    }
    else // (orientation == ORIENTATION_LANDSCAPE)
    {
        halfWidth = 240.0f;
        halfHeight = 160.0f;
    }
    quadVerts[0] = -halfWidth;
    quadVerts[1] = -halfHeight;
    quadVerts[2] = halfWidth;
    quadVerts[3] = -halfHeight;
    quadVerts[4] = -halfWidth;
    quadVerts[5] = halfHeight;
    quadVerts[6] = halfWidth;
    quadVerts[7] = halfHeight;
    
    glColor4f(0.0f, 0.0f, 0.0f, opacity);
    glVertexPointer(2, GL_FLOAT, 0, quadVerts);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
Quote this message in a reply
Member
Posts: 93
Joined: 2008.11
Post: #7
Works like a charm! Thanks a lot Smile
The problem was that TEXTURE_2D was enabled all the time.. I had to disable it for the time when I was drawing the fade effect. That's it.

I still don't understand why BLEND must be kept disabled as much as possible.. you didn't explain.. I would like to know.

Thanks!
Alex

TapMania - iPhone StepMania // Human knowledge belongs to the world!
Quote this message in a reply
Moderator
Posts: 3,574
Joined: 2003.06
Post: #8
Glad you finally got it working Smile

As I understand it: Blend should be disabled as much as possible because it conflicts with the way the Tile-Based Renderer does hidden surface removal. Since it does hidden surface removal fairly early on, that gives it an opportunity to discard hidden pixels early, for a performance advantage. If it's blended then it has to keep and perform more operations on blended pixels as they continue down the pipeline, hence the performance disadvantage of using blending.

In practice, what this means is that you'll still use blending a lot, but you shouldn't leave it on if not needed. Kind of like leaving the lights on in the kitchen when you go to the store.
Quote this message in a reply
Post Reply