From cc491f1f5fd8e76c6277eac674a63b9ce42f6af8 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 21 Aug 2020 21:26:58 -0700 Subject: [PATCH 1/6] add a core and framework csproj --- Kav.csproj => Kav.Core.csproj | 2 +- Kav.Framework.csproj | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) rename Kav.csproj => Kav.Core.csproj (89%) create mode 100644 Kav.Framework.csproj diff --git a/Kav.csproj b/Kav.Core.csproj similarity index 89% rename from Kav.csproj rename to Kav.Core.csproj index 4497042..812b812 100644 --- a/Kav.csproj +++ b/Kav.Core.csproj @@ -11,7 +11,7 @@ - + diff --git a/Kav.Framework.csproj b/Kav.Framework.csproj new file mode 100644 index 0000000..592a8ff --- /dev/null +++ b/Kav.Framework.csproj @@ -0,0 +1,26 @@ + + + + netstandard2.0 + Kav + Evan Hemsley + Evan Hemsley 2020 + true + Kav + + + + + + + + + + Kav.Resources.PBREffect.fxb + + + Kav.Resources.SimpleDepthEffect.fxb + + + + -- 2.25.1 From be611687a8b29e0bdb118a93d35e24cd9521b403 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 22 Aug 2020 02:01:41 -0700 Subject: [PATCH 2/6] rendering g-buffer --- Effects/FXB/GBufferEffect.fxb | Bin 0 -> 7476 bytes Effects/GBufferEffect.cs | 241 ++++++++++++++++++++++++++++++++++ Effects/HLSL/GBufferEffect.fx | 203 ++++++++++++++++++++++++++++ Kav.Core.csproj | 3 + Kav.Framework.csproj | 3 + Loaders/ModelLoader.cs | 2 +- Renderer.cs | 108 +++++++++++++++ Resources.cs | 12 ++ 8 files changed, 571 insertions(+), 1 deletion(-) create mode 100644 Effects/FXB/GBufferEffect.fxb create mode 100644 Effects/GBufferEffect.cs create mode 100644 Effects/HLSL/GBufferEffect.fx diff --git a/Effects/FXB/GBufferEffect.fxb b/Effects/FXB/GBufferEffect.fxb new file mode 100644 index 0000000000000000000000000000000000000000..9b2d6844f486894e8a28f804c05221fee8d81938 GIT binary patch literal 7476 zcmds6O=w(I6u$4hX)BVR!9iS95J^!%L}{9Y+Q3v}lh%NRCMHuGnP!HWq(*S@ zgf3iUF{q0!x_Dqf>9{E9BDkpw5er?E;-VD65oh5-(3J?5jNfR%7Pd%%bDZ{?;7W4VR7`BD!0E--zIU?CrZ z)FC!LS;vwUj^a54ei+VEu1Crj*?)FC!L z-G1DFejUtywA9(AA5XKOr5$)a20oUXo6P5Drj8fp-#$B=E0>#Hisxq0Dc6NE8}(@# z{uAKLI`vEUI3KM37Jn>>O>{ncz-FFLPUh!xdLC&{6D&)tLaN~$%h*f_Gxv0TX^k?y zco)xuEyTXi{R^iIaUuU(;#|H_DCMW|ly>$}u(Va}Jc9akJHxZ*bER@_tTZ`WE*8p+ ze`$Ad8`|9`?Vg;;y*pAWypx-nn<>mH&NIh$%eI+@%$VYHCzxw;H<*||04A1vH!^y- zRGNHG;{jD=EC_t(Vo#ZHv3j~N)+KIP_sHn*?DWi3t_)dV9kF%6)KVAwFnV@!I#)uO z+=A}=Uf3LW7E!dxxU|9kNIbHSuMEteIfK+dKiWC22f?iCQLs=Sgj1s6xd@INeHn7y z(f6UU1JV%eS;z~Heg*P%NBr$Us+mg2VuqIyN&^DwGRn<}wG4Kb1L}9nEG;z-0yt=ZZ7fOEL%ho;j$h)z>lnK=nqZ z>F|(r;c*NP^AciaDn|A~4>Dp7Q$e|2A!FV!4Icbd2>-xKcWc?a$2+almvTBp;fS*5 z$iDH>c3<01XgNr;9pfLQ{SXaVdylTC(J*UR$DzjUKPt{rBW|Bf*WEN1>1n8|u0 zW+Eror>9P6oVf4Z;l%5;Hyq>iCnp=W6dr=p?~wCg!D#{Vhv19aX4c;4*0zkN$#Pxl z24qqV>{~p=?{4rkN3hj-wCy>!&DxIR!Bo^K>~6m8N9MVTVS&O!2H(~BwjJ&sa6hG| z(yX^PwVV!pb)v!?jGP@R)d1H+zC+%oTrp*gAF#pyZeUy&-w&Q_`i7M4dtIlmeXqgy zX2`PCmAZ!VH_>igmknTp91frlzB0MNL!5~}-=T9+fcRlQ=^vmh`mO6^Khdb}6YSc? zKKSY~+Nx{2$x+NFb>O`%|1o24my-f@IilU{KSoZ*cc2>DXT4m-dYG$texS2i z1JA{4;8U2Ax#|*3Lo|b#tAK|lt_#Uki`LfZUK7XVHsq=%PuTwnN%2T=l=jUGLEgJ{@SfW>@3&a)cF2p)*IVT$X>N5uIC|kLoa~S#`se6>e z81HWUx65hD$!Q|5m%Hf0HNo%T8qv^eVklk{zraKrm&<<2AjUS&&U8-ACwEkwycfMCk%ro~P=VJ=HL+;1ioACt`-VggW;to0W-t5~0 z2%n8|yywKc$jN=&!#>V9=bcE6fve+uFpl$|U`odMEtnYRjQ!*{qQrTGccd#|iSzHZ zMdCcM3AZ^%$~WR>_wDVB@vYA5|A%-7oY8-k<2MuklIP90waMq$hcz*FNj%!P)Bw@O zrEm!X&eHMyr}D>-tTbMW*G8{)96v%|y$3+=0T0>ox-8@ga1D&h9o-(!K6k*)`%r#s znNt(Xw5R6xuYKR&>ervp!-O6s^luV+twne5UZrmwZabP=*!*SM3T`F_v%_PoXQi=6 z9U0FKvR?3B`_yxvfz1aCrL6D=s29YXB}B|b=AEhvR&YPr+^c`)OW26H#!0EnZOF1$ zGiOae=Y0tCm9J9BSr5fF-jfl#lzJkznZF-Ys{uSy_{Y9)1-1Wsfwm@Y^UrsBjajuh zCqypO=TOW?i2D_LCRHK6N9C@IJ~jID+=_2bD|_$}*$*-H8t$P2+)UKCSA!#?`&!3$ zv(-~t$G2^S_{MjySL5AhD%O3i?}+u3*1K$ZM29Y)j&)Q2&R93~?~3)b_TLR1xcKZR p+O9B47%P$k6o|NO^!GTH!Cb|}GTbj)_8aK*bK^k#TE1)G_YchewfX=6 literal 0 HcmV?d00001 diff --git a/Effects/GBufferEffect.cs b/Effects/GBufferEffect.cs new file mode 100644 index 0000000..ff8769d --- /dev/null +++ b/Effects/GBufferEffect.cs @@ -0,0 +1,241 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Kav +{ + public class GBufferEffect : Effect, TransformEffect + { + EffectParameter worldParam; + EffectParameter worldViewProjectionParam; + EffectParameter worldInverseTransposeParam; + + EffectParameter albedoTextureParam; + EffectParameter normalTextureParam; + EffectParameter metallicRoughnessTextureParam; + + EffectParameter albedoParam; + EffectParameter metallicParam; + EffectParameter roughnessParam; + + EffectParameter shaderIndexParam; + + Matrix world = Matrix.Identity; + Matrix view = Matrix.Identity; + Matrix projection = Matrix.Identity; + + Vector3 albedo; + float metallic; + float roughness; + + bool albedoTextureEnabled = false; + bool metallicRoughnessMapEnabled = false; + bool normalMapEnabled = false; + + EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; + + public Matrix World + { + get { return world; } + set + { + world = value; + dirtyFlags |= EffectDirtyFlags.World | EffectDirtyFlags.WorldViewProj; + } + } + + public Matrix View + { + get { return view; } + set + { + view = value; + dirtyFlags |= EffectDirtyFlags.WorldViewProj | EffectDirtyFlags.EyePosition; + } + } + + public Matrix Projection + { + get { return projection; } + set + { + projection = value; + dirtyFlags |= EffectDirtyFlags.WorldViewProj; + } + } + + public Vector3 Albedo + { + get { return albedo; } + set + { + albedo = value; + albedoParam.SetValue(albedo); + } + } + + public float Metallic + { + get { return metallic; } + set + { + metallic = value; + metallicParam.SetValue(metallic); + } + } + + public float Roughness + { + get { return roughness; } + set + { + roughness = value; + roughnessParam.SetValue(roughness); + } + } + + public Texture2D AlbedoTexture + { + get { return albedoTextureParam.GetValueTexture2D(); } + set + { + albedoTextureParam.SetValue(value); + albedoTextureEnabled = value != null; + dirtyFlags |= EffectDirtyFlags.ShaderIndex; + } + } + + public Texture2D NormalTexture + { + get { return normalTextureParam.GetValueTexture2D(); } + set + { + normalTextureParam.SetValue(value); + normalMapEnabled = value != null; + dirtyFlags |= EffectDirtyFlags.ShaderIndex; + } + } + + public Texture2D MetallicRoughnessTexture + { + get { return metallicRoughnessTextureParam.GetValueTexture2D(); } + set + { + metallicRoughnessTextureParam.SetValue(value); + metallicRoughnessMapEnabled = value != null; + dirtyFlags |= EffectDirtyFlags.ShaderIndex; + } + } + + public GBufferEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.GBufferEffect) + { + CacheEffectParameters(); + } + + protected GBufferEffect(GBufferEffect cloneSource) : base(cloneSource) + { + CacheEffectParameters(); + + World = cloneSource.World; + View = cloneSource.View; + Projection = cloneSource.Projection; + + AlbedoTexture = cloneSource.AlbedoTexture; + NormalTexture = cloneSource.NormalTexture; + MetallicRoughnessTexture = cloneSource.MetallicRoughnessTexture; + + Albedo = cloneSource.Albedo; + Metallic = cloneSource.Metallic; + Roughness = cloneSource.Roughness; + } + + public override Effect Clone() + { + return new GBufferEffect(this); + } + + protected override void OnApply() + { + if ((dirtyFlags & EffectDirtyFlags.World) != 0) + { + worldParam.SetValue(world); + + Matrix.Invert(ref world, out Matrix worldInverse); + Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose); + worldInverseTransposeParam.SetValue(worldInverseTranspose); + + dirtyFlags &= ~EffectDirtyFlags.World; + } + + if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) + { + Matrix.Multiply(ref world, ref view, out Matrix worldView); + Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj); + worldViewProjectionParam.SetValue(worldViewProj); + + dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; + } + + if ((dirtyFlags & EffectDirtyFlags.EyePosition) != 0) + { + Matrix.Invert(ref view, out Matrix inverseView); + + dirtyFlags &= ~EffectDirtyFlags.EyePosition; + } + + if ((dirtyFlags & EffectDirtyFlags.ShaderIndex) != 0) + { + int shaderIndex = 0; + + if (albedoTextureEnabled && metallicRoughnessMapEnabled && normalMapEnabled) + { + shaderIndex = 7; + } + else if (metallicRoughnessMapEnabled && normalMapEnabled) + { + shaderIndex = 6; + } + else if (albedoTextureEnabled && normalMapEnabled) + { + shaderIndex = 5; + } + else if (albedoTextureEnabled && metallicRoughnessMapEnabled) + { + shaderIndex = 4; + } + else if (normalMapEnabled) + { + shaderIndex = 3; + } + else if (metallicRoughnessMapEnabled) + { + shaderIndex = 2; + } + else if (albedoTextureEnabled) + { + shaderIndex = 1; + } + + shaderIndexParam.SetValue(shaderIndex); + + dirtyFlags &= ~EffectDirtyFlags.ShaderIndex; + } + } + + void CacheEffectParameters() + { + worldParam = Parameters["World"]; + worldViewProjectionParam = Parameters["WorldViewProjection"]; + worldInverseTransposeParam = Parameters["WorldInverseTranspose"]; + + albedoTextureParam = Parameters["AlbedoTexture"]; + normalTextureParam = Parameters["NormalTexture"]; + metallicRoughnessTextureParam = Parameters["MetallicRoughnessTexture"]; + + albedoParam = Parameters["AlbedoValue"]; + metallicParam = Parameters["MetallicValue"]; + roughnessParam = Parameters["RoughnessValue"]; + + shaderIndexParam = Parameters["ShaderIndex"]; + } + } +} diff --git a/Effects/HLSL/GBufferEffect.fx b/Effects/HLSL/GBufferEffect.fx new file mode 100644 index 0000000..63cb2ce --- /dev/null +++ b/Effects/HLSL/GBufferEffect.fx @@ -0,0 +1,203 @@ +#include "Macros.fxh" + +DECLARE_TEXTURE(AlbedoTexture, 0); +DECLARE_TEXTURE(NormalTexture, 1); +DECLARE_TEXTURE(MetallicRoughnessTexture, 2); + +BEGIN_CONSTANTS + + float3 AlbedoValue _ps(c0) _cb(c0); + float MetallicValue _ps(c1) _cb(c1); + float RoughnessValue _ps(c2) _cb(c2); + +MATRIX_CONSTANTS + + float4x4 World _vs(c0) _cb(c7); + float4x4 WorldInverseTranspose _vs(c4) _cb(c11); + float4x4 WorldViewProjection _vs(c8) _cb(c15); + +END_CONSTANTS + +struct VertexInput +{ + float4 Position : POSITION; + float3 Normal : NORMAL; + float2 TexCoord : TEXCOORD0; +}; + +struct PixelInput +{ + float4 Position : SV_POSITION; + float3 PositionWorld : TEXCOORD0; + float3 NormalWorld : TEXCOORD1; + float2 TexCoord : TEXCOORD2; +}; + +struct PixelOutput +{ + float4 gPosition : COLOR0; + float4 gNormal : COLOR1; + float4 gAlbedo : COLOR2; + float4 gMetallicRoughness : COLOR3; +}; + +// Vertex Shader + +PixelInput main_vs(VertexInput input) +{ + PixelInput output; + + output.PositionWorld = mul(input.Position, World).xyz; + output.NormalWorld = mul(input.Normal, (float3x3)WorldInverseTranspose).xyz; + output.TexCoord = input.TexCoord; + output.Position = mul(input.Position, WorldViewProjection); + + return output; +} + +// Pixel Shaders + +// Easy trick to get tangent-normals to world-space to keep PBR code simplified. +float3 GetNormalFromMap(float3 worldPos, float2 texCoords, float3 normal) +{ + float3 tangentNormal = SAMPLE_TEXTURE(NormalTexture, texCoords).xyz * 2.0 - 1.0; + + float3 Q1 = ddx(worldPos); + float3 Q2 = ddy(worldPos); + float2 st1 = ddx(texCoords); + float2 st2 = ddy(texCoords); + + float3 N = normalize(normal); + float3 T = normalize(Q1*st2.y - Q2*st1.y); + float3 B = -normalize(cross(N, T)); + float3x3 TBN = float3x3(T, B, N); + + return normalize(mul(tangentNormal, TBN)); +} + +PixelOutput NonePS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(normalize(input.NormalWorld), 0.0); + output.gAlbedo = float4(AlbedoValue, 1.0); + output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 0.0); + + return output; +} + +PixelOutput AlbedoPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(normalize(input.NormalWorld), 0.0); + output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); + output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 0.0); + + return output; +} + +PixelOutput MetallicRoughnessPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(normalize(input.NormalWorld), 0.0); + output.gAlbedo = float4(AlbedoValue, 1.0); + output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); + + return output; +} + +PixelOutput NormalPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 0.0); + output.gAlbedo = float4(AlbedoValue, 1.0); + output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 0.0); + + return output; +} + +PixelOutput AlbedoMetallicRoughnessPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(normalize(input.NormalWorld), 0.0); + output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); + output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); + + return output; +} + +PixelOutput AlbedoNormalPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 0.0); + output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); + output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 0.0); + + return output; +} + +PixelOutput MetallicRoughnessNormalPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 0.0); + output.gAlbedo = float4(AlbedoValue, 1.0); + output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); + + return output; +} + +PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input) +{ + PixelOutput output; + + output.gPosition = float4(input.PositionWorld, 0.0); + output.gNormal = float4(GetNormalFromMap(input.PositionWorld, input.TexCoord, input.NormalWorld), 0.0); + output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); + output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); + + return output; +} + +PixelShader PSArray[8] = +{ + compile ps_3_0 NonePS(), + + compile ps_3_0 AlbedoPS(), + compile ps_3_0 MetallicRoughnessPS(), + compile ps_3_0 NormalPS(), + + compile ps_3_0 AlbedoMetallicRoughnessPS(), + compile ps_3_0 AlbedoNormalPS(), + compile ps_3_0 MetallicRoughnessNormalPS(), + + compile ps_3_0 AlbedoMetallicRoughnessNormalMapPS() +}; + +int PSIndices[8] = +{ + 0, 1, 2, 3, 4, 5, 6, 7 +}; + +int ShaderIndex = 0; + +Technique GBuffer +{ + Pass + { + VertexShader = compile vs_3_0 main_vs(); + PixelShader = (PSArray[PSIndices[ShaderIndex]]); + } +} diff --git a/Kav.Core.csproj b/Kav.Core.csproj index 812b812..e143f89 100644 --- a/Kav.Core.csproj +++ b/Kav.Core.csproj @@ -15,6 +15,9 @@ + + Kav.Resources.GBufferEffect.fxb + Kav.Resources.PBREffect.fxb diff --git a/Kav.Framework.csproj b/Kav.Framework.csproj index 592a8ff..3d70199 100644 --- a/Kav.Framework.csproj +++ b/Kav.Framework.csproj @@ -15,6 +15,9 @@ + + Kav.Resources.GBufferEffect.fxb + Kav.Resources.PBREffect.fxb diff --git a/Loaders/ModelLoader.cs b/Loaders/ModelLoader.cs index fc5b206..2655368 100644 --- a/Loaders/ModelLoader.cs +++ b/Loaders/ModelLoader.cs @@ -15,7 +15,7 @@ namespace Kav foreach (var meshPartData in meshData.MeshParts) { - var effect = new Kav.PBREffect( + var effect = new Kav.GBufferEffect( graphicsDevice ) { diff --git a/Renderer.cs b/Renderer.cs index 77037b3..f31419e 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -13,6 +13,17 @@ namespace Kav private RenderTarget2D DepthRenderTarget { get; } private SimpleDepthEffect SimpleDepthEffect { get; } + private RenderTarget2D gPosition { get; } + private RenderTarget2D gNormal { get; } + private RenderTarget2D gAlbedo { get; } + private RenderTarget2D gMetallicRoughness { get; } + + private RenderTargetBinding[] GBuffer { get; } + + private GBufferEffect GBufferEffect { get; } + + private SpriteBatch SpriteBatch { get; } + public Renderer(GraphicsDevice graphicsDevice, int renderDimensionsX, int renderDimensionsY) { GraphicsDevice = graphicsDevice; @@ -28,7 +39,104 @@ namespace Kav DepthFormat.Depth24 ); + gPosition = new RenderTarget2D( + GraphicsDevice, + renderDimensionsX, + renderDimensionsY, + false, + SurfaceFormat.Color, + DepthFormat.None + ); + + gNormal = new RenderTarget2D( + GraphicsDevice, + renderDimensionsX, + renderDimensionsY, + false, + SurfaceFormat.Color, + DepthFormat.None + ); + + gAlbedo = new RenderTarget2D( + GraphicsDevice, + renderDimensionsX, + renderDimensionsY, + false, + SurfaceFormat.Color, + DepthFormat.None + ); + + gMetallicRoughness = new RenderTarget2D( + GraphicsDevice, + renderDimensionsX, + renderDimensionsY, + false, + SurfaceFormat.Color, + DepthFormat.None + ); + + GBuffer = new RenderTargetBinding[4] { + new RenderTargetBinding(gPosition), + new RenderTargetBinding(gNormal), + new RenderTargetBinding(gAlbedo), + new RenderTargetBinding(gMetallicRoughness) + }; + SimpleDepthEffect = new SimpleDepthEffect(GraphicsDevice); + + SpriteBatch = new SpriteBatch(GraphicsDevice); + } + + public void DeferredRender( + Camera camera, + IEnumerable<(Model, Matrix)> modelTransforms, + IEnumerable pointLights, + IEnumerable directionalLights + ) { + GraphicsDevice.SetRenderTargets(GBuffer); + GraphicsDevice.Clear(Color.Black); + + foreach (var (model, transform) in modelTransforms) + { + foreach (var modelMesh in model.Meshes) + { + foreach (var meshPart in modelMesh.MeshParts) + { + GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); + GraphicsDevice.Indices = meshPart.IndexBuffer; + + if (meshPart.Effect is TransformEffect transformEffect) + { + transformEffect.World = transform; + transformEffect.View = camera.View; + transformEffect.Projection = camera.Projection; + } + + foreach (var pass in meshPart.Effect.CurrentTechnique.Passes) + { + pass.Apply(); + + GraphicsDevice.DrawIndexedPrimitives( + PrimitiveType.TriangleList, + 0, + 0, + meshPart.VertexBuffer.VertexCount, + 0, + meshPart.Triangles.Length + ); + } + } + } + } + + GraphicsDevice.SetRenderTarget(null); + GraphicsDevice.Clear(Color.Black); + SpriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null); + SpriteBatch.Draw(gPosition, new Rectangle(0, 0, 640, 360), Color.White); + SpriteBatch.Draw(gAlbedo, new Rectangle(640, 0, 640, 360), Color.White); + SpriteBatch.Draw(gNormal, new Rectangle(0, 360, 640, 360), Color.White); + SpriteBatch.Draw(gMetallicRoughness, new Rectangle(640, 360, 640, 360), Color.White); + SpriteBatch.End(); } public void Render( diff --git a/Resources.cs b/Resources.cs index 6ff3806..293307d 100644 --- a/Resources.cs +++ b/Resources.cs @@ -4,6 +4,17 @@ namespace Kav { internal class Resources { + public static byte[] GBufferEffect + { + get + { + if (gBufferEffect == null) + { + gBufferEffect = GetResource("GBufferEffect"); + } + return gBufferEffect; + } + } public static byte[] PBREffect { get @@ -28,6 +39,7 @@ namespace Kav } } + private static byte[] gBufferEffect; private static byte[] pbrEffect; private static byte[] simpleDepthEffect; -- 2.25.1 From ffcb3326e822277388ecf31d0699f7e62f191850 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 22 Aug 2020 17:52:44 -0700 Subject: [PATCH 3/6] deferred pbr shading --- Effects/DeferredPBREffect.cs | 88 ++++++++++++++++ Effects/FXB/DeferredPBREffect.fxb | Bin 0 -> 50536 bytes Effects/HLSL/DeferredPBREffect.fx | 167 ++++++++++++++++++++++++++++++ Effects/PBREffect.cs | 48 +-------- Effects/PointLightCollection.cs | 49 +++++++++ Kav.Core.csproj | 3 + Kav.Framework.csproj | 3 + Renderer.cs | 55 +++++++--- Resources.cs | 14 +++ 9 files changed, 370 insertions(+), 57 deletions(-) create mode 100644 Effects/DeferredPBREffect.cs create mode 100644 Effects/FXB/DeferredPBREffect.fxb create mode 100644 Effects/HLSL/DeferredPBREffect.fx create mode 100644 Effects/PointLightCollection.cs diff --git a/Effects/DeferredPBREffect.cs b/Effects/DeferredPBREffect.cs new file mode 100644 index 0000000..04af0e8 --- /dev/null +++ b/Effects/DeferredPBREffect.cs @@ -0,0 +1,88 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Kav +{ + public class DeferredPBREffect : Effect + { + EffectParameter gPositionParam; + EffectParameter gAlbedoParam; + EffectParameter gNormalParam; + EffectParameter gMetallicRoughnessParam; + + EffectParameter eyePositionParam; + PointLightCollection pointLightCollection; + + public Texture2D GPosition { get; set; } + public Texture2D GAlbedo { get; set; } + public Texture2D GNormal { get; set; } + public Texture2D GMetallicRoughness { get; set; } + + public Vector3 EyePosition { get; set; } + + public int MaxPointLights { get; } = 64; + + public PointLightCollection PointLights + { + get { return pointLightCollection; } + private set { pointLightCollection = value; } + } + + public DeferredPBREffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBREffect) + { + CacheEffectParameters(); + + pointLightCollection = new PointLightCollection( + Parameters["PointLightPositions"], + Parameters["PointLightColors"], + MaxPointLights + ); + } + + protected DeferredPBREffect(DeferredPBREffect cloneSource) : base(cloneSource) + { + GPosition = cloneSource.GPosition; + GAlbedo = cloneSource.GAlbedo; + GNormal = cloneSource.GNormal; + GMetallicRoughness = cloneSource.GMetallicRoughness; + + EyePosition = cloneSource.EyePosition; + + PointLights = new PointLightCollection( + Parameters["LightPositions"], + Parameters["PositionLightColors"], + MaxPointLights + ); + + for (int i = 0; i < MaxPointLights; i++) + { + PointLights[i] = cloneSource.PointLights[i]; + } + } + + public override Effect Clone() + { + return new DeferredPBREffect(this); + } + + protected override void OnApply() + { + gPositionParam.SetValue(GPosition); + gAlbedoParam.SetValue(GAlbedo); + gNormalParam.SetValue(GNormal); + gMetallicRoughnessParam.SetValue(GMetallicRoughness); + + eyePositionParam.SetValue(EyePosition); + } + + void CacheEffectParameters() + { + gPositionParam = Parameters["gPosition"]; + gAlbedoParam = Parameters["gAlbedo"]; + gNormalParam = Parameters["gNormal"]; + gMetallicRoughnessParam = Parameters["gMetallicRoughness"]; + + eyePositionParam = Parameters["EyePosition"]; + } + } +} diff --git a/Effects/FXB/DeferredPBREffect.fxb b/Effects/FXB/DeferredPBREffect.fxb new file mode 100644 index 0000000000000000000000000000000000000000..b3cda6cd261cc0d33aa2276683b75ccdc06dbee7 GIT binary patch literal 50536 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 g1?!i7|8({v{umm4>q1+K>z>% literal 0 HcmV?d00001 diff --git a/Effects/HLSL/DeferredPBREffect.fx b/Effects/HLSL/DeferredPBREffect.fx new file mode 100644 index 0000000..9f4e74e --- /dev/null +++ b/Effects/HLSL/DeferredPBREffect.fx @@ -0,0 +1,167 @@ +#include "Macros.fxh" //from FNA + +static const float PI = 3.141592653589793; +static const int MAX_POINT_LIGHTS = 64; + +DECLARE_TEXTURE(gPosition, 0); +DECLARE_TEXTURE(gAlbedo, 1); +DECLARE_TEXTURE(gNormal, 2); +DECLARE_TEXTURE(gMetallicRoughness, 3); + +BEGIN_CONSTANTS + + float3 EyePosition _ps(c0) _cb(c0); + + float3 PointLightPositions[MAX_POINT_LIGHTS] _ps(c1) _cb(c1); + float3 PointLightColors[MAX_POINT_LIGHTS] _ps(c65) _cb(c65); + +MATRIX_CONSTANTS + +END_CONSTANTS + +struct PixelInput +{ + float4 Position : SV_POSITION; + float2 TexCoord : TEXCOORD0; +}; + +// Pixel Shader + +float3 FresnelSchlick(float cosTheta, float3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} + +float DistributionGGX(float3 N, float3 H, float roughness) +{ + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + + float num = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return num / denom; +} + +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r * r) / 8.0; + + float num = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return num / denom; +} + +float GeometrySmith(float3 N, float3 V, float3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} + +float3 ComputeLight( + float3 lightDir, + float3 radiance, + float3 F0, + float3 V, + float3 N, + float3 albedo, + float metallic, + float roughness +) { + float3 L = normalize(lightDir); + float3 H = normalize(V + L); + + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + float3 F = FresnelSchlick(max(dot(H, V), 0.0), F0); + + float3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); + float3 specular = numerator / max(denominator, 0.001); + + float3 kS = F; + float3 kD = float3(1.0, 1.0, 1.0) - kS; + + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + return (kD * albedo / PI + specular) * radiance * NdotL; +} + +float4 ComputeColor( + float3 worldPosition, + float3 worldNormal, + float3 albedo, + float metallic, + float roughness +) { + float3 V = normalize(EyePosition - worldPosition); + float3 N = normalize(worldNormal); + + float3 F0 = float3(0.04, 0.04, 0.04); + F0 = lerp(F0, albedo, metallic); + + float3 Lo = float3(0.0, 0.0, 0.0); + + // point light + for (int i = 0; i < MAX_POINT_LIGHTS; i++) + { + float3 lightDir = PointLightPositions[i] - worldPosition; + float distance = length(lightDir); + float attenuation = 1.0 / (distance * distance); + float3 radiance = PointLightColors[i] * attenuation; + + Lo += ComputeLight(lightDir, radiance, F0, V, N, albedo, metallic, roughness); + } + + // // directional light + // for (int i = 0; i < 4; i++) + // { + // float3 lightDir = LightDirections[i]; + // float3 radiance = DirectionLightColors[i]; + + // Lo += ComputeLight(lightDir, radiance, F0, V, N, albedo, metallic, roughness); + // } + + float3 ambient = float3(0.03, 0.03, 0.03) * albedo; // * AO; + float3 color = ambient + Lo; + + color = color / (color + float3(1.0, 1.0, 1.0)); + float exposureConstant = 1.0 / 2.2; + color = pow(color, float3(exposureConstant, exposureConstant, exposureConstant)); + + return float4(color, 1.0); +} + +float4 main_ps(PixelInput input) : SV_TARGET0 +{ + float3 fragPosition = SAMPLE_TEXTURE(gPosition, input.TexCoord).rgb; + float3 normal = SAMPLE_TEXTURE(gNormal, input.TexCoord).xyz; + float3 albedo = SAMPLE_TEXTURE(gAlbedo, input.TexCoord).rgb; + float2 metallicRoughness = SAMPLE_TEXTURE(gMetallicRoughness, input.TexCoord).rg; + + return ComputeColor( + fragPosition, + normal, + albedo, + metallicRoughness.r, + metallicRoughness.g + ); +} + +Technique DeferredPBR +{ + Pass + { + PixelShader = compile ps_3_0 main_ps(); + } +} diff --git a/Effects/PBREffect.cs b/Effects/PBREffect.cs index 09e313e..9efe2fe 100644 --- a/Effects/PBREffect.cs +++ b/Effects/PBREffect.cs @@ -3,48 +3,6 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav { - public class PointLightCollection - { - private readonly Vector3[] positions = new Vector3[4]; - private readonly Vector3[] colors = new Vector3[4]; - private readonly float[] intensities = new float[4]; - - readonly EffectParameter lightPositionsParam; - readonly EffectParameter lightColorsParam; - - public PointLightCollection(EffectParameter lightPositionsParam, EffectParameter lightColorsParam) - { - this.lightPositionsParam = lightPositionsParam; - this.lightColorsParam = lightColorsParam; - } - - public PointLight this[int i] - { - get - { - var color = colors[i] / intensities[i]; - return new PointLight( - positions[i], - new Color( - color.X, - color.Y, - color.Z, - 1f - ), - intensities[i] - ); - } - set - { - positions[i] = value.Position; - colors[i] = value.Color.ToVector3() * value.Intensity; - intensities[i] = value.Intensity; - lightPositionsParam.SetValue(positions); - lightColorsParam.SetValue(colors); - } - } - } - public class DirectionalLightCollection { private readonly Vector3[] directions = new Vector3[4]; @@ -285,7 +243,8 @@ namespace Kav pointLightCollection = new PointLightCollection( Parameters["LightPositions"], - Parameters["PositionLightColors"] + Parameters["PositionLightColors"], + MaxPointLights ); directionalLightCollection = new DirectionalLightCollection( @@ -304,7 +263,8 @@ namespace Kav PointLights = new PointLightCollection( Parameters["LightPositions"], - Parameters["PositionLightColors"] + Parameters["PositionLightColors"], + MaxPointLights ); for (int i = 0; i < MaxPointLights; i++) diff --git a/Effects/PointLightCollection.cs b/Effects/PointLightCollection.cs new file mode 100644 index 0000000..708a180 --- /dev/null +++ b/Effects/PointLightCollection.cs @@ -0,0 +1,49 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Kav +{ + public class PointLightCollection + { + private readonly Vector3[] positions; + private readonly Vector3[] colors; + private readonly float[] intensities = new float[4]; + + readonly EffectParameter lightPositionsParam; + readonly EffectParameter lightColorsParam; + + public PointLightCollection(EffectParameter lightPositionsParam, EffectParameter lightColorsParam, int maxLights) + { + this.positions = new Vector3[maxLights]; + this.colors = new Vector3[maxLights]; + this.lightPositionsParam = lightPositionsParam; + this.lightColorsParam = lightColorsParam; + } + + public PointLight this[int i] + { + get + { + var color = colors[i] / intensities[i]; + return new PointLight( + positions[i], + new Color( + color.X, + color.Y, + color.Z, + 1f + ), + intensities[i] + ); + } + set + { + positions[i] = value.Position; + colors[i] = value.Color.ToVector3() * value.Intensity; + intensities[i] = value.Intensity; + lightPositionsParam.SetValue(positions); + lightColorsParam.SetValue(colors); + } + } + } +} diff --git a/Kav.Core.csproj b/Kav.Core.csproj index e143f89..615ab97 100644 --- a/Kav.Core.csproj +++ b/Kav.Core.csproj @@ -18,6 +18,9 @@ Kav.Resources.GBufferEffect.fxb + + Kav.Resources.DeferredPBREffect.fxb + Kav.Resources.PBREffect.fxb diff --git a/Kav.Framework.csproj b/Kav.Framework.csproj index 3d70199..c0f517d 100644 --- a/Kav.Framework.csproj +++ b/Kav.Framework.csproj @@ -18,6 +18,9 @@ Kav.Resources.GBufferEffect.fxb + + Kav.Resources.DeferredPBREffect.fxb + Kav.Resources.PBREffect.fxb diff --git a/Renderer.cs b/Renderer.cs index f31419e..8c0384f 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -17,10 +17,11 @@ namespace Kav private RenderTarget2D gNormal { get; } private RenderTarget2D gAlbedo { get; } private RenderTarget2D gMetallicRoughness { get; } + private RenderTarget2D deferredRenderTarget { get; } private RenderTargetBinding[] GBuffer { get; } - private GBufferEffect GBufferEffect { get; } + private DeferredPBREffect DeferredPBREffect { get; } private SpriteBatch SpriteBatch { get; } @@ -35,7 +36,7 @@ namespace Kav renderDimensionsX, renderDimensionsY, false, - SurfaceFormat.Color, + SurfaceFormat.HalfSingle, // unused DepthFormat.Depth24 ); @@ -44,8 +45,8 @@ namespace Kav renderDimensionsX, renderDimensionsY, false, - SurfaceFormat.Color, - DepthFormat.None + SurfaceFormat.Vector4, + DepthFormat.Depth24 ); gNormal = new RenderTarget2D( @@ -53,7 +54,7 @@ namespace Kav renderDimensionsX, renderDimensionsY, false, - SurfaceFormat.Color, + SurfaceFormat.Vector4, DepthFormat.None ); @@ -71,7 +72,7 @@ namespace Kav renderDimensionsX, renderDimensionsY, false, - SurfaceFormat.Color, + SurfaceFormat.HalfVector2, DepthFormat.None ); @@ -82,9 +83,23 @@ namespace Kav new RenderTargetBinding(gMetallicRoughness) }; + deferredRenderTarget = new RenderTarget2D( + GraphicsDevice, + renderDimensionsX, + renderDimensionsY + ); + SimpleDepthEffect = new SimpleDepthEffect(GraphicsDevice); + DeferredPBREffect = new DeferredPBREffect(GraphicsDevice); SpriteBatch = new SpriteBatch(GraphicsDevice); + + Texture2D whitePixel = new Texture2D(GraphicsDevice, 1, 1); + whitePixel.SetData(new[] { Color.White }); + + GraphicsDevice.SetRenderTarget(deferredRenderTarget); + graphicsDevice.Clear(Color.White); + GraphicsDevice.SetRenderTarget(null); } public void DeferredRender( @@ -94,7 +109,9 @@ namespace Kav IEnumerable directionalLights ) { GraphicsDevice.SetRenderTargets(GBuffer); - GraphicsDevice.Clear(Color.Black); + GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0); + GraphicsDevice.DepthStencilState = DepthStencilState.Default; + GraphicsDevice.BlendState = BlendState.Opaque; foreach (var (model, transform) in modelTransforms) { @@ -130,12 +147,24 @@ namespace Kav } GraphicsDevice.SetRenderTarget(null); - GraphicsDevice.Clear(Color.Black); - SpriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null); - SpriteBatch.Draw(gPosition, new Rectangle(0, 0, 640, 360), Color.White); - SpriteBatch.Draw(gAlbedo, new Rectangle(640, 0, 640, 360), Color.White); - SpriteBatch.Draw(gNormal, new Rectangle(0, 360, 640, 360), Color.White); - SpriteBatch.Draw(gMetallicRoughness, new Rectangle(640, 360, 640, 360), Color.White); + GraphicsDevice.Clear(Color.CornflowerBlue); + + DeferredPBREffect.GPosition = gPosition; + DeferredPBREffect.GAlbedo = gAlbedo; + DeferredPBREffect.GNormal = gNormal; + DeferredPBREffect.GMetallicRoughness = gMetallicRoughness; + DeferredPBREffect.EyePosition = Matrix.Invert(camera.View).Translation; + + int i = 0; + foreach (var pointLight in pointLights) + { + if (i > DeferredPBREffect.MaxPointLights) { break; } + DeferredPBREffect.PointLights[i] = pointLight; + i++; + } + + SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, DeferredPBREffect); + SpriteBatch.Draw(deferredRenderTarget, Vector2.Zero, Color.White); SpriteBatch.End(); } diff --git a/Resources.cs b/Resources.cs index 293307d..5c50646 100644 --- a/Resources.cs +++ b/Resources.cs @@ -15,6 +15,19 @@ namespace Kav return gBufferEffect; } } + + public static byte[] DeferredPBREffect + { + get + { + if (deferredPBREffect == null) + { + deferredPBREffect = GetResource("DeferredPBREffect"); + } + return deferredPBREffect; + } + } + public static byte[] PBREffect { get @@ -40,6 +53,7 @@ namespace Kav } private static byte[] gBufferEffect; + private static byte[] deferredPBREffect; private static byte[] pbrEffect; private static byte[] simpleDepthEffect; -- 2.25.1 From 7d058402772ccdb2b9ac9d0879f9552ed70400bf Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 22 Aug 2020 18:00:04 -0700 Subject: [PATCH 4/6] fix intensity array for point lights --- Effects/PointLightCollection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Effects/PointLightCollection.cs b/Effects/PointLightCollection.cs index 708a180..53c459b 100644 --- a/Effects/PointLightCollection.cs +++ b/Effects/PointLightCollection.cs @@ -7,7 +7,7 @@ namespace Kav { private readonly Vector3[] positions; private readonly Vector3[] colors; - private readonly float[] intensities = new float[4]; + private readonly float[] intensities; readonly EffectParameter lightPositionsParam; readonly EffectParameter lightColorsParam; @@ -16,6 +16,7 @@ namespace Kav { this.positions = new Vector3[maxLights]; this.colors = new Vector3[maxLights]; + this.intensities = new float[maxLights]; this.lightPositionsParam = lightPositionsParam; this.lightColorsParam = lightColorsParam; } -- 2.25.1 From 737cb68f8d352089ea88c925a8218c9578b481eb Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 26 Aug 2020 13:24:01 -0700 Subject: [PATCH 5/6] fix texture leak --- Renderer.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Renderer.cs b/Renderer.cs index 8c0384f..0a77640 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -94,9 +94,6 @@ namespace Kav SpriteBatch = new SpriteBatch(GraphicsDevice); - Texture2D whitePixel = new Texture2D(GraphicsDevice, 1, 1); - whitePixel.SetData(new[] { Color.White }); - GraphicsDevice.SetRenderTarget(deferredRenderTarget); graphicsDevice.Clear(Color.White); GraphicsDevice.SetRenderTarget(null); -- 2.25.1 From abd6b1af91c6ad9949c986ecae30e3ed699b3438 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 26 Aug 2020 17:02:45 -0700 Subject: [PATCH 6/6] add directional light + rename GBufferEffect for clarity --- Effects/DeferredPBREffect.cs | 24 +++++++++ ...Effect.cs => DeferredPBR_GBufferEffect.cs} | 8 +-- Effects/DirectionalLightCollection.cs | 47 ++++++++++++++++++ Effects/FXB/DeferredPBREffect.fxb | Bin 50536 -> 53400 bytes Effects/FXB/DeferredPBR_GBufferEffect.fxb | Bin 0 -> 7476 bytes Effects/HLSL/DeferredPBREffect.fx | 24 +++++---- ...Effect.fx => DeferredPBR_GBufferEffect.fx} | 0 Effects/PBREffect.cs | 42 ---------------- Kav.Core.csproj | 4 +- Kav.Framework.csproj | 4 +- Loaders/ModelLoader.cs | 2 +- Renderer.cs | 8 +++ Resources.cs | 4 +- 13 files changed, 104 insertions(+), 63 deletions(-) rename Effects/{GBufferEffect.cs => DeferredPBR_GBufferEffect.cs} (95%) create mode 100644 Effects/DirectionalLightCollection.cs create mode 100644 Effects/FXB/DeferredPBR_GBufferEffect.fxb rename Effects/HLSL/{GBufferEffect.fx => DeferredPBR_GBufferEffect.fx} (100%) diff --git a/Effects/DeferredPBREffect.cs b/Effects/DeferredPBREffect.cs index 04af0e8..97c8615 100644 --- a/Effects/DeferredPBREffect.cs +++ b/Effects/DeferredPBREffect.cs @@ -12,6 +12,7 @@ namespace Kav EffectParameter eyePositionParam; PointLightCollection pointLightCollection; + DirectionalLightCollection directionalLightCollection; public Texture2D GPosition { get; set; } public Texture2D GAlbedo { get; set; } @@ -28,6 +29,14 @@ namespace Kav private set { pointLightCollection = value; } } + public int MaxDirectionalLights { get; } = 4; + + public DirectionalLightCollection DirectionalLights + { + get { return directionalLightCollection; } + private set { directionalLightCollection = value; } + } + public DeferredPBREffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBREffect) { CacheEffectParameters(); @@ -37,6 +46,11 @@ namespace Kav Parameters["PointLightColors"], MaxPointLights ); + + DirectionalLights = new DirectionalLightCollection( + Parameters["DirectionalLightDirections"], + Parameters["DirectionalLightColors"] + ); } protected DeferredPBREffect(DeferredPBREffect cloneSource) : base(cloneSource) @@ -58,6 +72,16 @@ namespace Kav { PointLights[i] = cloneSource.PointLights[i]; } + + DirectionalLights = new DirectionalLightCollection( + Parameters["DirectionalLightDirections"], + Parameters["DirectionalLightColors"] + ); + + for (int i = 0; i < MaxDirectionalLights; i++) + { + DirectionalLights[i] = cloneSource.DirectionalLights[i]; + } } public override Effect Clone() diff --git a/Effects/GBufferEffect.cs b/Effects/DeferredPBR_GBufferEffect.cs similarity index 95% rename from Effects/GBufferEffect.cs rename to Effects/DeferredPBR_GBufferEffect.cs index ff8769d..26a9c8f 100644 --- a/Effects/GBufferEffect.cs +++ b/Effects/DeferredPBR_GBufferEffect.cs @@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav { - public class GBufferEffect : Effect, TransformEffect + public class DeferredPBR_GBufferEffect : Effect, TransformEffect { EffectParameter worldParam; EffectParameter worldViewProjectionParam; @@ -126,12 +126,12 @@ namespace Kav } } - public GBufferEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.GBufferEffect) + public DeferredPBR_GBufferEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DeferredPBR_GBufferEffect) { CacheEffectParameters(); } - protected GBufferEffect(GBufferEffect cloneSource) : base(cloneSource) + protected DeferredPBR_GBufferEffect(DeferredPBR_GBufferEffect cloneSource) : base(cloneSource) { CacheEffectParameters(); @@ -150,7 +150,7 @@ namespace Kav public override Effect Clone() { - return new GBufferEffect(this); + return new DeferredPBR_GBufferEffect(this); } protected override void OnApply() diff --git a/Effects/DirectionalLightCollection.cs b/Effects/DirectionalLightCollection.cs new file mode 100644 index 0000000..10bcbda --- /dev/null +++ b/Effects/DirectionalLightCollection.cs @@ -0,0 +1,47 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Kav +{ + public class DirectionalLightCollection + { + private readonly Vector3[] directions = new Vector3[4]; + private readonly Vector3[] colors = new Vector3[4]; + private readonly float[] intensities = new float[4]; + + readonly EffectParameter lightDirectionsParam; + readonly EffectParameter lightColorsParam; + + public DirectionalLightCollection(EffectParameter lightDirectionsParam, EffectParameter lightColorsParam) + { + this.lightDirectionsParam = lightDirectionsParam; + this.lightColorsParam = lightColorsParam; + } + + public DirectionalLight this[int i] + { + get + { + var color = colors[i] / intensities[i]; + return new DirectionalLight( + directions[i], + new Color( + color.X, + color.Y, + color.Z, + 1f + ), + intensities[i] + ); + } + set + { + directions[i] = value.Direction; + colors[i] = value.Color.ToVector3() * value.Intensity; + intensities[i] = value.Intensity; + lightDirectionsParam.SetValue(directions); + lightColorsParam.SetValue(colors); + } + } + } +} diff --git a/Effects/FXB/DeferredPBREffect.fxb b/Effects/FXB/DeferredPBREffect.fxb index b3cda6cd261cc0d33aa2276683b75ccdc06dbee7..10298d5149531440477ff239977961028697e518 100644 GIT binary patch literal 53400 zcmeI0L2R5y702iMc5SbnHcpe!mbOsS8fYQ32@OynO`XIoEhHgLvS6T)I`PI{*m#ZY zKm!HVq=h<;ge5LLaM++oRQ8nvs*0$PkT~{$1QJ&t!i@t+t%SP#|1Gq&ZiguQ#W?OuYt*JUJ>d zUfTH0@t1vN6yGB#cc2vZj*Xw0Y1C%XRE+->1^<-rT|t@L*Em_5Xxdol`-<=97v<~u zehWHpq70&VTZLyCyPd)Mrw8BG@8Ra`nej&9_k}>G7dkRl#_>Cx^WzY9qgcPr)&{>9 z1DmwB4Q29BZGODbsGmC8JUclxU7MS8>%h6L1^SHfdNI5S{okS7b4|NNIEJ~V=^b25 z|45t2{Jst4sdKf02+B+Gy}J42DW43N1FBN`GfVzsd?ElbH)C+$PJ8V z1V#4@GojC|o&nwux_jn8v(cQz>DS#K|MYu?XW{?4XYR$=(fVxd6z??S4ZAxF8Q#S1 z^ZsshGrsP+hA){F>+R`{5%;JkQ$E+UeTtY;EGm{-fr0$n4|YgZDCyyBkHG9jJ_n zfbW-4UJK;cQU6OI{|EIg;tcg6)DH&oJnF9o@@3TD4&*ZK3PZttVGrtKfjomd!9{;B zpxet>ySM!MQQm?C?C?3J{F<-R#d1*pB|GuFgtiw^IB%Ne-G`63;JWb%LbP%RkFDTi z%b)O3>U7@g{3bhaeBXZFcbiNo+USxpo}nqUy^Tt4UV*{26t&{SDtGv}I_!f;yjfY#UoQo9&DZ z&oI7AcJzSR?b}9eoAWy+ZR@!9tgU9&OUdTWS-iQ=V!v$MKO207_eF^VQ@`f3VehZ5 z7WPK2IYJvX1Db(bDFfYiME6cD@0Agsh;{$xua@zjE8nv6-r4v+w)`)=x>5J)|J^tC zOBh`f8+2yoPCRyEr#VzVHQStPo}M3i=;*^k&m25Lt|o^C&Wd7`uis zYi$fJWu}kvLT=XDIO5S?X=P^37M#;isi42p!ZDR+zRqLLjq6xFd+gb9l%1}OV_$B4 zbXxo2gE5qR3?;-MV@symV!<7uEPm+sg6R}Glvx;e*~g98ZQMEhmk~D$cs;xy+ZF8=o5Bbs}V&ojK zd+Z!IcbNnBlbr*{u%C0Fof5v?T4$Jpu|C+(I(6ui`Enl>Uw8I1V|ljBUvM^5B)P|^pCy;<{$TJo5}bBTJ) zy`jlnuGR!YrH^)L5wpUtQwtdcZPei&#yg_$OPO}r#<_9~-y>kGV2&}e^nr0)p1i z_m1p!=@)z4>x_@~x=eQWA=`vW=?`VMhh*Q#o^|g?>SK+HeZcv-J=}dac^%)raUXwFb3*^p7c$Hk=u;S$7`V0^7c$H?=9_KgnQKfPGR!*t zuIIRvfa3$ov0WE3s2sa@@&B7++NSIgZTn?Fl$Oq#P^9kvZO+faAl;v2q-l~4rlw;*MGRJo$;P^S^SUHZ&@zw+!A61T(7z9Dh|gR*oZce0Ktl$CP8`I5NlYPr&il zlw;*MGROBM;P~sxv2q-l<9icu{0-$;IgZTneF->zUO85dBXj(L1RQ@;IaZD%bNs;s z9DhqWR*oZce18ItPbkOAab%8%5^(&2a;zLj=J-PiI38DymE*`9KahaqlghDj9GT+> z6L5S=IaZD%b3B}Y;|b+hIgZTnhZAsIQ;wD6$Q*wp0mrA6W92w9#~)3=@uYIB97pE( zp#&UHDaXojWR4$Bz;RtUR*oZc{ILWae_J_Ljw5sY@dO-yM>$rGBXhhX0mlvHSUHZ& z@h1{+d`3A|jw5sYNCJ+hm1E^NGRKc5;JB$AE60&J-kE^o8Rb|xj?D3{1RQ@?IaZD% zbNtB!9M3Ap%5h|lA4|aToN}xjN9K5U0*>dEW92w9$Dc~T@mb|qIgZTnrxS4eJ>^(A zj?D3A5^(%|z-3$Q*w@0mna7 zj+Nuc9PdfM@k`3FavYiCClYY{Bjs2*j?D4i1RVcZIaZD%bNnP2%Z(`+)7LU)ZDAw< z*FRCNmFoyxSHN**GIDH7pD{V*%$Qa$>LpXQ^`0*8g-pGYS+Rw>GLE|a*c-Ib^4tzU zF2hHTInWpV8jSDrem50ynAQce(jJCA?ymu_%Q!?=#?np?3dcgd#aKAj#hSxU)t0g` z_;Ydw{})W>(t4dxUNol7`N){C&tSZ>=kij5j}qFPei{B&5EJ8Zb>=|i%*G@AjAsR< zikyhPSzv5qHr@<<#_DwAE&H~vO=m-Fatv*n)>hbH&ROU9ip>@Mu&rwIO25=Wj;&wD zNf}DEU*ukl1B5 zS;o5c7QV=OjybU~K4CxPtJ~(*OJw0oWafl*vPE8KFE?d!(F*x;ZEmflP92V?OuiV8 z*rP2MqwCL2wcv~MgKYbSFK3f&)xxIC(fQyQ&bey&V$N9)`C?A#mw6>$)Iq)Ai!%9Q zKW$PbUn0Al(1&~fNRC`ia@cl#!Wa7)1APi#5(C$d<9rP0Uug@+()NnyhYb3dEoZ}? zub(Pk1q;fTdw<;sUq8DJU+0xCLT21@2J&pn?781P z6Wu-3<;vY7oj!9X=VOL-b-DZ()|WPTj=yWq$ISa>8|$wId{O4P9Nx)zb}yMun{6(S zw7q8U1dK)QT(0i&r2LtX3vGkLf< mduF_0ZDGxdr|93;I9Z!$+J3gl!}~(t?KNHp z5`OirorgX|A`&k=^kIYY5ZS!J1B!w`sDA(tk$B*BAMy_%Q3>_({m$Ikyq7`rj+qnLOozb^BLiD9JM~%YB$y!t(9D+T@%%n7!Bv| zbo{3Ojl6LZ-&3d$qxQ!;v#`9{tgS)S_kWW@UJ`sWz4~-!JxG zU~?OF0yQ72AKCftXR>)2!MBNfy0x~v(Co*3tza_>8|Ul%_+6aya}b_IHF51&JK|m~ zjLGr#q1I2;))$)1#`(F{#ro1pt=+c!z`6Dc_RR5qIoyW*A5kB@=eYfJglo;A4{e5_s_>w9$=Iy zR6R3X2`vx$3h@14aAr=lnyocF{Y1u4`5fgluvpyVkk6%)wF|Yiwc6tB@j2NAnSFdt z^BsnMkD$782#t9s;QI>dZwm5FwC@z;f1~}73x@V2+A{@t9ql&?@(r~AR**}0u1*%7 ztw+(GFUYHSeqPO=p$z+0em8K4+lBV8*@m!N?hkY2f3| zEqo+d_D*&wI`QiCalZTgo&!L~@hGEA{tmjEXfWLfpMSvjTc}*0Sf*u4Mx(oE|BDp~ z#jt`-cEgXl1Ncs$i=aEi@llQ%9kqMJy*n%!9lgipQf~K#(b>3f=DOnhM`T9kIQK3) zSlZs+c0N=0c2TXafUdv;v;u=WV(^YOd`ArZZrm>6mk@6>ckk@{&E|evZSS;w_iw?S z{Vt8c5IbyE+h?CSdst32&abuFtqbduPs}|z`O?gpnaMLt3yZb2$rG*R)dqfCPaZk^ z)DhW!1&@Y~OmzP-@$wY5_LxZe0_qg?8_6waW6HF@T&r&?!<0x7^rLKToge#R6C+EH zBL;Iw@*EQ6;CvIQrmT3Zm0TRg-H@zrLz$I%m-4)kyU9C7ZYAW+%DgGZu;q9ou%(_d z=XMbNqtK0@&3s1kd}8FozH;8j^+=?I@p_nlFU7kK;#Sf`wvgAB$&39Z6UWA)%zmx| za=*^`IUV&yxg*l$y1IVX$2roL^Gqa0yIL5_%G6nV=2J~OQtfiC&K~mh4szriaC*!f zICnP(oF_8}`mmpK;5Z4s?OsQigP0iXXPY*R$@R2r+e_{Eu^FH1$?-?9Mv=*Rt82%P z;Ws>fY-~6l-gWY}9Y4Yv(!P`Ly^UWrIaqs}57)@;5%-7jxn_)yz7E$P@19tb5@j={ z+mqZT*IOUPv~{p&l*!0w&PbG>n+n!|F*iia94X`QARp?gUAuP?btaF!$Yaddke%#0 z?Kqcl=(x6HdG549+xW2G`q+LaGcN7jT5w+?%&)j_mW7hhvwstLaxJ))TnonBM4rVQ z#xW-S@*L2=)uoO$Jj1vn`f(|9T0teb=R;ebb>_$M222jlA$5*P*I$%*&YbLGQ|6w~9(&Y32b>@GjQz!PK%Ld^ zJO@P|$1rV+409jc9y%7Vj{g(Gp3kMVBjo#PjkW98U0$9Q-5 z&heL(W98U0$M~O!caFcJ94p73ImZ8CymS1La;zMC<{1CS@Xqne%CU0nnPdEa&O66n zRgRTo&m7}_&fYoxnsTfhd**m|0FGyrW98U0$L|Ti@hRn4Irhx)o&X%5R*scp&m2z# z;P~sxv2yI0qph z_yYkr{+4pA9DC;Y(EuEOTRB#aJ#+lQ033fuIaZE6b9^8G$KO?sm1EBwe<%RQ-&2m2 zW6vCaH~`1rSB{lq&m2D%fa9~uv2yI0?!k7nEb=*fYnU2*7b& zIaZE6bNoaAj+c~U<=8XFPX^$)p&Tp6o;m(x0FHm494p73IsQ}tj(?~eE61KWJ`{lC zrgE$td*=Al0XSY(j+JB296uF+;}zvtIrhx)(*ZbcDaXpOXO0gC;CNLzR*pS$d?WzJ zKT?jBW6vCaCIH84%CU0nnd4^yaNJgom1EBwKO2DKb>&z&_RR5T18{s%IaZE6bNsmg z9RFB3R*pS${P_SJ|3o=fjy-eyTmX(QDaXpOXO6!RfaA-`v2yI0<1Yr__@~OTa_pJo zF9qQEXUeg1?3v@E0XY7-a;zMC=J@#l9RET&R*pS$eC$3PkBB5=Qcfe0bWD2bs7M@1 zWMuZaHv5PB#&f@4D#yyPXO3S0V=;IXFelRMOa&*Q_P})|zgNLASx(DCcW%zO zxr2xA-2ZkTyL&v%xh>(WlrVmbIWP|63hwqY+LU+o^N@5ywz>zA2V>KRwy{+Dw$7J+ zBe^fk&Diwivx2fn)zp#*{;V7!{)S}Nhi!^-N2JTSI-g>nz~7EnGHa3`MgpC+FCpF* za$((!{#Tk(L>DJovLeq?e g1?!i7|8({v{umm4>q1+K>z>% diff --git a/Effects/FXB/DeferredPBR_GBufferEffect.fxb b/Effects/FXB/DeferredPBR_GBufferEffect.fxb new file mode 100644 index 0000000000000000000000000000000000000000..9b2d6844f486894e8a28f804c05221fee8d81938 GIT binary patch literal 7476 zcmds6O=w(I6u$4hX)BVR!9iS95J^!%L}{9Y+Q3v}lh%NRCMHuGnP!HWq(*S@ zgf3iUF{q0!x_Dqf>9{E9BDkpw5er?E;-VD65oh5-(3J?5jNfR%7Pd%%bDZ{?;7W4VR7`BD!0E--zIU?CrZ z)FC!LS;vwUj^a54ei+VEu1Crj*?)FC!L z-G1DFejUtywA9(AA5XKOr5$)a20oUXo6P5Drj8fp-#$B=E0>#Hisxq0Dc6NE8}(@# z{uAKLI`vEUI3KM37Jn>>O>{ncz-FFLPUh!xdLC&{6D&)tLaN~$%h*f_Gxv0TX^k?y zco)xuEyTXi{R^iIaUuU(;#|H_DCMW|ly>$}u(Va}Jc9akJHxZ*bER@_tTZ`WE*8p+ ze`$Ad8`|9`?Vg;;y*pAWypx-nn<>mH&NIh$%eI+@%$VYHCzxw;H<*||04A1vH!^y- zRGNHG;{jD=EC_t(Vo#ZHv3j~N)+KIP_sHn*?DWi3t_)dV9kF%6)KVAwFnV@!I#)uO z+=A}=Uf3LW7E!dxxU|9kNIbHSuMEteIfK+dKiWC22f?iCQLs=Sgj1s6xd@INeHn7y z(f6UU1JV%eS;z~Heg*P%NBr$Us+mg2VuqIyN&^DwGRn<}wG4Kb1L}9nEG;z-0yt=ZZ7fOEL%ho;j$h)z>lnK=nqZ z>F|(r;c*NP^AciaDn|A~4>Dp7Q$e|2A!FV!4Icbd2>-xKcWc?a$2+almvTBp;fS*5 z$iDH>c3<01XgNr;9pfLQ{SXaVdylTC(J*UR$DzjUKPt{rBW|Bf*WEN1>1n8|u0 zW+Eror>9P6oVf4Z;l%5;Hyq>iCnp=W6dr=p?~wCg!D#{Vhv19aX4c;4*0zkN$#Pxl z24qqV>{~p=?{4rkN3hj-wCy>!&DxIR!Bo^K>~6m8N9MVTVS&O!2H(~BwjJ&sa6hG| z(yX^PwVV!pb)v!?jGP@R)d1H+zC+%oTrp*gAF#pyZeUy&-w&Q_`i7M4dtIlmeXqgy zX2`PCmAZ!VH_>igmknTp91frlzB0MNL!5~}-=T9+fcRlQ=^vmh`mO6^Khdb}6YSc? zKKSY~+Nx{2$x+NFb>O`%|1o24my-f@IilU{KSoZ*cc2>DXT4m-dYG$texS2i z1JA{4;8U2Ax#|*3Lo|b#tAK|lt_#Uki`LfZUK7XVHsq=%PuTwnN%2T=l=jUGLEgJ{@SfW>@3&a)cF2p)*IVT$X>N5uIC|kLoa~S#`se6>e z81HWUx65hD$!Q|5m%Hf0HNo%T8qv^eVklk{zraKrm&<<2AjUS&&U8-ACwEkwycfMCk%ro~P=VJ=HL+;1ioACt`-VggW;to0W-t5~0 z2%n8|yywKc$jN=&!#>V9=bcE6fve+uFpl$|U`odMEtnYRjQ!*{qQrTGccd#|iSzHZ zMdCcM3AZ^%$~WR>_wDVB@vYA5|A%-7oY8-k<2MuklIP90waMq$hcz*FNj%!P)Bw@O zrEm!X&eHMyr}D>-tTbMW*G8{)96v%|y$3+=0T0>ox-8@ga1D&h9o-(!K6k*)`%r#s znNt(Xw5R6xuYKR&>ervp!-O6s^luV+twne5UZrmwZabP=*!*SM3T`F_v%_PoXQi=6 z9U0FKvR?3B`_yxvfz1aCrL6D=s29YXB}B|b=AEhvR&YPr+^c`)OW26H#!0EnZOF1$ zGiOae=Y0tCm9J9BSr5fF-jfl#lzJkznZF-Ys{uSy_{Y9)1-1Wsfwm@Y^UrsBjajuh zCqypO=TOW?i2D_LCRHK6N9C@IJ~jID+=_2bD|_$}*$*-H8t$P2+)UKCSA!#?`&!3$ zv(-~t$G2^S_{MjySL5AhD%O3i?}+u3*1K$ZM29Y)j&)Q2&R93~?~3)b_TLR1xcKZR p+O9B47%P$k6o|NO^!GTH!Cb|}GTbj)_8aK*bK^k#TE1)G_YchewfX=6 literal 0 HcmV?d00001 diff --git a/Effects/HLSL/DeferredPBREffect.fx b/Effects/HLSL/DeferredPBREffect.fx index 9f4e74e..a49f27a 100644 --- a/Effects/HLSL/DeferredPBREffect.fx +++ b/Effects/HLSL/DeferredPBREffect.fx @@ -2,6 +2,7 @@ static const float PI = 3.141592653589793; static const int MAX_POINT_LIGHTS = 64; +static const int MAX_DIRECTIONAL_LIGHTS = 4; DECLARE_TEXTURE(gPosition, 0); DECLARE_TEXTURE(gAlbedo, 1); @@ -10,10 +11,13 @@ DECLARE_TEXTURE(gMetallicRoughness, 3); BEGIN_CONSTANTS - float3 EyePosition _ps(c0) _cb(c0); + float3 EyePosition _ps(c0) _cb(c0); - float3 PointLightPositions[MAX_POINT_LIGHTS] _ps(c1) _cb(c1); - float3 PointLightColors[MAX_POINT_LIGHTS] _ps(c65) _cb(c65); + float3 PointLightPositions[MAX_POINT_LIGHTS] _ps(c1) _cb(c1); + float3 PointLightColors[MAX_POINT_LIGHTS] _ps(c65) _cb(c65); + + float3 DirectionalLightDirections[MAX_DIRECTIONAL_LIGHTS] _ps(c129) _cb(c129); + float3 DirectionalLightColors[MAX_DIRECTIONAL_LIGHTS] _ps(c133) _cb(c133); MATRIX_CONSTANTS @@ -123,14 +127,14 @@ float4 ComputeColor( Lo += ComputeLight(lightDir, radiance, F0, V, N, albedo, metallic, roughness); } - // // directional light - // for (int i = 0; i < 4; i++) - // { - // float3 lightDir = LightDirections[i]; - // float3 radiance = DirectionLightColors[i]; + // directional light + for (int i = 0; i < MAX_DIRECTIONAL_LIGHTS; i++) + { + float3 lightDir = DirectionalLightDirections[i]; + float3 radiance = DirectionalLightColors[i]; - // Lo += ComputeLight(lightDir, radiance, F0, V, N, albedo, metallic, roughness); - // } + Lo += ComputeLight(lightDir, radiance, F0, V, N, albedo, metallic, roughness); + } float3 ambient = float3(0.03, 0.03, 0.03) * albedo; // * AO; float3 color = ambient + Lo; diff --git a/Effects/HLSL/GBufferEffect.fx b/Effects/HLSL/DeferredPBR_GBufferEffect.fx similarity index 100% rename from Effects/HLSL/GBufferEffect.fx rename to Effects/HLSL/DeferredPBR_GBufferEffect.fx diff --git a/Effects/PBREffect.cs b/Effects/PBREffect.cs index 9efe2fe..db04a25 100644 --- a/Effects/PBREffect.cs +++ b/Effects/PBREffect.cs @@ -3,48 +3,6 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav { - public class DirectionalLightCollection - { - private readonly Vector3[] directions = new Vector3[4]; - private readonly Vector3[] colors = new Vector3[4]; - private readonly float[] intensities = new float[4]; - - readonly EffectParameter lightPositionsParam; - readonly EffectParameter lightColorsParam; - - public DirectionalLightCollection(EffectParameter lightPositionsParam, EffectParameter lightColorsParam) - { - this.lightPositionsParam = lightPositionsParam; - this.lightColorsParam = lightColorsParam; - } - - public DirectionalLight this[int i] - { - get - { - var color = colors[i] / intensities[i]; - return new DirectionalLight( - directions[i], - new Color( - color.X, - color.Y, - color.Z, - 1f - ), - intensities[i] - ); - } - set - { - directions[i] = value.Direction; - colors[i] = value.Color.ToVector3() * value.Intensity; - intensities[i] = value.Intensity; - lightPositionsParam.SetValue(directions); - lightColorsParam.SetValue(colors); - } - } - } - public class PBREffect : Effect, TransformEffect, PointLightEffect, DirectionalLightEffect { EffectParameter worldParam; diff --git a/Kav.Core.csproj b/Kav.Core.csproj index 615ab97..7957739 100644 --- a/Kav.Core.csproj +++ b/Kav.Core.csproj @@ -15,8 +15,8 @@ - - Kav.Resources.GBufferEffect.fxb + + Kav.Resources.DeferredPBR_GBufferEffect.fxb Kav.Resources.DeferredPBREffect.fxb diff --git a/Kav.Framework.csproj b/Kav.Framework.csproj index c0f517d..0557675 100644 --- a/Kav.Framework.csproj +++ b/Kav.Framework.csproj @@ -15,8 +15,8 @@ - - Kav.Resources.GBufferEffect.fxb + + Kav.Resources.DeferredPBR_GBufferEffect.fxb Kav.Resources.DeferredPBREffect.fxb diff --git a/Loaders/ModelLoader.cs b/Loaders/ModelLoader.cs index 2655368..4e908a0 100644 --- a/Loaders/ModelLoader.cs +++ b/Loaders/ModelLoader.cs @@ -15,7 +15,7 @@ namespace Kav foreach (var meshPartData in meshData.MeshParts) { - var effect = new Kav.GBufferEffect( + var effect = new Kav.DeferredPBR_GBufferEffect( graphicsDevice ) { diff --git a/Renderer.cs b/Renderer.cs index 0a77640..c53f855 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -160,6 +160,14 @@ namespace Kav i++; } + i = 0; + foreach (var directionalLight in directionalLights) + { + if (i > DeferredPBREffect.MaxDirectionalLights) { break; } + DeferredPBREffect.DirectionalLights[i] = directionalLight; + i++; + } + SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, DeferredPBREffect); SpriteBatch.Draw(deferredRenderTarget, Vector2.Zero, Color.White); SpriteBatch.End(); diff --git a/Resources.cs b/Resources.cs index 5c50646..83d4b04 100644 --- a/Resources.cs +++ b/Resources.cs @@ -4,13 +4,13 @@ namespace Kav { internal class Resources { - public static byte[] GBufferEffect + public static byte[] DeferredPBR_GBufferEffect { get { if (gBufferEffect == null) { - gBufferEffect = GetResource("GBufferEffect"); + gBufferEffect = GetResource("DeferredPBR_GBufferEffect"); } return gBufferEffect; } -- 2.25.1