ID:1419019
 
Applies to:Dream Maker
Status: Open

Issue hasn't been assigned a status value.
The new blending modes are great. Now we can do some pretty cool stuff with lighting (and already are), but to do really good lighting, I would need to be able to use one other essential mode: 2x Multiplicative blending.

In the regular multiplicative mode, the blend operation is like so:

(source × Blend.Zero) + (destination × Blend.SourceColor)

In the 2x Multiplicative blending mode, it looks like this:

(source × Blend.DestinationColor) + (destination × Blend.SourceColor)

OR

2 * source * destination

Why is this good?

Well, using multiplicative blending with a regular icon or overlay, I can only ever get color values as high as the texture I'm multiplying against. I can't ever brighten the underlying texture, I can only darken.

Using 2x multiplicative blending, I can simply create a 50% gray overlay in order to see the original icon. To brighten, I use a brighter color. To darken, I use a darker color. Essentially this is just like plain multiplicative blending except it allows you to have a wider dynamic range in the game, and use lighting overlays to create brighter lights and deeper shadows than I could with just multiplicative blending alone.

As a workaround, I could probably bake the light overlay to whatever icon I'm trying to light, but that would mean I would have to redo that process every time the light changes, so it is unfeasibly slow.

I think that adding this other blend mode would be pretty simple given the other blend modes that have been added. Also I am coder, so I could probably furnish a c++ example if needed.

This probably explains it better than I can: http://msdn.microsoft.com/en-us/library/bb976070.aspx - With pictures!
I'm going to have to echo the sentiment that 2X Multiply would be a useful tool to have. Not just in lighting effects, but in any particle effect where a 'glow' is wanted as well.
Agreed, 2x multiply seems like a very good idea.
Agreed, having some more blending modes like that to work with would be fantastic.
+1
Would be useful and provide a lot compared to how much effort it takes to implement.

+1
+1 because everyone did so too.
Instead of this bollocks, add the multiplier variable that I had in the original suggestion, although it doesnt really need to be per-channel, it shouldent be too difficult to make that work in hardware mode
+2
In response to Tobba
That's not how directx works...
The current multiplicative blending isn't actually using Microsoft's formula; it's using (src × dst.color) + (dst × (1 - src.alpha)). After much experimenting, that was the one I found worked with alpha values mixed in. I don't think Microsoft's table properly accounts for that.

The proper way to handle a multiplicative blend is as follows:

(src.color × dst.color × src.alpha) + (dst.color × (1 - src.alpha))

The formula I'm using currently seems to work for this. But the 2x multiplicative blend Microsoft mentions wouldn't, I think, work on any images that have transparent pixels.
Which API are you using? DirectDraw or D3D?
DirectDraw is deprecated. We use Direct3D, though we're using a sprite blitter object with it.
Multistage rendering would do it...

    g_pd3dDevice->BeginScene();

        //
        // STAGE 0
        //

        g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
        g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );

        g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE ); // Modulate...
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );   // the texture for this stage with...
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );   // the diffuse color of the geometry.

        //
        // STAGE 1
        //

        g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
        g_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );

        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
        g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE2X );
        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE2X ); // Modulate...
        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); // the texture for this stage with...
        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); // the current argument passed down from stage 0
        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
        g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
        g_pd3dDevice->SetTexture( 0, g_pTexture_0 ); //Base Texture
        g_pd3dDevice->SetTexture( 1, g_pTexture_1 ); //Overlay Texture
Bump