deferred skybox

pull/3/head
cosmonaut 2020-10-17 13:53:26 -07:00
parent 19a61985ca
commit 06e5523996
8 changed files with 264 additions and 18 deletions

BIN
Effects/FXB/SkyboxEffect.fxb (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,45 @@
#include "Macros.fxh"
DECLARE_CUBEMAP(skybox, 0);
BEGIN_CONSTANTS
float4x4 ViewProjection _vs(c0) _cb(c0);
END_CONSTANTS
struct VertexShaderInput
{
float3 Position : POSITION;
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float3 TexCoord : TEXCOORD;
};
VertexShaderOutput main_vs(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = mul(float4(input.Position, 1.0), ViewProjection);
output.Position = output.Position.xyww;
output.TexCoord = input.Position;
return output;
}
float4 main_ps(VertexShaderOutput input) : SV_TARGET0
{
return SAMPLE_CUBEMAP(skybox, input.TexCoord);
}
Technique Skybox
{
Pass
{
VertexShader = compile vs_3_0 main_vs();
PixelShader = compile ps_3_0 main_ps();
}
}

77
Effects/SkyboxEffect.cs Normal file
View File

@ -0,0 +1,77 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Kav
{
public class SkyboxEffect : Effect
{
EffectParameter viewProjectionParam;
EffectParameter skyboxParam;
Matrix view;
Matrix projection;
TextureCube skybox;
EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All;
public Matrix View
{
get { return view; }
set
{
view = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public Matrix Projection
{
get { return projection; }
set
{
projection = value;
dirtyFlags |= EffectDirtyFlags.WorldViewProj;
}
}
public TextureCube Skybox
{
get { return skybox; }
set
{
skybox = value;
dirtyFlags |= EffectDirtyFlags.World; // hack flag but whatever
}
}
public SkyboxEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.SkyboxEffect)
{
CacheEffectParameters();
}
protected override void OnApply()
{
if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0)
{
Matrix.Multiply(ref view, ref projection, out Matrix viewProjection);
viewProjectionParam.SetValue(viewProjection);
dirtyFlags &= ~EffectDirtyFlags.WorldViewProj;
}
if ((dirtyFlags & EffectDirtyFlags.World) != 0)
{
skyboxParam.SetValue(skybox);
dirtyFlags &= ~EffectDirtyFlags.World;
}
}
private void CacheEffectParameters()
{
viewProjectionParam = Parameters["ViewProjection"];
skyboxParam = Parameters["skybox"];
}
}
}

View File

@ -42,6 +42,12 @@
<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\SkyboxEffect.fxb">
<LogicalName>Kav.Resources.SkyboxEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Models\UnitCube.glb">
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -42,6 +42,12 @@
<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\SkyboxEffect.fxb">
<LogicalName>Kav.Resources.SkyboxEffect.fxb</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Models\UnitCube.glb">
<LogicalName>Kav.Resources.UnitCube.glb</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

BIN
Models/UnitCube.glb Normal file

Binary file not shown.

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@ -29,6 +30,7 @@ namespace Kav
private Deferred_ToonEffect Deferred_ToonEffect { get; } private Deferred_ToonEffect Deferred_ToonEffect { get; }
private SimpleDepthEffect SimpleDepthEffect { get; } private SimpleDepthEffect SimpleDepthEffect { get; }
private Effect ToneMapEffect { get; } private Effect ToneMapEffect { get; }
private SkyboxEffect SkyboxEffect { get; }
private RenderTarget2D gPosition { get; } private RenderTarget2D gPosition { get; }
private RenderTarget2D gNormal { get; } private RenderTarget2D gNormal { get; }
@ -37,6 +39,8 @@ namespace Kav
private RenderTargetBinding[] GBuffer { get; } private RenderTargetBinding[] GBuffer { get; }
private Kav.Model UnitCube { get; }
private SpriteBatch SpriteBatch { get; } private SpriteBatch SpriteBatch { get; }
public Renderer( public Renderer(
@ -73,7 +77,7 @@ namespace Kav
renderDimensionsY, renderDimensionsY,
false, false,
SurfaceFormat.Color, SurfaceFormat.Color,
DepthFormat.None, DepthFormat.Depth24,
0, 0,
RenderTargetUsage.PreserveContents RenderTargetUsage.PreserveContents
); );
@ -142,6 +146,7 @@ namespace Kav
DeferredDirectionalLightEffect.ShadowMapSize = ShadowMapSize; DeferredDirectionalLightEffect.ShadowMapSize = ShadowMapSize;
ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect); ToneMapEffect = new Effect(graphicsDevice, Resources.ToneMapEffect);
Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice); Deferred_ToonEffect = new Deferred_ToonEffect(GraphicsDevice);
SkyboxEffect = new SkyboxEffect(GraphicsDevice);
FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly); FullscreenTriangle = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 3, BufferUsage.WriteOnly);
FullscreenTriangle.SetData(new VertexPositionTexture[3] { FullscreenTriangle.SetData(new VertexPositionTexture[3] {
@ -150,6 +155,11 @@ namespace Kav
new VertexPositionTexture(new Vector3(3, 1, 0), new Vector2(2, 0)) new VertexPositionTexture(new Vector3(3, 1, 0), new Vector2(2, 0))
}); });
UnitCube = Kav.ModelLoader.Load(
GraphicsDevice,
Smuggler.Importer.ImportGLB(GraphicsDevice, new MemoryStream(Resources.UnitCubeModel))
);
SpriteBatch = new SpriteBatch(graphicsDevice); SpriteBatch = new SpriteBatch(graphicsDevice);
} }
@ -187,23 +197,95 @@ namespace Kav
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms, IEnumerable<(Model, Matrix)> modelTransforms,
AmbientLight ambientLight, AmbientLight ambientLight,
DirectionalLight directionalLight DirectionalLight directionalLight,
) { TextureCube skybox
) {
GBufferRender(camera, modelTransforms); GBufferRender(camera, modelTransforms);
GraphicsDevice.SetRenderTarget(ColorRenderTarget); GraphicsDevice.SetRenderTarget(ColorRenderTarget);
GraphicsDevice.Clear(Color.Black); GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1f, 0);
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
DepthRender(camera, modelTransforms);
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
AmbientLightRender(ambientLight); AmbientLightRender(ambientLight);
DirectionalLightToonRender(camera, modelTransforms, directionalLight); DirectionalLightToonRender(camera, modelTransforms, directionalLight);
SkyboxRender(camera, skybox);
GraphicsDevice.SetRenderTarget(null); GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.Black);
SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null); SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null);
SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White);
SpriteBatch.End(); SpriteBatch.End();
} }
private void DepthRender(
PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms
) {
foreach (var (model, transform) in modelTransforms)
{
foreach (var modelMesh in model.Meshes)
{
foreach (var meshPart in modelMesh.MeshParts)
{
SimpleDepthEffect.Model = transform;
SimpleDepthEffect.View = camera.View;
SimpleDepthEffect.Projection = camera.Projection;
GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
GraphicsDevice.Indices = meshPart.IndexBuffer;
foreach (var pass in SimpleDepthEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
meshPart.VertexBuffer.VertexCount,
0,
meshPart.Triangles.Length
);
}
}
}
}
}
private void SkyboxRender(
PerspectiveCamera camera,
TextureCube skybox
) {
GraphicsDevice.RasterizerState.CullMode = CullMode.CullClockwiseFace;
SkyboxEffect.Skybox = skybox;
var view = camera.View;
view.Translation = Vector3.Zero;
SkyboxEffect.View = view;
SkyboxEffect.Projection = camera.Projection;
GraphicsDevice.SetVertexBuffer(UnitCube.Meshes[0].MeshParts[0].VertexBuffer);
GraphicsDevice.Indices = UnitCube.Meshes[0].MeshParts[0].IndexBuffer;
foreach (var pass in SkyboxEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
UnitCube.Meshes[0].MeshParts[0].VertexBuffer.VertexCount,
0,
UnitCube.Meshes[0].MeshParts[0].Triangles.Length
);
}
GraphicsDevice.RasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
}
private void GBufferRender( private void GBufferRender(
PerspectiveCamera camera, PerspectiveCamera camera,
IEnumerable<(Model, Matrix)> modelTransforms IEnumerable<(Model, Matrix)> modelTransforms
@ -255,8 +337,7 @@ namespace Kav
private void AmbientLightRender(AmbientLight ambientLight) private void AmbientLightRender(AmbientLight ambientLight)
{ {
GraphicsDevice.SetRenderTarget(ColorRenderTarget); GraphicsDevice.SetRenderTarget(ColorRenderTarget);
GraphicsDevice.BlendState = BlendState.Additive; GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.None;
DeferredAmbientLightEffect.GPosition = gPosition; DeferredAmbientLightEffect.GPosition = gPosition;
DeferredAmbientLightEffect.GAlbedo = gAlbedo; DeferredAmbientLightEffect.GAlbedo = gAlbedo;
@ -341,6 +422,7 @@ namespace Kav
RenderShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect); RenderShadows(camera, modelTransforms, directionalLight, Deferred_ToonEffect);
GraphicsDevice.SetRenderTarget(ColorRenderTarget); GraphicsDevice.SetRenderTarget(ColorRenderTarget);
GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
GraphicsDevice.BlendState = BlendState.Additive; GraphicsDevice.BlendState = BlendState.Additive;
Deferred_ToonEffect.GPosition = gPosition; Deferred_ToonEffect.GPosition = gPosition;

View File

@ -10,7 +10,7 @@ namespace Kav
{ {
if (ambientLightEffect == null) if (ambientLightEffect == null)
{ {
ambientLightEffect = GetResource("DeferredPBR_AmbientLightEffect"); ambientLightEffect = GetResource("DeferredPBR_AmbientLightEffect.fxb");
} }
return ambientLightEffect; return ambientLightEffect;
} }
@ -21,7 +21,7 @@ namespace Kav
{ {
if (pointLightEffect == null) if (pointLightEffect == null)
{ {
pointLightEffect = GetResource("DeferredPBR_PointLightEffect"); pointLightEffect = GetResource("DeferredPBR_PointLightEffect.fxb");
} }
return pointLightEffect; return pointLightEffect;
} }
@ -33,7 +33,7 @@ namespace Kav
{ {
if (directionalLightEffect == null) if (directionalLightEffect == null)
{ {
directionalLightEffect = GetResource("DeferredPBR_DirectionalLightEffect"); directionalLightEffect = GetResource("DeferredPBR_DirectionalLightEffect.fxb");
} }
return directionalLightEffect; return directionalLightEffect;
} }
@ -45,7 +45,7 @@ namespace Kav
{ {
if (gBufferEffect == null) if (gBufferEffect == null)
{ {
gBufferEffect = GetResource("DeferredPBR_GBufferEffect"); gBufferEffect = GetResource("DeferredPBR_GBufferEffect.fxb");
} }
return gBufferEffect; return gBufferEffect;
} }
@ -57,7 +57,7 @@ namespace Kav
{ {
if (toneMapEffect == null) if (toneMapEffect == null)
{ {
toneMapEffect = GetResource("ToneMapEffect"); toneMapEffect = GetResource("ToneMapEffect.fxb");
} }
return toneMapEffect; return toneMapEffect;
} }
@ -69,7 +69,7 @@ namespace Kav
{ {
if (deferredToonEffect == null) if (deferredToonEffect == null)
{ {
deferredToonEffect = GetResource("Deferred_ToonEffect"); deferredToonEffect = GetResource("Deferred_ToonEffect.fxb");
} }
return deferredToonEffect; return deferredToonEffect;
} }
@ -81,7 +81,7 @@ namespace Kav
{ {
if (deferredPBREffect == null) if (deferredPBREffect == null)
{ {
deferredPBREffect = GetResource("DeferredPBREffect"); deferredPBREffect = GetResource("DeferredPBREffect.fxb");
} }
return deferredPBREffect; return deferredPBREffect;
} }
@ -93,7 +93,7 @@ namespace Kav
{ {
if (pbrEffect == null) if (pbrEffect == null)
{ {
pbrEffect = GetResource("PBREffect"); pbrEffect = GetResource("PBREffect.fxb");
} }
return pbrEffect; return pbrEffect;
} }
@ -105,12 +105,36 @@ namespace Kav
{ {
if (simpleDepthEffect == null) if (simpleDepthEffect == null)
{ {
simpleDepthEffect = GetResource("SimpleDepthEffect"); simpleDepthEffect = GetResource("SimpleDepthEffect.fxb");
} }
return simpleDepthEffect; return simpleDepthEffect;
} }
} }
public static byte[] SkyboxEffect
{
get
{
if (skyboxEffect == null)
{
skyboxEffect = GetResource("SkyboxEffect.fxb");
}
return skyboxEffect;
}
}
public static byte[] UnitCubeModel
{
get
{
if (unitCubeModel == null)
{
unitCubeModel = GetResource("UnitCube.glb");
}
return unitCubeModel;
}
}
private static byte[] ambientLightEffect; private static byte[] ambientLightEffect;
private static byte[] pointLightEffect; private static byte[] pointLightEffect;
private static byte[] directionalLightEffect; private static byte[] directionalLightEffect;
@ -120,11 +144,14 @@ 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[] skyboxEffect;
private static byte[] unitCubeModel;
private static byte[] GetResource(string name) private static byte[] GetResource(string name)
{ {
Stream stream = typeof(Resources).Assembly.GetManifestResourceStream( Stream stream = typeof(Resources).Assembly.GetManifestResourceStream(
"Kav.Resources." + name + ".fxb" "Kav.Resources." + name
); );
using (MemoryStream ms = new MemoryStream()) using (MemoryStream ms = new MemoryStream())
{ {