diff --git a/Content/Shaders/GI/GlobalSurfaceAtlas.flax b/Content/Shaders/GI/GlobalSurfaceAtlas.flax index 3e22ac620..a5b50780a 100644 --- a/Content/Shaders/GI/GlobalSurfaceAtlas.flax +++ b/Content/Shaders/GI/GlobalSurfaceAtlas.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a32623b6d0fd375aa69671e25dd270b03d0c50a635b967750b4da046feab3a1 -size 14125 +oid sha256:e5da6c9b625db26134d72eb64524807f6e0ca2d8472f2c0ced1ed689f82834c7 +size 14117 diff --git a/Content/Shaders/Lights.flax b/Content/Shaders/Lights.flax index a2887c15d..adabf7a2f 100644 --- a/Content/Shaders/Lights.flax +++ b/Content/Shaders/Lights.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47c909b8247aaedd0a9a0a87ec2422a989a1d96f606609597eb5773f5ff36202 -size 5291 +oid sha256:34010147c3bc35b8ba299f6bafc0002f21dc8e5d8d65d7c7b6982a19269847a3 +size 4130 diff --git a/Content/Shaders/Shadows.flax b/Content/Shaders/Shadows.flax index 2be0477be..d29340328 100644 --- a/Content/Shaders/Shadows.flax +++ b/Content/Shaders/Shadows.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d5c8b4b9cd9bd4a8b2ad3026fe62177781483a0a659d6329a6a1a3c958edb9b -size 7408 +oid sha256:b22f97a46708fead33de675a0186d34da6f845ca1ac61bab63c1c8f12dbd44b4 +size 7029 diff --git a/Source/Engine/Graphics/GPUPipelineStatePermutations.h b/Source/Engine/Graphics/GPUPipelineStatePermutations.h index 030586313..efcf8f1d8 100644 --- a/Source/Engine/Graphics/GPUPipelineStatePermutations.h +++ b/Source/Engine/Graphics/GPUPipelineStatePermutations.h @@ -10,6 +10,7 @@ template class GPUPipelineStatePermutations { public: + enum { StaticSize = Size }; GPUPipelineState* States[Size]; public: @@ -97,13 +98,13 @@ public: } public: - bool Create(GPUPipelineState::Description& desc, GPUShader* shader, const StringAnsiView& psName) + bool Create(GPUPipelineState::Description& desc, GPUShader* shader, const StringAnsiView& psName, int32 permutationOffset = 0) { for (int i = 0; i < Size; i++) { ASSERT(Base::States[i]); - desc.PS = shader->GetPS(psName, i); + desc.PS = shader->GetPS(psName, i + permutationOffset); if (Base::States[i]->Init(desc)) return true; } diff --git a/Source/Engine/Renderer/LightPass.cpp b/Source/Engine/Renderer/LightPass.cpp index ea0ab02b0..51461610e 100644 --- a/Source/Engine/Renderer/LightPass.cpp +++ b/Source/Engine/Renderer/LightPass.cpp @@ -31,10 +31,8 @@ bool LightPass::Init() { // Create pipeline states _psLightDir.CreatePipelineStates(); - _psLightPoint.CreatePipelineStates(); - _psLightPointInside.CreatePipelineStates(); - _psLightSpot.CreatePipelineStates(); - _psLightSpotInside.CreatePipelineStates(); + _psLightLocal.CreatePipelineStates(); + _psLightLocalInside.CreatePipelineStates(); _psLightSky = GPUDevice::Instance->CreatePipelineState(); _psLightSkyInside = GPUDevice::Instance->CreatePipelineState(); _depthBounds = GPUDevice::Instance->Limits.HasDepthBounds && GPUDevice::Instance->Limits.HasReadOnlyDepth; @@ -81,7 +79,7 @@ bool LightPass::setupResources() if (_psLightDir.Create(psDesc, shader, "PS_Directional")) return true; } - if (!_psLightPoint.IsValid()) + if (!_psLightLocal.IsValid()) { psDesc = GPUPipelineState::Description::DefaultNoDepth; psDesc.BlendMode = BlendingMode::Add; @@ -90,27 +88,11 @@ bool LightPass::setupResources() psDesc.DepthEnable = true; psDesc.DepthBoundsEnable = _depthBounds; psDesc.CullMode = CullMode::Normal; - if (_psLightPoint.Create(psDesc, shader, "PS_Point")) + if (_psLightLocal.Create(psDesc, shader, "PS_LocalLight")) return true; psDesc.DepthFunc = ComparisonFunc::Greater; psDesc.CullMode = CullMode::Inverted; - if (_psLightPointInside.Create(psDesc, shader, "PS_Point")) - return true; - } - if (!_psLightSpot.IsValid()) - { - psDesc = GPUPipelineState::Description::DefaultNoDepth; - psDesc.BlendMode = BlendingMode::Add; - psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::RGB; - psDesc.VS = shader->GetVS("VS_Model"); - psDesc.DepthEnable = true; - psDesc.DepthBoundsEnable = _depthBounds; - psDesc.CullMode = CullMode::Normal; - if (_psLightSpot.Create(psDesc, shader, "PS_Spot")) - return true; - psDesc.DepthFunc = ComparisonFunc::Greater; - psDesc.CullMode = CullMode::Inverted; - if (_psLightSpotInside.Create(psDesc, shader, "PS_Spot")) + if (_psLightLocalInside.Create(psDesc, shader, "PS_LocalLight")) return true; } if (!_psLightSky->IsValid()) @@ -141,10 +123,8 @@ void LightPass::Dispose() // Cleanup _psLightDir.Delete(); - _psLightPoint.Delete(); - _psLightPointInside.Delete(); - _psLightSpot.Delete(); - _psLightSpotInside.Delete(); + _psLightLocal.Delete(); + _psLightLocalInside.Delete(); SAFE_DELETE_GPU_RESOURCE(_psLightSky); SAFE_DELETE_GPU_RESOURCE(_psLightSkyInside); SAFE_DELETE_GPU_RESOURCE(_psClearDiffuse); @@ -301,7 +281,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV context->BindCB(0, cb0); context->BindCB(1, cb1); int32 permutationIndex = (disableSpecular ? 1 : 0) + (useIES ? 2 : 0); - context->SetState((isViewInside ? _psLightPointInside : _psLightPoint).Get(permutationIndex)); + context->SetState((isViewInside ? _psLightLocalInside : _psLightLocal).Get(permutationIndex)); sphereMesh.Render(context); } @@ -349,7 +329,7 @@ void LightPass::RenderLights(RenderContextBatch& renderContextBatch, GPUTextureV context->BindCB(0, cb0); context->BindCB(1, cb1); int32 permutationIndex = (disableSpecular ? 1 : 0) + (useIES ? 2 : 0); - context->SetState((isViewInside ? _psLightSpotInside : _psLightSpot).Get(permutationIndex)); + context->SetState((isViewInside ? _psLightLocalInside : _psLightLocal).Get(permutationIndex)); sphereMesh.Render(context); } diff --git a/Source/Engine/Renderer/LightPass.h b/Source/Engine/Renderer/LightPass.h index f673d536b..328b718aa 100644 --- a/Source/Engine/Renderer/LightPass.h +++ b/Source/Engine/Renderer/LightPass.h @@ -16,10 +16,8 @@ class LightPass : public RendererPass private: AssetReference _shader; GPUPipelineStatePermutationsPs<2> _psLightDir; - GPUPipelineStatePermutationsPs<4> _psLightPoint; - GPUPipelineStatePermutationsPs<4> _psLightPointInside; - GPUPipelineStatePermutationsPs<4> _psLightSpot; - GPUPipelineStatePermutationsPs<4> _psLightSpotInside; + GPUPipelineStatePermutationsPs<4> _psLightLocal; + GPUPipelineStatePermutationsPs<4> _psLightLocalInside; GPUPipelineState* _psLightSky = nullptr; GPUPipelineState* _psLightSkyInside = nullptr; GPUPipelineState* _psClearDiffuse = nullptr; @@ -45,10 +43,8 @@ private: void OnShaderReloading(Asset* obj) { _psLightDir.Release(); - _psLightPoint.Release(); - _psLightPointInside.Release(); - _psLightSpot.Release(); - _psLightSpotInside.Release(); + _psLightLocal.Release(); + _psLightLocalInside.Release(); _psLightSky->ReleaseGPU(); _psLightSkyInside->ReleaseGPU(); invalidateResources(); diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index bdb151194..3361eed90 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -525,6 +525,7 @@ bool ShadowsPass::setupResources() if (_psShadowDir.Create(psDesc, shader, "PS_DirLight")) return true; } + StringAnsiView psLocalLight("PS_LocalLight"); if (!_psShadowPoint.IsValid()) { psDesc = GPUPipelineState::Description::DefaultNoDepth; @@ -533,11 +534,11 @@ bool ShadowsPass::setupResources() psDesc.DepthEnable = true; psDesc.DepthBoundsEnable = _depthBounds; psDesc.CullMode = CullMode::Normal; - if (_psShadowPoint.Create(psDesc, shader, "PS_PointLight")) + if (_psShadowPoint.Create(psDesc, shader, psLocalLight)) return true; psDesc.DepthFunc = ComparisonFunc::Greater; psDesc.CullMode = CullMode::Inverted; - if (_psShadowPointInside.Create(psDesc, shader, "PS_PointLight")) + if (_psShadowPointInside.Create(psDesc, shader, psLocalLight)) return true; } if (!_psShadowSpot.IsValid()) @@ -548,11 +549,11 @@ bool ShadowsPass::setupResources() psDesc.DepthEnable = true; psDesc.DepthBoundsEnable = _depthBounds; psDesc.CullMode = CullMode::Normal; - if (_psShadowSpot.Create(psDesc, shader, "PS_SpotLight")) + if (_psShadowSpot.Create(psDesc, shader, psLocalLight, 8)) return true; psDesc.DepthFunc = ComparisonFunc::Greater; psDesc.CullMode = CullMode::Inverted; - if (_psShadowSpotInside.Create(psDesc, shader, "PS_SpotLight")) + if (_psShadowSpotInside.Create(psDesc, shader, psLocalLight, 8)) return true; } if (_psDepthClear == nullptr) diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.shader b/Source/Shaders/GI/GlobalSurfaceAtlas.shader index bea998b63..76af07634 100644 --- a/Source/Shaders/GI/GlobalSurfaceAtlas.shader +++ b/Source/Shaders/GI/GlobalSurfaceAtlas.shader @@ -209,7 +209,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target // Calculate lighting #if RADIAL_LIGHT - bool isSpotLight = Light.SpotAngles.x > -2.0f; + bool isSpotLight = IsSpotLight(Light); #else bool isSpotLight = false; #endif diff --git a/Source/Shaders/LightingCommon.hlsl b/Source/Shaders/LightingCommon.hlsl index caa7600a1..04a32a5b9 100644 --- a/Source/Shaders/LightingCommon.hlsl +++ b/Source/Shaders/LightingCommon.hlsl @@ -58,6 +58,11 @@ struct LightSample float3 Transmission; }; +bool IsSpotLight(LightData lightData) +{ + return lightData.SpotAngles.x > -2.0f; +} + // Calculates radial light (point or spot) attenuation factors (distance, spot and radius mask) void GetRadialLightAttenuation( LightData lightData, diff --git a/Source/Shaders/Lights.shader b/Source/Shaders/Lights.shader index 0b4b77bea..e10e3c574 100644 --- a/Source/Shaders/Lights.shader +++ b/Source/Shaders/Lights.shader @@ -70,13 +70,13 @@ void PS_Directional(Quad_VS2PS input, out float4 output : SV_Target0) output = GetLighting(gBufferData.ViewPos, Light, gBuffer, shadowMask, false, false); } -// Pixel shader for point light rendering +// Pixel shader for point/spot light rendering META_PS(true, FEATURE_LEVEL_ES2) META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=0) META_PERMUTATION_2(LIGHTING_NO_SPECULAR=1, USE_IES_PROFILE=0) META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=1) META_PERMUTATION_2(LIGHTING_NO_SPECULAR=1, USE_IES_PROFILE=1) -void PS_Point(Model_VS2PS input, out float4 output : SV_Target0) +void PS_LocalLight(Model_VS2PS input, out float4 output : SV_Target0) { output = 0; @@ -103,48 +103,7 @@ void PS_Point(Model_VS2PS input, out float4 output : SV_Target0) } // Calculate lighting - output = GetLighting(gBufferData.ViewPos, Light, gBuffer, shadowMask, true, false); - - // Apply IES texture -#if USE_IES_PROFILE - output *= ComputeLightProfileMultiplier(IESTexture, gBuffer.WorldPos, Light.Position, -Light.Direction); -#endif -} - -// Pixel shader for spot light rendering -META_PS(true, FEATURE_LEVEL_ES2) -META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=0) -META_PERMUTATION_2(LIGHTING_NO_SPECULAR=1, USE_IES_PROFILE=0) -META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=1) -META_PERMUTATION_2(LIGHTING_NO_SPECULAR=1, USE_IES_PROFILE=1) -void PS_Spot(Model_VS2PS input, out float4 output : SV_Target0) -{ - output = 0; - - // Obtain UVs corresponding to the current pixel - float2 uv = (input.ScreenPos.xy / input.ScreenPos.w) * float2(0.5, -0.5) + float2(0.5, 0.5); - - // Sample GBuffer - GBufferData gBufferData = GetGBufferData(); - GBufferSample gBuffer = SampleGBuffer(gBufferData, uv); - - // Check if cannot shadow pixel - BRANCH - if (gBuffer.ShadingModel == SHADING_MODEL_UNLIT) - { - discard; - return; - } - - // Sample shadow mask - float4 shadowMask = 1; - if (Light.ShadowsBufferAddress != 0) - { - shadowMask = SAMPLE_RT(Shadow, uv); - } - - // Calculate lighting - output = GetLighting(gBufferData.ViewPos, Light, gBuffer, shadowMask, true, true); + output = GetLighting(gBufferData.ViewPos, Light, gBuffer, shadowMask, true, IsSpotLight(Light)); // Apply IES texture #if USE_IES_PROFILE diff --git a/Source/Shaders/Shadows.shader b/Source/Shaders/Shadows.shader index ae3c22694..275048333 100644 --- a/Source/Shaders/Shadows.shader +++ b/Source/Shaders/Shadows.shader @@ -70,36 +70,6 @@ Model_VS2PS VS_Model(ModelInput_PosOnly input) return output; } -// Pixel shader for point light shadow rendering -META_PS(true, FEATURE_LEVEL_ES2) -META_PERMUTATION_2(SHADOWS_QUALITY=0,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=1,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=2,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=3,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=0,CONTACT_SHADOWS=1) -META_PERMUTATION_2(SHADOWS_QUALITY=1,CONTACT_SHADOWS=1) -META_PERMUTATION_2(SHADOWS_QUALITY=2,CONTACT_SHADOWS=1) -META_PERMUTATION_2(SHADOWS_QUALITY=3,CONTACT_SHADOWS=1) -float4 PS_PointLight(Model_VS2PS input) : SV_Target0 -{ - // Obtain texture coordinates corresponding to the current pixel - float2 uv = (input.ScreenPos.xy / input.ScreenPos.w) * float2(0.5, -0.5) + float2(0.5, 0.5); - - // Sample GBuffer - GBufferData gBufferData = GetGBufferData(); - GBufferSample gBuffer = SampleGBuffer(gBufferData, uv); - - // Sample shadow - ShadowSample shadow = SamplePointLightShadow(Light, ShadowsBuffer, ShadowMap, gBuffer); - -#if CONTACT_SHADOWS && SHADOWS_QUALITY > 0 - // Calculate screen-space contact shadow - shadow.SurfaceShadow *= RayCastScreenSpaceShadow(gBufferData, gBuffer, gBuffer.WorldPos, normalize(Light.Position - gBuffer.WorldPos), ContactShadowsLength); -#endif - - return GetShadowMask(shadow); -} - // Pixel shader for directional light shadow rendering META_PS(true, FEATURE_LEVEL_ES2) META_PERMUTATION_3(SHADOWS_QUALITY=0,CONTACT_SHADOWS=0,SHADOWS_CSM_BLENDING=0) @@ -135,17 +105,25 @@ float4 PS_DirLight(Quad_VS2PS input) : SV_Target0 return GetShadowMask(shadow); } -// Pixel shader for spot light shadow rendering +// Pixel shader for point/spot light shadow rendering META_PS(true, FEATURE_LEVEL_ES2) -META_PERMUTATION_2(SHADOWS_QUALITY=0,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=1,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=2,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=3,CONTACT_SHADOWS=0) -META_PERMUTATION_2(SHADOWS_QUALITY=0,CONTACT_SHADOWS=1) -META_PERMUTATION_2(SHADOWS_QUALITY=1,CONTACT_SHADOWS=1) -META_PERMUTATION_2(SHADOWS_QUALITY=2,CONTACT_SHADOWS=1) -META_PERMUTATION_2(SHADOWS_QUALITY=3,CONTACT_SHADOWS=1) -float4 PS_SpotLight(Model_VS2PS input) : SV_Target0 +META_PERMUTATION_3(SHADOWS_QUALITY=0,CONTACT_SHADOWS=0,LIGHT_TYPE=0) // Point light +META_PERMUTATION_3(SHADOWS_QUALITY=1,CONTACT_SHADOWS=0,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=2,CONTACT_SHADOWS=0,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=3,CONTACT_SHADOWS=0,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=0,CONTACT_SHADOWS=1,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=1,CONTACT_SHADOWS=1,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=2,CONTACT_SHADOWS=1,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=3,CONTACT_SHADOWS=1,LIGHT_TYPE=0) +META_PERMUTATION_3(SHADOWS_QUALITY=0,CONTACT_SHADOWS=0,LIGHT_TYPE=1) // Spot light +META_PERMUTATION_3(SHADOWS_QUALITY=1,CONTACT_SHADOWS=0,LIGHT_TYPE=1) +META_PERMUTATION_3(SHADOWS_QUALITY=2,CONTACT_SHADOWS=0,LIGHT_TYPE=1) +META_PERMUTATION_3(SHADOWS_QUALITY=3,CONTACT_SHADOWS=0,LIGHT_TYPE=1) +META_PERMUTATION_3(SHADOWS_QUALITY=0,CONTACT_SHADOWS=1,LIGHT_TYPE=1) +META_PERMUTATION_3(SHADOWS_QUALITY=1,CONTACT_SHADOWS=1,LIGHT_TYPE=1) +META_PERMUTATION_3(SHADOWS_QUALITY=2,CONTACT_SHADOWS=1,LIGHT_TYPE=1) +META_PERMUTATION_3(SHADOWS_QUALITY=3,CONTACT_SHADOWS=1,LIGHT_TYPE=1) +float4 PS_LocalLight(Model_VS2PS input) : SV_Target0 { // Obtain texture coordinates corresponding to the current pixel float2 uv = (input.ScreenPos.xy / input.ScreenPos.w) * float2(0.5, -0.5) + float2(0.5, 0.5); @@ -155,7 +133,13 @@ float4 PS_SpotLight(Model_VS2PS input) : SV_Target0 GBufferSample gBuffer = SampleGBuffer(gBufferData, uv); // Sample shadow +#if LIGHT_TYPE == 0 + ShadowSample shadow = SamplePointLightShadow(Light, ShadowsBuffer, ShadowMap, gBuffer); +#elif LIGHT_TYPE == 1 ShadowSample shadow = SampleSpotLightShadow(Light, ShadowsBuffer, ShadowMap, gBuffer); +#else + ShadowSample shadow = (ShadowSample)0; +#endif #if CONTACT_SHADOWS && SHADOWS_QUALITY > 0 // Calculate screen-space contact shadow diff --git a/Source/Shaders/VolumetricFog.shader b/Source/Shaders/VolumetricFog.shader index c9facbdd7..7d2883e9d 100644 --- a/Source/Shaders/VolumetricFog.shader +++ b/Source/Shaders/VolumetricFog.shader @@ -175,7 +175,7 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0 uint samplesCount = historyAlpha < 0.01f ? MissedHistorySamplesCount : 1; float NoL = 0; - bool isSpotLight = LocalLight.SpotAngles.x > -2.0f; + bool isSpotLight = IsSpotLight(LocalLight); float4 scattering = 0; for (uint sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++) {