Add Transparent Lighting Modes for material with option to use non-directional shading
This commit is contained in:
@@ -78,7 +78,10 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
|
|
||||||
// Transparency
|
// Transparency
|
||||||
|
|
||||||
[EditorOrder(200), DefaultValue(true), EditorDisplay("Transparency"), Tooltip("Enables reflections when rendering material.")]
|
[EditorOrder(200), DefaultValue(MaterialTransparentLightingMode.Surface), EditorDisplay("Transparency"), Tooltip("Transparent material lighting mode.")]
|
||||||
|
public MaterialTransparentLightingMode TransparentLightingMode;
|
||||||
|
|
||||||
|
[EditorOrder(205), DefaultValue(true), EditorDisplay("Transparency"), Tooltip("Enables reflections when rendering material.")]
|
||||||
public bool EnableReflections;
|
public bool EnableReflections;
|
||||||
|
|
||||||
[VisibleIf(nameof(EnableReflections))]
|
[VisibleIf(nameof(EnableReflections))]
|
||||||
@@ -161,6 +164,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
MaxTessellationFactor = info.MaxTessellationFactor;
|
MaxTessellationFactor = info.MaxTessellationFactor;
|
||||||
MaskThreshold = info.MaskThreshold;
|
MaskThreshold = info.MaskThreshold;
|
||||||
DecalBlendingMode = info.DecalBlendingMode;
|
DecalBlendingMode = info.DecalBlendingMode;
|
||||||
|
TransparentLightingMode = info.TransparentLightingMode;
|
||||||
PostFxLocation = info.PostFxLocation;
|
PostFxLocation = info.PostFxLocation;
|
||||||
BlendMode = info.BlendMode;
|
BlendMode = info.BlendMode;
|
||||||
ShadingModel = info.ShadingModel;
|
ShadingModel = info.ShadingModel;
|
||||||
@@ -203,6 +207,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
info.MaxTessellationFactor = MaxTessellationFactor;
|
info.MaxTessellationFactor = MaxTessellationFactor;
|
||||||
info.MaskThreshold = MaskThreshold;
|
info.MaskThreshold = MaskThreshold;
|
||||||
info.DecalBlendingMode = DecalBlendingMode;
|
info.DecalBlendingMode = DecalBlendingMode;
|
||||||
|
info.TransparentLightingMode = TransparentLightingMode;
|
||||||
info.PostFxLocation = PostFxLocation;
|
info.PostFxLocation = PostFxLocation;
|
||||||
info.BlendMode = BlendMode;
|
info.BlendMode = BlendMode;
|
||||||
info.ShadingModel = ShadingModel;
|
info.ShadingModel = ShadingModel;
|
||||||
|
|||||||
@@ -439,7 +439,17 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
|
|||||||
options.Macros.Add({ "MATERIAL_REFLECTIONS", Numbers[1] });
|
options.Macros.Add({ "MATERIAL_REFLECTIONS", Numbers[1] });
|
||||||
options.Macros.Add({ "USE_FOG", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::DisableFog ? 0 : 1] });
|
options.Macros.Add({ "USE_FOG", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::DisableFog ? 0 : 1] });
|
||||||
if (useForward)
|
if (useForward)
|
||||||
|
{
|
||||||
options.Macros.Add({ "USE_PIXEL_NORMAL_OFFSET_REFRACTION", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::PixelNormalOffsetRefraction ? 1 : 0] });
|
options.Macros.Add({ "USE_PIXEL_NORMAL_OFFSET_REFRACTION", Numbers[info.FeaturesFlags & MaterialFeaturesFlags::PixelNormalOffsetRefraction ? 1 : 0] });
|
||||||
|
switch (info.TransparentLightingMode)
|
||||||
|
{
|
||||||
|
case MaterialTransparentLightingMode::Surface:
|
||||||
|
break;
|
||||||
|
case MaterialTransparentLightingMode::SurfaceNonDirectional:
|
||||||
|
options.Macros.Add({ "LIGHTING_NO_DIRECTIONAL", "1" });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: don't compile VS_Depth for deferred/forward materials if material doesn't use position offset or masking
|
// TODO: don't compile VS_Depth for deferred/forward materials if material doesn't use position offset or masking
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,14 @@ public:
|
|||||||
static const Upgrader upgraders[] =
|
static const Upgrader upgraders[] =
|
||||||
{
|
{
|
||||||
{ 18, 19, &Upgrade_18_To_19 },
|
{ 18, 19, &Upgrade_18_To_19 },
|
||||||
|
{ 19, 20, &Upgrade_19_To_20 },
|
||||||
};
|
};
|
||||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ============================================
|
// ============================================
|
||||||
// Version 18:
|
// Versions 18,19,20:
|
||||||
// Designed: 7/24/2019
|
// Designed: 7/24/2019
|
||||||
// Custom Data: Header
|
// Custom Data: Header
|
||||||
// Chunk 0: Material Params
|
// Chunk 0: Material Params
|
||||||
@@ -38,20 +39,46 @@ private:
|
|||||||
// Chunk 14: Visject Surface data
|
// Chunk 14: Visject Surface data
|
||||||
// Chunk 15: Source code: ANSI text (encrypted)
|
// Chunk 15: Source code: ANSI text (encrypted)
|
||||||
// ============================================
|
// ============================================
|
||||||
// Version 18:
|
|
||||||
// Designed: 9/13/2018
|
|
||||||
// Custom Data: Header
|
|
||||||
// Chunk 0: Material Params
|
|
||||||
// Chunk 1: Internal SM5 cache
|
|
||||||
// Chunk 2: Internal SM4 cache
|
|
||||||
// Chunk 14: Visject Surface data
|
|
||||||
// Chunk 15: Source code: ANSI text (encrypted)
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
typedef ShaderStorage::Header Header;
|
typedef ShaderStorage::Header Header;
|
||||||
|
typedef ShaderStorage::Header20 Header20;
|
||||||
typedef ShaderStorage::Header19 Header19;
|
typedef ShaderStorage::Header19 Header19;
|
||||||
typedef ShaderStorage::Header18 Header18;
|
typedef ShaderStorage::Header18 Header18;
|
||||||
|
|
||||||
|
static bool Upgrade_19_To_20(AssetMigrationContext& context)
|
||||||
|
{
|
||||||
|
ASSERT(context.Input.SerializedVersion == 19 && context.Output.SerializedVersion == 20);
|
||||||
|
|
||||||
|
// Convert header
|
||||||
|
if (context.Input.CustomData.IsInvalid())
|
||||||
|
return true;
|
||||||
|
auto& oldHeader = *(Header19*)context.Input.CustomData.Get();
|
||||||
|
Header20 newHeader;
|
||||||
|
Platform::MemoryClear(&newHeader, sizeof(newHeader));
|
||||||
|
if (context.Input.Header.TypeName == TEXT("FlaxEngine.ParticleEmitter"))
|
||||||
|
{
|
||||||
|
newHeader.ParticleEmitter.GraphVersion = oldHeader.ParticleEmitter.GraphVersion;
|
||||||
|
newHeader.ParticleEmitter.CustomDataSize = oldHeader.ParticleEmitter.CustomDataSize;
|
||||||
|
}
|
||||||
|
else if (context.Input.Header.TypeName == TEXT("FlaxEngine.Material"))
|
||||||
|
{
|
||||||
|
newHeader.Material.GraphVersion = oldHeader.Material.GraphVersion;
|
||||||
|
newHeader.Material.Info = oldHeader.Material.Info;
|
||||||
|
}
|
||||||
|
else if (context.Input.Header.TypeName == TEXT("FlaxEngine.Shader"))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(Warning, "Unknown input asset type.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
context.Output.CustomData.Copy(&newHeader);
|
||||||
|
|
||||||
|
// Copy all chunks
|
||||||
|
return CopyChunks(context);
|
||||||
|
}
|
||||||
|
|
||||||
static bool Upgrade_18_To_19(AssetMigrationContext& context)
|
static bool Upgrade_18_To_19(AssetMigrationContext& context)
|
||||||
{
|
{
|
||||||
ASSERT(context.Input.SerializedVersion == 18 && context.Output.SerializedVersion == 19);
|
ASSERT(context.Input.SerializedVersion == 18 && context.Output.SerializedVersion == 19);
|
||||||
|
|||||||
@@ -107,10 +107,10 @@ CreateMaterial::Options::Options()
|
|||||||
CreateAssetResult CreateMaterial::Create(CreateAssetContext& context)
|
CreateAssetResult CreateMaterial::Create(CreateAssetContext& context)
|
||||||
{
|
{
|
||||||
// Base
|
// Base
|
||||||
IMPORT_SETUP(Material, 19);
|
IMPORT_SETUP(Material, 20);
|
||||||
context.SkipMetadata = true;
|
context.SkipMetadata = true;
|
||||||
|
|
||||||
ShaderStorage::Header19 shaderHeader;
|
ShaderStorage::Header20 shaderHeader;
|
||||||
Platform::MemoryClear(&shaderHeader, sizeof(shaderHeader));
|
Platform::MemoryClear(&shaderHeader, sizeof(shaderHeader));
|
||||||
if (context.CustomArg)
|
if (context.CustomArg)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace FlaxEngine
|
|||||||
UsageFlags = MaterialUsageFlags.None,
|
UsageFlags = MaterialUsageFlags.None,
|
||||||
FeaturesFlags = MaterialFeaturesFlags.None,
|
FeaturesFlags = MaterialFeaturesFlags.None,
|
||||||
DecalBlendingMode = MaterialDecalBlendingMode.Translucent,
|
DecalBlendingMode = MaterialDecalBlendingMode.Translucent,
|
||||||
|
TransparentLightingMode = MaterialTransparentLightingMode.SurfaceNonDirectional,
|
||||||
PostFxLocation = MaterialPostFxLocation.AfterPostProcessingPass,
|
PostFxLocation = MaterialPostFxLocation.AfterPostProcessingPass,
|
||||||
MaskThreshold = 0.3f,
|
MaskThreshold = 0.3f,
|
||||||
OpacityThreshold = 0.12f,
|
OpacityThreshold = 0.12f,
|
||||||
@@ -61,6 +62,7 @@ namespace FlaxEngine
|
|||||||
&& UsageFlags == other.UsageFlags
|
&& UsageFlags == other.UsageFlags
|
||||||
&& FeaturesFlags == other.FeaturesFlags
|
&& FeaturesFlags == other.FeaturesFlags
|
||||||
&& DecalBlendingMode == other.DecalBlendingMode
|
&& DecalBlendingMode == other.DecalBlendingMode
|
||||||
|
&& TransparentLightingMode == other.TransparentLightingMode
|
||||||
&& PostFxLocation == other.PostFxLocation
|
&& PostFxLocation == other.PostFxLocation
|
||||||
&& Mathf.NearEqual(MaskThreshold, other.MaskThreshold)
|
&& Mathf.NearEqual(MaskThreshold, other.MaskThreshold)
|
||||||
&& Mathf.NearEqual(OpacityThreshold, other.OpacityThreshold)
|
&& Mathf.NearEqual(OpacityThreshold, other.OpacityThreshold)
|
||||||
@@ -86,6 +88,7 @@ namespace FlaxEngine
|
|||||||
hashCode = (hashCode * 397) ^ (int)FeaturesFlags;
|
hashCode = (hashCode * 397) ^ (int)FeaturesFlags;
|
||||||
hashCode = (hashCode * 397) ^ (int)PostFxLocation;
|
hashCode = (hashCode * 397) ^ (int)PostFxLocation;
|
||||||
hashCode = (hashCode * 397) ^ (int)DecalBlendingMode;
|
hashCode = (hashCode * 397) ^ (int)DecalBlendingMode;
|
||||||
|
hashCode = (hashCode * 397) ^ (int)TransparentLightingMode;
|
||||||
hashCode = (hashCode * 397) ^ (int)(MaskThreshold * 1000.0f);
|
hashCode = (hashCode * 397) ^ (int)(MaskThreshold * 1000.0f);
|
||||||
hashCode = (hashCode * 397) ^ (int)(OpacityThreshold * 1000.0f);
|
hashCode = (hashCode * 397) ^ (int)(OpacityThreshold * 1000.0f);
|
||||||
hashCode = (hashCode * 397) ^ (int)TessellationMode;
|
hashCode = (hashCode * 397) ^ (int)TessellationMode;
|
||||||
|
|||||||
@@ -355,6 +355,22 @@ API_ENUM() enum class MaterialDecalBlendingMode : byte
|
|||||||
Emissive = 3,
|
Emissive = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transparent material lighting modes.
|
||||||
|
/// </summary>
|
||||||
|
API_ENUM() enum class MaterialTransparentLightingMode : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default directional lighting evaluated per-pixel at the material surface. Use it for semi-transparent surfaces - with both diffuse and specular lighting component active.
|
||||||
|
/// </summary>
|
||||||
|
Surface = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Non-directional lighting evaluated per-pixel at material surface. Use it for volumetric objects such as smoke, rain or dust - only diffuse lighting term is active (no specular highlights).
|
||||||
|
/// </summary>
|
||||||
|
SurfaceNonDirectional = 1,
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Material input scene textures. Special inputs from the graphics pipeline.
|
/// Material input scene textures. Special inputs from the graphics pipeline.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -441,6 +457,33 @@ struct MaterialInfo8
|
|||||||
bool operator==(const MaterialInfo8& other) const;
|
bool operator==(const MaterialInfo8& other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Material info structure - version 9
|
||||||
|
/// [Deprecated on 13.07.2022, expires on 13.07.2024]
|
||||||
|
/// </summary>
|
||||||
|
struct MaterialInfo9
|
||||||
|
{
|
||||||
|
MaterialDomain Domain;
|
||||||
|
MaterialBlendMode BlendMode;
|
||||||
|
MaterialShadingModel ShadingModel;
|
||||||
|
MaterialUsageFlags UsageFlags;
|
||||||
|
MaterialFeaturesFlags FeaturesFlags;
|
||||||
|
MaterialDecalBlendingMode DecalBlendingMode;
|
||||||
|
MaterialPostFxLocation PostFxLocation;
|
||||||
|
CullMode CullMode;
|
||||||
|
float MaskThreshold;
|
||||||
|
float OpacityThreshold;
|
||||||
|
TessellationMethod TessellationMode;
|
||||||
|
int32 MaxTessellationFactor;
|
||||||
|
|
||||||
|
MaterialInfo9()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialInfo9(const MaterialInfo8& other);
|
||||||
|
bool operator==(const MaterialInfo9& other) const;
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Structure with basic information about the material surface. It describes how material is reacting on light and which graphical features of it requires to render.
|
/// Structure with basic information about the material surface. It describes how material is reacting on light and which graphical features of it requires to render.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -478,6 +521,11 @@ API_STRUCT() struct FLAXENGINE_API MaterialInfo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() MaterialDecalBlendingMode DecalBlendingMode;
|
API_FIELD() MaterialDecalBlendingMode DecalBlendingMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The transparent material lighting mode.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() MaterialTransparentLightingMode TransparentLightingMode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The post fx material rendering location.
|
/// The post fx material rendering location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -512,10 +560,10 @@ API_STRUCT() struct FLAXENGINE_API MaterialInfo
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialInfo(const MaterialInfo8& other);
|
MaterialInfo(const MaterialInfo9& other);
|
||||||
bool operator==(const MaterialInfo& other) const;
|
bool operator==(const MaterialInfo& other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The current material info descriptor version used by the material pipeline
|
// The current material info descriptor version used by the material pipeline
|
||||||
typedef MaterialInfo MaterialInfo9;
|
typedef MaterialInfo MaterialInfo10;
|
||||||
#define MaterialInfo_Version 9
|
#define MaterialInfo_Version 10
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ bool MaterialInfo8::operator==(const MaterialInfo8& other) const
|
|||||||
&& MaxTessellationFactor == other.MaxTessellationFactor;
|
&& MaxTessellationFactor == other.MaxTessellationFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialInfo::MaterialInfo(const MaterialInfo8& other)
|
MaterialInfo9::MaterialInfo9(const MaterialInfo8& other)
|
||||||
{
|
{
|
||||||
Domain = other.Domain;
|
Domain = other.Domain;
|
||||||
BlendMode = other.BlendMode;
|
BlendMode = other.BlendMode;
|
||||||
@@ -78,6 +78,39 @@ MaterialInfo::MaterialInfo(const MaterialInfo8& other)
|
|||||||
MaxTessellationFactor = other.MaxTessellationFactor;
|
MaxTessellationFactor = other.MaxTessellationFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MaterialInfo9::operator==(const MaterialInfo9& other) const
|
||||||
|
{
|
||||||
|
return Domain == other.Domain
|
||||||
|
&& BlendMode == other.BlendMode
|
||||||
|
&& ShadingModel == other.ShadingModel
|
||||||
|
&& UsageFlags == other.UsageFlags
|
||||||
|
&& FeaturesFlags == other.FeaturesFlags
|
||||||
|
&& DecalBlendingMode == other.DecalBlendingMode
|
||||||
|
&& PostFxLocation == other.PostFxLocation
|
||||||
|
&& CullMode == other.CullMode
|
||||||
|
&& Math::NearEqual(MaskThreshold, other.MaskThreshold)
|
||||||
|
&& Math::NearEqual(OpacityThreshold, other.OpacityThreshold)
|
||||||
|
&& TessellationMode == other.TessellationMode
|
||||||
|
&& MaxTessellationFactor == other.MaxTessellationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialInfo::MaterialInfo(const MaterialInfo9& other)
|
||||||
|
{
|
||||||
|
Domain = other.Domain;
|
||||||
|
BlendMode = other.BlendMode;
|
||||||
|
ShadingModel = other.ShadingModel;
|
||||||
|
UsageFlags = other.UsageFlags;
|
||||||
|
FeaturesFlags = other.FeaturesFlags;
|
||||||
|
DecalBlendingMode = other.DecalBlendingMode;
|
||||||
|
TransparentLightingMode = MaterialTransparentLightingMode::Surface;
|
||||||
|
PostFxLocation = other.PostFxLocation;
|
||||||
|
CullMode = other.CullMode;
|
||||||
|
MaskThreshold = other.MaskThreshold;
|
||||||
|
OpacityThreshold = other.OpacityThreshold;
|
||||||
|
TessellationMode = other.TessellationMode;
|
||||||
|
MaxTessellationFactor = other.MaxTessellationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
bool MaterialInfo::operator==(const MaterialInfo& other) const
|
bool MaterialInfo::operator==(const MaterialInfo& other) const
|
||||||
{
|
{
|
||||||
return Domain == other.Domain
|
return Domain == other.Domain
|
||||||
@@ -86,6 +119,7 @@ bool MaterialInfo::operator==(const MaterialInfo& other) const
|
|||||||
&& UsageFlags == other.UsageFlags
|
&& UsageFlags == other.UsageFlags
|
||||||
&& FeaturesFlags == other.FeaturesFlags
|
&& FeaturesFlags == other.FeaturesFlags
|
||||||
&& DecalBlendingMode == other.DecalBlendingMode
|
&& DecalBlendingMode == other.DecalBlendingMode
|
||||||
|
&& TransparentLightingMode == other.TransparentLightingMode
|
||||||
&& PostFxLocation == other.PostFxLocation
|
&& PostFxLocation == other.PostFxLocation
|
||||||
&& CullMode == other.CullMode
|
&& CullMode == other.CullMode
|
||||||
&& Math::NearEqual(MaskThreshold, other.MaskThreshold)
|
&& Math::NearEqual(MaskThreshold, other.MaskThreshold)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
|||||||
// Set reflection probe data
|
// Set reflection probe data
|
||||||
EnvironmentProbe* probe = nullptr;
|
EnvironmentProbe* probe = nullptr;
|
||||||
// TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it
|
// TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it
|
||||||
const Vector3 drawCallOrigin = drawCall.World.GetTranslation() + view.Origin;
|
const Vector3 drawCallOrigin = drawCall.ObjectPosition + view.Origin;
|
||||||
for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++)
|
for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++)
|
||||||
{
|
{
|
||||||
const auto p = cache->EnvironmentProbes[i];
|
const auto p = cache->EnvironmentProbes[i];
|
||||||
@@ -103,7 +103,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
|||||||
for (int32 i = 0; i < cache->PointLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
for (int32 i = 0; i < cache->PointLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
||||||
{
|
{
|
||||||
const auto& light = cache->PointLights[i];
|
const auto& light = cache->PointLights[i];
|
||||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint)
|
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.ObjectPosition) != ContainmentType::Disjoint)
|
||||||
{
|
{
|
||||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||||
data.LocalLightsCount++;
|
data.LocalLightsCount++;
|
||||||
@@ -112,7 +112,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
|||||||
for (int32 i = 0; i < cache->SpotLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
for (int32 i = 0; i < cache->SpotLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
||||||
{
|
{
|
||||||
const auto& light = cache->SpotLights[i];
|
const auto& light = cache->SpotLights[i];
|
||||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint)
|
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.ObjectPosition) != ContainmentType::Disjoint)
|
||||||
{
|
{
|
||||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||||
data.LocalLightsCount++;
|
data.LocalLightsCount++;
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
MaterialInfo8 MaterialInfo;
|
MaterialInfo8 MaterialInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// File header, version 19
|
/// File header, version 19
|
||||||
|
/// [Deprecated on 13.07.2022, expires on 13.07.2024]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct Header19
|
struct Header19
|
||||||
{
|
{
|
||||||
@@ -115,8 +115,53 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File header, version 20
|
||||||
|
/// </summary>
|
||||||
|
struct Header20
|
||||||
|
{
|
||||||
|
static const int32 Version = 20;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
} Shader;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The material graph version.
|
||||||
|
/// </summary>
|
||||||
|
int32 GraphVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The material additional information.
|
||||||
|
/// </summary>
|
||||||
|
MaterialInfo10 Info;
|
||||||
|
} Material;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The particle emitter graph version.
|
||||||
|
/// </summary>
|
||||||
|
int32 GraphVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The custom particles data size (in bytes).
|
||||||
|
/// </summary>
|
||||||
|
int32 CustomDataSize;
|
||||||
|
} ParticleEmitter;
|
||||||
|
};
|
||||||
|
|
||||||
|
Header20()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Current header type
|
/// Current header type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
typedef Header19 Header;
|
typedef Header20 Header;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
// Diffuse-only lighting
|
// Diffuse-only lighting
|
||||||
#define NO_SPECULAR 1
|
#define LIGHTING_NO_SPECULAR 1
|
||||||
|
|
||||||
#include "./Flax/Common.hlsl"
|
#include "./Flax/Common.hlsl"
|
||||||
#include "./Flax/Math.hlsl"
|
#include "./Flax/Math.hlsl"
|
||||||
|
|||||||
@@ -5,10 +5,6 @@
|
|||||||
|
|
||||||
#include "./Flax/LightingCommon.hlsl"
|
#include "./Flax/LightingCommon.hlsl"
|
||||||
|
|
||||||
#ifndef NO_SPECULAR
|
|
||||||
#define NO_SPECULAR 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ShadowData GetShadow(LightData lightData, GBufferSample gBuffer, float4 shadowMask)
|
ShadowData GetShadow(LightData lightData, GBufferSample gBuffer, float4 shadowMask)
|
||||||
{
|
{
|
||||||
ShadowData shadow;
|
ShadowData shadow;
|
||||||
@@ -28,7 +24,7 @@ LightingData StandardShading(GBufferSample gBuffer, float energy, float3 L, floa
|
|||||||
|
|
||||||
LightingData lighting;
|
LightingData lighting;
|
||||||
lighting.Diffuse = Diffuse_Lambert(diffuseColor);
|
lighting.Diffuse = Diffuse_Lambert(diffuseColor);
|
||||||
#if NO_SPECULAR
|
#if LIGHTING_NO_SPECULAR
|
||||||
lighting.Specular = 0;
|
lighting.Specular = 0;
|
||||||
#else
|
#else
|
||||||
float3 specularColor = GetSpecularColor(gBuffer);
|
float3 specularColor = GetSpecularColor(gBuffer);
|
||||||
@@ -95,7 +91,12 @@ float4 GetSkyLightLighting(LightData lightData, GBufferSample gBuffer, TextureCu
|
|||||||
// Compute the preconvolved incoming lighting with the normal direction (apply ambient color)
|
// Compute the preconvolved incoming lighting with the normal direction (apply ambient color)
|
||||||
// Some data is packed, see C++ RendererSkyLightData::SetupLightData
|
// Some data is packed, see C++ RendererSkyLightData::SetupLightData
|
||||||
float mip = lightData.SourceLength;
|
float mip = lightData.SourceLength;
|
||||||
float3 diffuseLookup = ibl.SampleLevel(SamplerLinearClamp, gBuffer.Normal, mip).rgb * lightData.Color.rgb;
|
#if LIGHTING_NO_DIRECTIONAL
|
||||||
|
float3 uvw = float3(0, 0, 0);
|
||||||
|
#else
|
||||||
|
float3 uvw = gBuffer.Normal;
|
||||||
|
#endif
|
||||||
|
float3 diffuseLookup = ibl.SampleLevel(SamplerLinearClamp, uvw, mip).rgb * lightData.Color.rgb;
|
||||||
diffuseLookup += float3(lightData.SpotAngles.rg, lightData.SourceRadius);
|
diffuseLookup += float3(lightData.SpotAngles.rg, lightData.SourceRadius);
|
||||||
|
|
||||||
// Fade out based on distance to capture
|
// Fade out based on distance to capture
|
||||||
@@ -117,26 +118,28 @@ float4 GetLighting(float3 viewPos, LightData lightData, GBufferSample gBuffer, f
|
|||||||
float3 N = gBuffer.Normal;
|
float3 N = gBuffer.Normal;
|
||||||
float3 L = lightData.Direction; // no need to normalize
|
float3 L = lightData.Direction; // no need to normalize
|
||||||
float NoL = saturate(dot(N, L));
|
float NoL = saturate(dot(N, L));
|
||||||
float distanceAttenuation = 1;
|
|
||||||
float lightRadiusMask = 1;
|
|
||||||
float spotAttenuation = 1;
|
|
||||||
float3 toLight = lightData.Direction;
|
float3 toLight = lightData.Direction;
|
||||||
|
|
||||||
|
// Calculate shadow
|
||||||
|
ShadowData shadow = GetShadow(lightData, gBuffer, shadowMask);
|
||||||
|
|
||||||
// Calculate attenuation
|
// Calculate attenuation
|
||||||
if (isRadial)
|
if (isRadial)
|
||||||
{
|
{
|
||||||
toLight = lightData.Position - gBuffer.WorldPos;
|
toLight = lightData.Position - gBuffer.WorldPos;
|
||||||
float distanceSqr = dot(toLight, toLight);
|
float distanceSqr = dot(toLight, toLight);
|
||||||
L = toLight * rsqrt(distanceSqr);
|
L = toLight * rsqrt(distanceSqr);
|
||||||
|
float distanceAttenuation = 1, lightRadiusMask = 1, spotAttenuation = 1;
|
||||||
GetRadialLightAttenuation(lightData, isSpotLight, N, distanceSqr, 1, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation);
|
GetRadialLightAttenuation(lightData, isSpotLight, N, distanceSqr, 1, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation);
|
||||||
|
float attenuation = distanceAttenuation * lightRadiusMask * spotAttenuation;
|
||||||
|
shadow.SurfaceShadow *= attenuation;
|
||||||
|
shadow.TransmissionShadow *= attenuation;
|
||||||
}
|
}
|
||||||
float attenuation = distanceAttenuation * lightRadiusMask * spotAttenuation;
|
|
||||||
|
|
||||||
// Calculate shadow
|
|
||||||
ShadowData shadow = GetShadow(lightData, gBuffer, shadowMask);
|
|
||||||
|
|
||||||
|
#if !LIGHTING_NO_DIRECTIONAL
|
||||||
// Reduce shadow mapping artifacts
|
// Reduce shadow mapping artifacts
|
||||||
shadow.SurfaceShadow *= saturate(NoL * 6.0f - 0.2f);
|
shadow.SurfaceShadow *= saturate(NoL * 6.0f - 0.2f) * NoL;
|
||||||
|
#endif
|
||||||
|
|
||||||
BRANCH
|
BRANCH
|
||||||
if (shadow.SurfaceShadow + shadow.TransmissionShadow > 0)
|
if (shadow.SurfaceShadow + shadow.TransmissionShadow > 0)
|
||||||
@@ -148,8 +151,8 @@ float4 GetLighting(float3 viewPos, LightData lightData, GBufferSample gBuffer, f
|
|||||||
LightingData lighting = SurfaceShading(gBuffer, energy, L, V, N);
|
LightingData lighting = SurfaceShading(gBuffer, energy, L, V, N);
|
||||||
|
|
||||||
// Calculate final light color
|
// Calculate final light color
|
||||||
float3 surfaceLight = (lighting.Diffuse + lighting.Specular) * (NoL * attenuation * shadow.SurfaceShadow);
|
float3 surfaceLight = (lighting.Diffuse + lighting.Specular) * shadow.SurfaceShadow;
|
||||||
float3 subsurfaceLight = lighting.Transmission * (attenuation * shadow.TransmissionShadow);
|
float3 subsurfaceLight = lighting.Transmission * shadow.TransmissionShadow;
|
||||||
result.rgb = lightData.Color * (surfaceLight + subsurfaceLight);
|
result.rgb = lightData.Color * (surfaceLight + subsurfaceLight);
|
||||||
result.a = 1;
|
result.a = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,16 @@
|
|||||||
#include "./Flax/BRDF.hlsl"
|
#include "./Flax/BRDF.hlsl"
|
||||||
#include "./Flax/GBufferCommon.hlsl"
|
#include "./Flax/GBufferCommon.hlsl"
|
||||||
|
|
||||||
|
// Disables directional lighting (no shadowing with dot(N, L), eg. for smoke particles)
|
||||||
|
#ifndef LIGHTING_NO_DIRECTIONAL
|
||||||
|
#define LIGHTING_NO_DIRECTIONAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Disables specular lighting (diffuse-only)
|
||||||
|
#ifndef LIGHTING_NO_SPECULAR
|
||||||
|
#define LIGHTING_NO_SPECULAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// Structure that contains information about light
|
// Structure that contains information about light
|
||||||
struct LightData
|
struct LightData
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ Model_VS2PS VS_Model(ModelInput_PosOnly input)
|
|||||||
|
|
||||||
// Pixel shader for directional light rendering
|
// Pixel shader for directional light rendering
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_1(NO_SPECULAR=0)
|
META_PERMUTATION_1(LIGHTING_NO_SPECULAR=0)
|
||||||
META_PERMUTATION_1(NO_SPECULAR=1)
|
META_PERMUTATION_1(LIGHTING_NO_SPECULAR=1)
|
||||||
void PS_Directional(Quad_VS2PS input, out float4 output : SV_Target0)
|
void PS_Directional(Quad_VS2PS input, out float4 output : SV_Target0)
|
||||||
{
|
{
|
||||||
output = 0;
|
output = 0;
|
||||||
@@ -72,10 +72,10 @@ void PS_Directional(Quad_VS2PS input, out float4 output : SV_Target0)
|
|||||||
|
|
||||||
// Pixel shader for point light rendering
|
// Pixel shader for point light rendering
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=0, USE_IES_PROFILE=0)
|
META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=0)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=1, USE_IES_PROFILE=0)
|
META_PERMUTATION_2(LIGHTING_NO_SPECULAR=1, USE_IES_PROFILE=0)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=0, USE_IES_PROFILE=1)
|
META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=1)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=1, 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_Point(Model_VS2PS input, out float4 output : SV_Target0)
|
||||||
{
|
{
|
||||||
output = 0;
|
output = 0;
|
||||||
@@ -114,10 +114,10 @@ void PS_Point(Model_VS2PS input, out float4 output : SV_Target0)
|
|||||||
|
|
||||||
// Pixel shader for spot light rendering
|
// Pixel shader for spot light rendering
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=0, USE_IES_PROFILE=0)
|
META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=0)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=1, USE_IES_PROFILE=0)
|
META_PERMUTATION_2(LIGHTING_NO_SPECULAR=1, USE_IES_PROFILE=0)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=0, USE_IES_PROFILE=1)
|
META_PERMUTATION_2(LIGHTING_NO_SPECULAR=0, USE_IES_PROFILE=1)
|
||||||
META_PERMUTATION_2(NO_SPECULAR=1, 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)
|
void PS_Spot(Model_VS2PS input, out float4 output : SV_Target0)
|
||||||
{
|
{
|
||||||
output = 0;
|
output = 0;
|
||||||
|
|||||||
@@ -458,6 +458,9 @@ float SampleShadow(LightData light, LightShadowData shadow, Texture2DArray shado
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
float3 samplePosWS = gBuffer.WorldPos;
|
||||||
|
|
||||||
|
#if !LIGHTING_NO_DIRECTIONAL
|
||||||
// Skip if surface is in a full shadow
|
// Skip if surface is in a full shadow
|
||||||
float NoL = dot(gBuffer.Normal, light.Direction);
|
float NoL = dot(gBuffer.Normal, light.Direction);
|
||||||
BRANCH
|
BRANCH
|
||||||
@@ -467,8 +470,8 @@ float SampleShadow(LightData light, LightShadowData shadow, Texture2DArray shado
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply normal offset bias
|
// Apply normal offset bias
|
||||||
float3 samplePosWS = gBuffer.WorldPos;
|
|
||||||
samplePosWS += GetShadowPositionOffset(shadow.NormalOffsetScale, NoL, gBuffer.Normal);
|
samplePosWS += GetShadowPositionOffset(shadow.NormalOffsetScale, NoL, gBuffer.Normal);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Sample shadow
|
// Sample shadow
|
||||||
return SampleShadow(light, shadow, shadowMap, samplePosWS, viewDepth);
|
return SampleShadow(light, shadow, shadowMap, samplePosWS, viewDepth);
|
||||||
@@ -480,7 +483,11 @@ float SampleShadow(LightData light, LightShadowData shadow, Texture2D shadowMap,
|
|||||||
float3 toLight = light.Position - worldPosition;
|
float3 toLight = light.Position - worldPosition;
|
||||||
float toLightLength = length(toLight);
|
float toLightLength = length(toLight);
|
||||||
float3 L = toLight / toLightLength;
|
float3 L = toLight / toLightLength;
|
||||||
|
#if LIGHTING_NO_DIRECTIONAL
|
||||||
|
float dirCheck = 1.0f;
|
||||||
|
#else
|
||||||
float dirCheck = dot(-light.Direction, L);
|
float dirCheck = dot(-light.Direction, L);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Skip pixels outside of the light influence
|
// Skip pixels outside of the light influence
|
||||||
BRANCH
|
BRANCH
|
||||||
@@ -539,7 +546,11 @@ float SampleShadow(LightData light, LightShadowData shadow, Texture2D shadowMap,
|
|||||||
float3 toLight = light.Position - gBuffer.WorldPos;
|
float3 toLight = light.Position - gBuffer.WorldPos;
|
||||||
float toLightLength = length(toLight);
|
float toLightLength = length(toLight);
|
||||||
float3 L = toLight / toLightLength;
|
float3 L = toLight / toLightLength;
|
||||||
|
#if LIGHTING_NO_DIRECTIONAL
|
||||||
|
float dirCheck = 1.0f;
|
||||||
|
#else
|
||||||
float dirCheck = dot(-light.Direction, L);
|
float dirCheck = dot(-light.Direction, L);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Skip pixels outside of the light influence
|
// Skip pixels outside of the light influence
|
||||||
BRANCH
|
BRANCH
|
||||||
@@ -569,7 +580,10 @@ float SampleShadow(LightData light, LightShadowData shadow, Texture2D shadowMap,
|
|||||||
subsurfaceShadow = lerp(1.0f, subsurfaceShadow, shadow.Fade);
|
subsurfaceShadow = lerp(1.0f, subsurfaceShadow, shadow.Fade);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
float3 samplePosWS = gBuffer.WorldPos;
|
||||||
|
|
||||||
|
#if !LIGHTING_NO_DIRECTIONAL
|
||||||
// Skip if surface is in a full shadow
|
// Skip if surface is in a full shadow
|
||||||
float NoL = dot(gBuffer.Normal, L);
|
float NoL = dot(gBuffer.Normal, L);
|
||||||
BRANCH
|
BRANCH
|
||||||
@@ -579,8 +593,8 @@ float SampleShadow(LightData light, LightShadowData shadow, Texture2D shadowMap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply normal offset bias
|
// Apply normal offset bias
|
||||||
float3 samplePosWS = gBuffer.WorldPos;
|
|
||||||
samplePosWS += GetShadowPositionOffset(shadow.NormalOffsetScale, NoL, gBuffer.Normal);
|
samplePosWS += GetShadowPositionOffset(shadow.NormalOffsetScale, NoL, gBuffer.Normal);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Sample shadow
|
// Sample shadow
|
||||||
return SampleShadow(light, shadow, shadowMap, samplePosWS);
|
return SampleShadow(light, shadow, shadowMap, samplePosWS);
|
||||||
@@ -686,7 +700,10 @@ float SampleShadow(LightData light, LightShadowData shadow, TextureCube<float> s
|
|||||||
subsurfaceShadow = lerp(1.0f, subsurfaceShadow, shadow.Fade);
|
subsurfaceShadow = lerp(1.0f, subsurfaceShadow, shadow.Fade);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
float3 samplePosWS = gBuffer.WorldPos;
|
||||||
|
|
||||||
|
#if !LIGHTING_NO_DIRECTIONAL
|
||||||
// Skip if surface is in a full shadow
|
// Skip if surface is in a full shadow
|
||||||
float NoL = dot(gBuffer.Normal, L);
|
float NoL = dot(gBuffer.Normal, L);
|
||||||
BRANCH
|
BRANCH
|
||||||
@@ -696,8 +713,8 @@ float SampleShadow(LightData light, LightShadowData shadow, TextureCube<float> s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply normal offset bias
|
// Apply normal offset bias
|
||||||
float3 samplePosWS = gBuffer.WorldPos;
|
|
||||||
samplePosWS += GetShadowPositionOffset(shadow.NormalOffsetScale, NoL, gBuffer.Normal);
|
samplePosWS += GetShadowPositionOffset(shadow.NormalOffsetScale, NoL, gBuffer.Normal);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Sample shadow
|
// Sample shadow
|
||||||
return SampleShadow(light, shadow, shadowMap, samplePosWS);
|
return SampleShadow(light, shadow, shadowMap, samplePosWS);
|
||||||
|
|||||||
Reference in New Issue
Block a user