diff --git a/Content/Editor/MaterialTemplates/Features/Distortion.hlsl b/Content/Editor/MaterialTemplates/Features/Distortion.hlsl new file mode 100644 index 000000000..c74014cca --- /dev/null +++ b/Content/Editor/MaterialTemplates/Features/Distortion.hlsl @@ -0,0 +1,50 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +@0// Distortion: Defines +@1// Distortion: Includes +@2// Distortion: Constants +@3// Distortion: Resources +@4// Distortion: Utilities +@5// Distortion: Shaders +#if USE_DISTORTION + +// Pixel Shader function for Distortion Pass +META_PS(USE_DISTORTION, FEATURE_LEVEL_ES2) +float4 PS_Distortion(PixelInput input) : SV_Target0 +{ +#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 + + float3 viewNormal = normalize(TransformWorldVectorToView(materialInput, material.WorldNormal)); + float airIOR = 1.0f; +#if USE_PIXEL_NORMAL_OFFSET_REFRACTION + float3 viewVertexNormal = TransformWorldVectorToView(materialInput, TransformTangentVectorToWorld(materialInput, float3(0, 0, 1))); + float2 distortion = (viewVertexNormal.xy - viewNormal.xy) * (material.Refraction - airIOR); +#else + float2 distortion = viewNormal.xy * (material.Refraction - airIOR); +#endif + + // Clip if the distortion distance (squared) is too small to be noticed + clip(dot(distortion, distortion) - 0.00001); + + // Scale up for better precision in low/subtle refractions at the expense of artefacts at higher refraction + distortion *= 4.0f; + + // Use separate storage for positive and negative offsets + float2 addOffset = max(distortion, 0); + float2 subOffset = abs(min(distortion, 0)); + return float4(addOffset.x, addOffset.y, subOffset.x, subOffset.y); +} + +#endif diff --git a/Content/Editor/MaterialTemplates/Particle.shader b/Content/Editor/MaterialTemplates/Particle.shader index f3121b6b0..72d633028 100644 --- a/Content/Editor/MaterialTemplates/Particle.shader +++ b/Content/Editor/MaterialTemplates/Particle.shader @@ -802,44 +802,6 @@ float4 PS_Forward(PixelInput input) : SV_Target0 return output; } -#if USE_DISTORTION - -// Pixel Shader function for Distortion Pass -META_PS(USE_DISTORTION, FEATURE_LEVEL_ES2) -float4 PS_Distortion(PixelInput input) : SV_Target0 -{ - // Get material parameters - MaterialInput materialInput = GetMaterialInput(input); - Material material = GetMaterialPS(materialInput); - - // Masking -#if MATERIAL_MASKED - clip(material.Mask - MATERIAL_MASK_THRESHOLD); -#endif - - float3 viewNormal = normalize(TransformWorldVectorToView(materialInput, material.WorldNormal)); - float airIOR = 1.0f; -#if USE_PIXEL_NORMAL_OFFSET_REFRACTION - float3 viewVertexNormal = TransformWorldVectorToView(materialInput, TransformTangentVectorToWorld(materialInput, float3(0, 0, 1))); - float2 distortion = (viewVertexNormal.xy - viewNormal.xy) * (material.Refraction - airIOR); -#else - float2 distortion = viewNormal.xy * (material.Refraction - airIOR); -#endif - - // Clip if the distortion distance (squared) is too small to be noticed - clip(dot(distortion, distortion) - 0.00001); - - // Scale up for better precision in low/subtle refractions at the expense of artefacts at higher refraction - distortion *= 4.0f; - - // Use separate storage for positive and negative offsets - float2 addOffset = max(distortion, 0); - float2 subOffset = abs(min(distortion, 0)); - return float4(addOffset.x, addOffset.y, subOffset.x, subOffset.y); -} - -#endif - // Pixel Shader function for Depth Pass META_PS(true, FEATURE_LEVEL_ES2) void PS_Depth(PixelInput input diff --git a/Content/Editor/MaterialTemplates/SurfaceForward.shader b/Content/Editor/MaterialTemplates/SurfaceForward.shader index 0e9c6db5f..cece1b231 100644 --- a/Content/Editor/MaterialTemplates/SurfaceForward.shader +++ b/Content/Editor/MaterialTemplates/SurfaceForward.shader @@ -562,12 +562,6 @@ void ClipLODTransition(PixelInput input) } } -#else - -void ClipLODTransition(PixelInput input) -{ -} - #endif // Pixel Shader function for Forward Pass @@ -576,9 +570,11 @@ 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); @@ -665,47 +661,6 @@ float4 PS_Forward(PixelInput input) : SV_Target0 return output; } -#if USE_DISTORTION - -// Pixel Shader function for Distortion Pass -META_PS(USE_DISTORTION, FEATURE_LEVEL_ES2) -float4 PS_Distortion(PixelInput input) : SV_Target0 -{ - // LOD masking - ClipLODTransition(input); - - // Get material parameters - MaterialInput materialInput = GetMaterialInput(input); - Material material = GetMaterialPS(materialInput); - - // Masking -#if MATERIAL_MASKED - clip(material.Mask - MATERIAL_MASK_THRESHOLD); -#endif - - float3 viewNormal = normalize(TransformWorldVectorToView(materialInput, material.WorldNormal)); - float airIOR = 1.0f; -#if USE_PIXEL_NORMAL_OFFSET_REFRACTION - float3 viewVertexNormal = TransformWorldVectorToView(materialInput, TransformTangentVectorToWorld(materialInput, float3(0, 0, 1))); - float2 distortion = (viewVertexNormal.xy - viewNormal.xy) * (material.Refraction - airIOR); -#else - float2 distortion = viewNormal.xy * (material.Refraction - airIOR); -#endif - - // Clip if the distortion distance (squared) is too small to be noticed - clip(dot(distortion, distortion) - 0.00001); - - // Scale up for better precision in low/subtle refractions at the expense of artefacts at higher refraction - distortion *= 4.0f; - - // Use separate storage for positive and negative offsets - float2 addOffset = max(distortion, 0); - float2 subOffset = abs(min(distortion, 0)); - return float4(addOffset.x, addOffset.y, subOffset.x, subOffset.y); -} - -#endif - // Pixel Shader function for Depth Pass META_PS(true, FEATURE_LEVEL_ES2) void PS_Depth(PixelInput input @@ -714,8 +669,10 @@ void PS_Depth(PixelInput input #endif ) { +#if USE_DITHERED_LOD_TRANSITION // LOD masking ClipLODTransition(input); +#endif // Get material parameters MaterialInput materialInput = GetMaterialInput(input); diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp index 585f4f1fd..3bd71290d 100644 --- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp @@ -70,8 +70,6 @@ void DeferredMaterialShader::Bind(BindParameters& params) int32 srv = 0; // Setup features - if (_info.TessellationMode != TessellationMethod::None) - TessellationFeature::Bind(params, cb, srv); const bool useLightmap = _info.BlendMode == MaterialBlendMode::Opaque && LightmapFeature::Bind(params, cb, srv); // Setup parameters diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index 7dc68a85a..f410d477c 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -79,8 +79,6 @@ void ForwardMaterialShader::Bind(BindParameters& params) int32 srv = 0; // Setup features - if (_info.TessellationMode != TessellationMethod::None) - TessellationFeature::Bind(params, cb, srv); // Setup parameters MaterialParameter::BindMeta bindMeta; diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index 0355b7435..0043a8d6e 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -159,7 +159,7 @@ void TessellationFeature::Generate(GeneratorData& data) { data.Template = TEXT("Tessellation.hlsl"); data.ConstantsSize = 0; - data.ResourcesCount = SRVs; + data.ResourcesCount = 0; } void LightmapFeature::Generate(GeneratorData& data) @@ -169,4 +169,11 @@ void LightmapFeature::Generate(GeneratorData& data) data.ResourcesCount = SRVs; } +void DistortionFeature::Generate(GeneratorData& data) +{ + data.Template = TEXT("Distortion.hlsl"); + data.ConstantsSize = 0; + data.ResourcesCount = 0; +} + #endif diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h index 0a2349dfe..9d2c06307 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.h @@ -43,11 +43,6 @@ struct ForwardShadingFeature : MaterialShaderFeature // Material shader feature that adds geometry hardware tessellation (using Hull and Domain shaders). struct TessellationFeature : MaterialShaderFeature { - enum { SRVs = 0 }; - - static void Bind(MaterialShader::BindParameters& params, byte*& cb, int32& srv) - { - } #if USE_EDITOR static void Generate(GeneratorData& data); #endif @@ -68,3 +63,11 @@ struct LightmapFeature : MaterialShaderFeature static void Generate(GeneratorData& data); #endif }; + +// Material shader feature that adds distortion vectors rendering pass. +struct DistortionFeature : MaterialShaderFeature +{ +#if USE_EDITOR + static void Generate(GeneratorData& data); +#endif +}; diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp index 5cfad0126..bfab56daf 100644 --- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp @@ -72,16 +72,23 @@ void ParticleMaterialShader::Bind(BindParameters& params) 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->GetSize() != 0; - const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset; + const bool hasCb1 = cb1 && cb1->GetSize() != 0; + byte* cb = _cb0Data.Get(); + auto materialData = reinterpret_cast(cb); + cb += sizeof(ParticleMaterialShaderData); + int32 srv = 0; + + // Setup features // Setup parameters MaterialParameter::BindMeta bindMeta; bindMeta.Context = context; - bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(ParticleMaterialShaderData) : nullptr; + bindMeta.Constants = cb; bindMeta.Input = nullptr; bindMeta.Buffers = params.RenderContext.Buffers; bindMeta.CanSampleDepth = GPUDevice::Instance->Limits.HasReadOnlyDepth; diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp index 633448fb5..89a96d902 100644 --- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp @@ -63,8 +63,6 @@ void TerrainMaterialShader::Bind(BindParameters& params) int32 srv = 3; // Setup features - if (_info.TessellationMode != TessellationMethod::None) - TessellationFeature::Bind(params, cb, srv); const bool useLightmap = LightmapFeature::Bind(params, cb, srv); // Setup parameters diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp index b6b1b55e1..8550febad 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp @@ -186,6 +186,8 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo ADD_FEATURE(TessellationFeature); if (materialInfo.BlendMode == MaterialBlendMode::Opaque) ADD_FEATURE(LightmapFeature); + if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0) + ADD_FEATURE(DistortionFeature); break; case MaterialDomain::Terrain: if (materialInfo.TessellationMode != TessellationMethod::None) @@ -193,6 +195,10 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo ADD_FEATURE(LightmapFeature); break; default: + case MaterialDomain::Particle: + if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0) + ADD_FEATURE(DistortionFeature); + break; break; } #undef ADD_FEATURE