diff --git a/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl new file mode 100644 index 000000000..085c66291 --- /dev/null +++ b/Content/Editor/MaterialTemplates/Features/ForwardShading.hlsl @@ -0,0 +1,123 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +@0// Forward Shading: Defines +#define MAX_LOCAL_LIGHTS 4 +@1// Forward Shading: Includes +#include "./Flax/LightingCommon.hlsl" +#if USE_REFLECTIONS +#include "./Flax/ReflectionsCommon.hlsl" +#endif +#include "./Flax/Lighting.hlsl" +#include "./Flax/ShadowsSampling.hlsl" +#include "./Flax/ExponentialHeightFog.hlsl" +@2// Forward Shading: Constants +LightData DirectionalLight; +LightShadowData DirectionalLightShadow; +LightData SkyLight; +ProbeData EnvironmentProbe; +ExponentialHeightFogData ExponentialHeightFog; +float3 Dummy2; +uint LocalLightsCount; +LightData LocalLights[MAX_LOCAL_LIGHTS]; +@3// Forward Shading: Resources +TextureCube EnvProbe : register(t__SRV__); +TextureCube SkyLightTexture : register(t__SRV__); +Texture2DArray DirectionalLightShadowMap : register(t__SRV__); +@4// Forward Shading: Utilities +DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow); +@5// Forward Shading: Shaders +// Pixel Shader function for Forward Pass +META_PS(USE_FORWARD, FEATURE_LEVEL_ES2) +float4 PS_Forward(PixelInput input) : SV_Target0 +{ + float4 output = 0; + +#if USE_DITHERED_LOD_TRANSITION + // LOD masking + ClipLODTransition(input); +#endif + + // Get material parameters + MaterialInput materialInput = GetMaterialInput(input); + Material material = GetMaterialPS(materialInput); + + // Masking +#if MATERIAL_MASKED + clip(material.Mask - MATERIAL_MASK_THRESHOLD); +#endif + + // Add emissive light + output = float4(material.Emissive, material.Opacity); + +#if MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT + + // Setup GBuffer data as proxy for lighting + GBufferSample gBuffer; + gBuffer.Normal = material.WorldNormal; + gBuffer.Roughness = material.Roughness; + gBuffer.Metalness = material.Metalness; + gBuffer.Color = material.Color; + gBuffer.Specular = material.Specular; + gBuffer.AO = material.AO; + gBuffer.ViewPos = mul(float4(materialInput.WorldPosition, 1), ViewMatrix).xyz; +#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE + gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity); +#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE + gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity); +#else + gBuffer.CustomData = float4(0, 0, 0, 0); +#endif + gBuffer.WorldPos = materialInput.WorldPosition; + gBuffer.ShadingModel = MATERIAL_SHADING_MODEL; + + // Calculate lighting from a single directional light + float4 shadowMask = 1.0f; + if (DirectionalLight.CastShadows > 0) + { + LightShadowData directionalLightShadowData = GetDirectionalLightShadowData(); + shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g); + } + float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false); + + // Calculate lighting from sky light + light += GetSkyLightLighting(SkyLight, gBuffer, SkyLightTexture); + + // Calculate lighting from local lights + LOOP + for (uint localLightIndex = 0; localLightIndex < LocalLightsCount; localLightIndex++) + { + const LightData localLight = LocalLights[localLightIndex]; + bool isSpotLight = localLight.SpotAngles.x > -2.0f; + shadowMask = 1.0f; + light += GetLighting(ViewPos, localLight, gBuffer, shadowMask, true, isSpotLight); + } + +#if USE_REFLECTIONS + // Calculate reflections + light.rgb += GetEnvProbeLighting(ViewPos, EnvProbe, EnvironmentProbe, gBuffer) * light.a; +#endif + + // Add lighting (apply ambient occlusion) + output.rgb += light.rgb * gBuffer.AO; + +#if USE_FOG + // Calculate exponential height fog + float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0); + + // Apply fog to the output color +#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE + output = float4(output.rgb * fog.a + fog.rgb, output.a); +#elif MATERIAL_BLEND == MATERIAL_BLEND_TRANSPARENT + output = float4(output.rgb * fog.a + fog.rgb, output.a); +#elif MATERIAL_BLEND == MATERIAL_BLEND_ADDITIVE + output = float4(output.rgb * fog.a + fog.rgb, output.a * fog.a); +#elif MATERIAL_BLEND == MATERIAL_BLEND_MULTIPLY + output = float4(lerp(float3(1, 1, 1), output.rgb, fog.aaa * fog.aaa), output.a); +#endif + +#endif + +#endif + + return output; +} diff --git a/Content/Editor/MaterialTemplates/GUI.shader b/Content/Editor/MaterialTemplates/GUI.shader index b927755ad..7eced6390 100644 --- a/Content/Editor/MaterialTemplates/GUI.shader +++ b/Content/Editor/MaterialTemplates/GUI.shader @@ -3,7 +3,6 @@ #define MATERIAL 1 @3 - #include "./Flax/Common.hlsl" #include "./Flax/MaterialCommon.hlsl" #include "./Flax/GBufferCommon.hlsl" @@ -22,7 +21,7 @@ float4 ViewInfo; float4 ScreenSize; @1META_CB_END -// Material shader resources +// Shader resources @2 // Interpolants passed from the vertex shader struct VertexOutput diff --git a/Content/Editor/MaterialTemplates/Particle.shader b/Content/Editor/MaterialTemplates/Particle.shader index 72d633028..a3befc24f 100644 --- a/Content/Editor/MaterialTemplates/Particle.shader +++ b/Content/Editor/MaterialTemplates/Particle.shader @@ -2,19 +2,13 @@ // Version: @0 #define MATERIAL 1 -#define MAX_LOCAL_LIGHTS 4 @3 +// Ribbons don't use sorted indices so overlap the segment distances buffer on the slot +#define HAS_SORTED_INDICES (!defined(_VS_Ribbon)) #include "./Flax/Common.hlsl" #include "./Flax/MaterialCommon.hlsl" #include "./Flax/GBufferCommon.hlsl" -#include "./Flax/LightingCommon.hlsl" -#if USE_REFLECTIONS -#include "./Flax/ReflectionsCommon.hlsl" -#endif -#include "./Flax/Lighting.hlsl" -#include "./Flax/ShadowsSampling.hlsl" -#include "./Flax/ExponentialHeightFog.hlsl" #include "./Flax/Matrix.hlsl" @7 struct SpriteInput @@ -55,44 +49,19 @@ uint RibbonSegmentCount; float4x4 WorldMatrixInverseTransposed; @1META_CB_END -// Secondary constantant buffer (for lighting) -META_CB_BEGIN(1, LightingData) -LightData DirectionalLight; -LightShadowData DirectionalLightShadow; -LightData SkyLight; -ProbeData EnvironmentProbe; -ExponentialHeightFogData ExponentialHeightFog; -float3 Dummy1; -uint LocalLightsCount; -LightData LocalLights[MAX_LOCAL_LIGHTS]; -META_CB_END - -DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow); - // Particles attributes buffer ByteAddressBuffer ParticlesData : register(t0); -// Ribbons don't use sorted indices so overlap the segment distances buffer on the slot -#define HAS_SORTED_INDICES (!defined(_VS_Ribbon)) - #if HAS_SORTED_INDICES - // Sorted particles indices Buffer SortedIndices : register(t1); - #else - // Ribbon particles segments distances buffer Buffer SegmentDistances : register(t1); - #endif // Shader resources -TextureCube EnvProbe : register(t2); -TextureCube SkyLightTexture : register(t3); -Texture2DArray DirectionalLightShadowMap : register(t4); @2 - // Interpolants passed from the vertex shader struct VertexOutput { @@ -711,97 +680,6 @@ VertexOutput VS_Ribbon(uint vertexIndex : SV_VertexID) return output; } -// Pixel Shader function for Forward Pass -META_PS(USE_FORWARD, FEATURE_LEVEL_ES2) -float4 PS_Forward(PixelInput input) : SV_Target0 -{ - float4 output = 0; - - // Get material parameters - MaterialInput materialInput = GetMaterialInput(input); - Material material = GetMaterialPS(materialInput); - - // Masking -#if MATERIAL_MASKED - clip(material.Mask - MATERIAL_MASK_THRESHOLD); -#endif - - // Add emissive light - output = float4(material.Emissive, material.Opacity); - -#if MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT - - // Setup GBuffer data as proxy for lighting - GBufferSample gBuffer; - gBuffer.Normal = material.WorldNormal; - gBuffer.Roughness = material.Roughness; - gBuffer.Metalness = material.Metalness; - gBuffer.Color = material.Color; - gBuffer.Specular = material.Specular; - gBuffer.AO = material.AO; - gBuffer.ViewPos = mul(float4(materialInput.WorldPosition, 1), ViewMatrix).xyz; -#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE - gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity); -#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE - gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity); -#else - gBuffer.CustomData = float4(0, 0, 0, 0); -#endif - gBuffer.WorldPos = materialInput.WorldPosition; - gBuffer.ShadingModel = MATERIAL_SHADING_MODEL; - - // Calculate lighting from a single directional light - float4 shadowMask = 1.0f; - if (DirectionalLight.CastShadows > 0) - { - LightShadowData directionalLightShadowData = GetDirectionalLightShadowData(); - shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g); - } - float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false); - - // Calculate lighting from sky light - light += GetSkyLightLighting(SkyLight, gBuffer, SkyLightTexture); - - // Calculate lighting from local lights - LOOP - for (uint localLightIndex = 0; localLightIndex < LocalLightsCount; localLightIndex++) - { - const LightData localLight = LocalLights[localLightIndex]; - bool isSpotLight = localLight.SpotAngles.x > -2.0f; - shadowMask = 1.0f; - light += GetLighting(ViewPos, localLight, gBuffer, shadowMask, true, isSpotLight); - } - -#if USE_REFLECTIONS - // Calculate reflections - light.rgb += GetEnvProbeLighting(ViewPos, EnvProbe, EnvironmentProbe, gBuffer) * light.a; -#endif - - // Add lighting (apply ambient occlusion) - output.rgb += light.rgb * gBuffer.AO; - -#if USE_FOG - // Calculate exponential height fog - float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0); - - // Apply fog to the output color -#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE - output = float4(output.rgb * fog.a + fog.rgb, output.a); -#elif MATERIAL_BLEND == MATERIAL_BLEND_TRANSPARENT - output = float4(output.rgb * fog.a + fog.rgb, output.a); -#elif MATERIAL_BLEND == MATERIAL_BLEND_ADDITIVE - output = float4(output.rgb * fog.a + fog.rgb, output.a * fog.a); -#elif MATERIAL_BLEND == MATERIAL_BLEND_MULTIPLY - output = float4(lerp(float3(1, 1, 1), output.rgb, fog.aaa * fog.aaa), output.a); -#endif - -#endif - -#endif - - return output; -} - // Pixel Shader function for Depth Pass META_PS(true, FEATURE_LEVEL_ES2) void PS_Depth(PixelInput input diff --git a/Content/Editor/MaterialTemplates/PostProcess.shader b/Content/Editor/MaterialTemplates/PostProcess.shader index 681a04248..f20bdc610 100644 --- a/Content/Editor/MaterialTemplates/PostProcess.shader +++ b/Content/Editor/MaterialTemplates/PostProcess.shader @@ -20,7 +20,7 @@ float4 ScreenSize; float4 TemporalAAJitter; @1META_CB_END -// Material shader resources +// Shader resources @2 // Interpolants passed to the pixel shader struct PixelInput diff --git a/Content/Editor/MaterialTemplates/SurfaceDeferred.shader b/Content/Editor/MaterialTemplates/SurfaceDeferred.shader index dcee96822..9ba1ea3de 100644 --- a/Content/Editor/MaterialTemplates/SurfaceDeferred.shader +++ b/Content/Editor/MaterialTemplates/SurfaceDeferred.shader @@ -30,9 +30,8 @@ float3 GeometrySize; float Dummy1; @1META_CB_END -// Material shader resources +// Shader resources @2 - // Geometry data passed though the graphics rendering stages up to the pixel shader struct GeometryData { diff --git a/Content/Editor/MaterialTemplates/SurfaceForward.shader b/Content/Editor/MaterialTemplates/SurfaceForward.shader index cece1b231..e7a86fb81 100644 --- a/Content/Editor/MaterialTemplates/SurfaceForward.shader +++ b/Content/Editor/MaterialTemplates/SurfaceForward.shader @@ -2,19 +2,10 @@ // Version: @0 #define MATERIAL 1 -#define MAX_LOCAL_LIGHTS 4 @3 - #include "./Flax/Common.hlsl" #include "./Flax/MaterialCommon.hlsl" #include "./Flax/GBufferCommon.hlsl" -#include "./Flax/LightingCommon.hlsl" -#if USE_REFLECTIONS -#include "./Flax/ReflectionsCommon.hlsl" -#endif -#include "./Flax/Lighting.hlsl" -#include "./Flax/ShadowsSampling.hlsl" -#include "./Flax/ExponentialHeightFog.hlsl" @7 // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) @@ -38,26 +29,8 @@ float3 GeometrySize; float Dummy1; @1META_CB_END -// Secondary constantant buffer (for lighting) -META_CB_BEGIN(1, LightingData) -LightData DirectionalLight; -LightShadowData DirectionalLightShadow; -LightData SkyLight; -ProbeData EnvironmentProbe; -ExponentialHeightFogData ExponentialHeightFog; -float3 Dummy2; -uint LocalLightsCount; -LightData LocalLights[MAX_LOCAL_LIGHTS]; -META_CB_END - -DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow); - // Shader resources -TextureCube EnvProbe : register(t0); -TextureCube SkyLightTexture : register(t1); -Texture2DArray DirectionalLightShadowMap : register(t2); @2 - // Interpolants passed from the vertex shader struct VertexOutput { @@ -564,103 +537,6 @@ void ClipLODTransition(PixelInput input) #endif -// Pixel Shader function for Forward Pass -META_PS(USE_FORWARD, FEATURE_LEVEL_ES2) -float4 PS_Forward(PixelInput input) : SV_Target0 -{ - float4 output = 0; - -#if USE_DITHERED_LOD_TRANSITION - // LOD masking - ClipLODTransition(input); - // TODO: make model LOD transition smoother for transparent materials by using opacity to reduce aliasing -#endif - - // Get material parameters - MaterialInput materialInput = GetMaterialInput(input); - Material material = GetMaterialPS(materialInput); - - // Masking -#if MATERIAL_MASKED - clip(material.Mask - MATERIAL_MASK_THRESHOLD); -#endif - - // Add emissive light - output = float4(material.Emissive, material.Opacity); - -#if MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT - - // Setup GBuffer data as proxy for lighting - GBufferSample gBuffer; - gBuffer.Normal = material.WorldNormal; - gBuffer.Roughness = material.Roughness; - gBuffer.Metalness = material.Metalness; - gBuffer.Color = material.Color; - gBuffer.Specular = material.Specular; - gBuffer.AO = material.AO; - gBuffer.ViewPos = mul(float4(materialInput.WorldPosition, 1), ViewMatrix).xyz; -#if MATERIAL_SHADING_MODEL == SHADING_MODEL_SUBSURFACE - gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity); -#elif MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE - gBuffer.CustomData = float4(material.SubsurfaceColor, material.Opacity); -#else - gBuffer.CustomData = float4(0, 0, 0, 0); -#endif - gBuffer.WorldPos = materialInput.WorldPosition; - gBuffer.ShadingModel = MATERIAL_SHADING_MODEL; - - // Calculate lighting from a single directional light - float4 shadowMask = 1.0f; - if (DirectionalLight.CastShadows > 0) - { - LightShadowData directionalLightShadowData = GetDirectionalLightShadowData(); - shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g); - } - float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false); - - // Calculate lighting from sky light - light += GetSkyLightLighting(SkyLight, gBuffer, SkyLightTexture); - - // Calculate lighting from local lights - LOOP - for (uint localLightIndex = 0; localLightIndex < LocalLightsCount; localLightIndex++) - { - const LightData localLight = LocalLights[localLightIndex]; - bool isSpotLight = localLight.SpotAngles.x > -2.0f; - shadowMask = 1.0f; - light += GetLighting(ViewPos, localLight, gBuffer, shadowMask, true, isSpotLight); - } - -#if USE_REFLECTIONS - // Calculate reflections - light.rgb += GetEnvProbeLighting(ViewPos, EnvProbe, EnvironmentProbe, gBuffer) * light.a; -#endif - - // Add lighting (apply ambient occlusion) - output.rgb += light.rgb * gBuffer.AO; - -#if USE_FOG - // Calculate exponential height fog - float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0); - - // Apply fog to the output color -#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE - output = float4(output.rgb * fog.a + fog.rgb, output.a); -#elif MATERIAL_BLEND == MATERIAL_BLEND_TRANSPARENT - output = float4(output.rgb * fog.a + fog.rgb, output.a); -#elif MATERIAL_BLEND == MATERIAL_BLEND_ADDITIVE - output = float4(output.rgb * fog.a + fog.rgb, output.a * fog.a); -#elif MATERIAL_BLEND == MATERIAL_BLEND_MULTIPLY - output = float4(lerp(float3(1, 1, 1), output.rgb, fog.aaa * fog.aaa), output.a); -#endif - -#endif - -#endif - - return output; -} - // Pixel Shader function for Depth Pass META_PS(true, FEATURE_LEVEL_ES2) void PS_Depth(PixelInput input diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader index c36d7f0c5..f1c257b04 100644 --- a/Content/Editor/MaterialTemplates/Terrain.shader +++ b/Content/Editor/MaterialTemplates/Terrain.shader @@ -42,9 +42,8 @@ Texture2D Heightmap : register(t0); Texture2D Splatmap0 : register(t1); Texture2D Splatmap1 : register(t2); -// Material shader resources +// Shader resources @2 - // Geometry data passed though the graphics rendering stages up to the pixel shader struct GeometryData { diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index f410d477c..0d9108566 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -4,13 +4,14 @@ #include "MaterialShaderFeatures.h" #include "MaterialParams.h" #include "Engine/Engine/Time.h" +#include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPULimits.h" -#include "Engine/Graphics/Models/SkinnedMeshDrawData.h" #include "Engine/Graphics/RenderView.h" -#include "Engine/Level/Actors/EnvironmentProbe.h" -#include "Engine/Renderer/DepthOfFieldPass.h" +#include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/Models/SkinnedMeshDrawData.h" +#include "Engine/Graphics/Shaders/GPUConstantBuffer.h" +#include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Renderer/DrawCall.h" -#include "Engine/Renderer/ShadowsPass.h" #include "Engine/Renderer/RenderList.h" #if USE_EDITOR #include "Engine/Renderer/Lightmaps.h" @@ -39,17 +40,6 @@ PACK_STRUCT(struct ForwardMaterialShaderData { float Dummy1; }); -PACK_STRUCT(struct ForwardMaterialShaderLightingData { - LightData DirectionalLight; - LightShadowData DirectionalLightShadow; - LightData SkyLight; - ProbeData EnvironmentProbe; - ExponentialHeightFogData ExponentialHeightFog; - Vector3 Dummy2; - uint32 LocalLightsCount; - LightData LocalLights[MAX_LOCAL_LIGHTS]; - }); - DrawPass ForwardMaterialShader::GetDrawModes() const { return _drawModes; @@ -66,19 +56,17 @@ void ForwardMaterialShader::Bind(BindParameters& params) // Prepare auto context = params.GPUContext; auto& view = params.RenderContext.View; - auto cache = params.RenderContext.List; auto& drawCall = *params.FirstDrawCall; const auto cb0 = _shader->GetCB(0); const bool hasCb0 = cb0 && cb0->GetSize() != 0; ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing - const auto cb1 = _shader->GetCB(1); - const bool hasCb1 = cb1 && cb1->GetSize() != 0; byte* cb = _cb0Data.Get(); auto materialData = reinterpret_cast(cb); cb += sizeof(ForwardMaterialShaderData); int32 srv = 0; // Setup features + ForwardShadingFeature::Bind(params, cb, srv); // Setup parameters MaterialParameter::BindMeta bindMeta; @@ -131,124 +119,12 @@ void ForwardMaterialShader::Bind(BindParameters& params) materialData->GeometrySize = drawCall.Surface.GeometrySize; } - // Setup lighting constants data - if (hasCb1) - { - auto& lightingData = *reinterpret_cast(_cb1Data.Get()); - const int32 envProbeShaderRegisterIndex = 0; - const int32 skyLightShaderRegisterIndex = 1; - const int32 dirLightShaderRegisterIndex = 2; - - // Set fog input - if (cache->Fog) - { - cache->Fog->GetExponentialHeightFogData(view, lightingData.ExponentialHeightFog); - } - else - { - lightingData.ExponentialHeightFog.FogMinOpacity = 1.0f; - lightingData.ExponentialHeightFog.ApplyDirectionalInscattering = 0.0f; - } - - // Set directional light input - if (cache->DirectionalLights.HasItems()) - { - const auto& dirLight = cache->DirectionalLights.First(); - const auto shadowPass = ShadowsPass::Instance(); - const bool useShadow = shadowPass->LastDirLightIndex == 0; - if (useShadow) - { - lightingData.DirectionalLightShadow = shadowPass->LastDirLight; - context->BindSR(dirLightShaderRegisterIndex, shadowPass->LastDirLightShadowMap); - } - else - { - context->UnBindSR(dirLightShaderRegisterIndex); - } - dirLight.SetupLightData(&lightingData.DirectionalLight, view, useShadow); - } - else - { - lightingData.DirectionalLight.Color = Vector3::Zero; - lightingData.DirectionalLight.CastShadows = 0.0f; - context->UnBindSR(dirLightShaderRegisterIndex); - } - - // Set sky light - if (cache->SkyLights.HasItems()) - { - auto& skyLight = cache->SkyLights.First(); - skyLight.SetupLightData(&lightingData.SkyLight, view, false); - const auto texture = skyLight.Image ? skyLight.Image->GetTexture() : nullptr; - context->BindSR(skyLightShaderRegisterIndex, GET_TEXTURE_VIEW_SAFE(texture)); - } - else - { - Platform::MemoryClear(&lightingData.SkyLight, sizeof(lightingData.SkyLight)); - context->UnBindSR(skyLightShaderRegisterIndex); - } - - // Set reflection probe data - EnvironmentProbe* probe = nullptr; - // TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it - for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++) - { - const auto p = cache->EnvironmentProbes[i]; - if (p->GetSphere().Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint) - { - probe = p; - break; - } - } - if (probe && probe->GetProbe()) - { - probe->SetupProbeData(&lightingData.EnvironmentProbe); - const auto texture = probe->GetProbe()->GetTexture(); - context->BindSR(envProbeShaderRegisterIndex, GET_TEXTURE_VIEW_SAFE(texture)); - } - else - { - lightingData.EnvironmentProbe.Data1 = Vector4::Zero; - context->UnBindSR(envProbeShaderRegisterIndex); - } - - // Set local lights - lightingData.LocalLightsCount = 0; - for (int32 i = 0; i < cache->PointLights.Count(); i++) - { - const auto& light = cache->PointLights[i]; - if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint) - { - light.SetupLightData(&lightingData.LocalLights[lightingData.LocalLightsCount], view, false); - lightingData.LocalLightsCount++; - if (lightingData.LocalLightsCount == MAX_LOCAL_LIGHTS) - break; - } - } - for (int32 i = 0; i < cache->SpotLights.Count(); i++) - { - const auto& light = cache->SpotLights[i]; - if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint) - { - light.SetupLightData(&lightingData.LocalLights[lightingData.LocalLightsCount], view, false); - lightingData.LocalLightsCount++; - if (lightingData.LocalLightsCount == MAX_LOCAL_LIGHTS) - break; - } - } - } - // Bind constants if (hasCb0) { context->UpdateCB(cb0, _cb0Data.Get()); context->BindCB(0, cb0); } - if (hasCb1) - { - context->UpdateCB(cb1, _cb1Data.Get()); - context->BindCB(1, cb1); - } // Select pipeline state based on current pass and render mode const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe; diff --git a/Source/Engine/Graphics/Materials/MaterialShader.cpp b/Source/Engine/Graphics/Materials/MaterialShader.cpp index 478992959..ee1cf22c4 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShader.cpp @@ -143,11 +143,6 @@ bool MaterialShader::Load(MemoryReadStream& shaderCacheStream, const MaterialInf { _cb0Data.Resize(cb0->GetSize(), false); } - const auto cb1 = _shader->GetCB(1); - if (cb1) - { - _cb1Data.Resize(cb1->GetSize(), false); - } // Initialize the material based on type (create pipeline states and setup) if (Load()) @@ -163,6 +158,5 @@ void MaterialShader::Unload() { _isLoaded = false; _cb0Data.Resize(0, false); - _cb1Data.Resize(0, false); _shader->ReleaseGPU(); } diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index 58ba297fa..baa463d3f 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -53,7 +53,6 @@ protected: bool _isLoaded; GPUShader* _shader; Array _cb0Data; - Array _cb1Data; MaterialInfo _info; protected: diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index 0043a8d6e..3ed31908c 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -155,23 +155,30 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, byte*& cb, in #if USE_EDITOR +void ForwardShadingFeature::Generate(GeneratorData& data) +{ + data.Template = TEXT("Features/ForwardShading.hlsl"); + data.ConstantsSize = sizeof(Data); + data.ResourcesCount = SRVs; +} + void TessellationFeature::Generate(GeneratorData& data) { - data.Template = TEXT("Tessellation.hlsl"); + data.Template = TEXT("Features/Tessellation.hlsl"); data.ConstantsSize = 0; data.ResourcesCount = 0; } void LightmapFeature::Generate(GeneratorData& data) { - data.Template = TEXT("Lightmap.hlsl"); + data.Template = TEXT("Features/Lightmap.hlsl"); data.ConstantsSize = sizeof(Data); data.ResourcesCount = SRVs; } void DistortionFeature::Generate(GeneratorData& data) { - data.Template = TEXT("Distortion.hlsl"); + data.Template = TEXT("Features/Distortion.hlsl"); data.ConstantsSize = 0; data.ResourcesCount = 0; } diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h index 9d2c06307..1ee46e2d1 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h @@ -38,6 +38,9 @@ struct ForwardShadingFeature : MaterialShaderFeature }); static void Bind(MaterialShader::BindParameters& params, byte*& cb, int32& srv); +#if USE_EDITOR + static void Generate(GeneratorData& data); +#endif }; // Material shader feature that adds geometry hardware tessellation (using Hull and Domain shaders). diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp index bfab56daf..8ee49ae78 100644 --- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp @@ -1,20 +1,19 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "ParticleMaterialShader.h" +#include "MaterialShaderFeatures.h" #include "MaterialParams.h" -#include "Engine/Renderer/DrawCall.h" -#include "Engine/Renderer/ShadowsPass.h" -#include "Engine/Graphics/RenderView.h" -#include "Engine/Renderer/RenderList.h" -#include "Engine/Graphics/GPUContext.h" -#include "Engine/Graphics/Shaders/GPUConstantBuffer.h" #include "Engine/Engine/Time.h" +#include "Engine/Renderer/DrawCall.h" +#include "Engine/Renderer/RenderList.h" +#include "Engine/Graphics/RenderView.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" -#include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/GPULimits.h" +#include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/Shaders/GPUShader.h" +#include "Engine/Graphics/Shaders/GPUConstantBuffer.h" #include "Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.h" -#include "Engine/Content/Assets/CubeTexture.h" -#include "Engine/Level/Actors/EnvironmentProbe.h" #define MAX_LOCAL_LIGHTS 4 @@ -49,17 +48,6 @@ PACK_STRUCT(struct ParticleMaterialShaderData { Matrix WorldMatrixInverseTransposed; }); -PACK_STRUCT(struct ParticleMaterialShaderLightingData { - LightData DirectionalLight; - LightShadowData DirectionalLightShadow; - LightData SkyLight; - ProbeData EnvironmentProbe; - ExponentialHeightFogData ExponentialHeightFog; - Vector3 Dummy1; - uint32 LocalLightsCount; - LightData LocalLights[MAX_LOCAL_LIGHTS]; - }); - DrawPass ParticleMaterialShader::GetDrawModes() const { return _drawModes; @@ -70,20 +58,18 @@ void ParticleMaterialShader::Bind(BindParameters& params) // Prepare auto context = params.GPUContext; auto& view = params.RenderContext.View; - auto cache = params.RenderContext.List; auto& drawCall = *params.FirstDrawCall; const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset; const auto cb0 = _shader->GetCB(0); const bool hasCb0 = cb0->GetSize() != 0; ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing - const auto cb1 = _shader->GetCB(1); - const bool hasCb1 = cb1 && cb1->GetSize() != 0; byte* cb = _cb0Data.Get(); auto materialData = reinterpret_cast(cb); cb += sizeof(ParticleMaterialShaderData); - int32 srv = 0; - + int32 srv = 2; + // Setup features + ForwardShadingFeature::Bind(params, cb, srv); // Setup parameters MaterialParameter::BindMeta bindMeta; @@ -95,25 +81,23 @@ void ParticleMaterialShader::Bind(BindParameters& params) bindMeta.CanSampleGBuffer = true; MaterialParams::Bind(params.ParamsLink, bindMeta); - // Setup particles data and attributes binding info + // Setup particles data + context->BindSR(0, drawCall.Particle.Particles->GPU.Buffer->View()); + context->BindSR(1, drawCall.Particle.Particles->GPU.SortedIndices ? drawCall.Particle.Particles->GPU.SortedIndices->View() : nullptr); + + // Setup particles attributes binding info + if (hasCb0) { - context->BindSR(0, drawCall.Particle.Particles->GPU.Buffer->View()); - if (drawCall.Particle.Particles->GPU.SortedIndices) - context->BindSR(1, drawCall.Particle.Particles->GPU.SortedIndices->View()); - - if (hasCb0) + const auto& p = *params.ParamsLink->This; + for (int32 i = 0; i < p.Count(); i++) { - const auto& p = *params.ParamsLink->This; - for (int32 i = 0; i < p.Count(); i++) + const auto& param = p.At(i); + if (param.GetParameterType() == MaterialParameterType::Integer && param.GetName().StartsWith(TEXT("Particle."))) { - const auto& param = p.At(i); - if (param.GetParameterType() == MaterialParameterType::Integer && param.GetName().StartsWith(TEXT("Particle."))) - { - auto name = StringView(param.GetName().Get() + 9); + auto name = StringView(param.GetName().Get() + 9); - const int32 offset = drawCall.Particle.Particles->Layout->FindAttributeOffset(name); - *((int32*)(bindMeta.Constants + param.GetBindOffset())) = offset; - } + const int32 offset = drawCall.Particle.Particles->Layout->FindAttributeOffset(name); + *((int32*)(bindMeta.Constants + param.GetBindOffset())) = offset; } } } @@ -147,8 +131,6 @@ void ParticleMaterialShader::Bind(BindParameters& params) if (hasCb0) { - const auto materialData = reinterpret_cast(_cb0Data.Get()); - materialData->RibbonWidthOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonWidth, ParticleAttribute::ValueTypes::Float, -1); materialData->RibbonTwistOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonTwist, ParticleAttribute::ValueTypes::Float, -1); materialData->RibbonFacingVectorOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonFacingVector, ParticleAttribute::ValueTypes::Vector3, -1); @@ -173,8 +155,6 @@ void ParticleMaterialShader::Bind(BindParameters& params) // Setup material constants data if (hasCb0) { - const auto materialData = reinterpret_cast(_cb0Data.Get()); - static StringView ParticlePosition(TEXT("Position")); static StringView ParticleSpriteSize(TEXT("SpriteSize")); static StringView ParticleSpriteFacingMode(TEXT("SpriteFacingMode")); @@ -207,124 +187,12 @@ void ParticleMaterialShader::Bind(BindParameters& params) Matrix::Invert(drawCall.World, materialData->WorldMatrixInverseTransposed); } - // Setup lighting constants data - if (hasCb1) - { - auto& lightingData = *reinterpret_cast(_cb1Data.Get()); - const int32 envProbeShaderRegisterIndex = 2; - const int32 skyLightShaderRegisterIndex = 3; - const int32 dirLightShaderRegisterIndex = 4; - - // Set fog input - if (cache->Fog) - { - cache->Fog->GetExponentialHeightFogData(view, lightingData.ExponentialHeightFog); - } - else - { - lightingData.ExponentialHeightFog.FogMinOpacity = 1.0f; - lightingData.ExponentialHeightFog.ApplyDirectionalInscattering = 0.0f; - } - - // Set directional light input - if (cache->DirectionalLights.HasItems()) - { - const auto& dirLight = cache->DirectionalLights.First(); - const auto shadowPass = ShadowsPass::Instance(); - const bool useShadow = shadowPass->LastDirLightIndex == 0; - if (useShadow) - { - lightingData.DirectionalLightShadow = shadowPass->LastDirLight; - context->BindSR(dirLightShaderRegisterIndex, shadowPass->LastDirLightShadowMap); - } - else - { - context->UnBindSR(dirLightShaderRegisterIndex); - } - dirLight.SetupLightData(&lightingData.DirectionalLight, view, useShadow); - } - else - { - lightingData.DirectionalLight.Color = Vector3::Zero; - lightingData.DirectionalLight.CastShadows = 0.0f; - context->UnBindSR(dirLightShaderRegisterIndex); - } - - // Set sky light - if (cache->SkyLights.HasItems()) - { - auto& skyLight = cache->SkyLights.Last(); - skyLight.SetupLightData(&lightingData.SkyLight, view, false); - const auto texture = skyLight.Image ? skyLight.Image->GetTexture() : nullptr; - context->BindSR(skyLightShaderRegisterIndex, texture); - } - else - { - Platform::MemoryClear(&lightingData.SkyLight, sizeof(lightingData.SkyLight)); - context->UnBindSR(skyLightShaderRegisterIndex); - } - - // Set reflection probe data - EnvironmentProbe* probe = nullptr; - // TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it - for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++) - { - const auto p = cache->EnvironmentProbes[i]; - if (p->GetSphere().Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint) - { - probe = p; - break; - } - } - if (probe && probe->GetProbe()) - { - probe->SetupProbeData(&lightingData.EnvironmentProbe); - const auto texture = probe->GetProbe()->GetTexture(); - context->BindSR(envProbeShaderRegisterIndex, texture); - } - else - { - lightingData.EnvironmentProbe.Data1 = Vector4::Zero; - context->UnBindSR(envProbeShaderRegisterIndex); - } - - // Set local lights - lightingData.LocalLightsCount = 0; - for (int32 i = 0; i < cache->PointLights.Count(); i++) - { - const auto& light = cache->PointLights[i]; - if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint) - { - light.SetupLightData(&lightingData.LocalLights[lightingData.LocalLightsCount], view, false); - lightingData.LocalLightsCount++; - if (lightingData.LocalLightsCount == MAX_LOCAL_LIGHTS) - break; - } - } - for (int32 i = 0; i < cache->SpotLights.Count(); i++) - { - const auto& light = cache->SpotLights[i]; - if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint) - { - light.SetupLightData(&lightingData.LocalLights[lightingData.LocalLightsCount], view, false); - lightingData.LocalLightsCount++; - if (lightingData.LocalLightsCount == MAX_LOCAL_LIGHTS) - break; - } - } - } - // Bind constants if (hasCb0) { context->UpdateCB(cb0, _cb0Data.Get()); context->BindCB(0, cb0); } - if (hasCb1) - { - context->UpdateCB(cb1, _cb1Data.Get()); - context->BindCB(1, cb1); - } // Bind pipeline context->SetState(state); diff --git a/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp b/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp index 2d9840103..8be86a4ac 100644 --- a/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp @@ -26,7 +26,6 @@ void PostFxMaterialShader::Bind(BindParameters& params) // Prepare auto context = params.GPUContext; auto& view = params.RenderContext.View; - auto& drawCall = *params.FirstDrawCall; const auto cb0 = _shader->GetCB(0); const bool hasCb0 = cb0->GetSize() != 0; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp index 45076f39f..9c9af3145 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp @@ -1,16 +1,16 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. -#include "GPUShaderDX11.h" #if GRAPHICS_API_DIRECTX11 #include "GPUContextDX11.h" -#include "Engine/Core/Math/Viewport.h" -#include "Engine/Core/Math/Rectangle.h" +#include "GPUShaderDX11.h" #include "GPUShaderProgramDX11.h" #include "GPUPipelineStateDX11.h" #include "GPUTextureDX11.h" #include "GPUBufferDX11.h" #include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h" +#include "Engine/Core/Math/Viewport.h" +#include "Engine/Core/Math/Rectangle.h" #include "Engine/Profiler/RenderStats.h" #define DX11_CLEAR_SR_ON_STAGE_DISABLE 0 diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp index 8550febad..ea342bd53 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp @@ -59,7 +59,7 @@ namespace bool FeatureData::Init() { // Load template file - const String path = Globals::EngineContentFolder / TEXT("Editor/MaterialTemplates/Features/") + Data.Template; + const String path = Globals::EngineContentFolder / TEXT("Editor/MaterialTemplates/") + Data.Template; String contents; if (File::ReadAllText(path, contents)) { @@ -188,17 +188,20 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo ADD_FEATURE(LightmapFeature); if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0) ADD_FEATURE(DistortionFeature); + if (materialInfo.BlendMode != MaterialBlendMode::Opaque) + ADD_FEATURE(ForwardShadingFeature); break; case MaterialDomain::Terrain: if (materialInfo.TessellationMode != TessellationMethod::None) ADD_FEATURE(TessellationFeature); ADD_FEATURE(LightmapFeature); break; - default: case MaterialDomain::Particle: if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0) ADD_FEATURE(DistortionFeature); + ADD_FEATURE(ForwardShadingFeature); break; + default: break; } #undef ADD_FEATURE @@ -390,18 +393,14 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo int32 srv = 0; switch (baseLayer->Domain) { - case MaterialDomain::Surface: - if (materialInfo.BlendMode != MaterialBlendMode::Opaque) - srv = 3; // Forward shading resources - break; case MaterialDomain::Decal: - srv = 1; + srv = 1; // Depth buffer break; case MaterialDomain::Terrain: srv = 3; // Heightmap + 2 splatmaps break; case MaterialDomain::Particle: - srv = 5; + srv = 2; // Particles data + Sorted indices/Ribbon segments break; } for (auto f : features)