Jump to content

  • Log In with Google      Sign In   
  • Create Account

SHilbert

Member Since 14 Jan 2000
Offline Last Active Jul 06 2012 10:53 AM

Posts I've Made

In Topic: Multi pass texturing

30 June 2012 - 02:33 PM

Looks like maybe it's because you're calling SetTexture inside Begin/EndPass.

If the application changes any effect state using any of the Effect::Setx methods inside of a ID3DXEffect::BeginPass/ID3DXEffect::EndPass matching pair, the application must call ID3DXEffect::CommitChanges to set the update the device with the state changes. If no state changes occur within a ID3DXEffect::BeginPass and ID3DXEffect::EndPass matching pair, it is not necessary to call ID3DXEffect::CommitChanges.


So one option is to call mFX->CommitChanges().

I don't think you actually need to manually change the texture per pass at all, though. If you just define 3 texture uniforms, instead of the single gTex you have now, and just fill them in with your 3 different textures before you begin drawing, and sample from the right one in each VS, the effect system will sort it all out for you.

EDIT: FYI, to further clean up your effect rendering loop, you can specify the blend modes in your FX file too, by setting states inside the passes:


technique TerrainMultiTexTech
{
    pass P0
    {
            // Specify the vertex and pixel shader associated with this pass.
            vertexShader = compile vs_2_0 TerrainMultiTexVS();
            pixelShader  = compile ps_2_0 TerrainMultiTexPS0();

            AlphaBlendEnable = FALSE;            
    }
    pass P1
    {
            // Specify the vertex and pixel shader associated with this pass.
            vertexShader = compile vs_2_0 TerrainMultiTexVS();
            pixelShader  = compile ps_2_0 TerrainMultiTexPS1();

            AlphaBlendEnable = TRUE;
            SrcBlend = SRCALPHA;
            DestBlend = INVSRCALPHA;
    }
    pass P2
    {
            // Specify the vertex and pixel shader associated with this pass.
            vertexShader = compile vs_2_0 TerrainMultiTexVS();
            pixelShader  = compile ps_2_0 TerrainMultiTexPS2();

            AlphaBlendEnable = TRUE;
            SrcBlend = SRCALPHA;
            DestBlend = INVSRCALPHA;
    }
}

In Topic: [Dx8] Texture & Blending

29 June 2012 - 07:41 AM

I don't understand why I used D3DRS_DESTBLEND=D3DBLEND_ONE to rendering the texture and I don't tried D3DRS_SRCBLEND=D3DBLEND_ONE.. It's so obvious now that I look stupid


I didn't even notice that it was DESTBLEND in your post and not SRCBLEND until you pointed it out. Easy mistake to make.

If that doesn't bother you I keep your code in C++, I think this is a good example for me when I will turn to this language.


No problem. A third of that code is just from a quick start tutorial somewhere on the internet anyway, to make the window & device & such.

However, I have a last question because it's the only thing I didn't quite understand. The D3DTA_ALPHAREPLICATE doesn't allow to use vertex color because he take the informations only in the texture ?


When you do something like D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE, it means it takes the (r,g,b,a) from the texture (the D3DTA_TEXTURE part) and turns it into (a,a,a) (the D3DTA_ALPHAREPLICATE part.) So when you do this:
[source lang="cpp"]g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE|D3DTA_ALPHAREPLICATE);[/source]
It means:
colorarg1 = (r,g,b) from the texture
colorarg2 = sample the alpha from the texture and produce a triplet (a,a,a)
modulate = the output is colorarg1 * colorarg2 = (r,g,b) * (a,a,a) = (r*a, g*a, b*a)

So if the texture at that point is (r,g,b,a) then the overall of that stage is (r*a, g*a, b*a, a). (The alpha processing is just left as default.)

In Topic: Multi pass texturing

28 June 2012 - 09:33 PM

Looks like you have alpha blending turned on for each pass, but the alpha value your pixel shaders are outputting is diffuse.a, which is probably just 1. So each pass is drawing opaquely over the previous one.

I'm not sure why you're not doing this all in one pass in a single pixel shader, though -- it doesn't seem like you'd run out of instruction slots or textures? I might be wrong though.

If you do want to do multipass, you probably want to draw the first pass w/ alpha blending turned off, without even referring to the blend map. Then, for the subsequent passes, turn on alpha blending, and instead of multiplying the tiled texture's color by the green or blue channel from the blend map, you use the green or blue channel as the alpha component you return from the pixel shader.

Not sure why your texture order is swapped (i.e. why stone is mapped to blue instead of green) though.

In Topic: [Dx8] Texture & Blending

28 June 2012 - 09:14 PM

I figured this may be more easily expressed in code so I put it together using DX9 and C++ (I haven't got VB6 or a DX8 SDK, sorry.) But the code should still be easy enough to read since it's mostly the Direct3D parts that matter.

Here it is: http://shilbert.com/...s/BlendTest.zip

This is the interesting part:

[source lang="cpp"]void Draw(){ g_device->BeginScene(); // Common states we always use g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); g_device->SetRenderState(D3DRS_LIGHTING, FALSE); g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // Render to 512x512 texture g_device->SetRenderTarget(0, g_rttSurf); D3DXMATRIX proj512x512; D3DXMatrixOrthoOffCenterRH(&proj512x512, 0, 512, 512, 0, -10, 10); g_device->SetTransform(D3DTS_PROJECTION, &proj512x512); // Clear all components to zero g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); // Premultiply alpha in the source texture using texture stage g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE|D3DTA_ALPHAREPLICATE); // Set blend mode to (ONE, INVSRCALPHA) g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // Draw textures 1 & 2 DrawTexturedQuad(g_tex1, 0, 0, 512, 512); DrawTexturedQuad(g_tex2, 0, 0, 512, 512); // Now switch to the main render target (1024x512) g_device->SetRenderTarget(0, g_defaultRT); D3DXMATRIX proj1024x512; D3DXMatrixOrthoOffCenterRH(&proj1024x512, 0, 1024, 512, 0, -10, 10); // Clear to some random color g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 0, 0); // Reset texture stage settings to default g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); g_device->SetTransform(D3DTS_PROJECTION, &proj1024x512); // Left side. (render to texture side) // Draw the back texture, 0.png -- use normal alpha blending // (doesn't matter since it's opaque) g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); DrawTexturedQuad(g_tex0, 0, 0, 512, 512); // Draw the offscreen texture we have generated. // It uses premultiplied alpha so we have to blend appropriately g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); DrawTexturedQuad(g_rtt, 0, 0, 512, 512); // Right side. (control side) // Now go back and draw each texture on top of one another w/ default alpha blending. g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); DrawTexturedQuad(g_tex0, 512, 0, 512, 512); DrawTexturedQuad(g_tex1, 512, 0, 512, 512); DrawTexturedQuad(g_tex2, 512, 0, 512, 512); // Done with scene, swap buffers, etc. g_device->EndScene(); g_device->Present(NULL, NULL, NULL, NULL);}[/source]

I'm drawing to the offscreen render target every frame, but it's the same idea as what you have. Also I did it with a single texture stage, because there is no reason to multiply in vertex color for this example.

Basically when drawing to the offscreen render target:
(1) clear to black w/ zero alpha
(2) set up texture stage 0 to multiply color components by alpha
(3) draw your textures w/ src=one, dest=invsrcalpha

Then when drawing to the target:
(1) reset all texture stages to default
(2) draw your checkerboard backdrop w/ an alpha blend (src=srcalpha, dest=invsrcalpha) or no blending at all
(3) draw the render target texture using src=one, dest=invsrcalpha

I hope that helps.

Here's a screenshot of what it looks like: http://shilbert.com/pics/blendtest.png

In Topic: [Dx8] Texture & Blending

27 June 2012 - 09:51 PM

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.

PARTNERS