Skip to content

Instantly share code, notes, and snippets.

@OptimisticPeach
Last active May 12, 2018 01:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OptimisticPeach/353b04699a1df134356cfbb16a03f635 to your computer and use it in GitHub Desktop.
Save OptimisticPeach/353b04699a1df134356cfbb16a03f635 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
namespace Testing_Project
{
//A primitive effect manager.
public class PrimitiveEffect
{
Effect internalEffect;
public Effect InternalEffect
{
get
{
if (!SetParams)
{
internalEffect.Parameters["World"].SetValue(World);
internalEffect.Parameters["WorldViewProj"].SetValue(World * View * Projection);
internalEffect.Parameters["WorldInverseTranspose"].SetValueTranspose(Matrix.Invert(World));
internalEffect.Parameters["EyePosition"].SetValue(Matrix.Invert(View).Translation);
internalEffect.Parameters["DiffuseColor"].SetValue(DiffuseColor);
internalEffect.Parameters["EmissiveColor"].SetValue(EmissiveColor);
internalEffect.Parameters["SpecularColor"].SetValue(SpecularColor);
internalEffect.Parameters["SpecularPower"].SetValue(SpecularPower);
internalEffect.Parameters["LightDirection"].SetValue(LightDirection);
internalEffect.Parameters["LightDiffuseColor"].SetValue(LightDiffuseColor);
internalEffect.Parameters["LightSpecularColor"].SetValue(LightSpecularColor);
internalEffect.Parameters["Time"].SetValue((float)DateTime.Now.TimeOfDay.TotalSeconds);
SetParams = true;
}
return internalEffect;
}
set
{
internalEffect = value;
SetParams = false;
}
}
private bool SetParams = false;
private Vector3 _lightSpecularColor = new Vector3(1);
private Vector3 _lightDiffuseColor = new Vector3(1);
private Vector3 _lightDirection = new Vector3(1);
private float _specularPower = 1;
private Vector3 _specularColor = new Vector3(1);
private Vector3 _emissiveColor = new Vector3(1);
private Vector4 _diffuseColor = new Vector4(1);
private Matrix _projection = Matrix.Identity;
private Matrix _view = Matrix.Identity;
private Matrix _world = Matrix.Identity;
public Vector4 DiffuseColor
{
get => _diffuseColor; set
{
_diffuseColor = value;
SetParams = false;
}
}
public Vector3 EmissiveColor
{
get => _emissiveColor; set
{
_emissiveColor = value;
SetParams = false;
}
}
public Vector3 SpecularColor
{
get => _specularColor; set
{
_specularColor = value;
SetParams = false;
}
}
public float SpecularPower
{
get => _specularPower; set
{
_specularPower = value;
SetParams = false;
}
}
public Vector3 LightDirection
{
get => _lightDirection; set
{
_lightDirection = value;
SetParams = false;
}
}
public Vector3 LightDiffuseColor
{
get => _lightDiffuseColor; set
{
_lightDiffuseColor = value;
SetParams = false;
}
}
public Vector3 LightSpecularColor
{
get => _lightSpecularColor; set
{
_lightSpecularColor = value;
SetParams = false;
}
}
public Matrix Projection
{
get => _projection; set
{
_projection = value;
SetParams = false;
}
}
public Matrix View
{
get => _view; set
{
_view = value;
SetParams = false;
}
}
public Matrix World
{
get => _world; set
{
_world = value;
SetParams = false;
}
}
public static explicit operator Effect(PrimitiveEffect source)
{
return source.InternalEffect;
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D11;
using Buffer = SharpDX.Direct3D11.Buffer;
using SharpDX.Direct3D;
using SharpDX.DXGI;
using Device = SharpDX.Direct3D11.Device;
using Utils = GardeningGame.Engine.Scenes.Common.Utils;
using GardeningGame.Engine.Scenes.Game.Terrain;
namespace Testing_Project
{
public static class Ext
{
public static void DrawWithGeom(this Water W, GraphicsDevice GD, Vector3 Position, bool UseID, PrimitiveEffect PEffect, GardeningGame.Engine.Scenes.Common.Camera Cam, GeometryShader GS)
{
PEffect.World = Cam.worldMatrix * Matrix.CreateTranslation(Position);
PEffect.View = Cam.viewMatrix;
PEffect.Projection = Cam.projectionMatrix;
if (UseID)
{
PEffect.InternalEffect.CurrentTechnique = PEffect.InternalEffect.Techniques["Plain"];
PEffect.DiffuseColor = W.ID.ToVector4(); //1, 1, 1 by default
}
else
{
PEffect.InternalEffect.CurrentTechnique = PEffect.InternalEffect.Techniques["Colored"];
//PEffect.DiffuseColor = new Vector4(0.35f, 0.35f, 0.35f, 1); //1, 1, 1 by default
PEffect.DiffuseColor = new Vector4(0.192f, 0.192f, 0.192f, 1); //1, 1, 1 by default
PEffect.LightSpecularColor = new Vector3(0f);
PEffect.SpecularColor = new Vector3(1f);
PEffect.SpecularPower = 0.14f;
PEffect.LightDirection = new Vector3(1, .71f, 1);
PEffect.EmissiveColor = new Vector3(0.125f);
}
//Utils.PrimitivesEffect.AmbientLightColor = new Vector3(0, .25f, .75f);
//Utils.PrimitivesEffect.EmissiveColor = new Vector3(0, 0, 1);
//Utils.PrimitivesEffect.SpecularColor = new Vector3(0, .9f, 0.25f);
GD.SetVertexBuffer(W.VertexBuffer);
PEffect.InternalEffect.CurrentTechnique = PEffect.InternalEffect.Techniques[0];
foreach (EffectPass pass in PEffect.InternalEffect.CurrentTechnique.Passes)
{
pass.Apply();
((Device)GD.Handle).ImmediateContext.GeometryShader.Set(GS);
((Device)GD.Handle).ImmediateContext.PixelShader.Set(pass._pixelShader._pixelShader);
((Device)GD.Handle).ImmediateContext.VertexShader.Set(pass._vertexShader._vertexShader);
// assume low-spec DX10 8 regs
// Requires enforcement that GS uses same CBuffers at the same registers as the VS, CBuffers the GS doesn't use are A-Okay, shader doesn't care
//Buffer[] vsBuffers = ((Device)GD.Handle).ImmediateContext.VertexShader.GetConstantBuffers(0, 8);
Buffer[] vsBuffers = PEffect.InternalEffect.ConstantBuffers.Select((a)=>a._cbuffer).ToArray();
if (vsBuffers != null)
{
for (int i = 0; i < vsBuffers.Length; ++i)
((Device)GD.Handle).ImmediateContext.GeometryShader.SetConstantBuffer(i, vsBuffers[i]);
}
if (vsBuffers != null)
{
for (int i = 0; i < vsBuffers.Length; ++i)
((Device)GD.Handle).ImmediateContext.VertexShader.SetConstantBuffer(i, vsBuffers[i]);
}
if (vsBuffers != null)
{
for (int i = 0; i < vsBuffers.Length; ++i)
((Device)GD.Handle).ImmediateContext.PixelShader.SetConstantBuffer(i, vsBuffers[i]);
}
GD.DrawPrimitives(PrimitiveType.TriangleList, 0, W.VertexBuffer.VertexCount / 3);
}
GD.SetVertexBuffer(null);
GD.Indices = null;
}
}
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GardeningGame.Engine.Scenes.Game.GameSceneVariables GSV = new GardeningGame.Engine.Scenes.Game.GameSceneVariables()
{
WaterSize = 10
};
GardeningGame.Engine.Scenes.Game.Terrain.Water W = new GardeningGame.Engine.Scenes.Game.Terrain.Water();
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GardeningGame.Engine.Scenes.Game.GameCam GC = new GardeningGame.Engine.Scenes.Game.GameCam();
public Game1()
{
//GraphicsAdapter.UseDebugLayers = true;
graphics = new GraphicsDeviceManager(this);
graphics.GraphicsProfile = GraphicsProfile.HiDef;
Content.RootDirectory = @".\Content";
}
GeometryShader GS;
PrimitiveEffect peffect = new PrimitiveEffect();
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
IsMouseVisible = true;
W.Generate(10, 10, 100, GraphicsDevice);
GC.Initialize(GraphicsDevice, 1000, 100, false, 1400);
peffect.InternalEffect = Content.Load<Effect>("WaterShader");
var CompiledGS = ShaderBytecode.CompileFromFile(@"Effects\Water\WaterShader.fx", "GeometryShader_", "gs_4_0");
GS = new GeometryShader((Device)GraphicsDevice.Handle, CompiledGS.Bytecode);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
return;
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
W.DrawWithGeom(GraphicsDevice, new Vector3(0), false, peffect, GC, GS);
base.Draw(gameTime);
}
}
}
//float4 FogVector;
//float3 FogColor;
cbuffer Data : register(b0)
{
float4x4 World;
float4x4 WorldViewProj;
float3 EyePosition;
float3x3 WorldInverseTranspose;
float3 LightDirection;
float3 LightDiffuseColor;
float3 LightSpecularColor;
float4 DiffuseColor;
float3 EmissiveColor;
float3 SpecularColor;
float SpecularPower;
float Time;
float WaveFactor;
float WaveLength;
};
// Vertex shader output structures.
struct VSOutput
{
float4 Position : S_POSITION;
float4 Color : COLOR;
float4 PositionPS : SV_Position;
};
struct CommonVSOutput
{
float4 Pos_ps;
float4 Diffuse;
float3 Specular;
};
struct LightColorPair
{
float3 Diffuse;
float3 Specular;
};
struct ColorPair
{
float4 Diffuse;
float3 Specular;
};
struct VSInput
{
float4 Position : POSITION;
float4 Color : COLOR;
};
struct GSInput
{
float4 Position : S_POSITION;
float4 Color : COLOR;
};
struct GSOutput
{
float4 PositionPS : SV_Position;
float4 Diffuse : COLOR0;
float3 Specular : COLOR1;
};
struct PSInput
{
float4 PositionPS : SV_Position;
float4 Diffuse : COLOR0;
float3 Specular : COLOR1;
};
LightColorPair ComputeLights(float3 eyeVector, float3 worldNormal, uniform int numLights)
{
// float3x3 lightDirections = 0;
// float3x3 lightDiffuse = 0;
// float3x3 lightSpecular = 0;
// float3x3 halfVectors = 0;
// lightDirections[0] = float3x3(LightDirection, DirLight1Direction, DirLight2Direction)[0];
// lightDiffuse[0] = float3x3(DirLight1DiffuseColor, DirLight1DiffuseColor, DirLight2DiffuseColor)[0];
// lightSpecular[0] = float3x3(DirLight0SpecularColor, DirLight1SpecularColor, DirLight2SpecularColor)[0];
// halfVectors[0] = normalize(eyeVector - lightDirections[0]);
float3 lightDirection = LightDirection;
float3 lightDiffuse = LightDiffuseColor;
float3 lightSpecular = LightSpecularColor;
float3 halfVectors = 0;
halfVectors = normalize(eyeVector - lightDirection);
float3 dotL = mul(-lightDirection, worldNormal);
float3 dotH = mul(halfVectors, worldNormal);
float3 zeroL = step(float3(0, 0, 0), dotL);
float3 diffuse = zeroL * dotL;
float3 specular = pow(max(dotH, 0) * zeroL, SpecularPower);
LightColorPair result;
result.Diffuse = mul(diffuse, lightDiffuse) * DiffuseColor.rgb + EmissiveColor;
result.Specular = mul(specular, lightSpecular) * SpecularColor;
return result;
}
//float ComputeFogFactor(float4 position)
//{
// return saturate(dot(position, FogVector));
//}
void AddSpecular(inout float4 color, float3 specular)
{
color.rgb += specular * color.a;
}
CommonVSOutput ComputeCommonVSOutputWithLighting(float4 position, float3 normal, uniform int numLights)
{
CommonVSOutput vout;
float4 pos_ws = mul(position, World);
float3 eyeVector = normalize(EyePosition - pos_ws.xyz);
float3 worldNormal = normalize(mul(normal, WorldInverseTranspose));
LightColorPair lightResult = ComputeLights(eyeVector, worldNormal, numLights);
vout.Pos_ps = mul(position, WorldViewProj);
vout.Diffuse = float4(lightResult.Diffuse, DiffuseColor.a);
vout.Specular = lightResult.Specular;
return vout;
}
float generateOffset(float x, float z, float val1, float val2)
{
float radiansX = ((((x + z * x * val1) % WaveLength) / WaveLength) + Time * ((x * 0.8f + z) % 1.5f)) * 6.283185307179586476925286766559f;
float radiansZ = (((val2 * (z * x + x * z) % WaveLength) / WaveLength) + Time * 2.0f * (x % 2.0f)) * 6.283185307179586476925286766559f;
return WaveFactor * 50 * (float) (sin(radiansZ) + cos(radiansX));
}
float3 applyDistortion(float3 vertex)
{
float xDistortion = generateOffset(vertex.x, vertex.z, 0.2f, 0.1f);
float yDistortion = generateOffset(vertex.x, vertex.z, 0.8f, 0.95f);
float zDistortion = generateOffset(vertex.x, vertex.z, 0.15f, 0.2f);
return vertex + float3(xDistortion * 1.5f, yDistortion * 1.5f, zDistortion * 1.5f);
}
[maxvertexcount(3)]
void GeometryShader_(triangle GSInput input[3], inout TriangleStream<GSOutput> outstream)
{
float3 v1 = input[1].Position.xyz - input[0].Position.xyz;
float3 v2 = input[2].Position.xyz - input[0].Position.xyz;
float3 normal = cross(v1, v2);
normalize(normal);
GSOutput output;
CommonVSOutput cout = ComputeCommonVSOutputWithLighting(input[0].Position, normal, 1);
output.PositionPS = cout.Pos_ps;
output.Diffuse = cout.Diffuse;
output.Specular = cout.Specular;
output.Diffuse *= input[0].Color;
outstream.Append(output);
cout = ComputeCommonVSOutputWithLighting(input[1].Position, normal, 1);
output.PositionPS = cout.Pos_ps;
output.Diffuse = cout.Diffuse;
output.Specular = cout.Specular;
output.Diffuse *= input[1].Color;
outstream.Append(output);
cout = ComputeCommonVSOutputWithLighting(input[2].Position, normal, 1);
output.PositionPS = cout.Pos_ps;
output.Diffuse = cout.Diffuse;
output.Specular = cout.Specular;
output.Diffuse *= input[2].Color;
outstream.Append(output);
}
VSOutput VertexShader_(VSInput input)
{
VSOutput r;
r.Position = float4(applyDistortion(input.Position.xyz), input.Position.w);
r.Color = input.Color;
r.PositionPS = mul(input.Position, World);
return r;
}
float4 PixelShader_(PSInput pin) : SV_Target
{
float4 color = pin.Diffuse;
AddSpecular(color, pin.Specular.rgb);
return color;
}
technique T
{
pass
{
VertexShader = compile vs_4_0 VertexShader_();
PixelShader = compile ps_4_0 PixelShader_();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment