| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- //////////////////////////////////////////////////////////////////////////////
- // ©2005 Electronic Arts Inc
- //
- // GPU vertex particle FX Shader
- //////////////////////////////////////////////////////////////////////////////
- #define USE_INTERACTIVE_LIGHTS 1
- #define SUPPORT_CLOUDS 1
- #define SUPPORT_FOG 1
- #define SUPPORT_GLOBAL_LIGHTS 1
- #include "Common.fxh"
- #include "CommonParticle.fxh"
- // ----------------------------------------------------------------------------
- // draw params
- // ----------------------------------------------------------------------------
- SAMPLER_2D_BEGIN( ParticleTextureSampler,
- string UIWidget = "None";
- string SasBindAddress = "Particle.Draw.Texture";
- )
- MinFilter = Linear;
- MagFilter = Linear;
- MipFilter = Linear;
- AddressU = Clamp;
- AddressV = Clamp;
- SAMPLER_2D_END
- // $Note(WSK) - We shouldn't need to use a different sampler, and it actually doesn't work on ps3
- // We should be able to do the same for pc and xenon but since they are close to final,
- // we want to be safe and make this change for ps3 only
- #if defined(EA_PLATFORM_PS3)
- static const sampler2D NextFrameTextureSamplerSampler = ParticleTextureSamplerSampler;
- #else // #if defined(EA_PLATFORM_PS3)
- SAMPLER_2D_BEGIN( NextFrameTextureSampler,
- string UIWidget = "None";
- string SasBindAddress = "Particle.Draw.Texture";
- )
- MinFilter = Linear;
- MagFilter = Linear;
- MipFilter = Linear;
- AddressU = Clamp;
- AddressV = Clamp;
- SAMPLER_2D_END
- #endif // #if defined(EA_PLATFORM_PS3)
- SAMPLER_2D_BEGIN( NormalTextureSampler,
- string UIWidget = "None";
- string SasBindAddress = "Particle.Draw.DetailTexture";
- )
- MinFilter = Linear;
- MagFilter = Linear;
- MipFilter = Linear;
- AddressU = Wrap;
- AddressV = Wrap;
- SAMPLER_2D_END
- //--------------------------------- GENERAL STUFF --------------------------------------
- // Variationgs for handling fog in the pixel shader
- static const int FogMode_Disabled = 0;
- static const int FogMode_Opaque = 1;
- static const int FogMode_Additive = 2;
- // Transformations
- float4x4 WorldViewProjection : WorldViewProjection;
- float4x3 View : View;
- float4x3 World : World;
- // Time (ie. material is animated)
- float Time : Time;
- // ----------------------------------------------------------------------------
- // SHADER: Default
- // ----------------------------------------------------------------------------
- struct ParticleVSOutput
- {
- float4 Position : POSITION;
- float2 ParticleTexCoord : TEXCOORD0;
- // float4 ShadowMapTexCoord : TEXCOORD1;
- float4 Color : COLOR0;
- // float3 Fog : TEXCOORD2; // This is just a scalar, but PS1.1 can't replicate-swizzle, so replicate scalar into a vector in vertex shader
- float Depth : TEXCOORD3; // For _CreateShadowMap technique
- float3 NextFrameTexCoord : TEXCOORD4; // for interpolating between two frames
- float4 LightVector[NumDirectionalLights] : TEXCOORD5;
- };
- // ----------------------------------------------------------------------------
- ParticleVSOutput ParticleVertexShader(
- float4 StartPositionLifeInFrames : POSITION,
- float4 StartVelocityCreationFrame : TEXCOORD0,
- float2 SeedAndIndex : TEXCOORD1,
- uniform int fogMode)
- {
- USE_DIRECTIONAL_LIGHT_INTERACTIVE(DirectionalLight, 0);
-
- 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);
- Out.Depth = Out.Position.z / Out.Position.w;
- //zVector = -zVector;
- float3 Normal = cross(xVector, zVector);
- float3 worldNormal = normalize(mul(Normal, (float3x3)World));
- float3 worldTangent = -zVector;
- float3 worldBinormal = xVector;
-
- float3x3 zRotation3D = float3x3(float3(zRotationMatrix[0], 0), float3(zRotationMatrix[1], 0), float3(0, 0, 1));
- // Build 3x3 tranform from object to tangent space
- float3x3 worldToTangentSpace = mul(transpose(float3x3(-worldBinormal, -worldTangent, worldNormal)), zRotation3D);
-
- for (int i = 0; i < NumDirectionalLights; i++)
- {
- // Compute lighting direction in tangent space
- Out.LightVector[i] = float4(mul(DirectionalLight[i].Direction, worldToTangentSpace), 0);
- }
- // if (fogMode != FogMode_Disabled)
- // {
- // // Fog depends on world position, but world matrix should be identity.
- // Out.Fog = CalculateFog(Fog, cornerPosition, GetEyePosition()).xxx;
- // }
- // else
- // {
- // Out.Fog = 0;
- // }
- // 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);
- Out.NextFrameTexCoord.xy = Particle_ComputeVideoTextureDefault(currentTexFrame + 1.0, texCoord);
- Out.NextFrameTexCoord.z = frac(currentTexFrame);
-
- // compute color
- float4 Color = Particle_ComputeColor(relativeAge, Seed, true);
-
- Out.Color = Color;
- // Out.ShadowMapTexCoord = CalculateShadowMapTexCoord(ShadowInfo, cornerPosition);
-
- return Out;
- }
- // ----------------------------------------------------------------------------
- float4 ParticlePixelShader(ParticleVSOutput In, uniform int fogMode) COLORTARGET
- {
- float4 Color = In.Color;
- float4 TextureColor = tex2D( SAMPLER(ParticleTextureSampler), In.ParticleTexCoord);
- float4 NextFrameColor = tex2D( SAMPLER(NextFrameTextureSampler), In.NextFrameTexCoord.xy);
- // Get bump map normal
- float3 bumpNormal = (float3)tex2D( SAMPLER(NormalTextureSampler), In.ParticleTexCoord) * 2.0 - 1.0;
- bumpNormal = normalize(bumpNormal * 10);
- float4 color = In.Color * TextureColor;// * 2;
- #if defined(EA_PLATFORM_PS3)
- float3 diffuselighting = 1.0;
- #else // #if defined(EA_PLATFORM_PS3)
- float3 diffuselighting = 0;
- for (int i = 0; i < NumDirectionalLights; i++)
- {
- // Compute lighting
- float diffuse = max(0, dot(bumpNormal, /*normalize*/(In.LightVector[i].xyz)));
-
- diffuselighting += DirectionalLight[i].Color * NoCloudMultiplier * diffuse;
- }
- #endif // #if defined(EA_PLATFORM_PS3)
- color.xyz *= diffuselighting;
-
- // Apply fog
- // float3 fogStrength = saturate(In.Fog) ;
- // if (fogMode == FogMode_Opaque)
- // {
- // // apply fog
- // Color.xyz = lerp(Fog.Color, Color.xyz, fogStrength);
- // }
- // else if (fogMode == FogMode_Additive)
- // {
- // // Fog used with additive blending just needs to reduce the additive influence, not blend towards the fog color
- // Color.xyz *= fogStrength;
- // }
-
- return color;
- }
- // ----------------------------------------------------------------------------
- float4 ParticlePixelShader_Xenon( ParticleVSOutput In ) : COLOR
- {
- return ParticlePixelShader( In, Fog.IsEnabled ? ((Draw.ShaderType == ShaderType_Additive || Draw.ShaderType == ShaderType_AdditiveAlphaTest || Draw.ShaderType == ShaderType_Multiply) ? FogMode_Additive : FogMode_Opaque) : FogMode_Disabled );
- }
- // ----------------------------------------------------------------------------
- // TECHNIQUE: DEFAULT
- // ----------------------------------------------------------------------------
- #define PS_ShaderType \
- compile PS_2_0 ParticlePixelShader(FogMode_Disabled), \
- compile PS_2_0 ParticlePixelShader(FogMode_Opaque), \
- compile PS_2_0 ParticlePixelShader(FogMode_Additive)
- DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_Final = 3 );
- #if SUPPORTS_SHADER_ARRAYS
- pixelshader PS_Array[PS_Multiplier_Final] =
- {
- PS_ShaderType
- };
- #endif
- // ----------------------------------------------------------------------------
- technique Default_M
- {
- pass P0
- <
- USE_EXPRESSION_EVALUATOR("Particle")
- >
- {
- VertexShader = compile VS_2_0 ParticleVertexShader(FogMode_Opaque);
- PixelShader = ARRAY_EXPRESSION_PS( PS_Array,
- Fog.IsEnabled ? ((Draw.ShaderType == ShaderType_Additive || Draw.ShaderType == ShaderType_AdditiveAlphaTest || Draw.ShaderType == ShaderType_Multiply) ? FogMode_Additive : FogMode_Opaque) : FogMode_Disabled,
- compile PS_VERSION ParticlePixelShader_Xenon()
- );
- ZEnable = true;
- ZFunc = ZFUNC_INFRONT;
- ZWriteEnable = false;
- CullMode = None;
- SETUP_ALPHA_BLEND_AND_TEST(Draw.ShaderType); }
- }
- #if ENABLE_LOD
- // ----------------------------------------------------------------------------
- // SHADER: LowQuality
- // ----------------------------------------------------------------------------
- struct ParticleVSLowOutput
- {
- float4 Position : POSITION;
- float2 ParticleTexCoord : TEXCOORD0;
- float4 Color : COLOR0;
- };
- // ----------------------------------------------------------------------------
- ParticleVSLowOutput ParticleVertexShaderLow(float4 StartPositionLifeInFrames : POSITION,
- float4 StartVelocityCreationFrame : TEXCOORD0, float2 SeedAndIndex : TEXCOORD1)
- {
- ParticleVSLowOutput 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_Simplified(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);
- // texture coordinate
- float2 texCoord = GetVertexTexCoord(vertexCorner);
- Out.ParticleTexCoord = Particle_ComputeVideoTextureDefault(age * Draw.SpeedMultiplier, texCoord);
- // compute color
- Out.Color = Particle_ComputeColor(relativeAge, Seed, false);
-
- return Out;
- }
- // ----------------------------------------------------------------------------
- float4 ParticlePixelShaderLow(ParticleVSLowOutput In) : COLOR
- {
- float4 TextureColor = tex2D( SAMPLER(ParticleTextureSampler), In.ParticleTexCoord);
- float4 Color = TextureColor * In.Color;
- return Color;
- }
- // ----------------------------------------------------------------------------
- // TECHNIQUE: LowQuality
- // ----------------------------------------------------------------------------
- technique _Default_L
- {
- pass P0
- <
- USE_EXPRESSION_EVALUATOR("Particle")
- >
- {
- VertexShader = compile VS_2_0 ParticleVertexShaderLow();
- PixelShader = compile PS_2_0 ParticlePixelShaderLow();
- ZEnable = true;
- ZFunc = ZFUNC_INFRONT;
- ZWriteEnable = false;
- CullMode = None;
-
- SETUP_ALPHA_BLEND_AND_TEST(Draw.ShaderType);
- }
- }
- #endif // #if ENABLE_LOD
- // ----------------------------------------------------------------------------
- // SHADER: ShadowMap
- // ----------------------------------------------------------------------------
- float4 CreateShadowMapPS(ParticleVSOutput In, uniform int shaderType) COLORTARGET
- {
- float4 textureColor = tex2D( SAMPLER(ParticleTextureSampler), In.ParticleTexCoord);
- float4 color = textureColor * In.Color;
- // Threshold where "alpha testing" or color equivalents set pixel to be opaque.
- // Needs to be much lower than common alpha test threshold as a single particle is usually quite transparent.
- const float opacityThreshold = 0.1;
-
- if (shaderType == ShaderType_Additive)
- {
- // The brighter the color the denser the particle. Clip dark areas.
- clip(dot(color, float3(1, 1, 1)) - 3 * opacityThreshold);
- }
- else if (shaderType == ShaderType_Multiply)
- {
- // The darker the color the denser the particle. Clip bright areas.
- clip(3 * opacityThreshold - dot(color, float3(1, 1, 1)));
- }
- else if (shaderType == ShaderType_AdditiveAlphaTest || shaderType == ShaderType_Alpha
- || shaderType == ShaderType_AlphaTest)
- {
- // Simulate alpha testing
- clip(color.a - opacityThreshold);
- }
- return In.Depth;
- }
- // ----------------------------------------------------------------------------
- float4 CreateShadowMapPS_Xenon( ParticleVSOutput In ) : COLOR
- {
- return CreateShadowMapPS( In, min(Draw.ShaderType, ShaderType_Multiply) );
- }
- // ----------------------------------------------------------------------------
- // TECHNIQUE: CreateShadowMap
- // ----------------------------------------------------------------------------
- #define PSCreateShadowMap_ShaderType \
- compile PS_2_0 CreateShadowMapPS(0), \
- compile PS_2_0 CreateShadowMapPS(ShaderType_Additive), \
- compile PS_2_0 CreateShadowMapPS(ShaderType_AdditiveAlphaTest), \
- compile PS_2_0 CreateShadowMapPS(ShaderType_Alpha), \
- compile PS_2_0 CreateShadowMapPS(ShaderType_AlphaTest), \
- compile PS_2_0 CreateShadowMapPS(ShaderType_Multiply)
- DEFINE_ARRAY_MULTIPLIER( PSCreateShadowMap_Multiplier_Final = 6 );
- #if SUPPORTS_SHADER_ARRAYS
- pixelshader PSCreateShadowMap_Array[PSCreateShadowMap_Multiplier_Final] =
- {
- PSCreateShadowMap_ShaderType
- };
- #endif
- // ----------------------------------------------------------------------------
- technique _CreateShadowMap
- {
- pass P0
- <
- USE_EXPRESSION_EVALUATOR("GPUParticle_CreateShadowMap")
- >
- {
- VertexShader = compile VS_2_0 ParticleVertexShader(FogMode_Disabled);
- PixelShader = ARRAY_EXPRESSION_PS( PSCreateShadowMap_Array,
- min(Draw.ShaderType, ShaderType_Multiply),
- compile PS_VERSION CreateShadowMapPS_Xenon()
- );
- ZEnable = true;
- ZFunc = ZFUNC_INFRONT;
- ZWriteEnable = true;
- CullMode = None;
- AlphaBlendEnable = false;
- AlphaTestEnable = false; // Handled in pixel shader
- }
- }
|