• Advertisement
Sign in to follow this  

Manipulating Particles alpha channel according to the Depth

This topic is 1653 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 trying to implement soft particles for the first time, I created a depth texture using MRT, sent it to the shader, now I'm trying to manipulate the particles alpha channel based on the depth texture.

 

What's going wrong with the following code? It's not working as expected.

 

Shader:

 
texture depthMapTexture;
sampler2D depthMap = sampler_state
{
    Texture = <depthMapTexture>;
    MagFilter = Point;
    MinFilter = Point;
    MipFilter = None;
};

VS_OUTPUT VS( VS_INPUT IN )
{
    ...
    ...
    ...
    OUT.DepthPos = mul(float4(IN.Pos.xyz, 1.0), mul(World, View)).xyz;
    return OUT;
}

float4 PS( VS_OUTPUT IN ) : COLOR
{
    float4 texDiffuse = tex2D(colorMap, IN.UV);
    float particleDepth = IN.DepthPos.z;
    float sceneDepth = tex2D(depthMap, IN.UV).x;
    float scale = 1.0;
    float zFade = saturate(scale * (particleDepth - sceneDepth)); 
    IN.Color.a *= zFade;
    return texDiffuse * IN.Color;
}
Edited by Medo3337

Share this post


Link to post
Share on other sites
Advertisement

I think I need to change this line to sample the depth texture according to the screen resolution?

float sceneDepth = tex2D(depthMap, IN.UV).x;

 

Any idea how do I fix my code?

Share this post


Link to post
Share on other sites

This is my first time testing "Soft Particles" so i might be wrong somewhere, but for now it looks good:

OFF

nosoft.jpg

 

ON

yessoft.jpg

 

relevant shader parts:

float4 ScreenParams;
...
struct FS_VS_OUTPUT
{
    float4 Position  : POSITION;
    float2 TexCoord0 : TEXCOORD0;
    float4 TexCoord1 : TEXCOORD1;
    float3 PosWV     : TEXCOORD2;
};

struct FS_PS_OUTPUT
{
    float4 Color : COLOR0;
};

void VertexProgram(in FS_VERTEX IN, out FS_VS_OUTPUT OUT)
{
    float4 oPosition = mul(float4(IN.Position, 1.0f), WorldViewProjection);
    OUT.Position     = oPosition;
    oPosition.x      = ((oPosition.x + oPosition.w) * ScreenParams.x + oPosition.w) * ScreenParams.z;
    oPosition.y      = ((oPosition.w - oPosition.y) * ScreenParams.y + oPosition.w) * ScreenParams.w;
    OUT.TexCoord0    = IN.TexCoord0;
    OUT.TexCoord1    = oPosition;
    OUT.PosWV        = mul(float4(IN.Position, 1.0f), WorldView).xyz;
}
 
// function from NVIDIA sample
float Contrast(float Input, float ContrastPower)
{
#if 1
     //piecewise contrast function
     bool IsAboveHalf = Input > 0.5 ;
     float ToRaise = saturate(2*(IsAboveHalf ? 1-Input : Input));
     float Output = 0.5*pow(ToRaise, ContrastPower);
     Output = IsAboveHalf ? 1-Output : Output;
     return Output;
#else
    // another solution to create a kind of contrast function
    return 1.0 - exp2(-2*pow(2.0*saturate(Input), ContrastPower));
#endif
}

void PixelProgram(in FS_VS_OUTPUT IN, out FS_PS_OUTPUT OUT)
{
    float scene_z    = tex2Dproj(DepthSamp, IN.TexCoord1).z;
    float particle_z = IN.PosWV.z;
    float depthDiff  = (scene_z - particle_z);
    float fade       = Contrast(depthDiff * 0.82f, 2.0f);
    float4 color     = tex2D(ColorSamp, IN.TexCoord0);
    color.a         *= fade;
    OUT.Color        = color;
}

technique tTech2
{
    pass p0
    {
        VertexShader = compile vs_3_0 VertexProgram();
        PixelShader  = compile ps_3_0 PixelProgram();

        ALPHABLENDENABLE = TRUE;
        SRCBLEND         = SRCALPHA;
        DESTBLEND        = INVSRCALPHA;
        ZWRITEENABLE     = FALSE;
    }
}

 

Where ScreenParams is:

D3DXVECTOR4 screenParams((float)WIN_DIM.cx, (float)WIN_DIM.cy, 1.0f / (2.0f * (float)WIN_DIM.cx), 1.0f / (2.0f * (float)WIN_DIM.cy));

Share this post


Link to post
Share on other sites

It didn't work for me, I can't see the particles most of the time, here is the shader code:

float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 WorldViewProj;

float4 ScreenParams;

struct VS_INPUT
{
   float3 Pos : POSITION;
   float4 Color : COLOR;
   float2 UV : TEXCOORD0;
   float3 Normal : NORMAL;
};

struct VS_OUTPUT
{
    float4 Pos : POSITION;
    float4 Color : COLOR;
    float2 UV : TEXCOORD0;
    float3 Normal : TEXCOORD1;
    float3 worldPos : TEXCOORD2;
    float3 WPos : TEXCOORD3;
    float3 DepthPos : TEXCOORD4;
    float4 screenPos : TEXCOORD5;
};


texture colorMapTexture;
sampler2D colorMap = sampler_state
{
    Texture = <colorMapTexture>;
    MagFilter = Linear;
    MinFilter = Anisotropic;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};


texture depthMapTexture;
sampler2D depthMap = sampler_state
{
    Texture = <depthMapTexture>;
    MIPFILTER   = LINEAR;
    MAGFILTER   = LINEAR;
    MINFILTER   = LINEAR;
};

//-----------------------------------------------------------------------
// Vertex shader function
//-----------------------------------------------------------------------
VS_OUTPUT VS( VS_INPUT IN )
{
    VS_OUTPUT OUT;
    OUT = (VS_OUTPUT)0;
    float4 oPosition = mul(float4(IN.Pos, 1.0f), WorldViewProj);
    OUT.Pos = oPosition;
    OUT.UV = IN.UV;
    OUT.Color = IN.Color;
    OUT.Normal    = mul(float4(IN.Normal, 0.0f), World).xyz;
    OUT.worldPos  = mul(float4(IN.Pos, 1.0f), World).xyz;
    OUT.WPos = IN.Pos;
    OUT.DepthPos = mul(float4(IN.Pos.xyz, 1.0), mul(World, View)).xyz;
    oPosition.x      = ((oPosition.x + oPosition.w) * ScreenParams.x + oPosition.w) * ScreenParams.z;
    oPosition.y      = ((oPosition.w - oPosition.y) * ScreenParams.y + oPosition.w) * ScreenParams.w;
    OUT.screenPos = oPosition;
    return OUT;
}

// function from NVIDIA sample
float Contrast(float Input, float ContrastPower)
{
#if 1
     //piecewise contrast function
     bool IsAboveHalf = Input > 0.5 ;
     float ToRaise = saturate(2*(IsAboveHalf ? 1-Input : Input));
     float Output = 0.5*pow(ToRaise, ContrastPower);
     Output = IsAboveHalf ? 1-Output : Output;
     return Output;
#else
    // another solution to create a kind of contrast function
    return 1.0 - exp2(-2*pow(2.0*saturate(Input), ContrastPower));
#endif
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( VS_OUTPUT IN ) : COLOR
{
    float4 texDiffuse = tex2D(colorMap, IN.UV);
    float scene_z    = tex2Dproj(depthMap, IN.screenPos).z;
    float particle_z = IN.DepthPos.z;
    float depthDiff  = (scene_z - particle_z);
    float fade       = Contrast(depthDiff * 0.82f, 2.0f);

    float4 color = texDiffuse * IN.Color;
    color.a *= fade;
    return color;
}


technique PTech
{
    pass
    {
        AlphaBlendEnable = TRUE;
        SrcBlend = SRCALPHA;
        DestBlend = INVSRCALPHA;
        ZEnable = TRUE;
        VertexShader = compile vs_3_0 VS();
        PixelShader = compile ps_3_0 PS();
    }
}

Share this post


Link to post
Share on other sites

There is a small problem which i did not solve yet:

terrain2013-08-1515-50-0.jpg

 

EDIT: Temporary fix:

if(depthDiff > 0.0f)
        color.a         *= fade;
Edited by belfegor

Share this post


Link to post
Share on other sites

@belfegor: When I change the line:

float fade       = Contrast(depthDiff * 0.82f, 2.0f);

To:

float fade       = Contrast(depthDiff * 0.001f, 2.0f);

The soft particles works, but ONLY on the terrain! I see hard particles on other meshes.

 

I'm rendering the terrain with a shader and all other meshes with another shader.

 

I also notice that the other meshes never get smoke at all if I rendered the terrain BEFORE the other meshes.

 

I think that the terrain shader maybe overriding the other meshes depth?

 

I appreciate your help! :)

Edited by Medo3337

Share this post


Link to post
Share on other sites

@belfegor: It's working now but I can notice some sort of hard edges (not like before) but still noticeable:

[attachment=17411:26226.png]

 

How do I fix it?

 

Last thing: How do I enable multisample anti-aliasing? It's not working anymore.

Share this post


Link to post
Share on other sites


How do I fix it?

I really don't know.

Only samples that i could find was obfuscated with other unrelated stuff so i could not see the main/key points to understand this properly, so i guessed some stuff and

shared my project with you as it is better then nothing, right?

 


How do I enable multisample anti-aliasing? It's not working anymore

I think you can't have dx "built in" AA with MRTs, research about other AA methods or do multiple render passes.

Share this post


Link to post
Share on other sites

@belfegor: I'm able to get better results by playing around with the soft particles scale value and of course much better than hard particles:

Contrast(depthDiff * Scale, 1.0f); // Not sure what is 1.0f

The only problem now which I'm concerned about is anti-aliasing, I think it's worth to open a new thread.

 

Many many thanks! You helped a lot :)

Share this post


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

  • Advertisement