From 2fb20747e4978d1b745cde76a1bcac452dfd34e7 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 1 Oct 2020 22:26:40 -0700 Subject: [PATCH] more toon effect + remove material from MeshPart --- Effects/Deferred_ToonEffect.cs | 14 ++++- Effects/FXB/Deferred_ToonEffect.fxb | 4 +- Effects/HLSL/Deferred_ToonEffect.fx | 39 ++++++++++-- Geometry/MeshPart.cs | 40 ++++++++++-- Geometry/Model.cs | 50 +++++++++++++++ Loaders/ModelLoader.cs | 30 ++++----- Renderer.cs | 98 ++++++++--------------------- 7 files changed, 174 insertions(+), 101 deletions(-) diff --git a/Effects/Deferred_ToonEffect.cs b/Effects/Deferred_ToonEffect.cs index 5b2cca3..9196197 100644 --- a/Effects/Deferred_ToonEffect.cs +++ b/Effects/Deferred_ToonEffect.cs @@ -11,6 +11,9 @@ namespace Kav EffectParameter eyePositionParam; EffectParameter directionalLightDirectionParam; + EffectParameter directionalLightColorParam; + + EffectParameter softnessParam; public Texture2D GPosition { get; set; } public Texture2D GAlbedo { get; set; } @@ -18,6 +21,9 @@ namespace Kav public Vector3 EyePosition { get; set; } public Vector3 DirectionalLightDirection { get; set; } + public Vector3 DirectionalLightColor { get; set; } + + public float Softness { get; set; } public Deferred_ToonEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.Deferred_ToonEffect) { @@ -29,9 +35,12 @@ namespace Kav gPositionParam.SetValue(GPosition); gAlbedoParam.SetValue(GAlbedo); gNormalParam.SetValue(GNormal); - + eyePositionParam.SetValue(EyePosition); directionalLightDirectionParam.SetValue(DirectionalLightDirection); + directionalLightColorParam.SetValue(DirectionalLightColor); + + softnessParam.SetValue(Softness); } void CacheEffectParameters() @@ -42,6 +51,9 @@ namespace Kav eyePositionParam = Parameters["EyePosition"]; directionalLightDirectionParam = Parameters["DirectionalLightDirection"]; + directionalLightColorParam = Parameters["DirectionalLightColor"]; + + softnessParam = Parameters["Softness"]; } } } diff --git a/Effects/FXB/Deferred_ToonEffect.fxb b/Effects/FXB/Deferred_ToonEffect.fxb index 1dbb741..4b5284e 100644 --- a/Effects/FXB/Deferred_ToonEffect.fxb +++ b/Effects/FXB/Deferred_ToonEffect.fxb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e49380a4f06e418f7056355d4b1426aa62d1025734c643c12ee9501c8a3d59b1 -size 1568 +oid sha256:1e5bd52fb74a48a7165a50bce38428a5f6d84550910129a6a17c66e87b2d8b0d +size 2504 diff --git a/Effects/HLSL/Deferred_ToonEffect.fx b/Effects/HLSL/Deferred_ToonEffect.fx index 7423236..42251a4 100644 --- a/Effects/HLSL/Deferred_ToonEffect.fx +++ b/Effects/HLSL/Deferred_ToonEffect.fx @@ -9,7 +9,9 @@ BEGIN_CONSTANTS float3 EyePosition _ps(c0) _cb(c0); float3 DirectionalLightDirection _ps(c1) _cb(c1); -float3 AmbientLightColor _ps(c2) _cb(c2); +float3 DirectionalLightColor _ps(c2) _cb(c2); + +float Softness _ps(c3) _cb(c3); END_CONSTANTS @@ -44,10 +46,39 @@ float4 main_ps(PixelInput input) : SV_TARGET0 float3 V = normalize(EyePosition - worldPosition); float3 L = normalize(DirectionalLightDirection); float3 N = normalize(normal); - float NdotL = dot(N, L); + float3 H = normalize(V + L); - float lightIntensity = (NdotL > 0.0) ? 1.0 : 0.0; - return float4(albedo * (lightIntensity, 1.0); + float NdotL = dot(N, L); + float NdotH = max(dot(N, H), 0.0); + + float lightIntensity; + if (Softness > 0.0) + { + lightIntensity = smoothstep(0, Softness, NdotL); + } + else + { + lightIntensity = (NdotL > 0.0) ? 1.0 : 0.0; + } + + float3 light = lightIntensity * DirectionalLightColor; + + float specularIntensity = pow(NdotH * lightIntensity, 32 * 32); + float specularSmooth = smoothstep(0.005, 0.01, specularIntensity); + + float3 specular = specularSmooth * float3(1.0, 1.0, 1.0); + + float rimColor = float3(1.0, 1.0, 1.0); + float rimThreshold = 0.1; + float rimAmount = 0.76; + float rimDot = 1 - dot(V, N); + float rimIntensity = rimDot * pow(max(NdotL, 0.0), rimThreshold); + rimIntensity = smoothstep(rimAmount - 0.01, rimAmount + 0.01, rimIntensity); + float3 rim = rimIntensity * rimColor; + + float3 color = albedo * (light + specular + rim); + + return float4(color, 1.0); } Technique Deferred_Toon diff --git a/Geometry/MeshPart.cs b/Geometry/MeshPart.cs index e97b49c..248fb1a 100644 --- a/Geometry/MeshPart.cs +++ b/Geometry/MeshPart.cs @@ -9,15 +9,47 @@ namespace Kav public VertexBuffer VertexBuffer { get; } public Triangle[] Triangles { get; } public Vector3[] Positions { get; } - public Effect Effect { get; } + + private Texture2D albedoTexture = null; + private Texture2D normalTexture = null; + private Texture2D metallicRoughnessTexture = null; - public MeshPart(VertexBuffer vertexBuffer, IndexBuffer indexBuffer, Vector3[] positions, Triangle[] triangles, Effect effect) - { + public Texture2D AlbedoTexture + { + get { return DisableAlbedoMap ? null : albedoTexture; } + set { albedoTexture = value; } + } + + public Texture2D NormalTexture + { + get { return DisableNormalMap ? null : normalTexture; } + set { normalTexture = value; } + } + + public Texture2D MetallicRoughnessTexture + { + get { return DisableMetallicRoughnessMap ? null : metallicRoughnessTexture; } + set { metallicRoughnessTexture = value; } + } + + public Vector3 Albedo { get; set; } = Vector3.One; + public float Metallic { get; set; } = 0.5f; + public float Roughness { get; set; } = 0.5f; + + public bool DisableAlbedoMap { get; set; } = false; + public bool DisableNormalMap { get; set; } = false; + public bool DisableMetallicRoughnessMap { get; set; } = false; + + public MeshPart( + VertexBuffer vertexBuffer, + IndexBuffer indexBuffer, + Vector3[] positions, + Triangle[] triangles + ) { VertexBuffer = vertexBuffer; IndexBuffer = indexBuffer; Positions = positions; Triangles = triangles; - Effect = effect; } } } diff --git a/Geometry/Model.cs b/Geometry/Model.cs index 1d83410..e9ad690 100644 --- a/Geometry/Model.cs +++ b/Geometry/Model.cs @@ -6,9 +6,59 @@ namespace Kav { public Mesh[] Meshes { get; } + private Color albedoValue; + + public Color Albedo + { + get { return albedoValue; } + set + { + foreach (var mesh in Meshes) + { + foreach (var meshPart in mesh.MeshParts) + { + meshPart.Albedo = value.ToVector3(); + } + } + } + } + public Model(Mesh[] meshes) { Meshes = meshes; } + + public void DisableAlbedoMaps() + { + foreach (var mesh in Meshes) + { + foreach (var meshPart in mesh.MeshParts) + { + meshPart.DisableAlbedoMap = true; + } + } + } + + public void DisableNormalMaps() + { + foreach (var mesh in Meshes) + { + foreach (var meshPart in mesh.MeshParts) + { + meshPart.DisableNormalMap = true; + } + } + } + + public void DisableMetallicRoughnessMaps() + { + foreach (var mesh in Meshes) + { + foreach (var meshPart in mesh.MeshParts) + { + meshPart.DisableMetallicRoughnessMap = true; + } + } + } } } diff --git a/Loaders/ModelLoader.cs b/Loaders/ModelLoader.cs index 4e908a0..634ae94 100644 --- a/Loaders/ModelLoader.cs +++ b/Loaders/ModelLoader.cs @@ -15,19 +15,6 @@ namespace Kav foreach (var meshPartData in meshData.MeshParts) { - var effect = new Kav.DeferredPBR_GBufferEffect( - graphicsDevice - ) - { - Albedo = meshPartData.Albedo, - Metallic = meshPartData.Metallic, - Roughness = meshPartData.Roughness, - - AlbedoTexture = meshPartData.AlbedoTexture, - NormalTexture = meshPartData.NormalTexture, - MetallicRoughnessTexture = meshPartData.MetallicRoughnessTexture - }; - var triangles = new Kav.Triangle[meshPartData.Triangles.Length]; for (int i = 0; i < meshPartData.Triangles.Length; i++) { @@ -40,13 +27,22 @@ namespace Kav ); } - meshParts.Add(new Kav.MeshPart( + var meshPart = new Kav.MeshPart( meshPartData.VertexBuffer, meshPartData.IndexBuffer, meshPartData.Positions, - triangles, - effect - )); + triangles + ); + + meshPart.Albedo = meshPartData.Albedo; + meshPart.Metallic = meshPartData.Metallic; + meshPart.Roughness = meshPartData.Roughness; + + meshPart.AlbedoTexture = meshPartData.AlbedoTexture; + meshPart.NormalTexture = meshPartData.NormalTexture; + meshPart.MetallicRoughnessTexture = meshPartData.MetallicRoughnessTexture; + + meshParts.Add(meshPart); } meshes.Add(new Kav.Mesh(meshParts.ToArray())); diff --git a/Renderer.cs b/Renderer.cs index 5978274..4861f2d 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -21,6 +21,8 @@ namespace Kav private RenderTarget2D[] ShadowRenderTargets { get; } private DeferredPBREffect DeferredPBREffect { get; } + /* FIXME: these next two dont actually have anything to do with PBR */ + private DeferredPBR_GBufferEffect Deferred_GBufferEffect { get; } private DeferredPBR_AmbientLightEffect DeferredAmbientLightEffect { get; } private DeferredPBR_PointLightEffect DeferredPointLightEffect { get; } private DeferredPBR_DirectionalLightEffect DeferredDirectionalLightEffect { get; } @@ -132,6 +134,8 @@ namespace Kav SimpleDepthEffect = new SimpleDepthEffect(GraphicsDevice); DeferredPBREffect = new DeferredPBREffect(GraphicsDevice); + + Deferred_GBufferEffect = new DeferredPBR_GBufferEffect(GraphicsDevice); DeferredAmbientLightEffect = new DeferredPBR_AmbientLightEffect(GraphicsDevice); DeferredPointLightEffect = new DeferredPBR_PointLightEffect(GraphicsDevice); DeferredDirectionalLightEffect = new DeferredPBR_DirectionalLightEffect(GraphicsDevice); @@ -199,7 +203,7 @@ namespace Kav GraphicsDevice.SetRenderTarget(null); GraphicsDevice.Clear(Color.Black); - SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, ToneMapEffect); + SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, null, null, null, null); SpriteBatch.Draw(ColorRenderTarget, Vector2.Zero, Color.White); SpriteBatch.End(); } @@ -219,17 +223,22 @@ namespace Kav { foreach (var meshPart in modelMesh.MeshParts) { + Deferred_GBufferEffect.World = transform; + Deferred_GBufferEffect.View = camera.View; + Deferred_GBufferEffect.Projection = camera.Projection; + + Deferred_GBufferEffect.Albedo = meshPart.Albedo; + Deferred_GBufferEffect.Metallic = meshPart.Metallic; + Deferred_GBufferEffect.Roughness = meshPart.Roughness; + + Deferred_GBufferEffect.AlbedoTexture = meshPart.AlbedoTexture; + Deferred_GBufferEffect.NormalTexture = meshPart.NormalTexture; + Deferred_GBufferEffect.MetallicRoughnessTexture = meshPart.MetallicRoughnessTexture; + 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) + foreach (var pass in Deferred_GBufferEffect.CurrentTechnique.Passes) { pass.Apply(); @@ -353,12 +362,16 @@ namespace Kav PerspectiveCamera camera, DirectionalLight directionalLight ) { - Deferred_ToonEffect.EyePosition = camera.Position; - Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction; - GraphicsDevice.SetRenderTarget(ColorRenderTarget); GraphicsDevice.BlendState = BlendState.Additive; + Deferred_ToonEffect.EyePosition = camera.Position; + Deferred_ToonEffect.DirectionalLightDirection = directionalLight.Direction; + Deferred_ToonEffect.DirectionalLightColor = + directionalLight.Color.ToVector3() * directionalLight.Intensity; + + Deferred_ToonEffect.Softness = 0.01f; + foreach (EffectPass pass in Deferred_ToonEffect.CurrentTechnique.Passes) { pass.Apply(); @@ -456,66 +469,5 @@ namespace Kav } } } - - public void Render( - PerspectiveCamera camera, - IEnumerable<(Model, Matrix)> modelTransforms, - IEnumerable pointLights, - IEnumerable directionalLights - ) { - Render(camera.View, camera.Projection, modelTransforms, pointLights, directionalLights); - } - - private void Render( - Matrix view, - Matrix projection, - IEnumerable<(Model, Matrix)> modelTransforms, - IEnumerable pointLights, - IEnumerable directionalLights - ) { - 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 = view; - transformEffect.Projection = projection; - } - - if (meshPart.Effect is PointLightEffect pointLightEffect) - { - int i = 0; - foreach (var pointLight in pointLights) - { - if (i > pointLightEffect.MaxPointLights) { break; } - pointLightEffect.PointLights[i] = pointLight; - i++; - } - } - - foreach (var pass in meshPart.Effect.CurrentTechnique.Passes) - { - pass.Apply(); - - GraphicsDevice.DrawIndexedPrimitives( - PrimitiveType.TriangleList, - 0, - 0, - meshPart.VertexBuffer.VertexCount, - 0, - meshPart.Triangles.Length - ); - } - } - } - } - } } }