[Dx8] Texture & Blending

Started by
13 comments, last by testt 11 years, 9 months ago
Hi all, (and sorry if my english is bad).

I develop a game in Vb6 with directx8, now I'm stuck on a problem and I don't know if it's correctable.
To explain my problem, I create textures in format A8R8G8B8 (32bits) and filled this with preloaded textures (png).

The problem is that the generated texture doesn't display a correct rendering. For example, if I draw something with transparent pixels, DirectX blending what I draw with the background color (transparent black) and so the texture rendered is darker than it should be.

I can't desactivate alphablending. So I tried different operation of blending (also srcblend and destblend) and I haven't found solutions..

You can download here the source who reproduce my problem and see here an image of the problem.

Thank for any help.


Edit : You can see here exactly le same problem, but he hasn't found a real solution.
Advertisement
So if I am interpreting you correctly, the problem is that doing this sequence:


device.RenderTarget = DeviceBuffer
Draw texture 0 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
device.RenderTarget = (an offscreen texture, which starts at transparent black, all values = 0x00000000)
Draw texture 1 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
Draw texture 2 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
device.RenderTarget = DeviceBuffer
Draw offscreen texture w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
[/quote]

is not equivalent to this sequence:


device.RenderTarget = DeviceBuffer
Draw texture 0 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
Draw texture 1 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
Draw texture 2 w/ SRCBLEND=SRCALPHA, DESTBLEND=INVSRCALPHA
[/quote]

And that makes sense, because they aren't equivalent!

If you want to composite two transparent textures into one transparent texture, you are better off working all in pre-multiplied alpha -- both with the loaded textures and the offscreen destination texture. That is, modify your source textures so the R, G, B values are already pre-multiplied by the A values, and draw everything using D3DRS_SRCBLEND=D3DBLEND_ONE and D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA. If you don't work in pre-multiplied alpha the equation is harder to capture with simple blend operators.

You may be able to avoid pre-multiplying the alpha on your source textures by rendering them with separate blending functions for the color channels & the alpha channel -- use these settings:


D3DRS_SRCBLEND=D3DBLEND_SRCALPHA
D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA,
D3DRS_SEPARATEALPHABLENDENABLE = TRUE
D3DRS_SRCBLENDALPHA=D3DBLEND_ONE
D3DRS_DESTBLENDALPHA=D3DBLEND_INVSRCALPHA.
[/quote]

When drawing the offscreen texture to the final device buffer you must disable the separate alpha blending & just use D3DRS_SRCBLEND=D3DBLEND_ONE, D3DRS_DESTBLEND=D3DBLEND_INVSRCALPHA.

I'm not sure if D3D8 supports this feature though -- I only have the D3D9 docs handy.
Yes, I thought to use D3DRS_SEPARATEALPHABLENDENABLE but D3D8 don't support this. I've searched a alternative to this but I don't find solution.
You should be able to accomplish it with with texture stage states.

For example, I think if you do add second color stage with

D3DTSS_COLOROP = D3DTOP_MODULATE
D3DTSS_COLORARG1 = D3DTA_CURRENT
D3DTSS_COLORARG2 = D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE

...you can get the same effect. You only need to use this extra stage when rendering from non-premultiplied alpha textures, like your textures from 1.png and 2.png.

You can also do the premultiplication 'offline' by modifying your texture files before you load them, or lock the texture after loading and do the premultiplication then.

Or you could switch to DX9, which is close to 10 years old at this point and enjoys near universal support. smile.png Don't know if that is feasible in VB6 though, I don't know much about that ecosystem. This guy seems to have a library for using DX9 in VB (see post #14.)
I see, but when you add second color stage, you use a different texture (example : stage0 for 1.png and stage1 for 2.png) or is the same texture ?

I don't want to modify the texture because I'll use several times (many textures and sometimes the same texture), I think it's problematic and longer to load after. It's even why I create a texture to preload all once.

Also, I already found the guy who propose a librarie for dx9 in vb6, but it's incomplete (For example, I use CreateTextureFromFileInMemoryEx and he isn't added). If I don't found solution for this, I migrate probably to vb.net (It's my last solution).
You can set the same texture to as many stages as you wish if that's what you need to do.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Yes, I know it's possible, but I don't understand exactly how Shilbert told me to do that. Use the same texture in 2 stages to separate opaque pixel and transparent pixel (with a different blending operation for each) or 2 textures in 2 stages for blending between them ?

Yes, I know it's possible, but I don't understand exactly how Shilbert told me to do that. Use the same texture in 2 stages to separate opaque pixel and transparent pixel (with a different blending operation for each) or 2 textures in 2 stages for blending between them ?


The same texture in 2 stages. The goal is to multiply the texture's normal RGB values by the texture's A value before it even gets to the blending stage. This makes the your texture effectively have "premultiplied alpha" at runtime, so you don't have to do it at or before load time. This isn't a pre-pass step, it's something you do every render.

It's been ages since I worked with texture stages but I am pretty sure this sort of approach will work.

If you don't care about vertex colors you can also do it in one stage like this, I think:

(Stage 0)
Texture = (your source texture)

[background=rgb(250, 251, 252)]D3DTSS_COLOROP = D3DTOP_MODULATE[/background]


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]D3DTSS_COLORARG1 = D3DTA_TEXTURE[/background][/font]


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

[background=rgb(250, 251, 252)]D3DTSS_COLORARG2 = D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE[/background][/font]

Hi and sorry for my absence (I had some problems with my pc).

This blending stage seem to work with the RGB blending, but the Alpha stay problematic. See here.
There are two problems, the alpha is too low and the blending of two color is incorrect when one of two isn't opaque (In fact, in the situation the opaque color became transparent).

I understood what you want to do but I'm not sure that the stage 1 is useful here (The ColorOp in the stage 1 is disable by default, so in this situation is ineffective, no ?).


Edit : The problem with blending of two colors has been resolved, there remains the problem of alpha too low.. See here.

Hi and sorry for my absence (I had some problems with my pc).

No worries!


Edit : The problem with blending of two colors has been resolved, there remains the problem of alpha too low.. See here.

Hmm, it looks like it is a lot closer! It's like somehow it's rendering as if the alpha is squared (i.e., always less than it ought to be unless alpha = 1.) It's almost as if the alpha is getting premultiplied by itself along with the color parts. Could you maybe post the source as it is now? I'd like to take a look at all of the render states together.

This topic is closed to new replies.

Advertisement