instancing + mega refactor #6
			
				
			
		
		
		
	|  | @ -0,0 +1,59 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public class DirectionalShadowMapData | ||||||
|  |     { | ||||||
|  |         public static readonly int MAX_SHADOW_CASCADES = 4; | ||||||
|  | 
 | ||||||
|  |         public RenderTarget2D[] ShadowMaps { get; } | ||||||
|  | 
 | ||||||
|  |         public Matrix[] LightSpaceViews { get; } | ||||||
|  |         public Matrix[] LightSpaceProjections { get; } | ||||||
|  | 
 | ||||||
|  |         public float[] CascadeFarPlanes { get; } | ||||||
|  | 
 | ||||||
|  |         public int ShadowMapSize { get; } | ||||||
|  |         public int NumShadowCascades { get; } | ||||||
|  | 
 | ||||||
|  |         internal DirectionalShadowMapData( | ||||||
|  |             GraphicsDevice graphicsDevice, | ||||||
|  |             int shadowMapSize, | ||||||
|  |             int numCascades | ||||||
|  |         ) { | ||||||
|  |             ShadowMapSize = shadowMapSize; | ||||||
|  |             NumShadowCascades = (int)MathHelper.Clamp(numCascades, 1, MAX_SHADOW_CASCADES); | ||||||
|  | 
 | ||||||
|  |             LightSpaceViews = new Matrix[4]; | ||||||
|  |             LightSpaceProjections = new Matrix[4]; | ||||||
|  | 
 | ||||||
|  |             ShadowMaps = new RenderTarget2D[NumShadowCascades]; | ||||||
|  | 
 | ||||||
|  |             for (var i = 0; i < NumShadowCascades; i++) | ||||||
|  |             { | ||||||
|  |                 ShadowMaps[i] = new RenderTarget2D( | ||||||
|  |                     graphicsDevice, | ||||||
|  |                     shadowMapSize, | ||||||
|  |                     shadowMapSize, | ||||||
|  |                     false, | ||||||
|  |                     SurfaceFormat.Single, | ||||||
|  |                     DepthFormat.Depth24, | ||||||
|  |                     0, | ||||||
|  |                     RenderTargetUsage.PreserveContents | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             CascadeFarPlanes = new float[MAX_SHADOW_CASCADES]; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void Clear(GraphicsDevice graphicsDevice) | ||||||
|  |         { | ||||||
|  |             foreach (var shadowMap in ShadowMaps) | ||||||
|  |             { | ||||||
|  |                 graphicsDevice.SetRenderTarget(shadowMap); | ||||||
|  |                 graphicsDevice.Clear(Color.White); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public interface IHasTranslation | ||||||
|  |     { | ||||||
|  |         Vector3 Translation { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public interface IHasWorldMatrix | ||||||
|  |     { | ||||||
|  |         Matrix World { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -6,8 +6,7 @@ namespace Kav | ||||||
|     public class DeferredPBR_GBufferEffect : Effect, TransformEffect |     public class DeferredPBR_GBufferEffect : Effect, TransformEffect | ||||||
|     { |     { | ||||||
|         EffectParameter worldParam; |         EffectParameter worldParam; | ||||||
|         EffectParameter worldViewProjectionParam; |         EffectParameter viewProjectionParam; | ||||||
|         EffectParameter worldInverseTransposeParam; |  | ||||||
| 
 | 
 | ||||||
|         EffectParameter albedoTextureParam; |         EffectParameter albedoTextureParam; | ||||||
|         EffectParameter normalTextureParam; |         EffectParameter normalTextureParam; | ||||||
|  | @ -17,6 +16,7 @@ namespace Kav | ||||||
|         EffectParameter metallicParam; |         EffectParameter metallicParam; | ||||||
|         EffectParameter roughnessParam; |         EffectParameter roughnessParam; | ||||||
| 
 | 
 | ||||||
|  |         EffectParameter vertexShaderIndexParam; | ||||||
|         EffectParameter shaderIndexParam; |         EffectParameter shaderIndexParam; | ||||||
| 
 | 
 | ||||||
|         Matrix world = Matrix.Identity; |         Matrix world = Matrix.Identity; | ||||||
|  | @ -30,6 +30,7 @@ namespace Kav | ||||||
|         bool albedoTextureEnabled = false; |         bool albedoTextureEnabled = false; | ||||||
|         bool metallicRoughnessMapEnabled = false; |         bool metallicRoughnessMapEnabled = false; | ||||||
|         bool normalMapEnabled = false; |         bool normalMapEnabled = false; | ||||||
|  |         bool hardwareInstancingEnabled = false; | ||||||
| 
 | 
 | ||||||
|         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; |         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; | ||||||
| 
 | 
 | ||||||
|  | @ -39,7 +40,7 @@ namespace Kav | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 world = value; |                 world = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.World | EffectDirtyFlags.WorldViewProj; |                 dirtyFlags |= EffectDirtyFlags.World; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -49,7 +50,7 @@ namespace Kav | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 view = value; |                 view = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.WorldViewProj | EffectDirtyFlags.EyePosition; |                 dirtyFlags |= EffectDirtyFlags.ViewProj | EffectDirtyFlags.EyePosition; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +60,7 @@ namespace Kav | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 projection = value; |                 projection = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.WorldViewProj; |                 dirtyFlags |= EffectDirtyFlags.ViewProj; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -100,7 +101,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 albedoTextureParam.SetValue(value); |                 albedoTextureParam.SetValue(value); | ||||||
|                 albedoTextureEnabled = value != null; |                 albedoTextureEnabled = value != null; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                 dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -111,7 +112,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 normalTextureParam.SetValue(value); |                 normalTextureParam.SetValue(value); | ||||||
|                 normalMapEnabled = value != null; |                 normalMapEnabled = value != null; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                 dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -122,7 +123,20 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 metallicRoughnessTextureParam.SetValue(value); |                 metallicRoughnessTextureParam.SetValue(value); | ||||||
|                 metallicRoughnessMapEnabled = value != null; |                 metallicRoughnessMapEnabled = value != null; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                 dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool HardwareInstancingEnabled | ||||||
|  |         { | ||||||
|  |             get { return hardwareInstancingEnabled; } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 if (value != hardwareInstancingEnabled) | ||||||
|  |                 { | ||||||
|  |                     hardwareInstancingEnabled = value; | ||||||
|  |                     dirtyFlags |= EffectDirtyFlags.VertexShaderIndex; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -159,30 +173,30 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 worldParam.SetValue(world); |                 worldParam.SetValue(world); | ||||||
| 
 | 
 | ||||||
|                 Matrix.Invert(ref world, out Matrix worldInverse); |  | ||||||
|                 Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose); |  | ||||||
|                 worldInverseTransposeParam.SetValue(worldInverseTranspose); |  | ||||||
| 
 |  | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.World; |                 dirtyFlags &= ~EffectDirtyFlags.World; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) |             if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0) | ||||||
|             { |             { | ||||||
|                 Matrix.Multiply(ref world, ref view, out Matrix worldView); |                 Matrix.Multiply(ref view, ref projection, out Matrix viewProj); | ||||||
|                 Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj); |                 viewProjectionParam.SetValue(viewProj); | ||||||
|                 worldViewProjectionParam.SetValue(worldViewProj); |  | ||||||
| 
 | 
 | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; |                 dirtyFlags &= ~EffectDirtyFlags.ViewProj; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.EyePosition) != 0) |             if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0) | ||||||
|             { |             { | ||||||
|                 Matrix.Invert(ref view, out Matrix inverseView); |                 int vertexShaderIndex = 0; | ||||||
| 
 | 
 | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.EyePosition; |                 if (hardwareInstancingEnabled) | ||||||
|  |                 { | ||||||
|  |                     vertexShaderIndex = 1; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0) |                 vertexShaderIndexParam.SetValue(vertexShaderIndex); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) | ||||||
|             { |             { | ||||||
|                 int shaderIndex = 0; |                 int shaderIndex = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -217,15 +231,14 @@ namespace Kav | ||||||
| 
 | 
 | ||||||
|                 shaderIndexParam.SetValue(shaderIndex); |                 shaderIndexParam.SetValue(shaderIndex); | ||||||
| 
 | 
 | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.ShaderIndex; |                 dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         void CacheEffectParameters() |         void CacheEffectParameters() | ||||||
|         { |         { | ||||||
|             worldParam = Parameters["World"]; |             worldParam = Parameters["World"]; | ||||||
|             worldViewProjectionParam = Parameters["WorldViewProjection"]; |             viewProjectionParam = Parameters["ViewProjection"]; | ||||||
|             worldInverseTransposeParam = Parameters["WorldInverseTranspose"]; |  | ||||||
| 
 | 
 | ||||||
|             albedoTextureParam = Parameters["AlbedoTexture"]; |             albedoTextureParam = Parameters["AlbedoTexture"]; | ||||||
|             normalTextureParam = Parameters["NormalTexture"]; |             normalTextureParam = Parameters["NormalTexture"]; | ||||||
|  | @ -235,7 +248,8 @@ namespace Kav | ||||||
|             metallicParam = Parameters["MetallicValue"]; |             metallicParam = Parameters["MetallicValue"]; | ||||||
|             roughnessParam = Parameters["RoughnessValue"]; |             roughnessParam = Parameters["RoughnessValue"]; | ||||||
| 
 | 
 | ||||||
|             shaderIndexParam = Parameters["ShaderIndex"]; |             shaderIndexParam = Parameters["PixelShaderIndex"]; | ||||||
|  |             vertexShaderIndexParam = Parameters["VertexShaderIndex"]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ namespace Kav | ||||||
|                 if (normalMapEnabled != value) |                 if (normalMapEnabled != value) | ||||||
|                 { |                 { | ||||||
|                     normalMapEnabled = value; |                     normalMapEnabled = value; | ||||||
|                     dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                     dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -142,7 +142,7 @@ namespace Kav | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; |                 dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0) |             if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) | ||||||
|             { |             { | ||||||
|                 int shaderIndex = 0; |                 int shaderIndex = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,9 @@ namespace Kav | ||||||
|         WorldViewProj = 1, |         WorldViewProj = 1, | ||||||
|         World = 2, |         World = 2, | ||||||
|         EyePosition = 4, |         EyePosition = 4, | ||||||
|         ShaderIndex = 8, |         VertexShaderIndex = 8, | ||||||
|  |         PixelShaderIndex = 16, | ||||||
|  |         ViewProj = 32, | ||||||
|         All = -1 |         All = -1 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								Effects/FXB/DeferredPBR_GBufferEffect.fxb (Stored with Git LFS)
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Effects/FXB/SimpleDepthEffect.fxb (Stored with Git LFS)
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								Effects/FXB/SimpleDepthEffect.fxb (Stored with Git LFS)
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -13,8 +13,7 @@ BEGIN_CONSTANTS | ||||||
| MATRIX_CONSTANTS | MATRIX_CONSTANTS | ||||||
| 
 | 
 | ||||||
|     float4x4 World                  _vs(c0)               _cb(c7); |     float4x4 World                  _vs(c0)               _cb(c7); | ||||||
|     float4x4 WorldInverseTranspose  _vs(c4)               _cb(c11); |     float4x4 ViewProjection         _vs(c4)               _cb(c11); | ||||||
|     float4x4 WorldViewProjection    _vs(c8)               _cb(c15); |  | ||||||
| 
 | 
 | ||||||
| END_CONSTANTS | END_CONSTANTS | ||||||
| 
 | 
 | ||||||
|  | @ -22,7 +21,7 @@ struct VertexInput | ||||||
| { | { | ||||||
|     float4 Position : POSITION; |     float4 Position : POSITION; | ||||||
|     float3 Normal   : NORMAL; |     float3 Normal   : NORMAL; | ||||||
|     float2 TexCoord : TEXCOORD0; |     float2 TexCoord : TEXCOORD; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct PixelInput | struct PixelInput | ||||||
|  | @ -48,9 +47,33 @@ PixelInput main_vs(VertexInput input) | ||||||
|     PixelInput output; |     PixelInput output; | ||||||
| 
 | 
 | ||||||
|     output.PositionWorld = mul(input.Position, World).xyz; |     output.PositionWorld = mul(input.Position, World).xyz; | ||||||
|     output.NormalWorld = mul(input.Normal, (float3x3)WorldInverseTranspose).xyz; |     output.NormalWorld = normalize(mul(input.Normal, World)); | ||||||
|     output.TexCoord = input.TexCoord; |     output.TexCoord = input.TexCoord; | ||||||
|     output.Position = mul(input.Position, WorldViewProjection); | 
 | ||||||
|  |     float4x4 worldViewProjection = mul(World, ViewProjection); | ||||||
|  |     output.Position = mul(input.Position, worldViewProjection); | ||||||
|  | 
 | ||||||
|  |     return output; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PixelInput instanced_vs(VertexInput input, float3 Translation : TEXCOORD2) | ||||||
|  | { | ||||||
|  |     PixelInput output; | ||||||
|  | 
 | ||||||
|  |     float4x4 world = float4x4( | ||||||
|  |         float4(1, 0, 0, 0), | ||||||
|  |         float4(0, 1, 0, 0), | ||||||
|  |         float4(0, 0, 1, 0), | ||||||
|  |         float4(Translation.x, Translation.y, Translation.z, 1) | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     float4x4 worldViewProjection = mul(world, ViewProjection); | ||||||
|  | 
 | ||||||
|  |     output.PositionWorld = mul(input.Position, world); | ||||||
|  |     output.NormalWorld = mul(input.Normal, world); | ||||||
|  |     output.TexCoord = input.TexCoord; | ||||||
|  | 
 | ||||||
|  |     output.Position = mul(input.Position, worldViewProjection); | ||||||
| 
 | 
 | ||||||
|     return output; |     return output; | ||||||
| } | } | ||||||
|  | @ -171,6 +194,19 @@ PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input) | ||||||
|     return output; |     return output; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | VertexShader VSArray[2] = | ||||||
|  | { | ||||||
|  |     compile vs_3_0 main_vs(), | ||||||
|  |     compile vs_3_0 instanced_vs() | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int VSIndices[2] = | ||||||
|  | { | ||||||
|  |     0, 1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int VertexShaderIndex = 0; | ||||||
|  | 
 | ||||||
| PixelShader PSArray[8] = | PixelShader PSArray[8] = | ||||||
| { | { | ||||||
|     compile ps_3_0 NonePS(), |     compile ps_3_0 NonePS(), | ||||||
|  | @ -191,13 +227,13 @@ int PSIndices[8] = | ||||||
|     0, 1, 2, 3, 4, 5, 6, 7 |     0, 1, 2, 3, 4, 5, 6, 7 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int ShaderIndex = 0; | int PixelShaderIndex = 0; | ||||||
| 
 | 
 | ||||||
| Technique GBuffer | Technique GBuffer | ||||||
| { | { | ||||||
|     Pass |     Pass | ||||||
|     { |     { | ||||||
|         VertexShader = compile vs_3_0 main_vs(); |         VertexShader = (VSArray[VSIndices[VertexShaderIndex]]); | ||||||
|         PixelShader = (PSArray[PSIndices[ShaderIndex]]); |         PixelShader  = (PSArray[PSIndices[PixelShaderIndex]]); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,10 +2,11 @@ | ||||||
| 
 | 
 | ||||||
| BEGIN_CONSTANTS | BEGIN_CONSTANTS | ||||||
| 
 | 
 | ||||||
|     float4x4 ModelViewProjection    _vs(c0)             _cb(c0); |  | ||||||
| 
 |  | ||||||
| MATRIX_CONSTANTS | MATRIX_CONSTANTS | ||||||
| 
 | 
 | ||||||
|  |     float4x4 World             _vs(c0)             _cb(c0); | ||||||
|  |     float4x4 ViewProjection    _vs(c4)             _cb(c4); | ||||||
|  | 
 | ||||||
| END_CONSTANTS | END_CONSTANTS | ||||||
| 
 | 
 | ||||||
| struct VertexShaderInput | struct VertexShaderInput | ||||||
|  | @ -15,15 +16,16 @@ struct VertexShaderInput | ||||||
| 
 | 
 | ||||||
| struct VertexShaderOutput | struct VertexShaderOutput | ||||||
| { | { | ||||||
|     float4 Position : SV_Position; |     float4 Position : SV_POSITION; | ||||||
|     float Depth : TEXCOORD0; |     float Depth : DEPTH; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| VertexShaderOutput main_vs(VertexShaderInput input) | VertexShaderOutput main_vs(VertexShaderInput input) | ||||||
| { | { | ||||||
|     VertexShaderOutput output; |     VertexShaderOutput output; | ||||||
| 
 | 
 | ||||||
|     output.Position = mul(input.Position, ModelViewProjection); |     float4x4 worldViewProjection = mul(World, ViewProjection); | ||||||
|  |     output.Position = mul(input.Position, worldViewProjection); | ||||||
|     output.Depth = output.Position.z / output.Position.w; |     output.Depth = output.Position.z / output.Position.w; | ||||||
| 
 | 
 | ||||||
|     return output; |     return output; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,45 @@ | ||||||
|  | float4x4 ViewProjection; | ||||||
|  | 
 | ||||||
|  | struct VertexShaderInput | ||||||
|  | { | ||||||
|  |     float4 Position : POSITION; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct VertexShaderOutput | ||||||
|  | { | ||||||
|  |     float4 Position : POSITION0; | ||||||
|  |     float4 ProjectedPosition : TEXCOORD0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | VertexShaderOutput instanced_vs(VertexShaderInput input, float3 Translation : TEXCOORD2) | ||||||
|  | { | ||||||
|  |     VertexShaderOutput output; | ||||||
|  |      | ||||||
|  |     float4x4 world = float4x4( | ||||||
|  |         float4(1, 0, 0, 0), | ||||||
|  |         float4(0, 1, 0, 0), | ||||||
|  |         float4(0, 0, 1, 0), | ||||||
|  |         float4(Translation.x, Translation.y, Translation.z, 1) | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     float4x4 worldViewProjection = mul(world, ViewProjection); | ||||||
|  | 
 | ||||||
|  |     output.Position = mul(input.Position, worldViewProjection); | ||||||
|  |     output.ProjectedPosition = output.Position; | ||||||
|  | 
 | ||||||
|  |     return output; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float4 main_ps(VertexShaderOutput input) : COLOR0 | ||||||
|  | { | ||||||
|  |     return float4(input.ProjectedPosition.z / input.ProjectedPosition.w, 0.0, 0.0, 0.0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Technique SimpleDepth | ||||||
|  | { | ||||||
|  |     Pass | ||||||
|  |     { | ||||||
|  |         VertexShader = compile vs_3_0 instanced_vs(); | ||||||
|  |         PixelShader  = compile ps_3_0 main_ps(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -3,28 +3,28 @@ using Microsoft.Xna.Framework.Graphics; | ||||||
| 
 | 
 | ||||||
| namespace Kav | namespace Kav | ||||||
| { | { | ||||||
|     public class LinearDepthEffect : Effect |     public class LinearDepthEffect : Effect, IHasWorldMatrix | ||||||
|     { |     { | ||||||
|         EffectParameter modelParam; |         EffectParameter worldParam; | ||||||
|         EffectParameter modelViewProjectionParam; |         EffectParameter worldViewProjectionParam; | ||||||
|         EffectParameter lightPositionParam; |         EffectParameter lightPositionParam; | ||||||
|         EffectParameter farPlaneParam; |         EffectParameter farPlaneParam; | ||||||
| 
 | 
 | ||||||
|         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; |         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; | ||||||
| 
 | 
 | ||||||
|         Matrix model; |         Matrix world; | ||||||
|         Matrix view; |         Matrix view; | ||||||
|         Matrix projection; |         Matrix projection; | ||||||
| 
 | 
 | ||||||
|         public Vector3 LightPosition { get; set; } |         public Vector3 LightPosition { get; set; } | ||||||
|         public float FarPlane { get; set; } |         public float FarPlane { get; set; } | ||||||
| 
 | 
 | ||||||
|         public Matrix Model |         public Matrix World | ||||||
|         { |         { | ||||||
|             get { return model; } |             get { return world; } | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 model = value; |                 world = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.World; |                 dirtyFlags |= EffectDirtyFlags.World; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.WorldViewProj; |                 dirtyFlags |= EffectDirtyFlags.WorldViewProj; | ||||||
|             } |             } | ||||||
|  | @ -60,16 +60,16 @@ namespace Kav | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) |             if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) | ||||||
|             { |             { | ||||||
|                 Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); |                 Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); | ||||||
|                 Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj); |                 Matrix.Multiply(ref world, ref viewProjection, out Matrix worldViewProj); | ||||||
| 
 | 
 | ||||||
|                 modelViewProjectionParam.SetValue(worldViewProj); |                 worldViewProjectionParam.SetValue(worldViewProj); | ||||||
| 
 | 
 | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; |                 dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.World) != 0) |             if ((dirtyFlags & EffectDirtyFlags.World) != 0) | ||||||
|             { |             { | ||||||
|                 modelParam.SetValue(model); |                 worldParam.SetValue(world); | ||||||
|                  |                  | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.World; |                 dirtyFlags &= ~EffectDirtyFlags.World; | ||||||
|             } |             } | ||||||
|  | @ -80,8 +80,8 @@ namespace Kav | ||||||
| 
 | 
 | ||||||
|         private void CacheEffectParameters() |         private void CacheEffectParameters() | ||||||
|         { |         { | ||||||
|             modelParam               = Parameters["Model"]; |             worldParam               = Parameters["Model"]; | ||||||
|             modelViewProjectionParam = Parameters["ModelViewProjection"]; |             worldViewProjectionParam = Parameters["ModelViewProjection"]; | ||||||
| 
 | 
 | ||||||
|             lightPositionParam       = Parameters["LightPosition"]; |             lightPositionParam       = Parameters["LightPosition"]; | ||||||
|             farPlaneParam            = Parameters["FarPlane"]; |             farPlaneParam            = Parameters["FarPlane"]; | ||||||
|  |  | ||||||
|  | @ -130,7 +130,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 albedoTextureParam.SetValue(value); |                 albedoTextureParam.SetValue(value); | ||||||
|                 albedoTextureEnabled = value != null; |                 albedoTextureEnabled = value != null; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                 dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -141,7 +141,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 normalTextureParam.SetValue(value); |                 normalTextureParam.SetValue(value); | ||||||
|                 normalMapEnabled = value != null; |                 normalMapEnabled = value != null; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                 dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -164,7 +164,7 @@ namespace Kav | ||||||
|             { |             { | ||||||
|                 metallicRoughnessTextureParam.SetValue(value); |                 metallicRoughnessTextureParam.SetValue(value); | ||||||
|                 metallicRoughnessMapEnabled = value != null; |                 metallicRoughnessMapEnabled = value != null; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.ShaderIndex; |                 dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -266,7 +266,7 @@ namespace Kav | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.EyePosition; |                 dirtyFlags &= ~EffectDirtyFlags.EyePosition; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0) |             if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) | ||||||
|             { |             { | ||||||
|                 int shaderIndex = 0; |                 int shaderIndex = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -301,7 +301,7 @@ namespace Kav | ||||||
| 
 | 
 | ||||||
|                 shaderIndexParam.SetValue(shaderIndex); |                 shaderIndexParam.SetValue(shaderIndex); | ||||||
| 
 | 
 | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.ShaderIndex; |                 dirtyFlags &= ~EffectDirtyFlags.PixelShaderIndex; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,23 +3,24 @@ using Microsoft.Xna.Framework.Graphics; | ||||||
| 
 | 
 | ||||||
| namespace Kav | namespace Kav | ||||||
| { | { | ||||||
|     public class SimpleDepthEffect : Effect |     public class SimpleDepthEffect : Effect, IHasWorldMatrix | ||||||
|     { |     { | ||||||
|         EffectParameter modelViewProjectionParam; |         EffectParameter worldParam; | ||||||
|  |         EffectParameter viewProjectionParam; | ||||||
| 
 | 
 | ||||||
|         Matrix model; |         Matrix world; | ||||||
|         Matrix view; |         Matrix view; | ||||||
|         Matrix projection; |         Matrix projection; | ||||||
| 
 | 
 | ||||||
|         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; |         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; | ||||||
| 
 | 
 | ||||||
|         public Matrix Model |         public Matrix World | ||||||
|         { |         { | ||||||
|             get { return model; } |             get { return world; } | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 model = value; |                 world = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.WorldViewProj; |                 dirtyFlags |= EffectDirtyFlags.World; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -29,7 +30,7 @@ namespace Kav | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 view = value; |                 view = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.WorldViewProj; |                 dirtyFlags |= EffectDirtyFlags.ViewProj; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -39,7 +40,7 @@ namespace Kav | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 projection = value; |                 projection = value; | ||||||
|                 dirtyFlags |= EffectDirtyFlags.WorldViewProj; |                 dirtyFlags |= EffectDirtyFlags.ViewProj; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -50,20 +51,26 @@ namespace Kav | ||||||
| 
 | 
 | ||||||
|         protected override void OnApply() |         protected override void OnApply() | ||||||
|         { |         { | ||||||
|             if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) |             if ((dirtyFlags & EffectDirtyFlags.World) != 0) | ||||||
|  |             { | ||||||
|  |                 worldParam.SetValue(world); | ||||||
|  | 
 | ||||||
|  |                 dirtyFlags &= ~EffectDirtyFlags.World; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0) | ||||||
|             { |             { | ||||||
|                 Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); |                 Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); | ||||||
|                 Matrix.Multiply(ref model, ref viewProjection, out Matrix worldViewProj); |                 viewProjectionParam.SetValue(viewProjection); | ||||||
| 
 | 
 | ||||||
|                 modelViewProjectionParam.SetValue(worldViewProj); |                 dirtyFlags &= ~EffectDirtyFlags.ViewProj; | ||||||
| 
 |  | ||||||
|                 dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void CacheEffectParameters() |         private void CacheEffectParameters() | ||||||
|         { |         { | ||||||
|             modelViewProjectionParam = Parameters["ModelViewProjection"]; |             worldParam = Parameters["World"]; | ||||||
|  |             viewProjectionParam = Parameters["ViewProjection"]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,56 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public class SimpleDepthEffectInstanced : Effect | ||||||
|  |     { | ||||||
|  |         EffectParameter viewProjectionParam; | ||||||
|  | 
 | ||||||
|  |         Matrix view; | ||||||
|  |         Matrix projection; | ||||||
|  | 
 | ||||||
|  |         EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; | ||||||
|  | 
 | ||||||
|  |         public Matrix View | ||||||
|  |         { | ||||||
|  |             get { return view; } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 view = value; | ||||||
|  |                 dirtyFlags |= EffectDirtyFlags.ViewProj; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Matrix Projection | ||||||
|  |         { | ||||||
|  |             get { return projection; } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 projection = value; | ||||||
|  |                 dirtyFlags |= EffectDirtyFlags.ViewProj; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public SimpleDepthEffectInstanced(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.SimpleDepthEffectInstanced) | ||||||
|  |         { | ||||||
|  |             CacheEffectParameters(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected override void OnApply() | ||||||
|  |         { | ||||||
|  |             if ((dirtyFlags & EffectDirtyFlags.ViewProj) != 0) | ||||||
|  |             { | ||||||
|  |                 Matrix.Multiply(ref view, ref projection, out Matrix viewProjection); | ||||||
|  |                 viewProjectionParam.SetValue(viewProjection); | ||||||
|  | 
 | ||||||
|  |                 dirtyFlags &= ~EffectDirtyFlags.ViewProj; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void CacheEffectParameters() | ||||||
|  |         { | ||||||
|  |             viewProjectionParam = Parameters["ViewProjection"]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public interface IGBufferDrawable | ||||||
|  |     { | ||||||
|  |         Vector3 Albedo { get; } | ||||||
|  |         float Metallic { get; } | ||||||
|  |         float Roughness { get; } | ||||||
|  | 
 | ||||||
|  |         Texture2D AlbedoTexture { get; } | ||||||
|  |         Texture2D NormalTexture { get; } | ||||||
|  |         Texture2D MetallicRoughnessTexture { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public interface IHasVertexPositions | ||||||
|  |     { | ||||||
|  |         Vector3[] Positions { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public interface IIndexDrawable | ||||||
|  |     { | ||||||
|  |         VertexBuffer VertexBuffer { get; } | ||||||
|  |         IndexBuffer IndexBuffer { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics; | ||||||
| 
 | 
 | ||||||
| namespace Kav | namespace Kav | ||||||
| { | { | ||||||
|     public class MeshPart |     public class MeshPart : IIndexDrawable, IGBufferDrawable, ICullable, IHasVertexPositions | ||||||
|     { |     { | ||||||
|         public IndexBuffer IndexBuffer { get; } |         public IndexBuffer IndexBuffer { get; } | ||||||
|         public VertexBuffer VertexBuffer { get; } |         public VertexBuffer VertexBuffer { get; } | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ using Microsoft.Xna.Framework.Graphics; | ||||||
| 
 | 
 | ||||||
| namespace Kav | namespace Kav | ||||||
| { | { | ||||||
|     public class MeshSprite : ICullable |     public class MeshSprite : ICullable, IIndexDrawable | ||||||
|     { |     { | ||||||
|         private static readonly int PixelScale = 40; |         private static readonly int PixelScale = 40; | ||||||
|         private static readonly short[] Indices = new short[] |         private static readonly short[] Indices = new short[] | ||||||
|  |  | ||||||
|  | @ -43,6 +43,9 @@ | ||||||
|     <EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb"> |     <EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb"> | ||||||
|       <LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName> |       <LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName> | ||||||
| 		</EmbeddedResource> | 		</EmbeddedResource> | ||||||
|  |     <EmbeddedResource Include="Effects\FXB\SimpleDepthEffectInstanced.fxb"> | ||||||
|  |       <LogicalName>Kav.Resources.SimpleDepthEffectInstanced.fxb</LogicalName> | ||||||
|  | 		</EmbeddedResource> | ||||||
|     <EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb"> |     <EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb"> | ||||||
|       <LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName> |       <LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName> | ||||||
| 		</EmbeddedResource> | 		</EmbeddedResource> | ||||||
|  |  | ||||||
|  | @ -43,6 +43,9 @@ | ||||||
|     <EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb"> |     <EmbeddedResource Include="Effects\FXB\SimpleDepthEffect.fxb"> | ||||||
|       <LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName> |       <LogicalName>Kav.Resources.SimpleDepthEffect.fxb</LogicalName> | ||||||
| 		</EmbeddedResource> | 		</EmbeddedResource> | ||||||
|  |     <EmbeddedResource Include="Effects\FXB\SimpleDepthEffectInstanced.fxb"> | ||||||
|  |       <LogicalName>Kav.Resources.SimpleDepthEffectInstanced.fxb</LogicalName> | ||||||
|  | 		</EmbeddedResource> | ||||||
|     <EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb"> |     <EmbeddedResource Include="Effects\FXB\LinearDepthEffect.fxb"> | ||||||
|       <LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName> |       <LogicalName>Kav.Resources.LinearDepthEffect.fxb</LogicalName> | ||||||
| 		</EmbeddedResource> | 		</EmbeddedResource> | ||||||
|  |  | ||||||
							
								
								
									
										991
									
								
								Renderer.cs
								
								
								
								
							
							
						
						
									
										991
									
								
								Renderer.cs
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								Resources.cs
								
								
								
								
							
							
						
						
									
										13
									
								
								Resources.cs
								
								
								
								
							|  | @ -111,6 +111,18 @@ namespace Kav | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         public static byte[] SimpleDepthEffectInstanced | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (simpleDepthEffectInstanced == null) | ||||||
|  |                 { | ||||||
|  |                     simpleDepthEffectInstanced = GetResource("SimpleDepthEffectInstanced.fxb"); | ||||||
|  |                 } | ||||||
|  |                 return simpleDepthEffectInstanced; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         public static byte[] LinearDepthEffect |         public static byte[] LinearDepthEffect | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
|  | @ -168,6 +180,7 @@ namespace Kav | ||||||
|         private static byte[] deferredPBREffect; |         private static byte[] deferredPBREffect; | ||||||
|         private static byte[] pbrEffect; |         private static byte[] pbrEffect; | ||||||
|         private static byte[] simpleDepthEffect; |         private static byte[] simpleDepthEffect; | ||||||
|  |         private static byte[] simpleDepthEffectInstanced; | ||||||
|         private static byte[] linearDepthEffect; |         private static byte[] linearDepthEffect; | ||||||
|         private static byte[] skyboxEffect; |         private static byte[] skyboxEffect; | ||||||
|         private static byte[] diffuseLitSpriteEffect; |         private static byte[] diffuseLitSpriteEffect; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     public static class VertexDeclarations | ||||||
|  |     { | ||||||
|  |         public static VertexDeclaration PositionInstanceDeclaration = new VertexDeclaration | ||||||
|  |         ( | ||||||
|  |             new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 2) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  | using Microsoft.Xna.Framework; | ||||||
|  | using Microsoft.Xna.Framework.Graphics; | ||||||
|  | 
 | ||||||
|  | namespace Kav | ||||||
|  | { | ||||||
|  |     [StructLayout(LayoutKind.Sequential, Pack = 1)] | ||||||
|  |     public struct PositionInstanceVertex : IVertexType, IHasTranslation | ||||||
|  |     { | ||||||
|  |         VertexDeclaration IVertexType.VertexDeclaration | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 return VertexDeclarations.PositionInstanceDeclaration; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Vector3 Translation { get; set; } | ||||||
|  | 
 | ||||||
|  |         public static readonly VertexDeclaration VertexDeclaration; | ||||||
|  | 
 | ||||||
|  |         public PositionInstanceVertex( | ||||||
|  |             Vector3 translation | ||||||
|  |         ) { | ||||||
|  |             Translation = translation; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue