//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Stream { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; using System.Diagnostics; using System.Threading; using PhysicsGpu; #endregion /// /// Compiles and stores all HLSL source code /// public class FXSourceCode { #region AI Vision Source private string AIVisionSource = @" //=================================================================================================== // Uniform Variables //=================================================================================================== float4x4 ViewProj; float4x4 inverseViewProj; float numberOfPlayers; //-- aiVisionTexture -- texture aiVisionTexture; sampler aiVisionSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //=================================================================================================== // Uniform, Varying, and FrameBuffer Stream Structures - // Used to Communicate between CPU, VertexProcessor, FragmentProcessor, and FrameBuffer //=================================================================================================== struct VertexInput { float4 position : POSITION0; // Position float4 texCoord : TEXCOORD0; // Texture coordinates }; struct VertexOutput { // These values are used directly by the rasterizer float4 position : POSITION; // Position float4 color : COLOR0; // Color (example: COLOR0) float4 texCoord : TEXCOORD0; // Texture coordinates (example: TEXCOORD0) }; struct FragmentInput { float4 color : COLOR0; // Color (example: COLOR0) float4 texCoord : TEXCOORD0; // Texture coordinates }; struct FragmentOutput { float4 color : COLOR0; // Color for render target n }; //=================================================================================================== // Vertex and Fragment Shaders //=================================================================================================== // AI Vision - Texture Scan Main //-------------------------------------------------------------------------------------------------- VertexOutput AI_Vision_VertexTextureScan(VertexInput IN) { VertexOutput OUT = (VertexOutput)0; OUT.position = IN.position; OUT.texCoord = IN.texCoord; float4 textureOut = tex2Dlod(aiVisionSampler, float4(IN.texCoord.x, IN.texCoord.y, 0, 0)); if(textureOut.r >= 0.1f) { // player index int index = round(textureOut.a * numberOfPlayers); OUT.position.x = (index % 4) / 4.0f; OUT.position.y = round(index / 4) / 4.0f; OUT.color.a = 1.0f; OUT.color.rgb = mul(float2(IN.texCoord.x, IN.texCoord.y), inverseViewProj); } else { OUT.position.xy = -1.0f; OUT.color = 0.4f; } OUT.position = mul(OUT.position, ViewProj); return OUT; } FragmentOutput AI_Vision_FragmentTextureScan(FragmentInput IN) { FragmentOutput OUT = (FragmentOutput)0; OUT.color = IN.color; return OUT; } // AI Vision - Scan AI Texture //-------------------------------------------------------------------------------------------------- technique AI_Vision_TextureScan { pass Pass0 { VertexShader = compile vs_3_0 AI_Vision_VertexTextureScan(); PixelShader = compile ps_3_0 AI_Vision_FragmentTextureScan(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } }"; #endregion #region ElementalGPU private string ElementalGPUSource = @" // Copywrited by its developers at darkwynter.com // All Rights Reserved Without Prejudice. //=================================================================================================== // Textures and Samplers //=================================================================================================== //- ScreenTexture1 -- texture ScreenTexture; sampler ScreenS = sampler_state { Texture = ; }; //- modelTexture1 -- texture modelTexture1; sampler modelTextureSampler1 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- modelTexture2 -- texture modelTexture2; sampler modelTextureSampler2 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- modelTexture3 -- texture modelTexture3; sampler modelTextureSampler3 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- modelTexture4 -- texture modelTexture4; sampler modelTextureSampler4 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- modelTexture5 -- texture modelTexture5; sampler modelTextureSampler5 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- modelTexture6 -- texture modelTexture6; sampler modelTextureSampler6 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- bumpTexture1 -- texture bumpTexture1; sampler bumpTextureSampler1 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- bumpTexture2 -- texture bumpTexture2; sampler bumpTextureSampler2 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- bumpTexture3 -- texture bumpTexture3; sampler bumpTextureSampler3 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- bumpTexture4 -- texture bumpTexture4; sampler bumpTextureSampler4 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- bumpTexture5 -- texture bumpTexture5; sampler bumpTextureSampler5 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- bumpTexture6 -- texture bumpTexture6; sampler bumpTextureSampler6 = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- terrainModTexture -- texture terrainModTexture; sampler terrainModTextureSampler = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- heightMapTexture -- texture heightMapTexture; sampler heightMapTextureSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- terrainNormalMapTexture -- texture terrainNormalMapTexture; sampler terrainNormalMapTextureSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //- Position -- texture CurrentPosition; sampler CurrentPositionSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //=================================================================================================== // Uniform Variables //=================================================================================================== // Viewport Projection Matrix float4x4 ViewProj; // Object position in 3D space float4x4 World; // ViewPort position in 3D space float4x4 EyePostion; // Raster Dimensions int ScreenWidth; int ScreenHeight; // Player Dead Shader bool playerIsDead; // Light Properties float3 lightPosition0; float4 lightAmbient0; float4 lightDiffuse0; float4 lightSpecular0; float3 lightPosition1; float4 lightAmbient1; float4 lightDiffuse1; float4 lightSpecular1; // Object Material Properties float4 materialDiffuse; float4 materialSpecular; float4 textureValue; float4 ambientColor; float4 diffuseColor; float4 specularColor; float shininess; // Lighting Calcs float3 lightVector1; float3 lightVector2; float3 vertexToEyeVector; float3 halfwayVector1; float3 halfwayVector2; // Terrain Height Scale float worldMinY; float worldMaxY; // Terrain float3 PlaneRayIntersectionPoint; float terrainScaleFactor; float TerrainModRange; float terrainBarrierWallHeight; bool terrainModEnabled; float mapSizeXScaleFactor; // Screen Saver Update float screenSaverTime; // Particle Uniform Variables float particleRichtor = 5.0f; // float particleAmplitude = 0.05f; // float particleRedShift = 0.3f; // Increase red components of color float waveFormScaler = 0.5f; // Scale the height of the flame float WaveRadius; float particleType; float particleEnergyValue; float3 normal; // Player Position for Terrain LOD calculations float2 playerPosition; float terrainMapSize; // Animation Stuff float4x4 MatrixPalette[56]; float scaleRange; float minimumValue; float fogStart, fogEnd, fogDropOff; // G2L shader float2 blendTexturePosition1; float2 blendTexturePosition2; //=================================================================================================== // Uniform, Varying, and FrameBuffer Stream Structures - // Used to Communicate between CPU, VertexProcessor, FragmentProcessor, and FrameBuffer //=================================================================================================== struct VertexInput { float4 position : POSITION0; // Position float4 indices : BLENDINDICES0; float4 weights : BLENDWEIGHT0; float3 normal : NORMAL0; // Normal vector float4 texCoord : TEXCOORD0; // Texture coordinates float4 fog : TEXCOORD1; // {-| float4 binormal : TEXCOORD2; // {-|---- Instancing float4 tangent : TEXCOORD3; // {-|---- Buffers float4 depth : TEXCOORD4; // {-| }; struct VertexOutput { // These values are used directly by the rasterizer float4 position : POSITION; // Position float2 fog : TEXCOORD3; // 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 }; struct FragmentInput { float4 color : COLOR0; // Color (example: COLOR0) float2 fog : TEXCOORD3; float4 texCoord : TEXCOORD0; // Texture coordinates float3 normal : TEXCOORD1; // Texture coordinates float3 worldPos : TEXCOORD2; // Texture coordinates }; struct FragmentOutput { float4 color : COLOR0; // Color for render target n }; //=================================================================================================== // Depricated Shaders //=================================================================================================== // ----------------------------------------------------------------------------------- FragmentOutput FS_FlickerFlame(FragmentInput IN, FragmentOutput OUT) { OUT.color = tex2D(modelTextureSampler1, IN.texCoord + blendTexturePosition1); float4 color2 = tex2D(bumpTextureSampler1, IN.texCoord + blendTexturePosition2); // float4 color3 = tex2D(modelTextureSampler6, IN.texCoord); // Blend if (OUT.color.a > 0) { //OUT.color.r = 0.5f; //OUT.color.g = 0.7f; //OUT.color.b = 0.6f; OUT.color = (OUT.color * .750f) + (color2 * .25f); // + (color3 * .25f); } return OUT; } VertexOutput VS_FlickerFlame(VertexInput IN, VertexOutput OUT) { OUT.position = mul(IN.position, mul(World, ViewProj)); OUT.texCoord = IN.texCoord; OUT.normal = IN.normal; return OUT; } FragmentOutput FlickerFlameFragmenMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_OUT = FS_FlickerFlame(FS_IN, FS_OUT); return FS_OUT; } VertexOutput FlickerFlameVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_FlickerFlame(VS_IN, VS_OUT); return VS_OUT; } // FlickerFlame Shader // -------------------------------------------------------------------------- technique FlickerFlame { pass Pass0 { PixelShader = compile ps_3_0 FlickerFlameFragmenMain(); VertexShader = compile vs_3_0 FlickerFlameVertexMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Particle Shader //---------------------------------------------------------------------------------------------------------------- FragmentOutput FS_Particle(FragmentInput IN, FragmentOutput OUT) { float4 col1, col2, colFinal; col1 = tex2D(modelTextureSampler1, IN.texCoord); col2 = tex2D(modelTextureSampler2, IN.texCoord); colFinal = lerp(col1, col2, particleEnergyValue); textureValue = colFinal; clip(textureValue.a - 0.2f); OUT.color = colFinal; return OUT; } VertexOutput VS_Particle(inout VertexInput IN, VertexOutput OUT) { /* // WaveForm Calculations (returns values 1-2) float waveForm = 1.0f + abs( cos(WaveRadius * WaveRadius * length(IN.position))); // Stop NaN errors and extreme values here if( waveForm < 0.001f) { waveForm = 0.001f; } modPosition.y = IN.position.y + 10.0f/ sqrt(0.5f + (abs(IN.position.x) + abs(IN.position.z)) * waveForm); */ // Squash the sphere on the y-axis float4 modPosition = IN.position; modPosition.y = 0.3f * modPosition.y; float waveForm; // Earth if(particleType == 0.0f) { if( IN.position.y > 0.0f ) { /* // Distance between vertex and wave crest float waveDistance = abs( length(IN.position) - WaveRadius ); // See Fire Shader Notes for explanation waveForm = //sqrt( // Create sharp wave... log() for rounded?? abs(cos( // Ensure that wave burns upward waveDistance // Cos creates a circular algorithm from linear distance ) ); //); // New vertex height modPosition *= waveForm; // * particleLookVector; */ // WaveForm Calculations (returns values 1-2) waveForm = 1.0f + abs( cos(WaveRadius * WaveRadius * length(IN.position)) ) ; // Stop NaN errors and extreme values here if( waveForm < 0.001f) { waveForm = 0.001f; } // waveForm = abs( cos( distance( IN.position, 0.0f) + WaveRadius )); // IN.position.y = distance( IN.position , 0.0f) /4.0f * waveForm; modPosition.y = IN.position.y * waveForm; } if(particleEnergyValue >= 0.4f) { IN.position = (IN.position * (1.0f - particleEnergyValue)) + (modPosition * particleEnergyValue ); IN.position.y *= 0.6f * (1.0f - particleEnergyValue) + 0.3f; } } // Water if(particleType == 1.0f) { shininess = 1.0f; // Don't modify vertices below a specific latitude if( IN.position.y > 0.0f ) { // WaveForm Calculations (returns values 1-2) waveForm = 1.0f + abs( cos(WaveRadius * WaveRadius * length(IN.position)) ) ; // Stop NaN errors and extreme values here if( waveForm < 0.001f) { waveForm = 0.001f; } // waveForm = abs( cos( distance(IN.position, 0.0f) + WaveRadius )); // IN.position.y = distance(IN.position , 0.0f) / 4.0f * waveForm; modPosition.y = IN.position.y * waveForm; } if(particleEnergyValue >= 0.4f) { IN.position = (IN.position * (1.0f - particleEnergyValue)) + (modPosition * particleEnergyValue ); IN.position.y *= 0.5f; } } // Air if(particleType == 2.0f) { // WaveForm Calculations (returns values 1-2) waveForm = 1.0f + abs( cos(WaveRadius * WaveRadius * length(IN.position)) ) ; // Stop NaN errors and extreme values here if( waveForm < 0.001f) { waveForm = 0.001f; } if( IN.position.y < 0.0f ) { // WaveForm Calculations (0-1) //waveForm = abs( cos(abs(IN.position.x) + abs(IN.position.z) + WaveRadius) ); IN.position.y = (abs(IN.position.x) + abs(IN.position.z)) * waveForm; IN.position.y -= 0.5f; } else { IN.position.y = (abs(IN.position.x) + abs(IN.position.z)) * waveForm; } } return OUT; } //=================================================================================================== // Vertex and Fragment Shaders //=================================================================================================== // Terrain LOD Shader //--------------------------------------------------------------------------------------------------- VertexInput VS_TerrainLOD(VertexInput IN) { float3 vertexWorldPosition = mul(IN.position, World).xyz; if(vertexWorldPosition.x >= 0.0f && vertexWorldPosition.z >= 0.0f && vertexWorldPosition.x <= mapSizeXScaleFactor && vertexWorldPosition.z <= mapSizeXScaleFactor) { IN.texCoord.x = (vertexWorldPosition.z / mapSizeXScaleFactor); IN.texCoord.y = (vertexWorldPosition.x / mapSizeXScaleFactor); IN.position.y = (tex2Dlod(heightMapTextureSampler, float4(IN.texCoord.x, IN.texCoord.y, 0, 0)).x * (worldMaxY - worldMinY)) + worldMinY; } else { IN.texCoord.xy = -1.0f; } return IN; } FragmentOutput FS_TerrainLOD(FragmentInput IN, FragmentOutput OUT) { clip(IN.texCoord.xy); return OUT; } // Terrain Bump Map Shader //--------------------------------------------------------------------------------------------------- FragmentOutput FS_TerrainBumpMapping(FragmentInput IN, FragmentOutput OUT) { // Get texture value float4 lowTex = tex2D(bumpTextureSampler1, IN.texCoord * 200); float4 middleTex = tex2D(bumpTextureSampler2, IN.texCoord * 100); float4 highTex = tex2D(bumpTextureSampler3, IN.texCoord * 10); // Shift Y Position between 0 - 1 float YRatio = IN.worldPos.y / (worldMaxY - worldMinY); float4 low = lerp(lowTex, middleTex, YRatio); float4 high = lerp(middleTex, highTex, YRatio); float4 value = lerp(low, high, YRatio); // ERROR: Algorithm calcs height and not angle // Check by replacing modTex in XML with a florecent colored texture // Get the angle between normal and up // float4 modTex = tex2D(bumpTextureSampler4, IN.texCoord * 200); // float angle = abs( degrees(acos(dot(IN.normal, float3(0, 1, 0))))); // value = lerp(value, modTex, angle/90.0f); //unpack the normal map value.xyz = 2.0f * (value.xyz - 0.5); normal = normalize(value + IN.normal); return OUT; } // Render Terrain Shader //-------------------------------------------------------------------------------------------------- FragmentOutput FS_RenderTerrain(FragmentInput IN, FragmentOutput OUT) { // Get texture value float4 lowTex = tex2D(modelTextureSampler1, IN.texCoord * 200); float4 middleTex = tex2D(modelTextureSampler2, IN.texCoord * 100); float4 highTex = tex2D(modelTextureSampler3, IN.texCoord * 10); // Shift Y Position between 0 - 1 float YRatio = IN.worldPos.y / (worldMaxY - worldMinY) ; // Multi Texture Mixing float4 low = lerp(lowTex, middleTex, YRatio); float4 high = lerp(middleTex, highTex, YRatio); float4 value = lerp(low, high, YRatio); // ERROR: Algorithm calcs height and not angle // Check by replacing modTex in XML with a florecent colored texture // Get the angle between normal and up // float4 modTex = tex2D(modelTextureSampler4, IN.texCoord * 200); // float angle = abs( degrees(acos(dot(IN.normal, float3(0, 1, 0))))); // value = lerp(value, modTex, angle/90.0f); // Mix color value with lighting //OUT.color = (diffuseColor + ambientColor) * value + specularColor; textureValue = value; return OUT; } // Lerp Bump Map Shader //--------------------------------------------------------------------------------------------------- FragmentOutput FS_LerpBumpMapping(FragmentInput IN, FragmentOutput OUT) { //Lookup from the normal map float3 normalNew1 = tex2D(bumpTextureSampler1, IN.texCoord); float3 normalNew2 = tex2D(bumpTextureSampler2, IN.texCoord); float3 normalNew = lerp(normalNew1, normalNew2, particleEnergyValue); //unpack the normal map normalNew.xyz = 2.0f * (normalNew.xyz - 0.5); normal = normalize(normalNew + IN.normal); return OUT; } // Single Bump Map Shader //--------------------------------------------------------------------------------------------------- FragmentOutput FS_BumpMapping(FragmentInput IN, FragmentOutput OUT) { //Lookup from the normal map float3 normalNew = tex2D(bumpTextureSampler1, IN.texCoord); //unpack the normal map normalNew.xyz = 2.0f * (normalNew.xyz - 0.5); normal = normalize(normalNew + IN.normal); return OUT; } // No Bump Mapping Shader //--------------------------------------------------------------------------------------------------- FragmentOutput FS_NoBumpMapping(FragmentInput IN, FragmentOutput OUT) { normal = IN.normal; return OUT; } // Basic Lighting Shader //--------------------------------------------------------------------------------------------------- VertexOutput VS_BasicLighting(VertexInput IN, VertexOutput OUT) { // Texturing OUT.texCoord = IN.texCoord; // Positional Calculations OUT.worldPos = mul(IN.position, World).xyz; // World Space Position OUT.position = mul(IN.position, mul(World, ViewProj)); // Raster Position // Calculate the pixel to light source vectors lightVector1 = normalize(lightPosition0 - OUT.worldPos); // Vertex to Light source 1 vector lightVector2 = normalize(lightPosition1 - OUT.worldPos); // Vertex to Light source 2 vector // Per Player Per Vertex Calculations vertexToEyeVector = normalize(EyePostion[3].xyz - OUT.worldPos); // Eye vector // Calculate each light source's halfway vector halfwayVector1 = normalize(vertexToEyeVector + lightVector1); // Halfway vector halfwayVector2 = normalize(vertexToEyeVector + lightVector2); // Halfway vector return OUT; } FragmentOutput FS_BasicLighting(FragmentInput IN, FragmentOutput OUT) { float diffuse0 = 0.0f; float diffuse1 = 0.0f; float specular0 = 0.0f; float specular1 = 0.0f; diffuse0 = max(0.0f, dot(normal, lightVector1)); // Diffuse component if(diffuse0 > 0.0f) { // If statement stops objects from becoming backlit specular0 = pow(dot(normal, halfwayVector1), shininess); // Specular component } if(length(lightVector1 - lightVector2) != 0.0) { diffuse1 = max(0.0f, dot(normal, lightVector2)); // Diffuse component if(diffuse1 > 0.0f) { specular1 = pow(dot(normal, halfwayVector2), shininess); // Specular component } } // Mix Components of Lighting with Material Properties ambientColor = materialDiffuse * (lightAmbient0 + lightAmbient1); diffuseColor = materialDiffuse * ((diffuse0 * lightDiffuse0) + (diffuse1 * lightDiffuse1)); specularColor = materialSpecular * ((specular0 * lightSpecular0) + (specular1 * lightSpecular1)); // Apply lighting to the color OUT.color = (diffuseColor + ambientColor + specularColor) * textureValue; //=== HACK POINT // Limit the number of colors to create splotchy effects //float3 rgb = float3((int)(OUT.color.r * 256.0f), (int) (OUT.color.g * 256.0f), (int) (OUT.color.b * 256.0f)); //OUT.color.rgb = rgb / 256.0f; //=== END HACK POINT // To frambuffer return OUT; } // Effect to apply when player is dead //--------------------------------------------------------------------------------------------------- FragmentOutput FS_PlayerDeadShader(FragmentInput IN, FragmentOutput OUT) { if (playerIsDead) { //take the inverse of the average of all colors float invAvg = 1.2f - (OUT.color.r + OUT.color.g + OUT.color.b)/3.0f; if (invAvg < 0) { invAvg = 0; } //make it a grayscale image OUT.color.r = invAvg; OUT.color.g = invAvg; OUT.color.b = invAvg; OUT.color.a = 1.0f; } return OUT; } // Energy Beam Shader //--------------------------------------------------------------------------------------------------- VertexOutput VS_EnergyBeam(VertexInput IN, VertexOutput OUT) { // Texturing OUT.texCoord = IN.texCoord; // Positional Calculations OUT.position = mul(IN.position, ViewProj); // Raster Position return OUT; } // Terrain Mod Shader //-------------------------------------------------------------------------------------------------- FragmentOutput FS_TerrainModTexture(FragmentInput IN, FragmentOutput OUT) { if(terrainModEnabled == true) { // Project PlaneRayIntersectionPoint.xz = PlaneRayIntersectionPoint.zx; PlaneRayIntersectionPoint.x = PlaneRayIntersectionPoint.x + 0.5f; PlaneRayIntersectionPoint.z = (-PlaneRayIntersectionPoint.z) - 0.5f; PlaneRayIntersectionPoint = mul(PlaneRayIntersectionPoint, World); // Find the range to be shaded float3 highCorner = PlaneRayIntersectionPoint + (float3) TerrainModRange; float3 lowCorner = PlaneRayIntersectionPoint - (float3) TerrainModRange; // See if this fragement falls within the range to be shaded if(lowCorner.x < IN.worldPos.x && IN.worldPos.x < highCorner.x ) { if(lowCorner.z < IN.worldPos.z && IN.worldPos.z < highCorner.z ) { OUT.color.r += tex2D(terrainModTextureSampler, (IN.worldPos.xz - lowCorner.xz) / TerrainModRange).a; } } } return OUT; } // Anti Aliasing Shader //--------------------------------------------------------------------------------------------------- VertexOutput VS_DrawQuad(VertexInput IN, VertexOutput OUT) { OUT.position = mul(IN.position, mul(World, ViewProj)); OUT.texCoord = IN.texCoord; return OUT; } FragmentOutput FS_DrawQuad(FragmentInput IN, FragmentOutput OUT) { OUT.color = tex2D(modelTextureSampler1, IN.texCoord); return OUT; } // Shield Shader //-------------------------------------------------------------------------------------------------- VertexOutput VS_Shield(VertexInput IN, VertexOutput OUT) { OUT.position = mul(IN.position, mul(World, ViewProj)); OUT.texCoord = IN.texCoord; return OUT; } FragmentOutput FS_Shield(FragmentInput IN, FragmentOutput OUT) { OUT.color = tex2D(modelTextureSampler1, IN.texCoord); OUT.color.a = 1.0f; return OUT; } // Full Screen Anti-Burn //-------------------------------------------------------------------------------------------------- float4 AntiBurnFSMain(float2 texCoord: TEXCOORD0) : Color { float time = (screenSaverTime % 10)/10 + .1; float4 color; if (time > .5) { color = tex2D(ScreenS, texCoord) * time; } else { color = tex2D(ScreenS, texCoord) * 1 - time; } return color; } // Generate instanced World matrix //-------------------------------------------------------------------------------------------------- void VS_GenerateWorldMatrix(VertexInput IN) { World._m00 = IN.fog.x; World._m01 = IN.fog.y; World._m02 = IN.fog.z; World._m03 = IN.fog.w; World._m10 = IN.binormal.x; World._m11 = IN.binormal.y; World._m12 = IN.binormal.z; World._m13 = IN.binormal.w; World._m20 = IN.tangent.x; World._m21 = IN.tangent.y; World._m22 = IN.tangent.z; World._m23 = IN.tangent.w; World._m30 = IN.depth.x; World._m31 = IN.depth.y; World._m32 = IN.depth.z; World._m33 = IN.depth.w; } // Skin Alteration for Animation //-------------------------------------------------------------------------------------------------- VertexInput VS_Skin(VertexInput IN) { VertexInput output = IN; output.position = 0.0f; output.normal = 0.0f; float lastWeight = 1.0; float weight = 0; for (int i = 0; i < 3; ++i) { weight = IN.weights[i]; lastWeight -= weight; output.position += mul(IN.position, MatrixPalette[IN.indices[i]]) * weight; output.normal += mul(IN.normal , MatrixPalette[IN.indices[i]]) * weight; } output.position += mul(IN.position, MatrixPalette[IN.indices[3]]) * lastWeight; output.normal += mul(IN.normal , MatrixPalette[IN.indices[3]]) * lastWeight; return output; } // Vertex Instancing //-------------------------------------------------------------------------------------------------- float4x4 GetRotationMatrix(float4 q) { float4x4 rotationMatrix = float4x4 (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); float sqw = q.z * q.z; float sqx = q.w * q.w; float sqy = q.x * q.x; float sqz = q.y * q.y; // invs (inverse square length) is only required if quaternion is not already normalised float invs = 1 / (sqx + sqy + sqz + sqw); rotationMatrix._m00 = (sqx - sqy - sqz + sqw) * invs; // since sqw + sqx + sqy + sqz =1/invs*invs rotationMatrix._m11 = (sqx - sqy + sqz - sqw) * invs; rotationMatrix._m22 = (sqx + sqy - sqz - sqw) * invs; float tmp1 = q.x * q.y; float tmp2 = q.z * q.w; rotationMatrix._m10 = 2.0f * (tmp1 + tmp2) * invs; rotationMatrix._m01 = 2.0f * (tmp1 - tmp2) * invs; tmp1 = q.x * q.z; tmp2 = q.y * q.w; rotationMatrix._m20 = 2.0f * (tmp1 + tmp2) * invs; rotationMatrix._m02 = 2.0f * (tmp1 - tmp2) * invs; tmp1 = q.y * q.z; tmp2 = q.x * q.w; rotationMatrix._m21 = 2.0f * (tmp1 + tmp2) * invs; rotationMatrix._m12 = 2.0f * (tmp1 - tmp2) * invs; return rotationMatrix; } float4x4 GetTranslationMatrix(float4 tangent) { float4x4 translationMatrix = float4x4 (1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); translationMatrix._m30 = tangent.x; translationMatrix._m31 = tangent.y; translationMatrix._m32 = tangent.z; return translationMatrix; } float4x4 GetScaleMatrix(float4 fog) { float4x4 scaleMatrix = float4x4 (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); scaleMatrix._m00 = fog.x; scaleMatrix._m11 = fog.y; scaleMatrix._m22 = fog.z; return scaleMatrix; } VertexInput VS_Instancing(VertexInput IN) { VertexInput output = IN; VS_GenerateWorldMatrix(IN); return output; } // Physix Vertex Instancing //-------------------------------------------------------------------------------------------------- void VS_GeneratePhysixWorldMatrix(VertexInput IN) { VS_GenerateWorldMatrix(IN); float3 currentPosition = tex2Dlod(CurrentPositionSampler, float4(IN.depth.x, IN.depth.y, 0.0f, 0.0f)); float scaleRangeY = worldMaxY - worldMinY; World._m30 = (currentPosition.x * scaleRange);// + minimumValue; World._m31 = (currentPosition.y * scaleRange);// + minimumValue; World._m32 = (currentPosition.z * scaleRange);// + minimumValue; } VertexInput VS_PhysixInstancing(VertexInput IN) { VertexInput output = IN; VS_GeneratePhysixWorldMatrix(IN); return output; } // Particle Instancing //-------------------------------------------------------------------------------------------------- FragmentOutput FS_InstancedParticle(FragmentInput IN, FragmentOutput OUT) { float4 col1, col2, colFinal; // Earth if(IN.fog.x == 0.0f) { col1 = tex2D(modelTextureSampler3, IN.texCoord); col2 = tex2D(modelTextureSampler4, IN.texCoord); } // Water else if(IN.fog.x == 1.0f) { col1 = tex2D(modelTextureSampler5, IN.texCoord); col2 = tex2D(modelTextureSampler6, IN.texCoord); } // Air else if(IN.fog.x == 2.0f) { col1 = tex2D(modelTextureSampler1, IN.texCoord); col2 = tex2D(modelTextureSampler2, IN.texCoord); } colFinal = lerp(col1, col2, IN.fog.y); textureValue = colFinal; clip(textureValue.a - 0.1f); OUT.color = colFinal; return OUT; } FragmentOutput FS_ParticleBumpMapping(FragmentInput IN, FragmentOutput OUT) { float4 normal1, normal2, normalNew; // Earth if(IN.fog.x == 0.0f) { normal1 = tex2D(bumpTextureSampler3, IN.texCoord); normal2 = tex2D(bumpTextureSampler4, IN.texCoord); } // Water else if(IN.fog.x == 1.0f) { normal1 = tex2D(bumpTextureSampler5, IN.texCoord); normal2 = tex2D(bumpTextureSampler6, IN.texCoord); } // Air else if(IN.fog.x == 2.0f) { normal1 = tex2D(bumpTextureSampler1, IN.texCoord); normal2 = tex2D(bumpTextureSampler2, IN.texCoord); } normalNew = lerp(normal1, normal2, IN.fog.y); //unpack the normal map normalNew.xyz = 2.0f * (normalNew.xyz - 0.5); normal = normalize(normalNew); return OUT; } void VS_GenerateWorldMatrix_Particle(VertexInput IN) { float4x4 rotationMatrix = GetRotationMatrix(IN.binormal); float4x4 translationMatrix = GetTranslationMatrix(IN.tangent); float4x4 scaleMatrix = float4x4 (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); scaleMatrix._m00 = scaleMatrix._m11 = scaleMatrix._m22 = IN.fog.x; particleType = IN.fog.y; particleEnergyValue = IN.fog.z; WaveRadius = IN.fog.w; //float4x4 tempMatrix = mul(scaleMatrix, rotationMatrix); World = mul(mul(scaleMatrix, rotationMatrix), translationMatrix); } void VS_ParticleInstancing(VertexInput IN) { VertexInput output = IN; VS_GenerateWorldMatrix_Particle(IN); } // Toon (Cell shading) Main //-------------------------------------------------------------------------------------------------- VertexOutput VS_Toon(VertexInput IN, VertexOutput OUT) { OUT.position = mul(IN.position, mul(World, ViewProj)); OUT.texCoord = IN.texCoord; OUT.normal = IN.normal; return OUT; } FragmentOutput FS_Toon(FragmentInput IN, FragmentOutput OUT) { float3 lightDir = normalize(lightPosition0); float intensity = dot(lightDir,normalize(IN.normal)); if (intensity > 0.95) OUT.color = float4(1.0,0.5,0.5,1.0); else if (intensity > 0.5) OUT.color = float4(0.6,0.3,0.8,1.0); else if (intensity > 0.25) OUT.color = float4(0.4,0.8,0.2,1.0); else OUT.color = float4(0.8,0.1,0.1,1.0); //get our colour OUT.color = tex2D(modelTextureSampler1, IN.texCoord); //return final pixel colour return OUT; } VertexOutput ToonVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_Toon(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput ToonFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_OUT = FS_Toon(FS_IN, FS_OUT); return FS_OUT; } technique ToonShaderMain { pass Pass0 { VertexShader = compile vs_3_0 ToonVertexMain(); PixelShader = compile ps_3_0 ToonFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } //-------------------------------------------------------------------------------------------------- //=================================================================================================== //Helpers //=================================================================================================== FragmentOutput FS_FogTransparency(FragmentInput IN, FragmentOutput OUT) { OUT.color.a = fogDropOff * OUT.color.a; return OUT; } void FS_DistanceAlphaClip(FragmentInput IN) { float fog = length(EyePostion[3].xyz - IN.worldPos); fogDropOff = (fogEnd - fog) / (fogEnd - fogStart) ;//1.0f / fog * fogDensity; //if(fogDropOff < 0.1f){ fogDropOff = 0.1f; } // Substitute for broken clamp op saturate(fogDropOff); clip(fogDropOff - 0.01f); } float2 split(float val) { float2 ret = float2(0.0, 0.0); ret.x = (int)val; ret.y = 10 * (val - (int)val); return ret; } void FS_AlphaClip(FragmentInput IN) { // Get texture value textureValue = tex2D(modelTextureSampler1, IN.texCoord); clip(textureValue.a - 0.1f); } //================================================================================================== // MAIN //================================================================================================== // Particle Main //-------------------------------------------------------------------------------------------------- VertexOutput ParticleVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_Particle(VS_IN, VS_OUT); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput ParticleFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; //FS_AlphaClip(FS_IN); FS_OUT = FS_Particle(FS_IN, FS_OUT); FS_OUT = FS_LerpBumpMapping(FS_IN, FS_OUT); FS_OUT = FS_BasicLighting(FS_IN, FS_OUT); FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); //wanted to do transparent water but having trouble with instancing if (particleType == 1.0f) { //Water type FS_OUT.color.a = 1.4f - particleEnergyValue; } return FS_OUT; } // Instanced Particle Main //-------------------------------------------------------------------------------------------------- VertexOutput InstancedParticleVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_ParticleInstancing(VS_IN); VS_OUT = VS_Particle(VS_IN, VS_OUT); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); VS_OUT.fog.x = VS_IN.fog.y; VS_OUT.fog.y = VS_IN.fog.z; return VS_OUT; } FragmentOutput InstancedParticleFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; //FS_AlphaClip(FS_IN); FS_OUT = FS_InstancedParticle(FS_IN, FS_OUT); FS_OUT = FS_ParticleBumpMapping(FS_IN, FS_OUT); FS_OUT = FS_BasicLighting(FS_IN, FS_OUT); FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); //wanted to do transparent water but having trouble with instancing if (FS_IN.fog.x == 1.0f) { //Water type FS_OUT.color.a = 1.4f - FS_IN.fog.y; } FS_OUT = FS_FogTransparency(FS_IN, FS_OUT); return FS_OUT; } // Energy Beam Main //-------------------------------------------------------------------------------------------------- VertexOutput EnergyBeamVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_EnergyBeam(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput EnergyBeamFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_DistanceAlphaClip(FS_IN); FS_AlphaClip(FS_IN); FS_OUT = FS_Particle(FS_IN, FS_OUT); FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); return FS_OUT; } // Basic Lighting Main //-------------------------------------------------------------------------------------------------- VertexOutput BasicLightingVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput BasicLightingFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_AlphaClip(FS_IN); FS_DistanceAlphaClip(FS_IN); FS_OUT = FS_BumpMapping(FS_IN, FS_OUT); FS_OUT = FS_BasicLighting(FS_IN, FS_OUT); FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); FS_OUT = FS_FogTransparency(FS_IN, FS_OUT); return FS_OUT; } // Basic Lighting (no bump-mapping) Main //-------------------------------------------------------------------------------------------------- FragmentOutput BasicLightingNoBumpsFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_AlphaClip(FS_IN); FS_DistanceAlphaClip(FS_IN); FS_OUT = FS_NoBumpMapping(FS_IN, FS_OUT); FS_OUT = FS_BasicLighting(FS_IN, FS_OUT); FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); return FS_OUT; } // Basic Lighting w/instancing Main //-------------------------------------------------------------------------------------------------- VertexOutput BasicLightingInstancedVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_IN = VS_Instancing(VS_IN); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } // Physix Instancing Main //-------------------------------------------------------------------------------------------------- VertexOutput GPUPhysixInstancedVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_IN = VS_PhysixInstancing(VS_IN); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } // Terrain Instanced Main //-------------------------------------------------------------------------------------------------- VertexOutput TerrainInstancedVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_GenerateWorldMatrix(VS_IN); VS_IN = VS_TerrainLOD(VS_IN); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } // Render Terrain Main //-------------------------------------------------------------------------------------------------- VertexOutput TerrainVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_IN = VS_TerrainLOD(VS_IN); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput TerrainFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_OUT = FS_TerrainLOD(FS_IN, FS_OUT); FS_DistanceAlphaClip(FS_IN); FS_OUT = FS_TerrainBumpMapping(FS_IN, FS_OUT); FS_OUT = FS_RenderTerrain(FS_IN, FS_OUT); FS_OUT = FS_BasicLighting(FS_IN, FS_OUT); FS_OUT = FS_TerrainModTexture(FS_IN, FS_OUT); //FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); //FS_OUT = FS_FogTransparency(FS_IN, FS_OUT); return FS_OUT; } // Render Terrain (no bump-mapping) Main //-------------------------------------------------------------------------------------------------- FragmentOutput TerrainNoBumpsFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_OUT = FS_TerrainLOD(FS_IN, FS_OUT); FS_DistanceAlphaClip(FS_IN); FS_OUT = FS_NoBumpMapping(FS_IN, FS_OUT); FS_OUT = FS_RenderTerrain(FS_IN, FS_OUT); FS_OUT = FS_BasicLighting(FS_IN, FS_OUT); FS_OUT = FS_TerrainModTexture(FS_IN, FS_OUT); //FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); FS_OUT = FS_FogTransparency(FS_IN, FS_OUT); return FS_OUT; } // Full Screen Anti-Aliasing //-------------------------------------------------------------------------------------------------- VertexOutput DrawQuadVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_DrawQuad(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput DrawQuadFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_OUT = FS_DrawQuad(FS_IN, FS_OUT); return FS_OUT; } // Shield Shader //-------------------------------------------------------------------------------------------------- VertexOutput ShieldVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_Shield(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput ShieldFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_OUT = FS_Shield(FS_IN, FS_OUT); FS_OUT = FS_PlayerDeadShader(FS_IN, FS_OUT); return FS_OUT; } // Instanced Animation Main //-------------------------------------------------------------------------------------------------- VertexOutput InstancedAnimationVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_IN = VS_Skin(VS_IN); VS_Instancing(VS_IN); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } // Skinned Player Main //-------------------------------------------------------------------------------------------------- VertexOutput SkinnedPlayerVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_IN = VS_Skin(VS_IN); VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } // Player Main //-------------------------------------------------------------------------------------------------- VertexOutput PlayerVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_OUT = VS_BasicLighting(VS_IN, VS_OUT); return VS_OUT; } //=================================================================================================== // Techniques //=================================================================================================== // Particle Shader Technique //-------------------------------------------------------------------------------------------------- technique ParticleShaderMain { pass Pass0 { VertexShader = compile vs_3_0 ParticleVertexMain(); PixelShader = compile ps_3_0 ParticleFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Instanced Particle Shader Technique //-------------------------------------------------------------------------------------------------- technique InstancedParticleShaderMain { pass Pass0 { VertexShader = compile vs_3_0 InstancedParticleVertexMain(); PixelShader = compile ps_3_0 InstancedParticleFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Energy Beam Shader Technique //-------------------------------------------------------------------------------------------------- technique EnergyBeamShaderMain { pass Pass0 { VertexShader = compile vs_3_0 EnergyBeamVertexMain(); PixelShader = compile ps_3_0 EnergyBeamFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Basic Lighting Technique //-------------------------------------------------------------------------------------------------- technique BasicLightingShaderMain { pass Pass0 { VertexShader = compile vs_3_0 BasicLightingVertexMain(); PixelShader = compile ps_3_0 BasicLightingFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Basic Lighting (no bump-mapping) Shader Technique //-------------------------------------------------------------------------------------------------- technique BasicLightingNoBumpsShaderMain { pass Pass0 { VertexShader = compile vs_3_0 BasicLightingVertexMain(); PixelShader = compile ps_3_0 BasicLightingNoBumpsFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Basic Lighting Technique with Instancing //-------------------------------------------------------------------------------------------------- technique BasicLightingInstancedShaderMain { pass Pass0 { VertexShader = compile vs_3_0 BasicLightingInstancedVertexMain(); PixelShader = compile ps_3_0 BasicLightingFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Basic Lighting Technique with Instancing //-------------------------------------------------------------------------------------------------- technique GPUPhysixInstancedShaderMain { pass Pass0 { VertexShader = compile vs_3_0 GPUPhysixInstancedVertexMain(); PixelShader = compile ps_3_0 BasicLightingFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Terrain Instanced Shader Technique //-------------------------------------------------------------------------------------------------- technique TerrainInstanced { pass Pass0 { VertexShader = compile vs_3_0 TerrainInstancedVertexMain(); PixelShader = compile ps_3_0 TerrainFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Terrain Shader Technique //-------------------------------------------------------------------------------------------------- technique TerrainShaderMain { pass Pass0 { VertexShader = compile vs_3_0 TerrainVertexMain(); PixelShader = compile ps_3_0 TerrainFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Terrain Instanced (no bump-mapping) Shader Technique //-------------------------------------------------------------------------------------------------- technique TerrainNoBumpsInstanced { pass Pass0 { VertexShader = compile vs_3_0 TerrainInstancedVertexMain(); PixelShader = compile ps_3_0 TerrainNoBumpsFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Terrain (no bump-mapping) Shader Technique //-------------------------------------------------------------------------------------------------- technique TerrainNoBumpsShaderMain { pass Pass0 { VertexShader = compile vs_3_0 TerrainVertexMain(); PixelShader = compile ps_3_0 TerrainFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Draw Quad Technique //-------------------------------------------------------------------------------------------------- technique DrawQuad { pass Pass0 { VertexShader = compile vs_3_0 DrawQuadVertexMain(); PixelShader = compile ps_3_0 DrawQuadFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Shield Shader Technique //-------------------------------------------------------------------------------------------------- technique ShieldShaderMain { pass Pass0 { VertexShader = compile vs_3_0 ShieldVertexMain(); PixelShader = compile ps_3_0 ShieldFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // AntiBurn //-------------------------------------------------------------------------------------------------- technique AntiBurn { pass Pass0 { PixelShader = compile ps_2_0 AntiBurnFSMain(); } } // Instanced Animation Technique //-------------------------------------------------------------------------------------------------- technique InstancedAnimation { pass Pass0 { VertexShader = compile vs_3_0 InstancedAnimationVertexMain(); PixelShader = compile ps_3_0 BasicLightingFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Skinned Player Technique //-------------------------------------------------------------------------------------------------- technique SkinnedPlayerShaderMain { pass Pass0 { VertexShader = compile vs_3_0 SkinnedPlayerVertexMain(); PixelShader = compile ps_3_0 BasicLightingFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Player Technique //-------------------------------------------------------------------------------------------------- technique PlayerShaderMain { pass Pass0 { VertexShader = compile vs_3_0 PlayerVertexMain(); PixelShader = compile ps_3_0 BasicLightingFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } //################################################################################################## //-------------------------------------------- AI Vision ------------------------------------------- //################################################################################################## float playerIndex; float numberOfPlayers; //-- aiVisionTexture -- texture aiVisionTexture; sampler aiVisionSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; VertexOutput VS_AIVision(VertexInput IN, VertexOutput OUT) { OUT.position = mul(IN.position, mul(World, ViewProj)); OUT.worldPos = mul(IN.position, World).xyz; return OUT; } FragmentOutput FS_AIVisionPlayer(FragmentInput IN, FragmentOutput OUT) { OUT.color = 1.0f; OUT.color.a = playerIndex; return OUT; } FragmentOutput FS_AIVisionTerrain(FragmentInput IN, FragmentOutput OUT) { OUT.color = 0.0f; return OUT; } // Player Main //-------------------------------------------------------------------------------------------------- VertexOutput AI_Vision_PlayerVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_IN = VS_Skin(VS_IN); VS_OUT = VS_AIVision(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput AI_Vision_PlayerFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_DistanceAlphaClip(FS_IN); FS_OUT = FS_AIVisionPlayer(FS_IN, FS_OUT); FS_OUT = FS_FogTransparency(FS_IN, FS_OUT); return FS_OUT; } // AI Vision Render Terrain Main //-------------------------------------------------------------------------------------------------- VertexOutput AI_Vision_TerrainVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_GenerateWorldMatrix(VS_IN); VS_IN = VS_TerrainLOD(VS_IN); VS_OUT = VS_AIVision(VS_IN, VS_OUT); return VS_OUT; } FragmentOutput AI_Vision_TerrainFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_DistanceAlphaClip(FS_IN); FS_OUT = FS_TerrainLOD(FS_IN, FS_OUT); FS_OUT = FS_AIVisionTerrain(FS_IN, FS_OUT); FS_OUT = FS_FogTransparency(FS_IN, FS_OUT); return FS_OUT; } // AI Vision - Player Technique //-------------------------------------------------------------------------------------------------- technique AI_Vision_PlayerShaderMain { pass Pass0 { VertexShader = compile vs_3_0 AI_Vision_PlayerVertexMain(); PixelShader = compile ps_3_0 AI_Vision_PlayerFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // AI Vision - Terrain Shader Technique //-------------------------------------------------------------------------------------------------- technique AI_Vision_TerrainShaderMain { pass Pass0 { VertexShader = compile vs_3_0 AI_Vision_TerrainVertexMain(); PixelShader = compile ps_3_0 AI_Vision_TerrainFragmentMain(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } "; #endregion #region GPU Physics Source private string GPUPhysicsSource = @" //=================================================================================================== // Uniform Variables //=================================================================================================== float dt; float4x4 ViewProj; float4x4 World; float4x4 WorldInverseTranspose; float gpuObjectScale; float gravity = 0.01f; float scaleMinY; float scaleRangeY; float cpScaleMinY; float cpScaleRangeY; float2 playerPosition; float invSpatMapHeight; float invSpatMapWidth; int IndexedPass; float3 normalComponent; float3 normalForce; float3 mass1Velocity; float3 mass1CurrentPosition; float mass; //=================================================================================================== // 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; }; //- WindMap -- texture WindMap; sampler WindMapSampler = 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 texCoord : TEXCOORD0; // Texture coordinates }; struct VertexOutput { // These values are used directly by the rasterizer float4 position : POSITION; // Position // These values are interpolated and sent to FragIn float4 color : COLOR0; // Color (example: COLOR0) float4 texCoord : TEXCOORD0; // Texture coordinates (example: TEXCOORD0) }; struct FragmentInput { float4 color : COLOR0; // Color (example: COLOR0) float4 texCoord : TEXCOORD0; // Texture coordinates }; struct FragmentOutput { float4 color : COLOR0; // Color for render target n }; //=================================================================================================== // Utility Functions //=================================================================================================== // Gets Indexed Coordinates from an objects Spatial Position Data float4 GetIndexedPosition(float2 spatialPosition) { return tex2D(LocationMapSampler, spatialPosition); } // Gets Spatial Coordinates from an objects Indexed Position Data float4 GetSpatialPosition(float2 indexedPosition) { return tex2D(CurrentPositionSampler, indexedPosition); } float GetUnscaledHeight(float2 texCoord) { float2 hackTexCoords; hackTexCoords.xy = texCoord.yx; float height = tex2D(TerrainHeightMapSampler, hackTexCoords).g * 3.0f; height += tex2D(TerrainHeightMapSampler, float2(hackTexCoords.x-invSpatMapWidth, hackTexCoords.y+invSpatMapWidth)).g; height += tex2D(TerrainHeightMapSampler, float2(hackTexCoords.x+invSpatMapWidth, hackTexCoords.y+invSpatMapWidth)).g; height += tex2D(TerrainHeightMapSampler, float2(hackTexCoords.x-invSpatMapWidth, hackTexCoords.y-invSpatMapWidth)).g; height += tex2D(TerrainHeightMapSampler, float2(hackTexCoords.x+invSpatMapWidth, hackTexCoords.y-invSpatMapWidth)).g; height = (height) / 7.0f; height = (height * scaleRangeY) + scaleMinY; height = (height) / cpScaleRangeY; return height; } void CalculateVectorComponents(float3 referenceNormal, float3 objectVelocity) { if( length(objectVelocity) >= 0.01f && !isinf(length(objectVelocity)) ) { normalComponent = dot(objectVelocity, referenceNormal) * referenceNormal; } else { normalComponent = (float3) 0.0f; } } void CalculateNormalForces(float mass2, float3 normalVelocity1, float3 normalVelocity2, float COR) { float3 resultantVelocity1, resultantVelocity2; float3 eV1MinusV2, m1V1PlusM2V2; float totalMass = mass + mass2; //float totalMass = 2.0f * mass; eV1MinusV2 = COR * (normalVelocity1 - normalVelocity2); m1V1PlusM2V2 = (mass * normalVelocity1) + (mass2 * normalVelocity2); resultantVelocity1 = (m1V1PlusM2V2 - (mass2 * eV1MinusV2)) / totalMass; normalForce = resultantVelocity1 * mass / dt; } float3 GetVelocity(float2 texCoord) { return tex2D(VelocitySampler, tex2D(LocationMapSampler, texCoord).xy); } float4 GetPosition(float2 texCoord) { return tex2D(CurrentPositionSampler, tex2D(LocationMapSampler, texCoord).xy); } float GetMass(float2 texCoord) { return tex2D(MassSampler, tex2D(LocationMapSampler, texCoord).xy).x; } //=================================================================================================== // Indexed Functions //=================================================================================================== void FS_Dummy(inout FragmentInput IN, inout FragmentOutput OUT) { //--- HACK : READ BELOW ---- // 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 has a chance to finalize the previous texture. OUT.color = tex2D(DummySampler, IN.texCoord); } //=================================================================================================== // Collision Detection //=================================================================================================== // HACK - Assuming that all gpuObjects have the same Mass.mass values float4 ObjObjCollision(float mass2, float3 mass2Velocity, float4 mass2CurrentPosition) { float3 object1NormalVelocity; float3 object2NormalVelocity; float3 normalVectorOfImpact; float3 zeroVector = (float3) 0.0f; if(mass2CurrentPosition.a == 1.0f) { normalVectorOfImpact = mass2CurrentPosition - mass1CurrentPosition; // HACK - This condition needs to be put back in when we start using more than one spatmap //if (distance(normalVectorOfImpact, zeroVector) != 0.0f) //{ normalize(normalVectorOfImpact); //} // Calculate Mass1's normal velocity component CalculateVectorComponents(normalVectorOfImpact, mass1Velocity); object1NormalVelocity = normalComponent; // Calculate Mass2's normal velocity component CalculateVectorComponents(normalVectorOfImpact, mass2Velocity); object2NormalVelocity = normalComponent; normalForce = (float3) 0.0f; if (length(mass1Velocity) > length(mass2Velocity)) { // Ensure that mass1's velocity is not equal to 0 if (length(mass1Velocity) != 0.0f) { // Check that the velocity is not moving away from the impact, ie, the angle between velocity // and impact vector is between 90->0->270. If so the two objects are moving away from each // other, so return. if (dot(mass1Velocity, normalVectorOfImpact) / length(mass1Velocity) > 0.0f) { CalculateNormalForces(mass2, object1NormalVelocity, object2NormalVelocity, 1.0f); } } } else { // Ensure that mass2's velocity is not equal to 0 if (length(mass2Velocity) != 0.0f) { // Check that the velocity is not moving away from the impact, ie, the angle between velocity // and impact vector is between 90->180->270. If so the two objects are moving away from each // other, so return. if (dot(mass2Velocity, normalVectorOfImpact) / length(mass2Velocity) < 0.0f) { CalculateNormalForces(mass2, object1NormalVelocity, object2NormalVelocity, 1.0f); } } } } return (float4)(normalForce, 0.0f); } float4 GetForce(float2 spatialPosition) { // Get Indexed Position of Object from SpatialPosition float4 ip = tex2D(LocationMapSampler, spatialPosition); // If object exists return it's force if(ip.a > 0.0f) { float4 v = tex2D(VelocitySampler, ip.xy); float4 m = tex2D(MassSampler, ip.xy); // Low-pass filter * velocity * mass (only stored in r channel) return v * (float4)m.r; } else{ return (float4)0.0f; } } void FS_TotalForce(inout FragmentInput IN, inout FragmentOutput OUT) { // Indexed CurrentPosition holds the object's Spatial Location float4 spatialPosition = tex2D(CurrentPositionSampler, IN.texCoord); //if(true) if(spatialPosition.a == 1.0f) { /* // Get any surrounding objects, and apply resultant force float4 sumForces = (float4)0.0f; sumForces += GetForce( float2(1 - spatialPosition.x - invSpatMapWidth , spatialPosition.z - invSpatMapHeight) ); sumForces += GetForce( float2(1 - spatialPosition.x - invSpatMapWidth , spatialPosition.z ) ); sumForces += GetForce( float2(1 - spatialPosition.x - invSpatMapWidth , spatialPosition.z + invSpatMapHeight) ); sumForces += GetForce( float2(1 - spatialPosition.x , spatialPosition.z - invSpatMapHeight) ); sumForces += GetForce( float2(1 - spatialPosition.x , spatialPosition.z + invSpatMapHeight) ); sumForces += GetForce( float2(1 - spatialPosition.x + invSpatMapWidth , spatialPosition.z - invSpatMapHeight) ); sumForces += GetForce( float2(1 - spatialPosition.x + invSpatMapWidth , spatialPosition.z ) ); sumForces += GetForce( float2(1 - spatialPosition.x + invSpatMapWidth , spatialPosition.z + invSpatMapHeight) ); OUT.color = sumForces / 8.0f; */ mass1Velocity = tex2D(VelocitySampler, IN.texCoord); mass1CurrentPosition = spatialPosition; mass = tex2D(MassSampler, IN.texCoord).x; // Get any surrounding objects, and apply resultant force float4 sumForces = (float4)0.0f; float2 currentNeighbor; currentNeighbor = float2(1 - spatialPosition.x - invSpatMapWidth , spatialPosition.z - invSpatMapHeight); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x - invSpatMapWidth , spatialPosition.z ); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x - invSpatMapWidth , spatialPosition.z + invSpatMapHeight); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x , spatialPosition.z - invSpatMapHeight); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x , spatialPosition.z + invSpatMapHeight); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x + invSpatMapWidth , spatialPosition.z - invSpatMapHeight); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x + invSpatMapWidth , spatialPosition.z ); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); currentNeighbor = float2(1 - spatialPosition.x + invSpatMapWidth , spatialPosition.z + invSpatMapHeight); sumForces += ObjObjCollision(GetMass(currentNeighbor), GetVelocity(currentNeighbor), GetPosition(currentNeighbor)); OUT.color = sumForces; // Wind Force (Scale to match lastForce value) float4 windForce = tex2D(WindMapSampler, spatialPosition.xz); // Get wind force from map windForce = (windForce - 0.5f) / 100000.0f; // Get Last TotalForce (removing gravity component) float4 lastForce = tex2D(TotalForceSampler, IN.texCoord); lastForce.g += .00065f; // Resultant wind force = windFriction - windForce; OUT.color += (.25f * lastForce- windForce); // Add Gravity OUT.color.g -= .00065f; // ------------ Start Object Reflex -------------- // Object distance below terrain (positive if below terrain). float objectReflexHeight = GetUnscaledHeight(OUT.color.xz) - OUT.color.g; //-- Reset Object Position To Terrain Height if( objectReflexHeight > 000.0f ) { // Add difference to object's height value //OUT.color.g += .0012f; //OUT.color.r = -OUT.color.r; //OUT.color.b = -OUT.color.b; } // ------------ End Object Reflex -------------- OUT.color.a = 1.0f; } else { clip(-1.0f); } } //=================================================================================================== // Physics //=================================================================================================== //--- 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); if(tf.a == 1.0f) { OUT.color.r = tf.r/m.r; OUT.color.g = tf.g/m.r; OUT.color.b = tf.b/m.r; OUT.color.a = 1.0f; } else { clip(-1.0f); } } //--- Equation: velocity += acceleration * dt; void FS_Velocity(inout FragmentInput IN, inout FragmentOutput OUT) { float4 a = tex2D(AccelerationSampler, IN.texCoord); float4 v0 = tex2D(VelocitySampler, IN.texCoord); if(v0.a == 1.0f) { // v = v0 + at OUT.color = v0 + a * dt; OUT.color.a = 1.0f; } else { clip(-1.0f); } } //--- Equation: angular momentum void FS_Rotation(inout FragmentInput IN, inout FragmentOutput OUT) { OUT.color = tex2D(RotationSampler, 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(CurrentPositionSampler, IN.texCoord); float4 v = tex2D(VelocitySampler, IN.texCoord); float4 a = tex2D(AccelerationSampler, IN.texCoord); if(lp.a == 1.0f) { // Calc new position using standard physics OUT.color = lp + v*dt + (0.5f * a * dt*dt); OUT.color.a = 1.0f; // Bounding for TerrainMap Positions (ENTIRE BOARD) float xmin = 0.0f; float xmax = 1.0f; float ymax = 1.0f; float zmin = 0.0f; float zmax = 1.0f; // ------------ Start Object Recycler -------------- // Axis Mins to Maxs if(OUT.color.x < xmin){ OUT.color.x = xmax; } if(OUT.color.z < zmin){ OUT.color.z = zmax; } // Axis Maxs to Mins if(OUT.color.x > xmax){ OUT.color.x = xmin; } if(OUT.color.y > ymax){ OUT.color.y = -1.0f; } if(OUT.color.z > zmax){ OUT.color.z = zmin; } // ------------ End Object Recycler -------------- // ------------ Start Object/Terrain Reset -------------- // Object distance below terrain (positive if below terrain). float objectResetHeight = GetUnscaledHeight(OUT.color.xz) - OUT.color.g; // If object below terrain, to terrain height if( objectResetHeight > 0.0f ) { // Add difference to object's height value OUT.color.g += objectResetHeight; } // ------------ End Object/Terrain Reset -------------- } else { clip(-1.0f); } } //--- 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; } //================================================================================================== // 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) { clip(IN.texCoord); OUT.color = IN.color; } void VS_Spatial(inout VertexInput IN, inout VertexOutput OUT) { // Set Vertex Position to the location stored in Position Indexed Map OUT.position = tex2Dlod(CurrentPositionSampler, float4(IN.position.x, IN.position.y, 0, 0)); // IN.position; if(OUT.position.a == 1.0f) { OUT.position.g = OUT.position.b; OUT.position.b = 0.0f; OUT.position = mul(OUT.position, ViewProj); // 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 //HACK FOR VISIBILITY //OUT.color.r = 1.0f; // Pass texCoords along OUT.texCoord = IN.position; } else { OUT.position = (float4) -1.0f; OUT.texCoord = -1.0f; } } //=================================================================================================== // Mains and Techniques //=================================================================================================== // Indexed Mains //-------------------------------------------------------------------------------------------------- //--- Indexed Vertex Shaders VertexOutput IndexedVertexMain(VertexInput VS_IN) { VertexOutput VS_OUT = (VertexOutput)0; VS_Indexed(VS_IN, VS_OUT); return VS_OUT; } //--- Indexed Fragment Shaders FragmentOutput TotalForceFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_TotalForce(FS_IN, FS_OUT); return FS_OUT; } FragmentOutput AccelerationFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_Acceleration(FS_IN, FS_OUT); return FS_OUT; } FragmentOutput VelocityFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_Velocity(FS_IN, FS_OUT); return FS_OUT; } FragmentOutput RotationFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_Rotation(FS_IN, FS_OUT); return FS_OUT; } FragmentOutput CurrentPositionFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_CurrentPosition(FS_IN, FS_OUT); return FS_OUT; } FragmentOutput DummyFragmentMain(FragmentInput FS_IN) { FragmentOutput FS_OUT = (FragmentOutput)0; FS_Dummy(FS_IN, FS_OUT); return FS_OUT; } // Indexed Techniques //-------------------------------------------------------------------------------------------------- technique TotalForce { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 TotalForceFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } technique Acceleration { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 AccelerationFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } technique Velocity { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 VelocityFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } technique Rotation { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 RotationFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } technique CurrentPosition { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 CurrentPositionFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } technique Dummy { pass Pass0 { VertexShader = compile vs_3_0 IndexedVertexMain(); PixelShader = compile ps_3_0 DummyFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } // Spatial Mains //-------------------------------------------------------------------------------------------------- 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; } // SpatialMapping Techniques //-------------------------------------------------------------------------------------------------- technique SpatialMain { pass Pass0 { VertexShader = compile vs_3_0 SpatialVertexMain(); PixelShader = compile ps_3_0 SpatialFragmentMain(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } "; #endregion #region Terrain Normal generation Source private string TerrainNormalSource = @" //=================================================================================================== // Uniform Variables //=================================================================================================== float4x4 ViewProj; float4x4 World; float invMapWidth; float terrainHeightScale; float terrainScaleMinY; float3 positionXZ, positionX1Z, positionXZ1, positionX1Z1; float2 texCoordX1Z, texCoordXZ1, texCoordX1Z1; float3 edge1, edge2, normal; //- heightMapTexture -- texture heightMapTexture; sampler heightMapTextureSampler = sampler_state { texture = ; AddressU = MIRROR; AddressV = MIRROR; AddressW = MIRROR; MIPFILTER = ANISOTROPIC; MINFILTER = ANISOTROPIC; MAGFILTER = ANISOTROPIC; }; //=================================================================================================== // Uniform, Varying, and FrameBuffer Stream Structures - // Used to Communicate between CPU, VertexProcessor, FragmentProcessor, and FrameBuffer //=================================================================================================== struct VertexInput { float4 position : POSITION0; // Position float4 texCoord : TEXCOORD0; // Texture coordinates }; struct VertexOutput { // These values are used directly by the rasterizer float4 position : POSITION; // Position float4 texCoord : TEXCOORD0; // Texture coordinates (example: TEXCOORD0) }; struct FragmentInput { float4 color : COLOR0; // Color (example: COLOR0) float4 texCoord : TEXCOORD0; // Texture coordinates }; struct FragmentOutput { float4 color : COLOR0; // Color for render target n }; //=================================================================================================== // Vertex and Fragment Shaders //=================================================================================================== // Helper functions //-------------------------------------------------------------------------------------------------- float GetTerrainHeight(float2 texCoord) { return (tex2D(heightMapTextureSampler, texCoord).r); } // Generate Terrain Normals Main //-------------------------------------------------------------------------------------------------- VertexOutput VS_GenerateTerrainNormals(VertexInput IN) { VertexOutput OUT = (VertexOutput)0; OUT.position = mul(IN.position, mul(World, ViewProj)); OUT.texCoord = IN.texCoord; return OUT; } FragmentOutput FS_GenerateTerrainNormals(FragmentInput IN) { FragmentOutput OUT = (FragmentOutput)0; // Set up the texture coordinates needed texCoordX1Z = float2(IN.texCoord.x + invMapWidth, IN.texCoord.y); texCoordXZ1 = float2(IN.texCoord.x, IN.texCoord.y + invMapWidth); texCoordX1Z1 = float2(IN.texCoord.x + invMapWidth, IN.texCoord.y + invMapWidth); // Set up the necessary position vectors positionXZ = float3( IN.texCoord.x, GetTerrainHeight(IN.texCoord.xy), IN.texCoord.y); positionX1Z = float3( texCoordX1Z.x, GetTerrainHeight(texCoordX1Z), texCoordX1Z.y); positionXZ1 = float3( texCoordXZ1.x, GetTerrainHeight(texCoordXZ1), texCoordXZ1.y); positionX1Z1 = float3( texCoordX1Z1.x, GetTerrainHeight(texCoordX1Z1), texCoordX1Z1.y); // Calculate edge vectors for first triangle on this fragment edge1 = positionXZ1 - positionXZ; edge2 = positionXZ - positionX1Z1; // Calculate the normal based on these two edges normal = cross(edge2, edge1); OUT.color.xyz = normal; // Calculate edge vectors for the second triangle on this fragment edge1 = positionXZ - positionX1Z; edge2 = positionX1Z - positionX1Z1; // Calculate the normal based on the two new edges normal = cross(edge2, edge1); OUT.color.xyz += normal; // Normalize and then save normal data to texture OUT.color.xyz = normalize(OUT.color.zyx); OUT.color.a = 1.0f; return OUT; } //=================================================================================================== // Techniques //=================================================================================================== // Generate Terrain Normals technique //-------------------------------------------------------------------------------------------------- technique GenerateTerrainNormals { pass Pass0 { VertexShader = compile vs_3_0 VS_GenerateTerrainNormals(); PixelShader = compile ps_3_0 FS_GenerateTerrainNormals(); // Alpha blending AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; FillMode = Solid; } } "; #endregion /// /// Constructor /// public FXSourceCode() { } /// /// Load compiled AI Vision Source /// /// Effect generated from source public Effect LoadAIVisionFX() { CompiledEffect shader = Effect.CompileEffectFromSource(AIVisionSource, null, null, CompilerOptions.None, TargetPlatform.Windows); if (shader.Success) { return new Effect(Statics_Stream.RenderSettings.graphics.GraphicsDevice, shader.GetEffectCode(), CompilerOptions.None, null); } else { throw new Exception("Missing Shader Code"); } } /// /// Load compiled Elemental GPU Source /// /// Effect generated from source public Effect LoadElementalGPUFX() { CompiledEffect shader = Effect.CompileEffectFromSource(ElementalGPUSource, null, null, CompilerOptions.None, TargetPlatform.Windows); if (shader.Success) { return new Effect(Statics_Stream.RenderSettings.graphics.GraphicsDevice, shader.GetEffectCode(), CompilerOptions.Debug, null); } else { throw new Exception("Missing Shader Code"); } } /// /// Load compiled GPUPhysics Source /// /// Effect generated from source public Effect LoadGPUPhysicsFX() { CompiledEffect shader = Effect.CompileEffectFromSource(GPUPhysicsSource, null, null, CompilerOptions.None, TargetPlatform.Windows); if (shader.Success) { return new Effect(Statics_Stream.RenderSettings.graphics.GraphicsDevice, shader.GetEffectCode(), CompilerOptions.None, null); } else { throw new Exception("Missing Shader Code"); } } /// /// Load compiled Terrain Normal Source /// /// Effect generated from source public Effect LoadTerrainNormalsFX() { CompiledEffect shader = Effect.CompileEffectFromSource(TerrainNormalSource, null, null, CompilerOptions.None, TargetPlatform.Windows); if (shader.Success) { return new Effect(Statics_Stream.RenderSettings.graphics.GraphicsDevice, shader.GetEffectCode(), CompilerOptions.None, null); } else { throw new Exception("Missing Shader Code"); } } } }