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!
ID:1419019
Nov 10 2013, 3:41 pm
|
|||||||
| |||||||
Nov 10 2013, 4:03 pm
|
|
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, having some more blending modes like that to work with would be fantastic.
|
Would be useful and provide a lot compared to how much effort it takes to implement.
+1 |
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
|
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. |
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 |