Refactor material shaders generator to use modular features as extensions
This commit is contained in:
50
Content/Editor/MaterialTemplates/Features/Distortion.hlsl
Normal file
50
Content/Editor/MaterialTemplates/Features/Distortion.hlsl
Normal file
@@ -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
|
||||||
@@ -802,44 +802,6 @@ float4 PS_Forward(PixelInput input) : SV_Target0
|
|||||||
return output;
|
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
|
// Pixel Shader function for Depth Pass
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
void PS_Depth(PixelInput input
|
void PS_Depth(PixelInput input
|
||||||
|
|||||||
@@ -562,12 +562,6 @@ void ClipLODTransition(PixelInput input)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void ClipLODTransition(PixelInput input)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pixel Shader function for Forward Pass
|
// Pixel Shader function for Forward Pass
|
||||||
@@ -576,9 +570,11 @@ float4 PS_Forward(PixelInput input) : SV_Target0
|
|||||||
{
|
{
|
||||||
float4 output = 0;
|
float4 output = 0;
|
||||||
|
|
||||||
|
#if USE_DITHERED_LOD_TRANSITION
|
||||||
// LOD masking
|
// LOD masking
|
||||||
ClipLODTransition(input);
|
ClipLODTransition(input);
|
||||||
// TODO: make model LOD transition smoother for transparent materials by using opacity to reduce aliasing
|
// TODO: make model LOD transition smoother for transparent materials by using opacity to reduce aliasing
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get material parameters
|
// Get material parameters
|
||||||
MaterialInput materialInput = GetMaterialInput(input);
|
MaterialInput materialInput = GetMaterialInput(input);
|
||||||
@@ -665,47 +661,6 @@ float4 PS_Forward(PixelInput input) : SV_Target0
|
|||||||
return output;
|
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
|
// Pixel Shader function for Depth Pass
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
void PS_Depth(PixelInput input
|
void PS_Depth(PixelInput input
|
||||||
@@ -714,8 +669,10 @@ void PS_Depth(PixelInput input
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if USE_DITHERED_LOD_TRANSITION
|
||||||
// LOD masking
|
// LOD masking
|
||||||
ClipLODTransition(input);
|
ClipLODTransition(input);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get material parameters
|
// Get material parameters
|
||||||
MaterialInput materialInput = GetMaterialInput(input);
|
MaterialInput materialInput = GetMaterialInput(input);
|
||||||
|
|||||||
@@ -70,8 +70,6 @@ void DeferredMaterialShader::Bind(BindParameters& params)
|
|||||||
int32 srv = 0;
|
int32 srv = 0;
|
||||||
|
|
||||||
// Setup features
|
// Setup features
|
||||||
if (_info.TessellationMode != TessellationMethod::None)
|
|
||||||
TessellationFeature::Bind(params, cb, srv);
|
|
||||||
const bool useLightmap = _info.BlendMode == MaterialBlendMode::Opaque && LightmapFeature::Bind(params, cb, srv);
|
const bool useLightmap = _info.BlendMode == MaterialBlendMode::Opaque && LightmapFeature::Bind(params, cb, srv);
|
||||||
|
|
||||||
// Setup parameters
|
// Setup parameters
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ void ForwardMaterialShader::Bind(BindParameters& params)
|
|||||||
int32 srv = 0;
|
int32 srv = 0;
|
||||||
|
|
||||||
// Setup features
|
// Setup features
|
||||||
if (_info.TessellationMode != TessellationMethod::None)
|
|
||||||
TessellationFeature::Bind(params, cb, srv);
|
|
||||||
|
|
||||||
// Setup parameters
|
// Setup parameters
|
||||||
MaterialParameter::BindMeta bindMeta;
|
MaterialParameter::BindMeta bindMeta;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ void TessellationFeature::Generate(GeneratorData& data)
|
|||||||
{
|
{
|
||||||
data.Template = TEXT("Tessellation.hlsl");
|
data.Template = TEXT("Tessellation.hlsl");
|
||||||
data.ConstantsSize = 0;
|
data.ConstantsSize = 0;
|
||||||
data.ResourcesCount = SRVs;
|
data.ResourcesCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightmapFeature::Generate(GeneratorData& data)
|
void LightmapFeature::Generate(GeneratorData& data)
|
||||||
@@ -169,4 +169,11 @@ void LightmapFeature::Generate(GeneratorData& data)
|
|||||||
data.ResourcesCount = SRVs;
|
data.ResourcesCount = SRVs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DistortionFeature::Generate(GeneratorData& data)
|
||||||
|
{
|
||||||
|
data.Template = TEXT("Distortion.hlsl");
|
||||||
|
data.ConstantsSize = 0;
|
||||||
|
data.ResourcesCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,11 +43,6 @@ struct ForwardShadingFeature : MaterialShaderFeature
|
|||||||
// Material shader feature that adds geometry hardware tessellation (using Hull and Domain shaders).
|
// Material shader feature that adds geometry hardware tessellation (using Hull and Domain shaders).
|
||||||
struct TessellationFeature : MaterialShaderFeature
|
struct TessellationFeature : MaterialShaderFeature
|
||||||
{
|
{
|
||||||
enum { SRVs = 0 };
|
|
||||||
|
|
||||||
static void Bind(MaterialShader::BindParameters& params, byte*& cb, int32& srv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
static void Generate(GeneratorData& data);
|
static void Generate(GeneratorData& data);
|
||||||
#endif
|
#endif
|
||||||
@@ -68,3 +63,11 @@ struct LightmapFeature : MaterialShaderFeature
|
|||||||
static void Generate(GeneratorData& data);
|
static void Generate(GeneratorData& data);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Material shader feature that adds distortion vectors rendering pass.
|
||||||
|
struct DistortionFeature : MaterialShaderFeature
|
||||||
|
{
|
||||||
|
#if USE_EDITOR
|
||||||
|
static void Generate(GeneratorData& data);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|||||||
@@ -72,16 +72,23 @@ void ParticleMaterialShader::Bind(BindParameters& params)
|
|||||||
auto& view = params.RenderContext.View;
|
auto& view = params.RenderContext.View;
|
||||||
auto cache = params.RenderContext.List;
|
auto cache = params.RenderContext.List;
|
||||||
auto& drawCall = *params.FirstDrawCall;
|
auto& drawCall = *params.FirstDrawCall;
|
||||||
|
const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset;
|
||||||
const auto cb0 = _shader->GetCB(0);
|
const auto cb0 = _shader->GetCB(0);
|
||||||
const bool hasCb0 = cb0->GetSize() != 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 auto cb1 = _shader->GetCB(1);
|
||||||
const bool hasCb1 = cb1->GetSize() != 0;
|
const bool hasCb1 = cb1 && cb1->GetSize() != 0;
|
||||||
const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset;
|
byte* cb = _cb0Data.Get();
|
||||||
|
auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(cb);
|
||||||
|
cb += sizeof(ParticleMaterialShaderData);
|
||||||
|
int32 srv = 0;
|
||||||
|
|
||||||
|
// Setup features
|
||||||
|
|
||||||
// Setup parameters
|
// Setup parameters
|
||||||
MaterialParameter::BindMeta bindMeta;
|
MaterialParameter::BindMeta bindMeta;
|
||||||
bindMeta.Context = context;
|
bindMeta.Context = context;
|
||||||
bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(ParticleMaterialShaderData) : nullptr;
|
bindMeta.Constants = cb;
|
||||||
bindMeta.Input = nullptr;
|
bindMeta.Input = nullptr;
|
||||||
bindMeta.Buffers = params.RenderContext.Buffers;
|
bindMeta.Buffers = params.RenderContext.Buffers;
|
||||||
bindMeta.CanSampleDepth = GPUDevice::Instance->Limits.HasReadOnlyDepth;
|
bindMeta.CanSampleDepth = GPUDevice::Instance->Limits.HasReadOnlyDepth;
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
|||||||
int32 srv = 3;
|
int32 srv = 3;
|
||||||
|
|
||||||
// Setup features
|
// Setup features
|
||||||
if (_info.TessellationMode != TessellationMethod::None)
|
|
||||||
TessellationFeature::Bind(params, cb, srv);
|
|
||||||
const bool useLightmap = LightmapFeature::Bind(params, cb, srv);
|
const bool useLightmap = LightmapFeature::Bind(params, cb, srv);
|
||||||
|
|
||||||
// Setup parameters
|
// Setup parameters
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
ADD_FEATURE(TessellationFeature);
|
ADD_FEATURE(TessellationFeature);
|
||||||
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
|
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
|
||||||
ADD_FEATURE(LightmapFeature);
|
ADD_FEATURE(LightmapFeature);
|
||||||
|
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0)
|
||||||
|
ADD_FEATURE(DistortionFeature);
|
||||||
break;
|
break;
|
||||||
case MaterialDomain::Terrain:
|
case MaterialDomain::Terrain:
|
||||||
if (materialInfo.TessellationMode != TessellationMethod::None)
|
if (materialInfo.TessellationMode != TessellationMethod::None)
|
||||||
@@ -193,6 +195,10 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
ADD_FEATURE(LightmapFeature);
|
ADD_FEATURE(LightmapFeature);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
case MaterialDomain::Particle:
|
||||||
|
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0)
|
||||||
|
ADD_FEATURE(DistortionFeature);
|
||||||
|
break;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#undef ADD_FEATURE
|
#undef ADD_FEATURE
|
||||||
|
|||||||
Reference in New Issue
Block a user