//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// 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");
}
}
}
}