📄 softparticles.fx
字号:
//--------------------------------------------------------------------------------------
// File: SoftParticles.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
// structs
struct VSSceneIn
{
float3 Pos : POSITION;
float3 Norm : NORMAL;
float2 Tex : TEXCOORD;
float3 Tan : TANGENT;
};
struct PSSceneIn
{
float4 Pos : SV_POSITION;
float3 Norm : NORMAL;
float2 Tex : TEXCOORD0;
float3 Tan : TEXCOORD1;
float3 vPos : TEXCOORD2;
};
struct VSParticleIn
{
float3 Pos : POSITION;
float3 Vel : VELOCITY;
float Life : LIFE;
float Size : SIZE;
};
struct GSParticleIn
{
float3 Pos : POSITION;
float Life : LIFE; //stage of animation we're in [0..1] 0 is first frame, 1 is last
float Size : SIZE;
};
struct PSParticleIn
{
float4 Pos : SV_POSITION;
float3 Tex : TEXCOORD0;
float2 ScreenTex : TEXCOORD1;
float2 Depth : TEXCOORD2;
float Size : TEXCOORD3;
float3 worldPos : TEXCOORD4;
float3 particleOrig : TEXCOORD5;
float3 particleColor : TEXCOORD6;
};
cbuffer cbPerObject
{
matrix g_mWorldViewProj;
matrix g_mWorldView;
matrix g_mWorld;
matrix g_mInvView;
matrix g_mInvProj;
float3 g_vViewDir;
};
cbuffer cbUser
{
float g_fFadeDistance;
float g_fSizeZScale;
float4 g_vViewLightDir1;
float4 g_vViewLightDir2;
float4 g_vWorldLightDir1;
float4 g_vWorldLightDir2;
float4 g_vEyePt;
float g_stepSize = 0.01;
float g_noiseSize = 40.0;
float g_noiseOpacity = 20.0;
};
cbuffer cbNoiseOffset
{
float4 g_OctaveOffsets[4];
};
cbuffer cbImmutable
{
float3 g_positions[4] =
{
float3( -1, 1, 0 ),
float3( 1, 1, 0 ),
float3( -1, -1, 0 ),
float3( 1, -1, 0 ),
};
float2 g_texcoords[4] =
{
float2(0,0),
float2(1,0),
float2(0,1),
float2(1,1),
};
float4 g_directional1 = float4( 0.992, 1.0, 0.880, 0.0 );
float4 g_directional2 = float4( 0.595, 0.6, 0.528, 0.0 );
float4 g_ambient = float4(0.525,0.474,0.474,0.0);
};
Texture2D g_txDiffuse;
Texture2D g_txNormal;
Texture2D g_txColorGradient;
Texture3D g_txVolumeDiff;
Texture3D g_txVolumeNorm;
Texture2D g_txDepth;
SamplerState g_samLinearClamp
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
SamplerState g_samLinearWrap
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
SamplerState g_samPoint
{
Filter = MIN_MAG_MIP_POINT;
AddressU = Clamp;
AddressV = Clamp;
};
SamplerState g_samVolume
{
Filter = MIN_MAG_LINEAR_MIP_POINT;
AddressU = Wrap;
AddressV = Wrap;
AddressW = Wrap;
};
BlendState AlphaBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA;
DestBlend = INV_SRC_ALPHA;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
BlendState NoBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
};
DepthStencilState EnableDepth
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
};
DepthStencilState DisableDepth
{
DepthEnable = FALSE;
DepthWriteMask = ZERO;
};
DepthStencilState DisableDepthWrite
{
DepthEnable = TRUE;
DepthWriteMask = ZERO;
};
DepthStencilState DisableDepthTest
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
DepthFunc = ALWAYS;
};
//
// Vertex shader for drawing the scene
//
PSSceneIn VSScenemain(VSSceneIn input)
{
PSSceneIn output;
output.vPos = mul( float4(input.Pos,1), g_mWorld );
output.Pos = mul( float4(input.Pos,1), g_mWorldViewProj );
output.Norm = normalize( mul( input.Norm, (float3x3)g_mWorld ) );
output.Tan = normalize( mul( input.Tan, (float3x3)g_mWorld ) );
output.Tex = input.Tex;
return output;
}
//
// PS for the scene
//
float4 PSScenemain(PSSceneIn input) : SV_Target
{
float4 diffuse = g_txDiffuse.Sample( g_samLinearWrap, input.Tex );
float specMask = diffuse.a;
float3 norm = g_txNormal.Sample( g_samLinearWrap, input.Tex );
norm *= 2;
norm -= float3(1,1,1);
float3 binorm = normalize( cross( input.Norm, input.Tan ) );
float3x3 BTNMatrix = float3x3( binorm, input.Tan, input.Norm );
norm = normalize(mul( norm, BTNMatrix ));
// diffuse lighting
float4 lighting = saturate( dot( norm, g_vWorldLightDir1.xyz ) )*g_directional1;
lighting += saturate( dot( norm, g_vWorldLightDir2.xyz ) )*g_directional2;
lighting += g_ambient;
// Calculate specular power
float3 viewDir = normalize( g_vEyePt - input.vPos );
float3 halfAngle = normalize( viewDir + g_vWorldLightDir1.xyz );
float4 specPower1 = saturate( pow( dot( halfAngle, norm ), 32 ) ) * g_directional1;
halfAngle = normalize( viewDir + g_vWorldLightDir2.xyz );
float4 specPower2 = saturate( pow( dot( halfAngle, norm ), 32 ) ) * g_directional2;
return lighting*diffuse + (specPower1+specPower2)*specMask;
}
//
// PS for the sky
//
float4 PSSkymain(PSSceneIn input) : SV_Target
{
return g_txDiffuse.Sample( g_samLinearWrap, input.Tex );
}
//
// Vertex shader for drawing particles
//
GSParticleIn VSParticlemain(VSParticleIn input)
{
GSParticleIn output;
output.Pos = input.Pos;
output.Life = input.Life;
output.Size = input.Size;
return output;
}
//
// Geometry shader for creating point sprites
//
[maxvertexcount(4)]
void GSParticlemain(point GSParticleIn input[1], inout TriangleStream<PSParticleIn> SpriteStream)
{
PSParticleIn output;
float4 orig = mul( float4(input[0].Pos,1), g_mWorld );
output.particleOrig = orig.xyz;
if( input[0].Life > -1 )
{
// calculate color from a 1d gradient texture
float3 particleColor = g_txColorGradient.SampleLevel( g_samLinearClamp, float2(input[0].Life,0), 0 );
output.particleColor = particleColor;
//
// Emit two new triangles
//
[unroll] for(int i=0; i<4; i++)
{
float3 position = g_positions[i]*input[0].Size;
position = mul( position, (float3x3)g_mInvView ) + input[0].Pos;
output.Pos = mul( float4(position,1.0), g_mWorldViewProj );
// pass along the texcoords
output.Tex = float3(g_texcoords[i],input[0].Life);
// screenspace coordinates for the lookup into the depth buffer
output.ScreenTex = output.Pos.xy/output.Pos.w;
// output depth of this particle
output.Depth = output.Pos.zw;
// size
output.Size = input[0].Size;
// world position
float4 posWorld = mul( float4(position,1.0), g_mWorld );
output.worldPos = posWorld;
SpriteStream.Append(output);
}
SpriteStream.RestartStrip();
}
}
//
// PS for the particles
//
float4 PSBillboardParticlemain(PSParticleIn input, uniform bool bSoftParticles ) : SV_TARGET
{
float2 screenTex = 0.5*( (input.ScreenTex) + float2(1,1));
screenTex.y = 1 - screenTex.y;
float4 particleSample = g_txVolumeDiff.Sample( g_samVolume, input.Tex );
float particleDepth = input.Depth.x;
particleDepth /= input.Depth.y;
float depthFade = 1;
if( bSoftParticles )
{
// We need to determine the distance between the value stored in the depth buffer
// and the value that came in from the GS
// Because the depth values aren't linear, we need to transform the depthsample back into view space
// in order for the comparison to give us an accurate distance
float depthSample = g_txDepth.Sample( g_samPoint, screenTex );
float4 depthViewSample = mul( float4( input.ScreenTex, depthSample, 1 ), g_mInvProj );
float4 depthViewParticle = mul( float4( input.ScreenTex, particleDepth, 1 ), g_mInvProj );
float depthDiff = depthViewSample.z/depthViewSample.w - depthViewParticle.z/depthViewParticle.w;
if( depthDiff < 0 )
discard;
depthFade = saturate( depthDiff / g_fFadeDistance );
}
float4 Light = g_directional1 + g_ambient;
particleSample.rgb *= Light.xyz*input.particleColor;
particleSample.a *= depthFade;
return particleSample;
}
struct PSParticleOut
{
float4 Color : SV_Target;
float Depth : SV_Depth;
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -