From 3a0aa8894d69ddeb2a491a775363989e04a239c1 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 12 Dec 2020 00:17:10 -0800 Subject: [PATCH] draw zero alpha pixels in g buffer --- Data/MeshSpriteDrawData.cs | 6 ++- Effects/DeferredPBR_GBufferEffect.cs | 37 +++++++++++++++ Effects/FXB/DeferredPBR_GBufferEffect.fxb | 4 +- Effects/HLSL/DeferredPBR_GBufferEffect.fx | 18 ++++++- Geometry/Interfaces/ITransformable.cs | 9 ++++ Renderer.cs | 57 +++++++++++++++++++++++ 6 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 Geometry/Interfaces/ITransformable.cs diff --git a/Data/MeshSpriteDrawData.cs b/Data/MeshSpriteDrawData.cs index 2280bab..4eb57df 100644 --- a/Data/MeshSpriteDrawData.cs +++ b/Data/MeshSpriteDrawData.cs @@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics; namespace Kav.Data { - public struct MeshSpriteDrawData + public struct MeshSpriteDrawData : IIndexDrawable, ICullable, ITransformable { public SpriteMesh MeshSprite { get; } public Texture2D Texture { get; } @@ -12,6 +12,10 @@ namespace Kav.Data public Matrix TransformMatrix { get; } public UVData UVOffset { get; } + public IndexBuffer IndexBuffer => MeshSprite.IndexBuffer; + public VertexBuffer VertexBuffer => MeshSprite.VertexBuffer; + public BoundingBox BoundingBox => MeshSprite.BoundingBox; + public MeshSpriteDrawData( SpriteMesh meshSprite, Texture2D texture, diff --git a/Effects/DeferredPBR_GBufferEffect.cs b/Effects/DeferredPBR_GBufferEffect.cs index be3e3ff..aa7c769 100644 --- a/Effects/DeferredPBR_GBufferEffect.cs +++ b/Effects/DeferredPBR_GBufferEffect.cs @@ -16,6 +16,8 @@ namespace Kav EffectParameter metallicParam; EffectParameter roughnessParam; + EffectParameter uvOffsetAndDimensionsParam; + EffectParameter numTextureRowsParam; EffectParameter numTextureColumnsParam; @@ -30,6 +32,9 @@ namespace Kav float metallic; float roughness; + Vector2 uvOffset; + Vector2 subTextureDimensions; + int numTextureRows = 1; int numTextureColumns = 1; @@ -153,6 +158,26 @@ namespace Kav } } + public Vector2 UVOffset + { + get { return uvOffset; } + set + { + uvOffset = value; + dirtyFlags |= EffectDirtyFlags.UVOrDimensions; + } + } + + public Vector2 SubTextureDimensions + { + get { return subTextureDimensions; } + set + { + subTextureDimensions = value; + dirtyFlags |= EffectDirtyFlags.UVOrDimensions; + } + } + public bool HardwareInstancingEnabled { get { return hardwareInstancingEnabled; } @@ -210,6 +235,16 @@ namespace Kav dirtyFlags &= ~EffectDirtyFlags.ViewProj; } + if ((dirtyFlags & EffectDirtyFlags.UVOrDimensions) != 0) + { + uvOffsetAndDimensionsParam.SetValue(new Vector4( + UVOffset.X, UVOffset.Y, + SubTextureDimensions.X, SubTextureDimensions.Y + )); + + dirtyFlags &= ~EffectDirtyFlags.UVOrDimensions; + } + if ((dirtyFlags & EffectDirtyFlags.VertexShaderIndex) != 0) { int vertexShaderIndex = 0; @@ -277,6 +312,8 @@ namespace Kav numTextureRowsParam = Parameters["NumTextureRows"]; numTextureColumnsParam = Parameters["NumTextureColumns"]; + uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"]; + shaderIndexParam = Parameters["PixelShaderIndex"]; vertexShaderIndexParam = Parameters["VertexShaderIndex"]; } diff --git a/Effects/FXB/DeferredPBR_GBufferEffect.fxb b/Effects/FXB/DeferredPBR_GBufferEffect.fxb index 0f379e6..192aa11 100644 --- a/Effects/FXB/DeferredPBR_GBufferEffect.fxb +++ b/Effects/FXB/DeferredPBR_GBufferEffect.fxb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebcbca875c8ce99a59a733d9bf45f35126b22dbee7e2a6378c91088fce2181dc -size 9232 +oid sha256:0c58e459d43bf43461f48bc4986b7c923fc63c319fd68f074bb1cddc4c8b564f +size 9564 diff --git a/Effects/HLSL/DeferredPBR_GBufferEffect.fx b/Effects/HLSL/DeferredPBR_GBufferEffect.fx index b73b617..c546e01 100644 --- a/Effects/HLSL/DeferredPBR_GBufferEffect.fx +++ b/Effects/HLSL/DeferredPBR_GBufferEffect.fx @@ -4,6 +4,8 @@ DECLARE_TEXTURE(AlbedoTexture, 0); DECLARE_TEXTURE(NormalTexture, 1); DECLARE_TEXTURE(MetallicRoughnessTexture, 2); +float4 UVOffsetAndDimensions; + BEGIN_CONSTANTS float3 AlbedoValue _ps(c0) _cb(c0); @@ -51,7 +53,11 @@ PixelInput main_vs(VertexInput input) output.PositionWorld = mul(input.Position, World).xyz; output.NormalWorld = normalize(mul(input.Normal, World)); - output.TexCoord = input.TexCoord; + + float2 texCoord; + texCoord.x = (input.TexCoord.x * UVOffsetAndDimensions.z) + UVOffsetAndDimensions.x; + texCoord.y = (input.TexCoord.y * UVOffsetAndDimensions.w) + UVOffsetAndDimensions.y; + output.TexCoord = texCoord; float4x4 worldViewProjection = mul(World, ViewProjection); output.Position = mul(input.Position, worldViewProjection); @@ -60,7 +66,7 @@ PixelInput main_vs(VertexInput input) } PixelInput instanced_vs( - VertexInput input, + VertexInput input, float3 Translation : TEXCOORD2, float2 UVOffset : TEXCOORD5 ) { @@ -129,6 +135,8 @@ PixelOutput AlbedoPS(PixelInput input) output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0); + if (output.gAlbedo.a == 0.0) { discard; } + return output; } @@ -165,6 +173,8 @@ PixelOutput AlbedoMetallicRoughnessPS(PixelInput input) output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); + if (output.gAlbedo.a == 0.0) { discard; } + return output; } @@ -177,6 +187,8 @@ PixelOutput AlbedoNormalPS(PixelInput input) output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gMetallicRoughness = float4(MetallicValue, RoughnessValue, 0.0, 1.0); + if (output.gAlbedo.a == 0.0) { discard; } + return output; } @@ -201,6 +213,8 @@ PixelOutput AlbedoMetallicRoughnessNormalMapPS(PixelInput input) output.gAlbedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord); output.gMetallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord); + if (output.gAlbedo.a == 0.0) { discard; } + return output; } diff --git a/Geometry/Interfaces/ITransformable.cs b/Geometry/Interfaces/ITransformable.cs new file mode 100644 index 0000000..6047ad9 --- /dev/null +++ b/Geometry/Interfaces/ITransformable.cs @@ -0,0 +1,9 @@ +using Microsoft.Xna.Framework; + +namespace Kav +{ + public interface ITransformable + { + Matrix TransformMatrix { get; } + } +} diff --git a/Renderer.cs b/Renderer.cs index 3bf8bd2..154b6da 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -196,6 +196,48 @@ namespace Kav } } + public void RenderMeshSpriteGBuffer( + RenderTargetBinding[] gBuffer, + PerspectiveCamera camera, + IEnumerable meshSpriteDrawDatas + ) { + GraphicsDevice.SetRenderTargets(gBuffer); + GraphicsDevice.RasterizerState = RasterizerState.CullNone; + GraphicsDevice.DepthStencilState = DepthStencilState.Default; + GraphicsDevice.BlendState = BlendState.AlphaBlend; + + Deferred_GBufferEffect.HardwareInstancingEnabled = false; + Deferred_GBufferEffect.View = camera.View; + Deferred_GBufferEffect.Projection = camera.Projection; + + var boundingFrustum = new BoundingFrustum(camera.View * camera.Projection); + + foreach (var data in meshSpriteDrawDatas) + { + var matrix = BillboardTransforms(camera, data.TransformMatrix, data.BillboardConstraint); + + if (FrustumCull(boundingFrustum, data.MeshSprite, matrix)) + { + continue; + } + + Deferred_GBufferEffect.World = matrix; + + Deferred_GBufferEffect.UVOffset = data.UVOffset.Offset; + Deferred_GBufferEffect.SubTextureDimensions = data.UVOffset.Percentage; + + Deferred_GBufferEffect.Albedo = Color.White.ToVector3(); + Deferred_GBufferEffect.Metallic = 0f; + Deferred_GBufferEffect.Roughness = 1f; + + Deferred_GBufferEffect.AlbedoTexture = data.Texture; + Deferred_GBufferEffect.NormalTexture = data.Normal; + Deferred_GBufferEffect.MetallicRoughnessTexture = null; + + RenderIndexed(GraphicsDevice, data, Deferred_GBufferEffect); + } + } + private static Matrix BillboardTransforms( PerspectiveCamera camera, Matrix transform, @@ -942,6 +984,21 @@ namespace Kav return (containment == ContainmentType.Disjoint); } + private static IEnumerable FrustumCull( + BoundingFrustum boundingFrustum, + IEnumerable cullableTransformables + ) where T : ICullable, ITransformable { + foreach (var cullableTransformable in cullableTransformables) + { + var boundingBox = TransformedBoundingBox(cullableTransformable.BoundingBox, cullableTransformable.TransformMatrix); + var containment = boundingFrustum.Contains(boundingBox); + if (containment != ContainmentType.Disjoint) + { + yield return cullableTransformable; + } + } + } + private static BoundingBox TransformedBoundingBox(BoundingBox boundingBox, Matrix matrix) { var center = (boundingBox.Min + boundingBox.Max) / 2f;