//=================================================================================================== // Uniform Variables //=================================================================================================== float dt; float4x4 ViewProj; float4x4 World; float4x4 WorldInverseTranspose; float gpuObjectScale; float gravity = 0.01f; int IndexedPass; //=================================================================================================== // Object Properties //=================================================================================================== //- LocationMap -- texture LocationMap; sampler LocationMapSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- TerrainHeightMap -- texture TerrainHeightMap; sampler TerrainHeightMapSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- TerrainNormalMap -- texture TerrainNormalMap; sampler TerrainNormalMapSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Position -- texture CurrentPosition; sampler CurrentPositionSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Rotation -- texture Rotation; sampler RotationSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Scale -- texture Scale; sampler ScaleSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Mass -- texture Mass; sampler MassSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Velocity -- texture Velocity; sampler VelocitySampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Acceleration -- texture Acceleration; sampler AccelerationSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- LastPosition -- texture LastPosition; sampler LastPositionSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- TotalForce -- texture TotalForce; sampler TotalForceSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- TotalForce -- texture ForceMap; sampler ForceMapSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Radius -- texture Radius; sampler RadiusSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //- Dummy -- texture Dummy; sampler DummySampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = POINT; MINFILTER = POINT; MAGFILTER = POINT; }; //=================================================================================================== // Uniform, Varying, and FrameBuffer "Stream" Structures - // Used to Communicate between CPU, VertexProcessor, FragmentProcessor, and FrameBuffer //=================================================================================================== struct VertexInput { float4 position : POSITION0; // Position float4 fog : FOG; float4 color : COLOR0; // Color float4 texCoord : TEXCOORD0; // Texture coordinates float3 normal : NORMAL0; // Normal vector float4 tangent : TANGENT0; // Tangent float4 binormal : BINORMAL0; // Binormal half4 indices : BLENDINDICES0; float4 weights : BLENDWEIGHT0; float pointSize : PSIZE0; // Point size float tessFactor : TESSFACTOR0; // Tessellation factor }; struct VertexOutput { // These values are used directly by the rasterizer float4 position : POSITION; // Position float2 fog : FOG; // Point size // These values are interpolated and sent to FragIn float4 color : COLOR0; // Color (example: COLOR0) float4 texCoord : TEXCOORD0; // Texture coordinates (example: TEXCOORD0) float3 normal : TEXCOORD1; // Texture coordinates float3 worldPos : TEXCOORD2; // Texture coordinates float4 shadowMapSamplingPos1 : TEXCOORD3; // Texture coordinates float4 shadowMapSamplingPos2 : TEXCOORD4; // Texture coordinates float2 realDepth : TEXCOORD5; float3 tangent : TEXCOORD6; float3 binormal : TEXCOORD7; }; struct FragmentInput { float4 color : COLOR0; // Color (example: COLOR0) float2 fog : FOG; float4 texCoord : TEXCOORD0; // Texture coordinates float3 normal : TEXCOORD1; // Texture coordinates float3 worldPos : TEXCOORD2; // Texture coordinates float4 shadowMapSamplingPos1 : TEXCOORD3; float4 shadowMapSamplingPos2 : TEXCOORD4; // Texture coordinates float2 realDepth : TEXCOORD5; float3 tangent : TEXCOORD6; float3 binormal : TEXCOORD7; }; struct FragmentOutput { float4 color : COLOR0; // Color for render target n }; //=================================================================================================== // Indexed Functions //=================================================================================================== //-------------------------- //--- HACK : READ BELOW ---- void FS_Dummy(inout FragmentInput IN, inout FragmentOutput OUT) { // This function exists b/c the our multipass sequence must be "null-terminated"... // Because of something with xna, or dx, or my code.. the last Render To Texture in a sequence will sometimes come out black. // So we make a extra trivial pass so the graphics card a chance to finalize the last real texture. OUT.color = tex2D(DummySampler, IN.texCoord); } //-------- END HACK -------- //-------------------------- //--- Equation: acceleration = totalForce / mass; void FS_Acceleration(inout FragmentInput IN, inout FragmentOutput OUT) { float4 tf = tex2D(TotalForceSampler, IN.texCoord); float4 m = tex2D(MassSampler, IN.texCoord); OUT.color.r = tf.r/m.r; OUT.color.g = tf.g/m.r; OUT.color.b = tf.b/m.r; OUT.color.a = tf.a/m.r; } //--- Equation: velocity += acceleration * dt; void FS_Velocity(inout FragmentInput IN, inout FragmentOutput OUT) { float4 a = tex2D(AccelerationSampler, IN.texCoord); OUT.color = a * dt; } //--- Equation: angular momentum void FS_Rotation(inout FragmentInput IN, inout FragmentOutput OUT) { OUT.color = tex2D(RotationSampler, IN.texCoord); } //--- Equation: lastPosition = currentPosition; void FS_LastPosition(inout FragmentInput IN, inout FragmentOutput OUT) { OUT.color = tex2D(CurrentPositionSampler, IN.texCoord); } //--- Equation: currentPosition = lastPosition + velocity * dt + (0.5f * acceleration * dt * dt); void FS_CurrentPosition(inout FragmentInput IN, inout FragmentOutput OUT) { // Get Parameters float4 lp = tex2D(LastPositionSampler, IN.texCoord); float4 v = tex2D(VelocitySampler, IN.texCoord); float4 a = tex2D(AccelerationSampler, IN.texCoord); // Calc new position using standard physics OUT.color = lp + v*dt + (0.5f * a * dt*dt); // ------------ Start Object Recycler -------------- // Axis Mins to Maxs if(OUT.color.x < 0.0f){ OUT.color.x = 1.0f; } if(OUT.color.y < 0.5f){ OUT.color.y = 1.0f; } if(OUT.color.z < 0.0f){ OUT.color.z = 1.0f; } // Axis Maxs to Mins if(OUT.color.x > 1.0f){ OUT.color.x = 0.0f; } if(OUT.color.y > 1.0f){ OUT.color.y = 0.5f; } if(OUT.color.z > 1.0f){ OUT.color.z = 0.0f; } // ------------ End Object Recycler -------------- } //--- Trivial vertex shader for Indexed Fragment Shaders void VS_Indexed(inout VertexInput IN, inout VertexOutput OUT) { // Copy OUT to IN OUT.position = mul(IN.position, ViewProj); OUT.texCoord = IN.texCoord; } //=================================================================================================== // Pointer Conversion Functions //=================================================================================================== // Gets Indexed Coordinates from an objects Spatial Position Data float2 GetIndexedPointer( float spatialPositionX, float spatialPositionY ) { return tex2D(LocationMapSampler, float2(spatialPositionX ,spatialPositionY) ).xy; } // Gets Spatial Coordinates from an objects Indexed Position Data //float2 GetSpatialPointer( float indexedPositionX, float indexedPositionY ) //{ // return tex2D(CurrentPositionSampler, float2(indexedPositionX, indexedPositionY) ).xy; //} //=================================================================================================== // Collision Detection //=================================================================================================== float4 GetForce( float spatialPositionX, float spatialPositionY ){ // Indexed Pointer float2 ip = GetIndexedPointer( spatialPositionX, spatialPositionY ); // Get Mass and Acceleration from Index float4 m = tex2D(MassSampler, ip); float4 a = tex2D(AccelerationSampler, ip); // F = M * A float4 force; force.r = a.r * m.r; force.g = a.g * m.r; force.b = a.b * m.r; force.a = a.a * m.r; return force; } void FS_TotalForce(inout FragmentInput IN, inout FragmentOutput OUT) { // Indexed CurrentPosition holds the object's Spatial Location float4 spatialPosition = tex2D(CurrentPositionSampler, IN.texCoord); // Get the Spatial Location's Alpha, which tells if an object exists float spatialValue = tex2D(LocationMapSampler, spatialPosition.xz).a; // If alpha value = isObject = true if( spatialValue > 0.0f ){ // Bring in Radius // Get any surrounding objects, and apply resultant force float4 sumForces = (float4)0.0f; sumForces += GetForce(spatialPosition.x - 1, spatialPosition.z - 1); sumForces += GetForce(spatialPosition.x - 1, spatialPosition.z ); sumForces += GetForce(spatialPosition.x - 1, spatialPosition.z + 1); sumForces += GetForce(spatialPosition.x, spatialPosition.z - 1); sumForces += GetForce(spatialPosition.x, spatialPosition.z ); sumForces += GetForce(spatialPosition.x, spatialPosition.z + 1); sumForces += GetForce(spatialPosition.x + 1, spatialPosition.z - 1); sumForces += GetForce(spatialPosition.x + 1, spatialPosition.z ); sumForces += GetForce(spatialPosition.x + 1, spatialPosition.z + 1); OUT.color.r = sumForces.r/(9.0f); OUT.color.g = sumForces.g/(9.0f); OUT.color.b = sumForces.b/(9.0f); // =========== HACK ============ OUT.color = (float4) 0.01f; //OUT.color = mul(OUT.color, RotationalForce); OUT.color = tex2D(ForceMapSampler, spatialPosition.xz) / 10.0f; OUT.color.a = 1.0f; } else { OUT.color = (float4) 0.001f; //OUT.color = mul(OUT.color, RotationalForce); OUT.color = tex2D(ForceMapSampler, spatialPosition.xz) / 10.0f; OUT.color.a = 0.0f; } // Add Gravity OUT.color.g -= gravity * dt; // Add Terrain Collision if( tex2D(CurrentPositionSampler, IN.texCoord).g < tex2D(TerrainHeightMapSampler, spatialPosition.xz).g ){ OUT.color.g += 2* gravity * dt; } } void FS_AttackForce(inout FragmentInput IN, inout FragmentOutput OUT) { } //================================================================================================== // Spatial Function // Using a Quad of Verts mapped to the CurrentPosition indexed map, // relocate each vert to it's spatial position and render to LocationMap //================================================================================================== void FS_Spatial(inout FragmentInput IN, inout FragmentOutput OUT) { OUT.color = IN.color; } void VS_Spatial(inout VertexInput IN, inout VertexOutput OUT) { // Get Object Velocity to mark as dynamic //float3 currVelocity = tex2Dlod(VelocitySampler, float4(IN.texCoord.x, IN.texCoord.y, 0, 0)).xyz; // Set Vertex Position to the location stored in Position Indexed Map OUT.position = tex2Dlod(CurrentPositionSampler, float4(IN.texCoord.x, IN.texCoord.y, 0, 0)); // IN.position; OUT.position.g = OUT.position.b; OUT.position.b = 0.0f; OUT.position = mul(OUT.position, ViewProj); // Keep it on the board //clamp(OUT.position, -1.0f, 1.0f); // DEBUG - Set color to position data to show valid points //OUT.color = tex2Dlod(CurrentPositionSampler, float4(IN.texCoord.x, IN.texCoord.y, 0, 0)); // Pack data into pixel values OUT.color.rg = IN.texCoord.xy; // Pointer to Indexed Object OUT.color.b = 0.0f; // Empty OUT.color.a = 1.0f; // isObject Flag - marks object as active // Pass texCoords along OUT.texCoord = IN.texCoord; } //================================================================================================== // MAIN //================================================================================================== // Indexed Main //-------------------------------------------------------------------------------------------------- VertexOutput IndexedVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_Indexed(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput IndexedFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; // Switch Variables if(IndexedPass == 0){ FS_TotalForce(FS_IN, FS_OUT); } if(IndexedPass == 1){ FS_Acceleration(FS_IN, FS_OUT); } if(IndexedPass == 2){ FS_Velocity(FS_IN, FS_OUT); } if(IndexedPass == 3){ FS_Rotation(FS_IN, FS_OUT); } if(IndexedPass == 4){ FS_LastPosition(FS_IN, FS_OUT); } if(IndexedPass == 5){ FS_CurrentPosition(FS_IN, FS_OUT); } if(IndexedPass == 6){ FS_Dummy(FS_IN, FS_OUT); } return FS_OUT; } // Spatial Main //-------------------------------------------------------------------------------------------------- VertexOutput SpatialVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_Spatial(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput SpatialFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_Spatial(FS_IN, FS_OUT); return FS_OUT; } //=================================================================================================== // Techniques //=================================================================================================== // Collision Technique //-------------------------------------------------------------------------------------------------- technique IndexedMain { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 IndexedFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // SpatialMapping Technique //-------------------------------------------------------------------------------------------------- technique SpatialMain { pass Pass0 { VertexShader = compile vs_3_0 SpatialVertexMain(); PixelShader = compile ps_3_0 SpatialFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } }