Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ namespace ExtendedTranslucency
static const uint RimLight = 1;
static const uint IsotropicFabric = 2;
static const uint AnisotropicFabric = 3;
static const uint Disabled = 4; // Any value >= 4
static const uint ScatteringVolume = 4;
static const uint Disabled = 5; // Any value >= 5
}

bool IsValidMaterial(uint Material)
Expand Down Expand Up @@ -41,6 +42,11 @@ namespace ExtendedTranslucency
return a0 * (length(cross(v, t)) + length(cross(v, b))) / (abs(dot(v, n)) + 0.001) - a0 * a0;
}

float GetViewDependentAlphaScatteringVolume(float alpha, float3 view, float3 normal)
{
return 1.0 - pow(1.0 - alpha, dot(view, normal));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The distance a ray of light traveled in a sphere is 2R*cos(theta), which scatters light at exp(k*2R*cos(theta)) where k is a absorbing factor. k can be deduced from the input alpha, assuming its the transparency when viewing from its normal direction.
And the math turns out to be this simple...

}

float SoftClamp(float alpha, float limit)
{
// soft clamp [alpha,1] and remap the transparency
Expand Down
6 changes: 5 additions & 1 deletion package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3205,7 +3205,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)

[branch] if (ExtendedTranslucency::IsValidMaterial(AlphaMaterialModel))
{
if (alpha >= 0.0156862754 && alpha < 1.0) {
if (alpha >= 0.0156862754 && alpha <= 1.0 - 0.0156862754) {
float originalAlpha = alpha;
alpha = alpha * (1.0 - AlphaMaterialReduction);
[branch] if (AlphaMaterialModel == ExtendedTranslucency::MaterialModel::AnisotropicFabric)
Expand All @@ -3220,6 +3220,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
{
alpha = ExtendedTranslucency::GetViewDependentAlphaFabric1D(alpha, viewDirection, worldNormal.xyz);
}
else if (AlphaMaterialModel == ExtendedTranslucency::MaterialModel::ScatteringVolume)
{
alpha = ExtendedTranslucency::GetViewDependentAlphaScatteringVolume(alpha, viewDirection, worldNormal.xyz);
}
else
{
alpha = ExtendedTranslucency::GetViewDependentAlphaNaive(alpha, viewDirection, worldNormal.xyz);
Expand Down
6 changes: 4 additions & 2 deletions src/Features/ExtendedTranslucency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ void ExtendedTranslucency::DrawSettings()
"1 - Rim Edge",
"2 - Isotropic Fabric, Glass, ...",
"3 - Anisotropic Fabric",
"4 - Scattering Volume",
};

static constexpr int AlphaModeSize = static_cast<int>(std::size(AlphaModeNames));
Expand All @@ -104,7 +105,8 @@ void ExtendedTranslucency::DrawSettings()
" - Disabled: No anisotropic transluency, flat alpha.\n"
" - Rim Edge: Naive rim light effect with no physics model, the edge of the geometry is always opaque even its full transparent.\n"
" - Isotropic Fabric: Imaginary fabric weaved from threads in one direction, respect normal map, also works well for layer of glass panels.\n"
" - Anisotropic Fabric: Common fabric weaved from tangent and birnormal direction, ignores normal map.\n");
" - Anisotropic Fabric: Common fabric weaved from tangent and birnormal direction, ignores normal map.\n"
" - Scattering Volume: A **volumn** (instead of a layer) of light scattering or absoring material, it fade the geometry out at its edge instead of strength them like other material.\n");
Copy link
Collaborator

@Pentalimbed Pentalimbed Aug 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling and grammar mistakes:

  • volumn - volume
  • absoring - absorbing
  • what does "fade the geometry out at its edge instead of strength(en?) them" mean? It becomes more transparent towards the edges instead of the other way around?

I suggest you put your texts through a spell checker or LLM

}
if (ImGui::Checkbox("Skinned Mesh Only", &settings.SkinnedOnly)) {
changed = true;
Expand Down Expand Up @@ -160,7 +162,7 @@ std::pair<std::string, std::vector<std::string>> ExtendedTranslucency::GetFeatur
return {
"Extended Translucency provides realistic rendering of thin fabric and other translucent materials.\n"
"This feature supports multiple material models for different types of translucent surfaces.",
{ "Multiple translucency material models (rim edge, isotropic/anisotropic fabric)",
{ "Multiple translucency material models (rim edge, isotropic/anisotropic fabric, scattering volume)",
"Realistic fabric translucency with directional light transmission",
"Per-material override support via NIF extra data",
"Configurable transparency and softness controls",
Expand Down
1 change: 1 addition & 0 deletions src/Features/ExtendedTranslucency.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct ExtendedTranslucency final : Feature
RimLight = 1, // Similar effect like rim light
IsotropicFabric = 2, // 1D fabric model, respect normal map
AnisotropicFabric = 3, // 2D fabric model alone tangent and binormal, ignores normal map
ScatteringVolume = 4, // Fade out at the edge, models a ball of fog (light decays in exponential on distance)

DescriptorUseDefault = 0, // In ExtraFeatureDescriptor, 0 means 'UseDefault' instead of 'Disabled'
DescriptorDisabled = 7, // In ExtraFeatureDescriptor, value >= 5 means 'Disabled'
Expand Down
Loading