Skip to content
Merged
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
Comment thread
ArcEarth marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace ExtendedTranslucency
{
namespace MaterialModel
{
static const uint Default = 0; // Use ExtendedTranslucencySettings
static const uint RimLight = 1;
static const uint IsotropicFabric = 2;
static const uint AnisotropicFabric = 3;
static const uint Disabled = 4; // Any value >= 4
}

bool IsValidMaterial(uint Material)
{
return Material > 0 && Material < MaterialModel::Disabled;
}

uint GetMaterialModelFromDescriptor(uint Descriptor)
{
// TerrainHelper : 6
// ExtraFeatureDescriptor : 3
return (Descriptor >> 6) & 7;
}

float GetViewDependentAlphaNaive(float alpha, float3 view, float3 normal)
{
return 1.0 - (1.0 - alpha) * dot(view, normal);
}

float GetViewDependentAlphaFabric1D(float alpha, float3 view, float3 normal)
{
return alpha / min(1.0, (abs(dot(view, normal)) + 0.001));
}

float GetViewDependentAlphaFabric2D(float alpha, float3 view, float3x3 tbnTr)
{
float3 t = tbnTr[0];
float3 b = tbnTr[1];
float3 n = tbnTr[2];
float3 v = view;
float a0 = 1 - sqrt(1.0 - alpha);
return a0 * (length(cross(v, t)) + length(cross(v, b))) / (abs(dot(v, n)) + 0.001) - a0 * a0;
}

float SoftClamp(float alpha, float limit)
{
// soft clamp [alpha,1] and remap the transparency
alpha = min(alpha, limit / (1 + exp(-4 * (alpha - limit * 0.5) / limit)));
return saturate(alpha);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Info]
Version = 1-0-0
9 changes: 9 additions & 0 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@ namespace SharedData
uint3 pad;
};

struct ExtendedTranslucencySettings
{
uint MaterialModel; // [0,1,2,3] The MaterialModel
float Reduction; // [0, 1.0] The factor to reduce the transparency to matain the average transparency [0,1]
float Softness; // [0, 2.0] The soft remap upper limit [0,2]
float Strength; // [0, 1.0] The inverse blend weight of the effect
};

cbuffer FeatureData : register(b6)
{
GrassLightingSettings grassLightingSettings;
Expand All @@ -197,6 +205,7 @@ namespace SharedData
HairSpecularSettings hairSpecularSettings;
TerrainVariationSettings terrainVariationSettings;
IBLSettings iblSettings;
ExtendedTranslucencySettings extendedTranslucencySettings;
};

Texture2D<float4> DepthTexture : register(t17);
Expand Down
46 changes: 46 additions & 0 deletions package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,11 @@ float GetSnowParameterY(float texProjTmp, float alpha)
# include "TerrainVariation/TerrainVariation.hlsli"
# endif

# if defined(EXTENDED_TRANSLUCENCY) && !(defined(LOD) || defined(SKIN) || defined(HAIR) || defined(EYE) || defined(TREE_ANIM) || defined(LODOBJECTSHD) || defined(LODOBJECTS) || defined(DEPTH_WRITE_DECALS))
# include "ExtendedTranslucency/ExtendedTranslucency.hlsli"
# define ANISOTROPIC_ALPHA
# endif

# define LinearSampler SampColorSampler

# include "Common/ShadowSampling.hlsli"
Expand Down Expand Up @@ -3108,6 +3113,47 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
discard;
}
# endif // DO_ALPHA_TEST

# if defined(ANISOTROPIC_ALPHA)
// Uniform alpha material settings
uint AlphaMaterialModel = ExtendedTranslucency::GetMaterialModelFromDescriptor(Permutation::ExtraFeatureDescriptor);
float AlphaMaterialReduction = 0.f;
float AlphaMaterialSoftness = 0.f;
float AlphaMaterialStrength = 0.f;
if (AlphaMaterialModel == ExtendedTranslucency::MaterialModel::Default) {
AlphaMaterialModel = SharedData::extendedTranslucencySettings.MaterialModel;
AlphaMaterialReduction = SharedData::extendedTranslucencySettings.Reduction;
AlphaMaterialSoftness = SharedData::extendedTranslucencySettings.Softness;
AlphaMaterialStrength = SharedData::extendedTranslucencySettings.Strength;
}

[branch] if (ExtendedTranslucency::IsValidMaterial(AlphaMaterialModel))
{
if (alpha >= 0.0156862754 && alpha < 1.0) {
float originalAlpha = alpha;
alpha = alpha * (1.0 - AlphaMaterialReduction);
[branch] if (AlphaMaterialModel == ExtendedTranslucency::MaterialModel::AnisotropicFabric)
{
# if defined(SKINNED) || !defined(MODELSPACENORMALS)
alpha = ExtendedTranslucency::GetViewDependentAlphaFabric2D(alpha, viewDirection, tbnTr);
# else
alpha = ExtendedTranslucency::GetViewDependentAlphaFabric1D(alpha, viewDirection, modelNormal.xyz);
# endif
}
else if (AlphaMaterialModel == ExtendedTranslucency::MaterialModel::IsotropicFabric)
{
alpha = ExtendedTranslucency::GetViewDependentAlphaFabric1D(alpha, viewDirection, modelNormal.xyz);
}
else
{
alpha = ExtendedTranslucency::GetViewDependentAlphaNaive(alpha, viewDirection, modelNormal.xyz);
}
alpha = saturate(ExtendedTranslucency::SoftClamp(alpha, 2.0f - AlphaMaterialSoftness));
alpha = lerp(alpha, originalAlpha, AlphaMaterialStrength);
}
}
# endif // ANISOTROPIC_ALPHA

psout.Diffuse.w = alpha;

# endif
Expand Down
4 changes: 3 additions & 1 deletion src/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Features/CloudShadows.h"
#include "Features/DynamicCubemaps.h"
#include "Features/ExtendedMaterials.h"
#include "Features/ExtendedTranslucency.h"
#include "Features/GrassCollision.h"
#include "Features/GrassLighting.h"
#include "Features/HairSpecular.h"
Expand Down Expand Up @@ -207,7 +208,8 @@ const std::vector<Feature*>& Feature::GetFeatureList()
globals::features::hairSpecular,
globals::features::interiorSunShadows,
globals::features::terrainVariation,
globals::features::ibl
globals::features::ibl,
globals::features::extendedTranslucency
};

static std::vector<Feature*> featuresVR = [] {
Expand Down
4 changes: 3 additions & 1 deletion src/FeatureBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Features/CloudShadows.h"
#include "Features/DynamicCubemaps.h"
#include "Features/ExtendedMaterials.h"
#include "Features/ExtendedTranslucency.h"
#include "Features/GrassLighting.h"
#include "Features/HairSpecular.h"
#include "Features/IBL.h"
Expand Down Expand Up @@ -45,5 +46,6 @@ std::pair<unsigned char*, size_t> GetFeatureBufferData(bool a_inWorld)
globals::features::lodBlending->settings,
globals::features::hairSpecular->settings,
globals::features::terrainVariation->settings,
globals::features::ibl->settings);
globals::features::ibl->settings,
globals::features::extendedTranslucency->settings);
}
133 changes: 133 additions & 0 deletions src/Features/ExtendedTranslucency.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "ExtendedTranslucency.h"

#include "../ShaderCache.h"
#include "../State.h"
#include "../Util.h"

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
ExtendedTranslucency::MaterialParams,
AlphaMode,
AlphaReduction,
AlphaSoftness,
AlphaStrength);

const RE::BSFixedString ExtendedTranslucency::NiExtraDataName_AnisotropicAlphaMaterial = "AnisotropicAlphaMaterial";

ExtendedTranslucency* ExtendedTranslucency::GetSingleton()
{
static ExtendedTranslucency singleton;
return &singleton;
}

void ExtendedTranslucency::BSLightingShader_SetupGeometry(RE::BSRenderPass* pass)
{
globals::state->currentExtraFeatureDescriptor &= ~(ExtraFeatureDescriptorMask << ExtraFeatureDescriptorShift);
// TODO: PERFORMANCE: Caching the feature descriptor in map<RE::BSGeometry*, uint> if this get more complex
if (auto* data = pass->geometry->GetExtraData(NiExtraDataName_AnisotropicAlphaMaterial)) {
static const REL::Relocation<const RE::NiRTTI*> NiIntegerExtraDataRTTI{ RE::NiIntegerExtraData::Ni_RTTI };
// netimmerse_cast<RE::NiIntegerExtraData*>(data) seems not working here
if (data->GetRTTI() == NiIntegerExtraDataRTTI.get()) {
Comment thread
ArcEarth marked this conversation as resolved.
uint32_t material = static_cast<uint32_t>(static_cast<RE::NiIntegerExtraData*>(data)->value) & ExtraFeatureDescriptorMask;
if (material == MaterialModel::Disabled) {
// MaterialModel::Disabled (0) is the flag when this extra does not exist
// And it will let the effect use default settings instead of force disable it
// Ensure this is disabled by using the ForceDisabled flag
material = MaterialModel::ForceDisabled;
}
globals::state->currentExtraFeatureDescriptor |= (material << ExtraFeatureDescriptorShift);

// TODO: Per-material settings from Nif
// Mods supporting this feature should adjust their alpha value in texture already
// And the texture should be adjusted based on full strength param
}
}
}

struct ExtendedTranslucency::Hooks
{
struct BSLightingShader_SetupGeometry
{
static void thunk(RE::BSShader* This, RE::BSRenderPass* Pass, uint32_t RenderFlags)
{
ExtendedTranslucency::BSLightingShader_SetupGeometry(Pass);
func(This, Pass, RenderFlags);
}
static inline REL::Relocation<decltype(thunk)> func;
};

static void Install()
{
stl::write_vfunc<0x6, BSLightingShader_SetupGeometry>(RE::VTABLE_BSLightingShader[0]);
logger::info("[ExtendedTranslucency] Installed hooks - BSLightingShader_SetupGeometry");
}
};

void ExtendedTranslucency::PostPostLoad()
{
Hooks::Install();
}

void ExtendedTranslucency::DrawSettings()
{
if (ImGui::TreeNodeEx("Translucent Material", ImGuiTreeNodeFlags_DefaultOpen)) {
static const char* AlphaModeNames[4] = {
"Disabled",
"Rim Light",
"Isotropic Fabric",
"Anisotropic Fabric"
};

bool changed = false;
if (ImGui::Combo("Default Material Model", (int*)&settings.AlphaMode, AlphaModeNames, 4)) {
changed = true;
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text(
"Anisotropic transluency will make the surface more opaque when you view it parallel to the surface.\n"
" - Disabled: No anisotropic transluency\n"
" - Rim Light: Naive rim light effect\n"
" - Isotropic Fabric: Imaginary fabric weaved from threads in one direction, respect normal map.\n"
" - Anisotropic Fabric: Common fabric weaved from tangent and birnormal direction, ignores normal map.\n");
}

if (ImGui::SliderFloat("Transparency Increase", &settings.AlphaReduction, 0.f, 1.f)) {
changed = true;
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text("Transluent material will make the material more opaque on average, which could be different from the intent, reduce the alpha to counter this effect and increase the dynamic range of the output.");
}

if (ImGui::SliderFloat("Softness", &settings.AlphaSoftness, 0.0f, 1.0f)) {
changed = true;
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text("Control the softness of the alpha increase, increase the softness reduce the increased amount of alpha.");
}

if (ImGui::SliderFloat("Blend Weight", &settings.AlphaStrength, 0.0f, 1.0f)) {
changed = true;
}
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text("Control the blend weight of the effect applied to the final result.");
}

ImGui::Spacing();
ImGui::Spacing();
ImGui::TreePop();
}
}

void ExtendedTranslucency::LoadSettings(json& o_json)
{
settings = o_json;
}

void ExtendedTranslucency::SaveSettings(json& o_json)
{
o_json = settings;
}

void ExtendedTranslucency::RestoreDefaultSettings()
{
settings = {};
}
53 changes: 53 additions & 0 deletions src/Features/ExtendedTranslucency.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include "../Buffer.h"
#include "../Feature.h"

struct ExtendedTranslucency final : Feature
{
static ExtendedTranslucency* GetSingleton();

virtual inline std::string GetName() override { return "Extended Translucency"; }
virtual inline std::string GetShortName() override { return "ExtendedTranslucency"; }
virtual inline std::string_view GetShaderDefineName() override { return "EXTENDED_TRANSLUCENCY"; }
virtual bool HasShaderDefine(RE::BSShader::Type shaderType) override { return RE::BSShader::Type::Lighting == shaderType; };
virtual void PostPostLoad() override;
virtual void DrawSettings() override;
virtual void LoadSettings(json& o_json) override;
virtual void SaveSettings(json& o_json) override;
virtual void RestoreDefaultSettings() override;
virtual bool SupportsVR() override { return true; };

// Future proof function for UI refactoring
std::string GetFeatureDescription() { return "Realistic rendering of thin fabric and other translucent materials"; } // Feature description for settings page
std::string GetFeatureModLink() { return "https://www.nexusmods.com/skyrimspecialedition/mods/150755"; }

static void BSLightingShader_SetupGeometry(RE::BSRenderPass* pass);

struct Hooks;

// TODO: Support more material model like glasses or arcylic
enum MaterialModel : uint32_t
{
Disabled = 0, // In ExtraFeatureDescriptor, this value means 'Default' instead of 'Disabled'
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
ForceDisabled = 7, // In ExtraFeatureDescriptor, value >= 4 means 'Disabled'
};

static constexpr uint32_t ExtraFeatureDescriptorShift = 6;
static constexpr uint32_t ExtraFeatureDescriptorMask = 7;

struct alignas(16) MaterialParams
{
uint32_t AlphaMode = MaterialModel::AnisotropicFabric;
float AlphaReduction = 0.15f;
float AlphaSoftness = 0.f;
float AlphaStrength = 0.f;
};

MaterialParams settings;

static const RE::BSFixedString NiExtraDataName_AnisotropicAlphaMaterial;
};
1 change: 1 addition & 0 deletions src/Features/TerrainHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ void TerrainHelper::BSLightingShader_SetupMaterial(RE::BSLightingShaderMaterialB
const auto& stateData = globals::game::graphicsState->GetRuntimeData();

// Populate extended slots
// Please update bits allocation in ExtraFeatureDescriptor/Permutation.hlsli and other feature code if you need to change the constant 6
for (uint32_t textureI = 0; textureI < 6; ++textureI) {
if (materialBase.parallax[textureI] != nullptr && materialBase.parallax[textureI] != stateData.defaultTextureNormalMap) {
thExtendedRendererState.SetPSTexture(textureI, materialBase.parallax[textureI]->rendererTexture);
Expand Down
3 changes: 3 additions & 0 deletions src/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Features/CloudShadows.h"
#include "Features/DynamicCubemaps.h"
#include "Features/ExtendedMaterials.h"
#include "Features/ExtendedTranslucency.h"
#include "Features/GrassCollision.h"
#include "Features/GrassLighting.h"
#include "Features/HairSpecular.h"
Expand Down Expand Up @@ -75,6 +76,7 @@ namespace globals
VR* vr = nullptr;
WaterEffects* waterEffects = nullptr;
WetnessEffects* wetnessEffects = nullptr;
ExtendedTranslucency* extendedTranslucency = nullptr;

namespace llf
{
Expand Down Expand Up @@ -158,6 +160,7 @@ namespace globals
features::vr = VR::GetSingleton();
features::waterEffects = WaterEffects::GetSingleton();
features::wetnessEffects = WetnessEffects::GetSingleton();
features::extendedTranslucency = ExtendedTranslucency::GetSingleton();

features::llf::particleLights = ParticleLights::GetSingleton();
}
Expand Down
Loading