• Advertisement
Sign in to follow this  

Soft Particles

This topic is 1655 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm converting my current hard particles to soft particles in D3D9

 

Here is the steps that I know:

1. Render the scene without particles to the back buffer

2. Create depth texture

3. Send the depth texture to the particles pixel shader

4. Compare the particles depth with the scene depth and modify the alpha channel accordingly

5. Show the scene

 

 

Now, I'm trying to create the depth texture as the following:

#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))

void Init()
{
     // Create an INTZ depth stencil texture
     device->CreateTexture(WindowWidth, WindowHeight, 1,
                           D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ,
                           D3DPOOL_DEFAULT, &pINTZDST,
                           NULL);

     // Retrieve depth buffer surface from texture interface
     IDirect3DSurface9 *pINTZDSTSurface;
     pINTZDST->GetSurfaceLevel(0, &pINTZDSTSurface);

     device->SetRenderState(D3DRS_STENCILENABLE, TRUE);

     // Bind depth buffer
     device->SetDepthStencilSurface(pINTZDSTSurface);
}

When I execute the above code once, I see that the scene depth get messed up.

 

What's going wrong?

Edited by Medo3337

Share this post


Link to post
Share on other sites
Advertisement

I have never tried INTZ format and i am not sure if it is even supported on nvidia hw since i got that kind of graphic card.

 

Basically i think you need to do this:

1. Create INTZ texture as you showed in code snippet:

#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))

void Init()
{
// Create an INTZ depth stencil texture
device->CreateTexture(WindowWidth, WindowHeight, 1,
                      D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ,
                      D3DPOOL_DEFAULT, &pINTZDST,
                     NULL);

// Retrieve depth buffer surface from texture interface
//IDirect3DSurface9 *pINTZDSTSurface; // store it somewhere else as you will need to access it
pINTZDST->GetSurfaceLevel(0, &pINTZDSTSurface);
 
// DO NOT SET IT NOW!!!
//device->SetDepthStencilSurface(pINTZDSTSurface);
}

2. While rendering:

void DrawAll()
{
...
IDirect3DSurface9*  oldDS;
device->GetDepthStencilSurface(&oldDS); // store "old" depth stencil surface, note that this Get call increments ref count
 
device->SetDepthStencilSurface(pINTZDSTSurface); // set your INTZ
 
DrawAllWithoutParticles();
 
device->SetDepthStencilSurface(oldDS); // restore back old DS so you can read from INTZ texture
oldDS->Release(); // decrement ref count
 
shader->SetTexture("DepthTexture", pINTZDST);
DrawParticles();
}

3. Now in pixel shader you need to know how depth is stored in INTZ texture (which i don't) so you can extract xyz positions that you need

Edited by belfegor

Share this post


Link to post
Share on other sites

@belfegor: I'm getting a black screen when I run the program, when I remove the line device->SetDepthStencilSurface(pINTZDSTSurface); the program run normally.

 

Perhaps I should render the scene twice? Once for creating depth texture and another for showing the scene?

Edited by Medo3337

Share this post


Link to post
Share on other sites

The black screen problem was fixed after I moved my code to be before the line device->Clear(...);

 

Now, I see the scene depth is messed up, I can see things I'm not supposed to see, here is a screenshot:

[attachment=17338:4184.png]

Share this post


Link to post
Share on other sites

Since i lost my crystal ball somewhere, so i cannot read your mind at long distances, could you please show your effect file where you use INTZ as texture so maybe i could spot where is the source of the problem?

Share this post


Link to post
Share on other sites

I'm not sending the depth texture to the shader yet, I'm just starting by trying to create a depth texture in D3D9.

 

The results is that I get messed up scene depth as you can see in the screenshot.

 

Here is my render code:

HRESULT hr;
IDirect3DSurface9*  oldDS;
hr = device->GetDepthStencilSurface(&oldDS); // store "old" depth stencil surface, note that this Get call increments ref count
assert(SUCCEEDED(hr));

hr = device->SetDepthStencilSurface(pINTZDSTSurface); // set your INTZ
assert(SUCCEEDED(hr));

device->SetRenderState(D3DRS_ZENABLE, TRUE);
device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
device->BeginScene();

RenderScene();

device->SetDepthStencilSurface(oldDS); // restore back old DS so you can read from INTZ texture
oldDS->Release(); // decrement ref count

device->EndScene();

Init code:

#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))

// Create an INTZ depth stencil texture
device->CreateTexture(WindowWidth, WindowHeight, 1,
                      D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ,
                      D3DPOOL_DEFAULT, &pINTZDST,
                      NULL);

// Retrieve depth buffer surface from texture interface
pINTZDST->GetSurfaceLevel(0, &pINTZDSTSurface);

Share this post


Link to post
Share on other sites

I don't think that INTZ can hold stencil bits so you might want to remove D3DCLEAR_STENCIL flag from Clear function.

Better yet before you try that see if Clear fails with that flag on:

hr = device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
assert(SUCCEEDED(hr));

Just tried this and it works fine for me, no artifacts.

test2013-08-1212-41-52.jpg

 

Do you have some sates set in RenderScene(), probably in effect technique block?

Edited by belfegor

Share this post


Link to post
Share on other sites

device->Clear() is not failing, removing the flag D3DCLEAR_STENCIL doesn't make any difference.

 

I think that the depth buffer is being MOVED to the depth texture, so the scene is getting rendered without depth? Have you tried to check my code in your own program?

 

The problem is only getting fixed when I remove the line:

device->SetDepthStencilSurface(pINTZDSTSurface);

Share this post


Link to post
Share on other sites

Yes, i have tried your code in my program and it works fine, look at above screenshot.

I will repeat my question:


Do you have some sates set in RenderScene(), probably in effect technique block?

Share this post


Link to post
Share on other sites

This problem is really disturbing, I tried removing the render states, same problem!

 

I also tried to make changes to your terrain project (terrain2.rar), I don't get this problem with your project sample.

 

BTW, I'm using texture splatting pixel shader for the terrain, tried to use just one texture and render the terrain only (no other meshes), same problem too.

 

Effect technique:

technique tech
{
    pass
    {
         AlphaBlendEnable = FALSE;
         ZEnable = TRUE;
         VertexShader = compile vs_3_0 VS();
         PixelShader  = compile ps_3_0 PS();
    }
}
Edited by Medo3337

Share this post


Link to post
Share on other sites

@belfegor: After searching and trying to resolve the problem for the whole day, I figured out that the problem only occur when I have antianalysing turned on, I don't know why.

 

I tried adding the following line to your old project, and I got the same problem:

d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES;

 

When I remove the above line, the problem get fixed, though I need antianalysing turned on, I attached your old project after modifying it, you can notice the problem:

[attachment=17346:Problem.rar]

Share this post


Link to post
Share on other sites

I think INTZ depth buffer can't be used with anti aliasing, this check fails for me:

DWORD ql;
    hr = d3d9->CheckDeviceMultiSampleType( adapter, deviceType, FOURCC_INTZ, TRUE, D3DMULTISAMPLE_4_SAMPLES, &ql);
    if(FAILED(hr))
    {
        MessageBox(0, "CheckDeviceMultiSampleType() failed!", 0, 0);
        return false;
    }

Result is not available:

x862013-08-1311-33-13.jpg

Edited by belfegor

Share this post


Link to post
Share on other sites

@belfegor: hmm... what to do now? I want to create depth texture for soft particles and at the same time have antialiasing enabled like in most modern FPS games.

Edited by Medo3337

Share this post


Link to post
Share on other sites

Here is the reason you can't use anti-aliasing for render targets, it isn't supported for DX 9...

http://msdn.microsoft.com/en-us/library/windows/desktop/bb147221(v=vs.85).aspx

 

This link says you can use anti-aliasing but unfortunately on my card it didn't work (GTX 250)

http://msdn.microsoft.com/en-us/library/windows/desktop/bb174361(v=vs.85).aspx

Edited by LancerSolurus

Share this post


Link to post
Share on other sites

In D3D9, you can indeed create a multisample render target, but it is not a texture, and cannot be used in a shader.  Your only option would be to resolve this target to a non-multisample texture of the same size, and use that in your shader.  Use StretchRect for the resolve.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement