Refactor material shaders generator to use modular features as extensions

This commit is contained in:
Wojtek Figat
2021-02-05 11:22:47 +01:00
parent b5847eb0d6
commit 01777a2c1b
16 changed files with 182 additions and 563 deletions

View File

@@ -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;
}

View File

@@ -3,7 +3,6 @@
#define MATERIAL 1 #define MATERIAL 1
@3 @3
#include "./Flax/Common.hlsl" #include "./Flax/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl" #include "./Flax/MaterialCommon.hlsl"
#include "./Flax/GBufferCommon.hlsl" #include "./Flax/GBufferCommon.hlsl"
@@ -22,7 +21,7 @@ float4 ViewInfo;
float4 ScreenSize; float4 ScreenSize;
@1META_CB_END @1META_CB_END
// Material shader resources // Shader resources
@2 @2
// Interpolants passed from the vertex shader // Interpolants passed from the vertex shader
struct VertexOutput struct VertexOutput

View File

@@ -2,19 +2,13 @@
// Version: @0 // Version: @0
#define MATERIAL 1 #define MATERIAL 1
#define MAX_LOCAL_LIGHTS 4
@3 @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/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl" #include "./Flax/MaterialCommon.hlsl"
#include "./Flax/GBufferCommon.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" #include "./Flax/Matrix.hlsl"
@7 @7
struct SpriteInput struct SpriteInput
@@ -55,44 +49,19 @@ uint RibbonSegmentCount;
float4x4 WorldMatrixInverseTransposed; float4x4 WorldMatrixInverseTransposed;
@1META_CB_END @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 // Particles attributes buffer
ByteAddressBuffer ParticlesData : register(t0); 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 #if HAS_SORTED_INDICES
// Sorted particles indices // Sorted particles indices
Buffer<uint> SortedIndices : register(t1); Buffer<uint> SortedIndices : register(t1);
#else #else
// Ribbon particles segments distances buffer // Ribbon particles segments distances buffer
Buffer<float> SegmentDistances : register(t1); Buffer<float> SegmentDistances : register(t1);
#endif #endif
// Shader resources // Shader resources
TextureCube EnvProbe : register(t2);
TextureCube SkyLightTexture : register(t3);
Texture2DArray DirectionalLightShadowMap : register(t4);
@2 @2
// Interpolants passed from the vertex shader // Interpolants passed from the vertex shader
struct VertexOutput struct VertexOutput
{ {
@@ -711,97 +680,6 @@ VertexOutput VS_Ribbon(uint vertexIndex : SV_VertexID)
return output; 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 // 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

View File

@@ -20,7 +20,7 @@ float4 ScreenSize;
float4 TemporalAAJitter; float4 TemporalAAJitter;
@1META_CB_END @1META_CB_END
// Material shader resources // Shader resources
@2 @2
// Interpolants passed to the pixel shader // Interpolants passed to the pixel shader
struct PixelInput struct PixelInput

View File

@@ -30,9 +30,8 @@ float3 GeometrySize;
float Dummy1; float Dummy1;
@1META_CB_END @1META_CB_END
// Material shader resources // Shader resources
@2 @2
// Geometry data passed though the graphics rendering stages up to the pixel shader // Geometry data passed though the graphics rendering stages up to the pixel shader
struct GeometryData struct GeometryData
{ {

View File

@@ -2,19 +2,10 @@
// Version: @0 // Version: @0
#define MATERIAL 1 #define MATERIAL 1
#define MAX_LOCAL_LIGHTS 4
@3 @3
#include "./Flax/Common.hlsl" #include "./Flax/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl" #include "./Flax/MaterialCommon.hlsl"
#include "./Flax/GBufferCommon.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 @7
// Primary constant buffer (with additional material parameters) // Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data) META_CB_BEGIN(0, Data)
@@ -38,26 +29,8 @@ float3 GeometrySize;
float Dummy1; float Dummy1;
@1META_CB_END @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 // Shader resources
TextureCube EnvProbe : register(t0);
TextureCube SkyLightTexture : register(t1);
Texture2DArray DirectionalLightShadowMap : register(t2);
@2 @2
// Interpolants passed from the vertex shader // Interpolants passed from the vertex shader
struct VertexOutput struct VertexOutput
{ {
@@ -564,103 +537,6 @@ void ClipLODTransition(PixelInput input)
#endif #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 // 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

View File

@@ -42,9 +42,8 @@ Texture2D Heightmap : register(t0);
Texture2D Splatmap0 : register(t1); Texture2D Splatmap0 : register(t1);
Texture2D Splatmap1 : register(t2); Texture2D Splatmap1 : register(t2);
// Material shader resources // Shader resources
@2 @2
// Geometry data passed though the graphics rendering stages up to the pixel shader // Geometry data passed though the graphics rendering stages up to the pixel shader
struct GeometryData struct GeometryData
{ {

View File

@@ -4,13 +4,14 @@
#include "MaterialShaderFeatures.h" #include "MaterialShaderFeatures.h"
#include "MaterialParams.h" #include "MaterialParams.h"
#include "Engine/Engine/Time.h" #include "Engine/Engine/Time.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPULimits.h" #include "Engine/Graphics/GPULimits.h"
#include "Engine/Graphics/Models/SkinnedMeshDrawData.h"
#include "Engine/Graphics/RenderView.h" #include "Engine/Graphics/RenderView.h"
#include "Engine/Level/Actors/EnvironmentProbe.h" #include "Engine/Graphics/RenderTask.h"
#include "Engine/Renderer/DepthOfFieldPass.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/DrawCall.h"
#include "Engine/Renderer/ShadowsPass.h"
#include "Engine/Renderer/RenderList.h" #include "Engine/Renderer/RenderList.h"
#if USE_EDITOR #if USE_EDITOR
#include "Engine/Renderer/Lightmaps.h" #include "Engine/Renderer/Lightmaps.h"
@@ -39,17 +40,6 @@ PACK_STRUCT(struct ForwardMaterialShaderData {
float Dummy1; 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 DrawPass ForwardMaterialShader::GetDrawModes() const
{ {
return _drawModes; return _drawModes;
@@ -66,19 +56,17 @@ void ForwardMaterialShader::Bind(BindParameters& params)
// Prepare // Prepare
auto context = params.GPUContext; auto context = params.GPUContext;
auto& view = params.RenderContext.View; auto& view = params.RenderContext.View;
auto cache = params.RenderContext.List;
auto& drawCall = *params.FirstDrawCall; auto& drawCall = *params.FirstDrawCall;
const auto cb0 = _shader->GetCB(0); const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0 && cb0->GetSize() != 0; const bool hasCb0 = cb0 && cb0->GetSize() != 0;
ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing 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(); byte* cb = _cb0Data.Get();
auto materialData = reinterpret_cast<ForwardMaterialShaderData*>(cb); auto materialData = reinterpret_cast<ForwardMaterialShaderData*>(cb);
cb += sizeof(ForwardMaterialShaderData); cb += sizeof(ForwardMaterialShaderData);
int32 srv = 0; int32 srv = 0;
// Setup features // Setup features
ForwardShadingFeature::Bind(params, cb, srv);
// Setup parameters // Setup parameters
MaterialParameter::BindMeta bindMeta; MaterialParameter::BindMeta bindMeta;
@@ -131,124 +119,12 @@ void ForwardMaterialShader::Bind(BindParameters& params)
materialData->GeometrySize = drawCall.Surface.GeometrySize; materialData->GeometrySize = drawCall.Surface.GeometrySize;
} }
// Setup lighting constants data
if (hasCb1)
{
auto& lightingData = *reinterpret_cast<ForwardMaterialShaderLightingData*>(_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 // Bind constants
if (hasCb0) if (hasCb0)
{ {
context->UpdateCB(cb0, _cb0Data.Get()); context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0); 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 // Select pipeline state based on current pass and render mode
const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe; const bool wireframe = (_info.FeaturesFlags & MaterialFeaturesFlags::Wireframe) != 0 || view.Mode == ViewMode::Wireframe;

View File

@@ -143,11 +143,6 @@ bool MaterialShader::Load(MemoryReadStream& shaderCacheStream, const MaterialInf
{ {
_cb0Data.Resize(cb0->GetSize(), false); _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) // Initialize the material based on type (create pipeline states and setup)
if (Load()) if (Load())
@@ -163,6 +158,5 @@ void MaterialShader::Unload()
{ {
_isLoaded = false; _isLoaded = false;
_cb0Data.Resize(0, false); _cb0Data.Resize(0, false);
_cb1Data.Resize(0, false);
_shader->ReleaseGPU(); _shader->ReleaseGPU();
} }

View File

@@ -53,7 +53,6 @@ protected:
bool _isLoaded; bool _isLoaded;
GPUShader* _shader; GPUShader* _shader;
Array<byte> _cb0Data; Array<byte> _cb0Data;
Array<byte> _cb1Data;
MaterialInfo _info; MaterialInfo _info;
protected: protected:

View File

@@ -155,23 +155,30 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, byte*& cb, in
#if USE_EDITOR #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) void TessellationFeature::Generate(GeneratorData& data)
{ {
data.Template = TEXT("Tessellation.hlsl"); data.Template = TEXT("Features/Tessellation.hlsl");
data.ConstantsSize = 0; data.ConstantsSize = 0;
data.ResourcesCount = 0; data.ResourcesCount = 0;
} }
void LightmapFeature::Generate(GeneratorData& data) void LightmapFeature::Generate(GeneratorData& data)
{ {
data.Template = TEXT("Lightmap.hlsl"); data.Template = TEXT("Features/Lightmap.hlsl");
data.ConstantsSize = sizeof(Data); data.ConstantsSize = sizeof(Data);
data.ResourcesCount = SRVs; data.ResourcesCount = SRVs;
} }
void DistortionFeature::Generate(GeneratorData& data) void DistortionFeature::Generate(GeneratorData& data)
{ {
data.Template = TEXT("Distortion.hlsl"); data.Template = TEXT("Features/Distortion.hlsl");
data.ConstantsSize = 0; data.ConstantsSize = 0;
data.ResourcesCount = 0; data.ResourcesCount = 0;
} }

View File

@@ -38,6 +38,9 @@ struct ForwardShadingFeature : MaterialShaderFeature
}); });
static void Bind(MaterialShader::BindParameters& params, byte*& cb, int32& srv); 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). // Material shader feature that adds geometry hardware tessellation (using Hull and Domain shaders).

View File

@@ -1,20 +1,19 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#include "ParticleMaterialShader.h" #include "ParticleMaterialShader.h"
#include "MaterialShaderFeatures.h"
#include "MaterialParams.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/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/GPUDevice.h"
#include "Engine/Graphics/Shaders/GPUShader.h"
#include "Engine/Graphics/GPULimits.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/Particles/Graph/CPU/ParticleEmitterGraph.CPU.h"
#include "Engine/Content/Assets/CubeTexture.h"
#include "Engine/Level/Actors/EnvironmentProbe.h"
#define MAX_LOCAL_LIGHTS 4 #define MAX_LOCAL_LIGHTS 4
@@ -49,17 +48,6 @@ PACK_STRUCT(struct ParticleMaterialShaderData {
Matrix WorldMatrixInverseTransposed; 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 DrawPass ParticleMaterialShader::GetDrawModes() const
{ {
return _drawModes; return _drawModes;
@@ -70,20 +58,18 @@ void ParticleMaterialShader::Bind(BindParameters& params)
// Prepare // Prepare
auto context = params.GPUContext; auto context = params.GPUContext;
auto& view = params.RenderContext.View; auto& view = params.RenderContext.View;
auto cache = params.RenderContext.List;
auto& drawCall = *params.FirstDrawCall; auto& drawCall = *params.FirstDrawCall;
const uint32 sortedIndicesOffset = drawCall.Particle.Module->SortedIndicesOffset; 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 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(); byte* cb = _cb0Data.Get();
auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(cb); auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(cb);
cb += sizeof(ParticleMaterialShaderData); cb += sizeof(ParticleMaterialShaderData);
int32 srv = 0; int32 srv = 2;
// Setup features // Setup features
ForwardShadingFeature::Bind(params, cb, srv);
// Setup parameters // Setup parameters
MaterialParameter::BindMeta bindMeta; MaterialParameter::BindMeta bindMeta;
@@ -95,25 +81,23 @@ void ParticleMaterialShader::Bind(BindParameters& params)
bindMeta.CanSampleGBuffer = true; bindMeta.CanSampleGBuffer = true;
MaterialParams::Bind(params.ParamsLink, bindMeta); 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()); const auto& p = *params.ParamsLink->This;
if (drawCall.Particle.Particles->GPU.SortedIndices) for (int32 i = 0; i < p.Count(); i++)
context->BindSR(1, drawCall.Particle.Particles->GPU.SortedIndices->View());
if (hasCb0)
{ {
const auto& p = *params.ParamsLink->This; const auto& param = p.At(i);
for (int32 i = 0; i < p.Count(); i++) if (param.GetParameterType() == MaterialParameterType::Integer && param.GetName().StartsWith(TEXT("Particle.")))
{ {
const auto& param = p.At(i); auto name = StringView(param.GetName().Get() + 9);
if (param.GetParameterType() == MaterialParameterType::Integer && param.GetName().StartsWith(TEXT("Particle.")))
{
auto name = StringView(param.GetName().Get() + 9);
const int32 offset = drawCall.Particle.Particles->Layout->FindAttributeOffset(name); const int32 offset = drawCall.Particle.Particles->Layout->FindAttributeOffset(name);
*((int32*)(bindMeta.Constants + param.GetBindOffset())) = offset; *((int32*)(bindMeta.Constants + param.GetBindOffset())) = offset;
}
} }
} }
} }
@@ -147,8 +131,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
if (hasCb0) if (hasCb0)
{ {
const auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(_cb0Data.Get());
materialData->RibbonWidthOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonWidth, ParticleAttribute::ValueTypes::Float, -1); 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->RibbonTwistOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonTwist, ParticleAttribute::ValueTypes::Float, -1);
materialData->RibbonFacingVectorOffset = drawCall.Particle.Particles->Layout->FindAttributeOffset(ParticleRibbonFacingVector, ParticleAttribute::ValueTypes::Vector3, -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 // Setup material constants data
if (hasCb0) if (hasCb0)
{ {
const auto materialData = reinterpret_cast<ParticleMaterialShaderData*>(_cb0Data.Get());
static StringView ParticlePosition(TEXT("Position")); static StringView ParticlePosition(TEXT("Position"));
static StringView ParticleSpriteSize(TEXT("SpriteSize")); static StringView ParticleSpriteSize(TEXT("SpriteSize"));
static StringView ParticleSpriteFacingMode(TEXT("SpriteFacingMode")); static StringView ParticleSpriteFacingMode(TEXT("SpriteFacingMode"));
@@ -207,124 +187,12 @@ void ParticleMaterialShader::Bind(BindParameters& params)
Matrix::Invert(drawCall.World, materialData->WorldMatrixInverseTransposed); Matrix::Invert(drawCall.World, materialData->WorldMatrixInverseTransposed);
} }
// Setup lighting constants data
if (hasCb1)
{
auto& lightingData = *reinterpret_cast<ParticleMaterialShaderLightingData*>(_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 // Bind constants
if (hasCb0) if (hasCb0)
{ {
context->UpdateCB(cb0, _cb0Data.Get()); context->UpdateCB(cb0, _cb0Data.Get());
context->BindCB(0, cb0); context->BindCB(0, cb0);
} }
if (hasCb1)
{
context->UpdateCB(cb1, _cb1Data.Get());
context->BindCB(1, cb1);
}
// Bind pipeline // Bind pipeline
context->SetState(state); context->SetState(state);

View File

@@ -26,7 +26,6 @@ void PostFxMaterialShader::Bind(BindParameters& params)
// Prepare // Prepare
auto context = params.GPUContext; auto context = params.GPUContext;
auto& view = params.RenderContext.View; auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
const auto cb0 = _shader->GetCB(0); const auto cb0 = _shader->GetCB(0);
const bool hasCb0 = cb0->GetSize() != 0; const bool hasCb0 = cb0->GetSize() != 0;

View File

@@ -1,16 +1,16 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#include "GPUShaderDX11.h"
#if GRAPHICS_API_DIRECTX11 #if GRAPHICS_API_DIRECTX11
#include "GPUContextDX11.h" #include "GPUContextDX11.h"
#include "Engine/Core/Math/Viewport.h" #include "GPUShaderDX11.h"
#include "Engine/Core/Math/Rectangle.h"
#include "GPUShaderProgramDX11.h" #include "GPUShaderProgramDX11.h"
#include "GPUPipelineStateDX11.h" #include "GPUPipelineStateDX11.h"
#include "GPUTextureDX11.h" #include "GPUTextureDX11.h"
#include "GPUBufferDX11.h" #include "GPUBufferDX11.h"
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h" #include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
#include "Engine/Core/Math/Viewport.h"
#include "Engine/Core/Math/Rectangle.h"
#include "Engine/Profiler/RenderStats.h" #include "Engine/Profiler/RenderStats.h"
#define DX11_CLEAR_SR_ON_STAGE_DISABLE 0 #define DX11_CLEAR_SR_ON_STAGE_DISABLE 0

View File

@@ -59,7 +59,7 @@ namespace
bool FeatureData::Init() bool FeatureData::Init()
{ {
// Load template file // 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; String contents;
if (File::ReadAllText(path, contents)) if (File::ReadAllText(path, contents))
{ {
@@ -188,17 +188,20 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
ADD_FEATURE(LightmapFeature); ADD_FEATURE(LightmapFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0) if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0)
ADD_FEATURE(DistortionFeature); ADD_FEATURE(DistortionFeature);
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
ADD_FEATURE(ForwardShadingFeature);
break; break;
case MaterialDomain::Terrain: case MaterialDomain::Terrain:
if (materialInfo.TessellationMode != TessellationMethod::None) if (materialInfo.TessellationMode != TessellationMethod::None)
ADD_FEATURE(TessellationFeature); ADD_FEATURE(TessellationFeature);
ADD_FEATURE(LightmapFeature); ADD_FEATURE(LightmapFeature);
break; break;
default:
case MaterialDomain::Particle: case MaterialDomain::Particle:
if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0) if (materialInfo.BlendMode != MaterialBlendMode::Opaque && (materialInfo.FeaturesFlags & MaterialFeaturesFlags::DisableDistortion) == 0)
ADD_FEATURE(DistortionFeature); ADD_FEATURE(DistortionFeature);
ADD_FEATURE(ForwardShadingFeature);
break; break;
default:
break; break;
} }
#undef ADD_FEATURE #undef ADD_FEATURE
@@ -390,18 +393,14 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
int32 srv = 0; int32 srv = 0;
switch (baseLayer->Domain) switch (baseLayer->Domain)
{ {
case MaterialDomain::Surface:
if (materialInfo.BlendMode != MaterialBlendMode::Opaque)
srv = 3; // Forward shading resources
break;
case MaterialDomain::Decal: case MaterialDomain::Decal:
srv = 1; srv = 1; // Depth buffer
break; break;
case MaterialDomain::Terrain: case MaterialDomain::Terrain:
srv = 3; // Heightmap + 2 splatmaps srv = 3; // Heightmap + 2 splatmaps
break; break;
case MaterialDomain::Particle: case MaterialDomain::Particle:
srv = 5; srv = 2; // Particles data + Sorted indices/Ribbon segments
break; break;
} }
for (auto f : features) for (auto f : features)