| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633 |
- //////////////////////////////////////////////////////////////////////////////
- // 2008 Electronic Arts Inc
- //
- // Common GPU geometry particle FX Shader
- //////////////////////////////////////////////////////////////////////////////
- #ifndef _COMMON_GEOMETRY_PARTICLE_FXH_
- #define _COMMON_GEOMETRY_PARTICLE_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)
- // 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;
- // 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 WorldView : WorldView;
- float4x4 Projection : Projection;
- float4x4 WorldViewProjection : WorldViewProjection;
- float4x3 View : View;
- float4x4 ProjectionI : ProjectionInverse;
- #if defined(_WW3D_)
- #if !defined(USE_INDIRECT_CONSTANT)
- float3 EyePosition
- <
- string UIWidget = "None";
- string SasBindAddress = "Sas.Camera.Position";
- >;
- #endif // #if !defined(USE_INDIRECT_CONSTANT)
- float3 GetEyePosition()
- {
- return EyePosition;
- }
- #else // #if defined(_WW3D_)
- float4x3 ViewI : ViewInverse;
- float3 GetEyePosition()
- {
- return ViewI[3];
- }
- #endif // #if defined(_WW3D_)
- // Time (ie. material is animated)
- float Time : Time;
- // ----------------------------------------------------------------------------
- // SHADER: HIGH ~ ULTRAHIGH
- // ----------------------------------------------------------------------------
- struct ParticleVSOutput_H
- {
- float4 Position : POSITION;
- float2 ParticleTexCoord : TEXCOORD0;
- float4 Color : COLOR0;
- float3 Fog : TEXCOORD1; // This is just a scalar, but PS1.1 can't replicate-swizzle, so replicate scalar into a vector in vertex shader
- float Depth : TEXCOORD2; // For _CreateShadowMap technique
- float3 NextFrameTexCoord : TEXCOORD3; // for interpolating between two frames
- float4 NDCPosition : TEXCOORD4;
- float2 ZPositions : TEXCOORD5; // 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 1.5
- // For indexing the shader array based on what type of blend is needed for the particle draw type.
- #define SOFTBLEND_ADDITIVE 0
- #define SOFTBLEND_ALPHA 1
- #define SOFTBLEND_DISABLED 2
- // These are the FXParticleSystem_RotationType values in FXParticleBase.xsd minus 1. We subtract
- // 1 so that it's easier to index into a shader array.
- #define ROTATION_OFF 0
- #define ROTATE_AROUND_VELOCITY 1
- #define ROTATE_IN_WORLD_SPACE 2
- //
- // Geometry update params. These update every frame.
- //
- struct ParticleGeometryUpdate
- {
- float3 StartSizeMinimums;
- float3 StartSizeSpreads;
- float3 SizeRateMinimums;
- float3 SizeRateSpreads;
- float3 SizeDampingMinimums;
- float3 SizeDampingSpreads;
- float3 AngleMinimums;
- float3 AngleSpreads;
- float3 AngularRateMinimums;
- float3 AngularRateSpreads;
- float2 AngleDampingMin_AngleDampingSpread;
- int RotationType;
- };
- ParticleGeometryUpdate GeometryUpdate
- <
- string UIWidget = "None";
- string SasBindAddress = "Particle.GeometryUpdate";
- >
- #if !defined(EA_PLATFORM_PS3) // PS3 TODO - Does not like this being initialized.
- =
- {
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0),
- float2(0, 0),
- int(0)
- }
- #endif // #if !defined(EA_PLATFORM_PS3) // PS3 TODO - Does not like this being initialized.
- ;
- // ----------------------------------------------------------------------------
- float3 CalculateDampingIntegral(float3 damping, float age)
- {
- // The following computation is derived from this:
- // In the iterative integration we do: v = v' * damp, with v: new velocity, v' old velocity
- // To get the fixed function solution based only starting values, we need to integrate from 0 to t over the integral((damp ^ u) du).
- // The solution to the integral is (damp ^ u) / ln(damp).
- // Entering the two borders (0 and t) into it leads to: (damp ^ t - 1) / ln(damp)
-
- // The integral is undefined at 1.0, but it's approaching a good value (= age). Be pragmatic.
- //if (abs(damping - 1.0) < 0.0001)
- if (damping.x == 1.0)
- damping.x = 1.0001;
- if (damping.y == 1.0)
- damping.y = 1.0001;
- if (damping.z == 1.0)
- damping.z = 1.0001;
-
- return (pow(damping, age) - 1) / log(damping);
- }
- // ----------------------------------------------------------------------------
- float3 GeometryParticle_ComputeSize(float age, float particleSeed)
- {
- // start size, rate, and damping
- float3 sizeStart = GetRandomFloatValues(GeometryUpdate.StartSizeMinimums, GeometryUpdate.StartSizeSpreads, particleSeed, 3);
- float3 sizeRate = GetRandomFloatValues(GeometryUpdate.SizeRateMinimums, GeometryUpdate.SizeRateSpreads, particleSeed, 3);
- float3 sizeDamping = GetRandomFloatValues(GeometryUpdate.SizeDampingMinimums, GeometryUpdate.SizeDampingSpreads, particleSeed, 3);
-
- return sizeStart + sizeRate * CalculateDampingIntegral(sizeDamping, age);
- }
- // ----------------------------------------------------------------------------
- float3 GeometryParticle_ComputeAngles(float age, float particleSeed)
- {
- // start size, rate, and damping
- float3 angleStart = GetRandomFloatValues(GeometryUpdate.AngleMinimums, GeometryUpdate.AngleSpreads, particleSeed, 3);
- float3 angleRate = GetRandomFloatValues(GeometryUpdate.AngularRateMinimums, GeometryUpdate.AngularRateSpreads, particleSeed, 3);
- float angleDamping = GetRandomFloatValue(float2(GeometryUpdate.AngleDampingMin_AngleDampingSpread.x, GeometryUpdate.AngleDampingMin_AngleDampingSpread.y), particleSeed, 3);
-
- return angleStart + angleRate * CalculateDampingIntegral(angleDamping, age);
- }
- // ----------------------------------------------------------------------------
- float3 GeometryParticle_UpdatePosition(float3 startPosition, float3 startVelocity, float age, float particleSeed, out float3 finalVelocity)
- {
- // update particle position
- float velocityDamping = GetRandomFloatValue(Physics.VelocityDampingRange, particleSeed, 13);
- float integratedDampedVelocity = CalculateDampingIntegral(velocityDamping, age);
- finalVelocity = startVelocity * integratedDampedVelocity + (Physics.DriftVelocity + 0.5 * age * Physics.Gravity) * age;
- return startPosition + finalVelocity;
- }
- // ----------------------------------------------------------------------------
- // Modified from rwmath
- float3x3 Matrix33FromEulerXYZ(float3 euler)
- {
- float ci, cj, ch, si, sj, sh;
- sincos(euler.x, si, ci);
- sincos(euler.y, sj, cj);
- sincos(euler.z, sh, ch);
- float cc = ci * ch;
- float cs = ci * sh;
- float sc = si * ch;
- float ss = si * sh;
- return float3x3(
- cj * ch , cj * sh , -sj ,
- sj * sc - cs, sj * ss + cc, cj * si ,
- sj * cc + ss, sj * cs - sc, cj * ci
- );
- }
- float3x3 Matrix33FromEulerSinCosXYZ(float3 eulerSin, float3 eulerCos)
- {
- float ci, cj, ch, si, sj, sh;
- si = eulerSin.x;
- ci = eulerCos.x;
- sj = eulerSin.y;
- cj = eulerCos.y;
- sh = eulerSin.z;
- ch = eulerCos.z;
- float cc = ci * ch;
- float cs = ci * sh;
- float sc = si * ch;
- float ss = si * sh;
- return float3x3(
- cj * ch , cj * sh , -sj ,
- sj * sc - cs, sj * ss + cc, cj * si ,
- sj * cc + ss, sj * cs - sc, cj * ci
- );
- }
- // Build a look-at matrix so that the x-axis points along the given direction
- // Modified from Matrix3x4::Obj_Look_At
- float3x3 ObjectLookAt(float3 lookAtDirection)
- {
- float3 d = lookAtDirection;
- float len1 = length(d);
- float len2 = length(d.xy);
- float sinp, cosp; //sine and cosine of the pitch ("up-down" tilt about y)
- if (len1 != 0.0f)
- {
- sinp = d.z / len1;
- cosp = len2 / len1;
- }
- else
- {
- sinp = 0.0f;
- cosp = 1.0f;
- }
- float siny, cosy; //sine and cosine of the yaw ("left-right"tilt about z)
- if (len2 != 0.0f)
- {
- siny = d.y / len2;
- cosy = d.x / len2;
- }
- else
- {
- siny = 0.0f;
- cosy = 1.0f;
- }
- // Use 0 degree roll for now
- float sinRoll = 0.0;
- float cosRoll = 1.0;
- // Yaw rotation to projection of target in x-y plane and then pitch rotation
- return Matrix33FromEulerSinCosXYZ(float3(sinRoll, -sinp, siny), float3(cosRoll, cosp, cosy));
- }
- // ----------------------------------------------------------------------------
- ParticleVSOutput_H ParticleVertexShader_H(float4 StartPositionLifeInFrames : POSITION,
- float4 StartVelocityCreationFrame : TEXCOORD0, float2 SeedAndIndex : TEXCOORD1,
- uniform int rotationType)
- {
- ParticleVSOutput_H 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);
- //////////////////////////////////////////
- // UPDATE CORNER POSITION
- //////////////////////////////////////////
-
- // Calculate the particle position based on the physics parameters.
- float3 finalVelocity;
- float3 particlePosition = GeometryParticle_UpdatePosition(StartPosition, StartVelocity, age, Seed, finalVelocity);
- // SCALE
- // The size can change depending on 3 factors (size, rate, and damping).
- float3 size = GeometryParticle_ComputeSize(age, Seed);
- float3 cornerPosition = GEOMETRY_VERTEX_CORNERS[Index] * size;
-
- // ROTATE
- // Depending on the rotation type we either rotate in world space
- // or we rotate around the velocity of the particle.
- if (rotationType != ROTATION_OFF)
- {
- float3 eulerAngles = GeometryParticle_ComputeAngles(age, Seed);
- float3x3 rotateMatrix = Matrix33FromEulerXYZ(eulerAngles);
-
- if (rotationType == ROTATE_AROUND_VELOCITY)
- {
- if (length(finalVelocity) < 0.001)
- {
- finalVelocity = StartVelocity;
- }
-
- float3x3 lookAt = ObjectLookAt(finalVelocity);
- rotateMatrix = mul(rotateMatrix, lookAt);
- }
-
- cornerPosition = mul(cornerPosition, rotateMatrix);
- }
-
- // TRANSLATE
- cornerPosition += particlePosition;
-
- //////////////////////////////////////////
- // PROJECT AND SETUP SOFT PARTICLES
- //////////////////////////////////////////
-
- 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;
- Out.Depth = Out.Position.z / Out.Position.w;
- // 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;
- //////////////////////////////////////////
- // IDENTICAL TO GpuParticle.fx
- //////////////////////////////////////////
- // Fog depends on world position, but world matrix should be identity.
- Out.Fog = CalculateFog(Fog, cornerPosition, GetEyePosition()).xxx;
- Particle_ComputeVideoTexture(age, Seed, GEOMETRY_VERTEX_CORNERS[Index], GEOMETRY_VERTEX_TEXCOORDS[Index], Out.ParticleTexCoord, Out.NextFrameTexCoord);
- // compute color
- float relativeAge = age / LifeInFrames;
- Out.Color = Particle_ComputeColor(relativeAge, Seed, true);
- return Out;
- }
- // ----------------------------------------------------------------------------
- float4 SoftParticlePixelShader(ParticleVSOutput_H In, uniform int fogMode, uniform int blendMode) COLORTARGET
- {
- 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);
- // do interpolation between two frames (for particles with video textures)
- float4 TextureColor = tex2D( SAMPLER(ParticleTextureSampler), In.ParticleTexCoord);
- float4 NextFrameColor = tex2D( SAMPLER(NextFrameTextureSampler), In.NextFrameTexCoord.xy);
- float4 Color = lerp(TextureColor, NextFrameColor, In.NextFrameTexCoord.z) * In.Color;
- // Modify the color (or alpha) of a the particle depending on how it's being drawn
- // so the particle has a soft edge to it.
- if (blendMode == SOFTBLEND_ALPHA)
- {
- Color.w *= linearBlend;
- }
- else if (blendMode == SOFTBLEND_ADDITIVE)
- {
- Color.xyz *= linearBlend;
- }
- // 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;
- }
- // ----------------------------------------------------------------------------
- // SHADER: XENON
- // ----------------------------------------------------------------------------
- ParticleVSOutput_H ParticleVertexShader_Xenon(float4 StartPositionLifeInFrames : POSITION,
- float4 StartVelocityCreationFrame : TEXCOORD0, float2 SeedAndIndex : TEXCOORD1,
- uniform int rotationType)
- {
- return ParticleVertexShader_H(StartPositionLifeInFrames, StartVelocityCreationFrame, SeedAndIndex, GeometryUpdate.RotationType - 1);
- }
- float4 ParticlePixelShader_Xenon(ParticleVSOutput_H In ) : COLOR
- {
- return SoftParticlePixelShader( In,
- Fog.IsEnabled ? ((Draw.ShaderType == ShaderType_Additive || Draw.ShaderType == ShaderType_AdditiveAlphaTest || Draw.ShaderType == ShaderType_Multiply) ? FogMode_Additive : FogMode_Opaque) : FogMode_Disabled,
- !ShouldDrawParticleSoft ? SOFTBLEND_DISABLED : ((Draw.ShaderType == ShaderType_Alpha) ? SOFTBLEND_ALPHA : SOFTBLEND_ADDITIVE));
- }
- // ----------------------------------------------------------------------------
- // TECHNIQUE: HIGH ~ ULTRAHIGH (And XENON)
- // ----------------------------------------------------------------------------
- #define VS_ShaderType_H \
- compile VS_3_0 ParticleVertexShader_H(ROTATION_OFF), \
- compile VS_3_0 ParticleVertexShader_H(ROTATE_AROUND_VELOCITY), \
- compile VS_3_0 ParticleVertexShader_H(ROTATE_IN_WORLD_SPACE)
- DEFINE_ARRAY_MULTIPLIER( VS_Multiplier_Final_H = 3 );
- #if SUPPORTS_SHADER_ARRAYS
- vertexshader VS_Array_H[VS_Multiplier_Final_H] =
- {
- VS_ShaderType_H
- };
- #endif
- DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_FogMode = 1 );
- #define PS_FogMode_H(drawType) \
- compile PS_3_0 SoftParticlePixelShader(FogMode_Disabled, drawType), \
- compile PS_3_0 SoftParticlePixelShader(FogMode_Opaque, drawType), \
- compile PS_3_0 SoftParticlePixelShader(FogMode_Additive, drawType)
- DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_ShaderType = PS_Multiplier_FogMode * 3 );
- #define PS_ShaderType_H \
- PS_FogMode_H(SOFTBLEND_ADDITIVE), \
- PS_FogMode_H(SOFTBLEND_ALPHA), \
- PS_FogMode_H(SOFTBLEND_DISABLED)
- DEFINE_ARRAY_MULTIPLIER( PS_Multiplier_Final_H = PS_Multiplier_ShaderType * 3 );
- #if SUPPORTS_SHADER_ARRAYS
- pixelshader PS_Array_H[PS_Multiplier_Final_H] =
- {
- PS_ShaderType_H
- };
- #endif
- // ----------------------------------------------------------------------------
- // TECHNIQUE: LOW
- // ----------------------------------------------------------------------------
- struct ParticleVSOutput_L
- {
- float4 Position : POSITION;
- float2 ParticleTexCoord : TEXCOORD0;
- float4 Color : COLOR0;
- float Depth : TEXCOORD1; // For _CreateShadowMap technique
- };
- // ----------------------------------------------------------------------------
- ParticleVSOutput_L ParticleVertexShader_L(float4 StartPositionLifeInFrames : POSITION,
- float4 StartVelocityCreationFrame : TEXCOORD0, float2 SeedAndIndex : TEXCOORD1,
- uniform int rotationType)
- {
- ParticleVSOutput_L 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);
- //////////////////////////////////////////
- // UPDATE CORNER POSITION
- //////////////////////////////////////////
- // Calculate the particle position based on the physics parameters.
- float3 finalVelocity;
- float3 particlePosition = GeometryParticle_UpdatePosition(StartPosition, StartVelocity, age, Seed, finalVelocity);
- // SCALE
- // The size can change depending on 3 factors (size, rate, and damping).
- float3 size = GeometryParticle_ComputeSize(age, Seed);
- float3 cornerPosition = GEOMETRY_VERTEX_CORNERS[Index] * size;
- // ROTATE
- // Depending on the rotation type we either rotate in world space
- // or we rotate around the velocity of the particle.
- if (rotationType != ROTATION_OFF)
- {
- float3 eulerAngles = GeometryParticle_ComputeAngles(age, Seed);
- float3x3 rotateMatrix = Matrix33FromEulerXYZ(eulerAngles);
- if (rotationType == ROTATE_AROUND_VELOCITY)
- {
- if (length(finalVelocity) < 0.001)
- {
- finalVelocity = StartVelocity;
- }
- float3x3 lookAt = ObjectLookAt(finalVelocity);
- rotateMatrix = mul(rotateMatrix, lookAt);
- }
- cornerPosition = mul(cornerPosition, rotateMatrix);
- }
- // TRANSLATE
- cornerPosition += particlePosition;
- //////////////////////////////////////////
- // PROJECT
- //////////////////////////////////////////
- // Finish projecting the position.
- Out.Position = mul(float4(cornerPosition, 1), WorldViewProjection);
- Out.Depth = Out.Position.z / Out.Position.w;
- // texture coordinate
- Particle_ComputeVideoTextureNoNextFrame(age, Seed, GEOMETRY_VERTEX_TEXCOORDS[Index], Out.ParticleTexCoord);
- //////////////////////////////////////////
- // IDENTICAL TO GpuParticle.fx
- //////////////////////////////////////////
- // compute color
- float relativeAge = age / LifeInFrames;
- Out.Color = Particle_ComputeColor(relativeAge, Seed, true);
- return Out;
- }
- // ----------------------------------------------------------------------------
- float4 ParticlePixelShader_L(ParticleVSOutput_L In) : COLOR
- {
- float4 TextureColor = tex2D( SAMPLER(ParticleTextureSampler), In.ParticleTexCoord);
- float4 Color = TextureColor * In.Color;
- return Color;
- }
- #define VS_ShaderType_L \
- compile VS_2_0 ParticleVertexShader_L(ROTATION_OFF), \
- compile VS_2_0 ParticleVertexShader_L(ROTATE_AROUND_VELOCITY), \
- compile VS_2_0 ParticleVertexShader_L(ROTATE_IN_WORLD_SPACE)
- DEFINE_ARRAY_MULTIPLIER( VS_Multiplier_Final_L = 3 );
- #if SUPPORTS_SHADER_ARRAYS
- vertexshader VS_Array_L[VS_Multiplier_Final_L] =
- {
- VS_ShaderType_L
- };
- #endif
- #endif // _COMMON_GEOMETRY_PARTICLE_FXH_
|