| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- //////////////////////////////////////////////////////////////////////////////
- // ©2005 Electronic Arts Inc
- //
- // GPU vertex particle FX Shader
- //////////////////////////////////////////////////////////////////////////////
- #include "Common.fxh"
- #include "CommonParticle.fxh"
- int _SasGlobal : SasGlobal
- <
- string UIWidget = "None";
- int3 SasVersion = int3(1, 0, 0);
-
- string RenderBin = "Distorter";
- > = 0;
- SAMPLER_2D_BEGIN( NormalTexture,
- string UIWidget = "None";
- string SasBindAddress = "Particle.Draw.Texture";
- )
- MinFilter = Linear;
- MagFilter = Linear;
- MipFilter = Linear;
- AddressU = Wrap;
- AddressV = Wrap;
- SAMPLER_2D_END
- // Used to see where the particle volume intersects an object.
- SAMPLER_2D_BEGIN( DepthTexture,
- string SasBindAddress = "WW3D.DepthTexture";
- )
- MinFilter = Linear;
- MagFilter = Linear;
- MipFilter = Point;
- AddressU = Clamp;
- AddressV = Clamp;
- SAMPLER_2D_END
- //--------------------------------- GENERAL STUFF --------------------------------------
- bool ShouldDrawParticleSoft
- <
- string UIWidget = "None";
- string SasBindAddress = "Particle.Draw.ShouldDrawParticleSoft";
- > = false;
- // Transformations
- float4x4 WorldView : WorldView;
- float4x4 Projection: Projection;
- float4x4 WorldViewProjection : WorldViewProjection;
- float4x3 View : View;
- float4x3 World : World;
- float4x4 ProjectionI : ProjectionInverse;
- // Time (ie. material is animated)
- float Time : Time;
- // ----------------------------------------------------------------------------
- // SHADER: Default
- // ----------------------------------------------------------------------------
- struct ParticleVSOutput
- {
- float4 Position : POSITION;
- float2 ParticleTexCoord : TEXCOORD0;
- float4 Color : TEXCOORD1; // Not in color register to have increased range from -1 to 1
- float3x3 TangentToViewSpace : TEXCOORD2;
- float4 NDCPosition : TEXCOORD5;
- float2 ZPositions : TEXCOORD6; // x is the particle z position, y is the ViewEyeDirection z component.
- };
- // Making this value smaller will increase the size of the transparent edge where
- // the particle intersects the background.
- #define PARTICLE_VOLUME_SCALE 5
- // ----------------------------------------------------------------------------
- ParticleVSOutput ParticleVertexShader(
- float4 StartPositionLifeInFrames : POSITION,
- float4 StartVelocityCreationFrame : TEXCOORD0,
- float2 SeedAndIndex : TEXCOORD1)
- {
- ParticleVSOutput Out;
- // decode vertex data
- float3 StartPosition = StartPositionLifeInFrames.xyz;
- float LifeInFrames = StartPositionLifeInFrames.w;
- float3 StartVelocity = StartVelocityCreationFrame.xyz;
- float CreationFrame = StartVelocityCreationFrame.w;
- float Seed = SeedAndIndex.x;
- float Index = SeedAndIndex.y;
- // particle system works with frames, so first convert time to frame
- // rather than converting everything else to time
- float age = (Time * CLIENT_FRAMES_PER_SECOND - CreationFrame);
-
- // first eliminate dead particles
- if (age > LifeInFrames)
- {
- Index = 0;
- }
- float relativeAge = age / LifeInFrames;
- float3 particlePosition;
- float size;
- float2x2 zRotationMatrix;
-
- Particle_ComputePhysics(particlePosition, size, zRotationMatrix,
- age, StartPosition, StartVelocity, Seed);
- // Calculate vertex position
- float2 vertexCorner = VertexCorners[Index];
- float2 relativeCornerPos = mul(vertexCorner, zRotationMatrix);
- float3 xVector = float3( View[0][0], View[1][0], View[2][0] );
- float3 zVector = float3( View[0][1], View[1][1], View[2][1] );
- float3 cornerPosition = particlePosition + size * (relativeCornerPos.x * xVector + relativeCornerPos.y * zVector);
-
- Out.Position = mul(float4(cornerPosition, 1), WorldViewProjection);
- //zVector = -zVector;
- float3 Normal = cross(xVector, zVector);
- float3 worldNormal = normalize(mul(Normal, (float3x3)World));
- float3 worldTangent = -zVector;
- float3 worldBinormal = -xVector; // This is inverted to what the normal mapping particles do as screen space xy is upside down otherwise
- float3x3 zRotation3D = float3x3(float3(zRotationMatrix[0], 0), float3(zRotationMatrix[1], 0), float3(0, 0, 1));
- // Build 3x3 tranform from tangent to world space
- float3x3 tangentToWorldSpace = mul(transpose(zRotation3D), float3x3(-worldBinormal, -worldTangent, worldNormal));
- Out.TangentToViewSpace = mul(tangentToWorldSpace, (float3x3)View);
-
- // Texture coordinate
- float randomIndex = GetRandomFloatValue(float2(0.0f, 1.0f), Seed, 7) * Draw.VideoTex_NumPerRow_LastFrame_SingleRow_isRand.y;
- randomIndex -= frac(randomIndex);
- float currentTexFrame = age * Draw.SpeedMultiplier + randomIndex;
- float2 texCoord = GetVertexTexCoord(vertexCorner);
- Out.ParticleTexCoord = Particle_ComputeVideoTextureDefault(currentTexFrame, texCoord);
- // Convert the particle position into view space so that we can get the distance
- // between the particle and the background.
- float particleSize = size / PARTICLE_VOLUME_SCALE;
- float4 particlePosView = mul(float4(cornerPosition, 1), WorldView);
- Out.ZPositions.x = particlePosView.z / particleSize;
-
- // Finish projecting the position.
- float4 ndcPos = mul(particlePosView, Projection);
- Out.Position = ndcPos;
- Out.NDCPosition = ndcPos;
-
- // Convert the position into a view vector to the far plane.
- float4 screenFarPlanePosition = float4(ndcPos.xy, 1, 1);
- float4 viewFarPlanePosition4 = mul(screenFarPlanePosition, ProjectionI);
- float3 viewFarPlanePosition = viewFarPlanePosition4.xyz / viewFarPlanePosition4.w;
-
- // We don't really want a vector to the far plane. We want the vector with a z length of 1,
- // so that we know how much in x-y we need to step per z-depth that we get from the depth texture.
- Out.ZPositions.y = (viewFarPlanePosition.z / viewFarPlanePosition.z) / particleSize;
-
- // compute color
- float4 color = Particle_ComputeColor(relativeAge, Seed, true);
- color.xyz = color.xyz * 2.0 - 1.0; // Unpack to treat the color as normal
- Out.Color = color;
- return Out;
- }
- // ----------------------------------------------------------------------------
- float4 SoftParticlePixelShader(ParticleVSOutput In, uniform bool shouldDrawParticleSoft) COLORTARGET
- {
- float4 normalMapSample = tex2D( SAMPLER(NormalTexture), In.ParticleTexCoord);
- // Get bump map normal
- float3 bumpNormal = normalMapSample.xyz * 2.0 - 1.0;
- bumpNormal = normalize(bumpNormal);
- float3 normal = mul(bumpNormal, In.TangentToViewSpace);
- float4 color = float4(In.Color.xyz * normal * 0.5 + 0.5, In.Color.w * normalMapSample.w);
- if (shouldDrawParticleSoft)
- {
- float3 ndcPosition = In.NDCPosition.xyz / In.NDCPosition.w;
- // Convert the position into texture space then grab the depth value from the
- // depth texture. Then, move along that vector by the depth to find the pixel position.
- float2 depthTexCoord = ndcPosition.xy * float2(0.5, -0.5) + 0.5;
- float backgroundDepth = tex2D(SAMPLER(DepthTexture), depthTexCoord).x;
- float backgroundPosView = backgroundDepth * In.ZPositions.y;
- // The closer the particle is to the background, the more transparent it is.
- float linearBlend = saturate(In.ZPositions.x - backgroundPosView);
- // Don't do soft particles for ground aligned particles, as they will often be almost fully transparent due to terrain proximity
- #if !defined(FORCE_PARTICLES_INTO_XY_PLANE)
- color.w *= linearBlend;
- #endif
- }
-
- return color;
- }
- // ----------------------------------------------------------------------------
- // SHADER: XENON
- // ----------------------------------------------------------------------------
- float4 ParticlePixelShader_Xenon(ParticleVSOutput In) : COLOR
- {
- return SoftParticlePixelShader(In, ShouldDrawParticleSoft);
- }
- // ----------------------------------------------------------------------------
- // TECHNIQUE: Default (High and up)
- // ----------------------------------------------------------------------------
- DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_ShouldDrawParticleSoft_H = 1 );
- #define PS_ShouldDrawParticleSoft_H \
- compile PS_2_0 SoftParticlePixelShader(false), \
- compile PS_2_0 SoftParticlePixelShader(true)
- DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_Final_H = PS_Multiplier_ShouldDrawParticleSoft_H * 2 );
- #if SUPPORTS_SHADER_ARRAYS
- pixelshader PS_Array_H[PS_Multiplier_Final_H] =
- {
- PS_ShouldDrawParticleSoft_H
- };
- #endif
- technique Default
- {
- pass P0
- <
- USE_EXPRESSION_EVALUATOR("Particle")
- >
- {
- VertexShader = compile VS_2_0 ParticleVertexShader();
- PixelShader = ARRAY_EXPRESSION_PS( PS_Array_H,
- ShouldDrawParticleSoft,
- compile PS_VERSION ParticlePixelShader_Xenon()
- );
- ZEnable = true;
- ZFunc = ZFUNC_INFRONT;
- ZWriteEnable = false;
- CullMode = None;
- SETUP_ALPHA_BLEND_AND_TEST(Draw.ShaderType);
- }
- }
- #if ENABLE_LOD
- // ----------------------------------------------------------------------------
- // TECHNIQUE: Default (Medium and up)
- // ----------------------------------------------------------------------------
- technique Default_M
- {
- pass P0
- <
- USE_EXPRESSION_EVALUATOR("Particle")
- >
- {
- VertexShader = compile VS_2_0 ParticleVertexShader();
- PixelShader = compile PS_2_0 SoftParticlePixelShader(false);
- ZEnable = true;
- ZFunc = ZFUNC_INFRONT;
- ZWriteEnable = false;
- CullMode = None;
- SETUP_ALPHA_BLEND_AND_TEST(Draw.ShaderType);
- }
- }
- // ----------------------------------------------------------------------------
- // TECHNIQUE: LowQuality
- // ----------------------------------------------------------------------------
- technique Default_L
- {
- // Disabled
- }
- #endif
|