Cheesington
Cheesington

Reputation: 249

How do I separate the colour and alpha blend functions in opengl?

In the process of trying to port my 2D shadow rendering technique from Directx to Opengl, I've run across a problem where I can't seem to get fine enough access to the opengl blender.

But first, so that the following makes sense, my algorithm:

I sort and render all sprites from back to front without using a depth buffer. Shadow sprites are drawn just before the objects that cast them and use the second blendstate below, gShadowBlendState. That makes them draw only their alpha values to the alpha channel on the framebuffer.

Sprites for regular objects use gBlendState specified first below, which is just a regular alpha blend to the backbuffer. However, they also remove alpha from the backbuffer alpha channel to the extent that they are opaque; this makes sure that shadows don't show through opaque objects that are in front of them.

The third thing that is drawn, and which is drawn after everything else, is a fullscreen quad that renders using the shadow colour and the final blend state below. It uses the backbuffer's alpha channel for opacity, effectively bringing out all the shadow information inscribed earlier.

The whole point of this exercise is to get shadows that don't get darker where they overlap.

    gBlendState.SrcBlend       = D3DBLEND_SRCALPHA;
    gBlendState.BlendOp        = D3DBLENDOP_ADD;
    gBlendState.DestBlend      = D3DBLEND_INVSRCALPHA;
    gBlendState.SrcBlendAlpha  = D3DBLEND_ZERO;
    gBlendState.BlendOpAlpha   = D3DBLENDOP_ADD;
    gBlendState.DestBlendAlpha = D3DBLEND_INVSRCALPHA;

    gShadowBlendState.SrcBlend       = D3DBLEND_ZERO;
    gShadowBlendState.BlendOp        = D3DBLENDOP_ADD;
    gShadowBlendState.DestBlend      = D3DBLEND_ONE;
    gShadowBlendState.SrcBlendAlpha  = D3DBLEND_ONE;
    gShadowBlendState.BlendOpAlpha   = D3DBLENDOP_MAX;
    gShadowBlendState.DestBlendAlpha = D3DBLEND_ONE;

    gShadowFillBlendState.SrcBlend       = D3DBLEND_DESTALPHA;
    gShadowFillBlendState.BlendOp        = D3DBLENDOP_ADD;
    gShadowFillBlendState.DestBlend      = D3DBLEND_INVDESTALPHA;
    gShadowFillBlendState.SrcBlendAlpha  = D3DBLEND_ONE;
    gShadowFillBlendState.BlendOpAlpha   = D3DBLENDOP_MAX;
    gShadowFillBlendState.DestBlendAlpha = D3DBLEND_ONE;

Anyway. I'm trying to do this now in Opengl. Currently I have alpha blending enabled with

    glEnable(GL_BLEND);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

but I'm not sure how to give it separate instructions for how to calculate the colour and alpha components. So my question is this: Is there a way to get finer control over the blender in OpenGL than just glBlendFunc() ?

Upvotes: 1

Views: 2922

Answers (3)

Zarathustra
Zarathustra

Reputation:

I left the answer here:

http://pastie.org/542369

Except there's one problem: Replace all the GL_ ADD with GL_ FUNC_ ADD. My mistake.

Upvotes: 1

Eric
Eric

Reputation: 6425

I'm not sure that you can get finer control, but you should be able to achieve most of what you want to do through using glColorMask to first render the color channels and then render the alpha channel. The last step seems like it should remain unchanged.

Upvotes: 1

Related Questions