diff --git a/features/TruePBR/CORE b/features/TruePBR/CORE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/features/TruePBR/Shaders/Features/TruePBR.ini b/features/TruePBR/Shaders/Features/TruePBR.ini new file mode 100644 index 0000000000..000b60a568 --- /dev/null +++ b/features/TruePBR/Shaders/Features/TruePBR.ini @@ -0,0 +1,2 @@ +[Info] +Version = 1-0-0 diff --git a/src/Deferred.cpp b/src/Deferred.cpp index c21f22091f..05236a6bba 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -4,7 +4,6 @@ #include "ShaderCache.h" #include "State.h" -#include "TruePBR.h" #include "Utils/D3D.h" #include "Features/DynamicCubemaps.h" @@ -217,7 +216,6 @@ void Deferred::PrepassPasses() auto context = globals::d3d::context; context->OMSetRenderTargets(0, nullptr, nullptr); // Unbind all bound render targets - globals::truePBR->PrePass(); Feature::ForEachLoadedFeature("Prepass", [](Feature* feature) { feature->Prepass(); }, true); } @@ -768,7 +766,4 @@ void Deferred::Hooks::Renderer_ResetState::thunk(void* This) ID3D11Buffer* buffers[3] = { state->permutationCB->CB(), state->sharedDataCB->CB(), state->featureDataCB->CB() }; context->PSSetConstantBuffers(4, 3, buffers); context->CSSetConstantBuffers(5, 2, buffers + 1); - - auto* singleton = globals::truePBR; - singleton->SetupFrame(); } diff --git a/src/Feature.cpp b/src/Feature.cpp index ab2a8db684..0a5f8010f1 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -43,6 +43,7 @@ #include "WeatherVariableRegistry.h" #include "State.h" +#include "TruePBR.h" void Feature::Load(json& o_json) { @@ -209,6 +210,7 @@ void Feature::WriteDiskCacheInfo(CSimpleIniA& a_ini) const std::vector& Feature::GetFeatureList() { static std::vector features = { + &globals::features::truePBR, &globals::features::volumetricShadows, &globals::features::grassLighting, &globals::features::grassCollision, diff --git a/src/Feature.h b/src/Feature.h index 3667391bad..95ca1741a7 100644 --- a/src/Feature.h +++ b/src/Feature.h @@ -95,6 +95,18 @@ struct Feature virtual void Prepass() {} virtual void EarlyPrepass() {} + /** + * @brief Called during disk-cache shader loading to generate additional shader permutations. + * + * Invoked once per BSShader load when the shader cache is in disk-cache mode. + * Features can override this to inject custom permutation descriptors into the + * shader cache so that feature-specific technique variants are compiled and stored. + * This is a cold path (disk I/O, not per-frame); performance is not critical here. + * + * @param shader The BSShader being loaded. + */ + virtual void GenerateShaderPermutations(RE::BSShader*) {} + virtual void Load() {} // Called during SKSE Load - earliest hook point only for critical hooks like d3d virtual void DataLoaded() {} virtual void PostPostLoad() {} diff --git a/src/FeatureBuffer.cpp b/src/FeatureBuffer.cpp index 813fa75027..f876879095 100644 --- a/src/FeatureBuffer.cpp +++ b/src/FeatureBuffer.cpp @@ -17,8 +17,6 @@ #include "Features/TerrainVariation.h" #include "Features/WetnessEffects.h" -#include "TruePBR.h" - template std::pair _GetFeatureBufferData(Ts... feat_datas) { diff --git a/src/Features/TerrainHelper.cpp b/src/Features/TerrainHelper.cpp index 852017d243..300c5543ce 100644 --- a/src/Features/TerrainHelper.cpp +++ b/src/Features/TerrainHelper.cpp @@ -1,5 +1,6 @@ #include "TerrainHelper.h" +#include "Globals.h" #include "ShaderCache.h" #include "State.h" @@ -191,4 +192,46 @@ void TerrainHelper::BSLightingShader_SetupMaterial(RE::BSLightingShaderMaterialB state->permutationData.ExtraFeatureDescriptor &= ~(1 << textureI); } } +} + +struct TH_TESObjectLAND_SetupMaterial +{ + static bool thunk(RE::TESObjectLAND* land) + { + bool result = func(land); + + // TruePBR sets flag 8 on land cells it processes as PBR; skip TerrainHelper for those. + if (!land->data.flags.any(static_cast(8))) { + auto& terrainHelper = globals::features::terrainHelper; + if (result && terrainHelper.loaded) { + terrainHelper.TESObjectLAND_SetupMaterial(land); + } + } + + return result; + } + static inline REL::Relocation func; +}; + +struct TH_BSLightingShader_SetupMaterial +{ + static void thunk(RE::BSLightingShader* shader, RE::BSLightingShaderMaterialBase const* material) + { + func(shader, material); + + auto& terrainHelper = globals::features::terrainHelper; + if (terrainHelper.loaded) { + terrainHelper.BSLightingShader_SetupMaterial(material); + } + } + static inline REL::Relocation func; +}; + +void TerrainHelper::PostPostLoad() +{ + logger::info("[Terrain Helper] Hooking TESObjectLAND"); + stl::detour_thunk(REL::RelocationID(18368, 18791)); + + logger::info("[Terrain Helper] Hooking BSLightingShader::SetupMaterial"); + stl::write_vfunc<0x4, TH_BSLightingShader_SetupMaterial>(RE::VTABLE_BSLightingShader[0]); } \ No newline at end of file diff --git a/src/Features/TerrainHelper.h b/src/Features/TerrainHelper.h index 1e3ca470cb..69166c0d7f 100644 --- a/src/Features/TerrainHelper.h +++ b/src/Features/TerrainHelper.h @@ -38,6 +38,7 @@ struct TerrainHelper : Feature bool enabled = false; virtual void DataLoaded() override; + virtual void PostPostLoad() override; virtual bool SupportsVR() override { return true; }; virtual std::string GetFeatureModLink() override { return MakeNexusModURL(MOD_ID); } diff --git a/src/Globals.cpp b/src/Globals.cpp index 221bb8c3ad..144a307c96 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -86,6 +86,7 @@ namespace globals RenderDoc renderDoc{}; WeatherEditor weatherEditor{}; ExponentialHeightFog exponentialHeightFog{}; + TruePBR truePBR{}; namespace llf { @@ -144,7 +145,6 @@ namespace globals State* state = nullptr; Deferred* deferred = nullptr; - TruePBR* truePBR = nullptr; Menu* menu = nullptr; SIE::ShaderCache* shaderCache = nullptr; @@ -154,7 +154,6 @@ namespace globals state = State::GetSingleton(); menu = Menu::GetSingleton(); deferred = Deferred::GetSingleton(); - truePBR = TruePBR::GetSingleton(); } void ReInit() diff --git a/src/Globals.h b/src/Globals.h index c73b7c1e9e..3aa2f06e04 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -93,6 +93,7 @@ namespace globals extern RenderDoc renderDoc; extern WeatherEditor weatherEditor; extern ExponentialHeightFog exponentialHeightFog; + extern TruePBR truePBR; namespace llf { @@ -257,7 +258,6 @@ namespace globals extern State* state; extern Deferred* deferred; - extern TruePBR* truePBR; extern Menu* menu; extern SIE::ShaderCache* shaderCache; diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 767ab92288..d97cf4da87 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -7,13 +7,11 @@ #include "Menu.h" #include "ShaderCache.h" #include "State.h" -#include "TruePBR.h" #include "Util.h" #include "Features/HDRDisplay.h" #include "Features/InteriorSun.h" #include "Features/LightLimitFix.h" -#include "Features/TerrainHelper.h" #include "Features/Upscaling.h" #include "Features/VR.h" #include "Features/VolumetricLighting.h" @@ -77,11 +75,11 @@ struct BSShader_LoadShaders auto state = globals::state; auto shaderCache = globals::shaderCache; - auto truePBR = globals::truePBR; - if (shaderCache->IsDiskCache() || shaderCache->IsDump()) { if (shaderCache->IsDiskCache()) { - truePBR->GenerateShaderPermutations(shader); + Feature::ForEachLoadedFeature("GenerateShaderPermutations", [shader](Feature* feature) { + feature->GenerateShaderPermutations(shader); + }); } for (const auto& entry : shader->vertexShaders) { @@ -758,53 +756,6 @@ namespace Hooks static inline REL::Relocation func; }; - struct TESObjectLAND_SetupMaterial - { - static bool thunk(RE::TESObjectLAND* land) - { - bool vanillaResult = func(land); - - // setup material for PBR - auto TruePBRSingleton = globals::truePBR; - if (TruePBRSingleton->TESObjectLAND_SetupMaterial(land)) { - // if PBR, we are done - return true; - } - - // setup material for terrain helper - auto& terrainHelper = globals::features::terrainHelper; - if (vanillaResult && terrainHelper.loaded) { - terrainHelper.TESObjectLAND_SetupMaterial(land); - } - - return vanillaResult; - } - static inline REL::Relocation func; - }; - - struct BSLightingShader_SetupMaterial - { - static void thunk(RE::BSLightingShader* shader, RE::BSLightingShaderMaterialBase const* material) - { - // setup material for PBR - auto TruePBRSingleton = globals::truePBR; - if (TruePBRSingleton->BSLightingShader_SetupMaterial(shader, material)) { - // if PBR, we are done - return; - } - - // vanilla - func(shader, material); - - // terrain helper - auto& terrainHelper = globals::features::terrainHelper; - if (terrainHelper.loaded) { - terrainHelper.BSLightingShader_SetupMaterial(material); - } - }; - static inline REL::Relocation func; - }; - #ifdef TRACY_ENABLE struct Main_Update { @@ -1010,12 +961,6 @@ namespace Hooks stl::write_thunk_call(REL::RelocationID(15214, 15383).address() + REL::Relocate(0x45B, 0x4F5)); stl::write_vfunc<0x6, GrassExtensions::BSGrassShader_SetupGeometry>(RE::VTABLE_BSGrassShader[0]); - logger::info("Hooking TESObjectLAND"); - stl::detour_thunk(REL::RelocationID(18368, 18791)); - - logger::info("Hooking BSLightingShader"); - stl::write_vfunc<0x4, BSLightingShader_SetupMaterial>(RE::VTABLE_BSLightingShader[0]); - // Patch render space in BSLightingShader::SetupGeometry to always use world space // The variable updateEyePosition is set to 1 when not skinned. By patching to be 0 it will always use world space // We offset from the base address of the containing function to the start of the patch diff --git a/src/Menu.cpp b/src/Menu.cpp index 2bd4d7398a..d12a9f5aa0 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -35,7 +35,6 @@ #include "Menu/ThemeManager.h" #include "ShaderCache.h" #include "State.h" -#include "TruePBR.h" #include "Util.h" #include "Utils/UI.h" @@ -771,9 +770,7 @@ void Menu::DrawGeneralSettings() */ void Menu::DrawAdvancedSettings() { - // Render advanced settings using extracted component AdvancedSettingsRenderer::RenderAdvancedSettings( - [this]() { globals::truePBR->DrawSettings(); }, [this]() { DrawDisableAtBootSettings(); }); } @@ -789,27 +786,6 @@ void Menu::DrawDisableAtBootSettings() ImGui::Spacing(); - if (ImGui::CollapsingHeader("Special Features", ImGuiTreeNodeFlags_DefaultOpen)) { - // Prepare a sorted list of special feature names - std::vector specialFeatureNames; - for (const auto& [featureName, _] : state->specialFeatures) { - specialFeatureNames.push_back(featureName); - } - std::sort(specialFeatureNames.begin(), specialFeatureNames.end()); - - // Display sorted special features - for (const auto& featureName : specialFeatureNames) { - // Check if the feature is currently disabled - bool isDisabled = disabledFeatures.contains(featureName) && disabledFeatures[featureName]; - - // Create a checkbox for each feature - if (ImGui::Checkbox(featureName.c_str(), &isDisabled)) { - // Update the disabledFeatures map based on user interaction - disabledFeatures[featureName] = isDisabled; - } - } - } - if (ImGui::CollapsingHeader("Features", ImGuiTreeNodeFlags_DefaultOpen)) { // Prepare a sorted list of feature pointers auto featureList = Feature::GetFeatureList(); diff --git a/src/Menu/AdvancedSettingsRenderer.cpp b/src/Menu/AdvancedSettingsRenderer.cpp index 03695094c5..c69f4f4bc0 100644 --- a/src/Menu/AdvancedSettingsRenderer.cpp +++ b/src/Menu/AdvancedSettingsRenderer.cpp @@ -13,13 +13,11 @@ #include "Menu.h" #include "ShaderCache.h" #include "State.h" -#include "TruePBR.h" #include "Util.h" #include "Utils/Format.h" #include "Utils/UI.h" void AdvancedSettingsRenderer::RenderAdvancedSettings( - const std::function& drawTruePBRSettings, const std::function& drawDisableAtBootSettings) { // Use TabBar system - tabs sorted alphabetically @@ -51,14 +49,6 @@ void AdvancedSettingsRenderer::RenderAdvancedSettings( ImGui::EndTabItem(); } - // PBR Settings Tab - if (MenuFonts::BeginTabItemWithFont("PBR Settings", Menu::FontRole::Subheading)) { - if (ImGui::BeginChild("##PBRSettingsContent", ImVec2(0, 0), false)) { - RenderPBRSection(drawTruePBRSettings); - } - ImGui::EndChild(); - ImGui::EndTabItem(); - } // Shader Debug Tab if (MenuFonts::BeginTabItemWithFont("Shader Debug", Menu::FontRole::Subheading)) { if (ImGui::BeginChild("##ShaderDebugContent", ImVec2(0, 0), false)) { @@ -514,11 +504,6 @@ void AdvancedSettingsRenderer::RenderShaderDebugSection() } } -void AdvancedSettingsRenderer::RenderPBRSection(const std::function& drawTruePBRSettings) -{ - drawTruePBRSettings(); -} - void AdvancedSettingsRenderer::RenderDisableAtBootSection(const std::function& drawDisableAtBootSettings) { drawDisableAtBootSettings(); diff --git a/src/Menu/AdvancedSettingsRenderer.h b/src/Menu/AdvancedSettingsRenderer.h index 3d466e2a09..086486c246 100644 --- a/src/Menu/AdvancedSettingsRenderer.h +++ b/src/Menu/AdvancedSettingsRenderer.h @@ -10,13 +10,11 @@ class AdvancedSettingsRenderer { public: static void RenderAdvancedSettings( - const std::function& drawTruePBRSettings, const std::function& drawDisableAtBootSettings); private: static void RenderLoggingSection(); static void RenderShaderDebugSection(); - static void RenderPBRSection(const std::function& drawTruePBRSettings); static void RenderDisableAtBootSection(const std::function& drawDisableAtBootSettings); static void RenderDeveloperSection(); static void RenderTestingSection(); diff --git a/src/State.cpp b/src/State.cpp index 96275c3a01..3a761caee5 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -52,7 +52,7 @@ void State::Draw() auto& terrainHelper = globals::features::terrainHelper; auto& cloudShadows = globals::features::cloudShadows; auto& weatherEditor = globals::features::weatherEditor; - auto truePBR = globals::truePBR; + auto& truePBR = globals::features::truePBR; auto context = globals::d3d::context; auto& volumetricShadows = globals::features::volumetricShadows; @@ -80,9 +80,9 @@ void State::Draw() terrainHelper.SetShaderResouces(context); } - { + if (truePBR.loaded) { ZoneScopedN("TruePBR::SetShaderResouces"); - truePBR->SetShaderResouces(context); + truePBR.SetShaderResouces(context); } if (permutationData != permutationDataPrevious) { @@ -205,7 +205,6 @@ void State::Reset() void State::Setup() { - globals::truePBR->SetupResources(); SetupResources(); // Probe typed UAV load support before features set up their resources, so any @@ -351,11 +350,6 @@ void State::Load(ConfigMode a_configMode, bool a_allowReload) logger::warn("Invalid entry for feature '{}' in 'Disable at Boot', expected boolean.", featureName); } } - for (const auto& [featureName, _] : specialFeatures) { - if (IsFeatureDisabled(featureName)) { - logger::info("Special Feature '{}' disabled at boot", featureName); - } - } for (auto* feature : Feature::GetFeatureList()) { try { const std::string featureName = feature->GetShortName(); diff --git a/src/State.h b/src/State.h index 78b08527fb..fe9ea593bb 100644 --- a/src/State.h +++ b/src/State.h @@ -325,10 +325,6 @@ class State }); } - // Features that are more special then others - std::unordered_map specialFeatures = { - { "TruePBR", false } - }; std::unordered_map disabledFeatures; std::mutex m_mutex; diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 9ac42daae1..9ba3ff0708 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -106,199 +106,197 @@ void SetupPBRLandscapeTextureParameters(BSLightingShaderMaterialPBRLandscape& ma void TruePBR::DrawSettings() { - if (ImGui::CollapsingHeader("PBR", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) { - if (ImGui::TreeNodeEx("Texture Set Settings", ImGuiTreeNodeFlags_DefaultOpen)) { - if (Util::SearchableCombo("Texture Set", selectedPbrTextureSetName, pbrTextureSets)) { - selectedPbrTextureSet = &pbrTextureSets[selectedPbrTextureSetName]; + if (ImGui::TreeNodeEx("Texture Set Settings", ImGuiTreeNodeFlags_DefaultOpen)) { + if (Util::SearchableCombo("Texture Set", selectedPbrTextureSetName, pbrTextureSets)) { + selectedPbrTextureSet = &pbrTextureSets[selectedPbrTextureSetName]; + } + + if (selectedPbrTextureSet != nullptr) { + bool wasEdited = false; + if (ImGui::SliderFloat("Displacement Scale", &selectedPbrTextureSet->displacementScale, 0.f, 3.f, "%.3f")) { + wasEdited = true; + } + if (ImGui::SliderFloat("Roughness Scale", &selectedPbrTextureSet->roughnessScale, 0.f, 3.f, "%.3f")) { + wasEdited = true; + } + if (ImGui::SliderFloat("Specular Level", &selectedPbrTextureSet->specularLevel, 0.f, 3.f, "%.3f")) { + wasEdited = true; } + if (ImGui::TreeNodeEx("Subsurface")) { + if (ImGui::ColorPicker3("Subsurface Color", &selectedPbrTextureSet->subsurfaceColor.red)) { + wasEdited = true; + } + if (ImGui::SliderFloat("Subsurface Opacity", &selectedPbrTextureSet->subsurfaceOpacity, 0.f, 1.f, "%.3f")) { + wasEdited = true; + } - if (selectedPbrTextureSet != nullptr) { - bool wasEdited = false; - if (ImGui::SliderFloat("Displacement Scale", &selectedPbrTextureSet->displacementScale, 0.f, 3.f, "%.3f")) { + ImGui::TreePop(); + } + if (ImGui::TreeNodeEx("Coat")) { + if (ImGui::ColorPicker3("Coat Color", &selectedPbrTextureSet->coatColor.red)) { wasEdited = true; } - if (ImGui::SliderFloat("Roughness Scale", &selectedPbrTextureSet->roughnessScale, 0.f, 3.f, "%.3f")) { + if (ImGui::SliderFloat("Coat Strength", &selectedPbrTextureSet->coatStrength, 0.f, 1.f, "%.3f")) { wasEdited = true; } - if (ImGui::SliderFloat("Specular Level", &selectedPbrTextureSet->specularLevel, 0.f, 3.f, "%.3f")) { + if (ImGui::SliderFloat("Coat Roughness", &selectedPbrTextureSet->coatRoughness, 0.f, 1.f, "%.3f")) { wasEdited = true; } - if (ImGui::TreeNodeEx("Subsurface")) { - if (ImGui::ColorPicker3("Subsurface Color", &selectedPbrTextureSet->subsurfaceColor.red)) { - wasEdited = true; - } - if (ImGui::SliderFloat("Subsurface Opacity", &selectedPbrTextureSet->subsurfaceOpacity, 0.f, 1.f, "%.3f")) { - wasEdited = true; - } - - ImGui::TreePop(); + if (ImGui::SliderFloat("Coat Specular Level", &selectedPbrTextureSet->coatSpecularLevel, 0.f, 1.f, "%.3f")) { + wasEdited = true; } - if (ImGui::TreeNodeEx("Coat")) { - if (ImGui::ColorPicker3("Coat Color", &selectedPbrTextureSet->coatColor.red)) { - wasEdited = true; - } - if (ImGui::SliderFloat("Coat Strength", &selectedPbrTextureSet->coatStrength, 0.f, 1.f, "%.3f")) { + if (ImGui::SliderFloat("Inner Layer Displacement Offset", &selectedPbrTextureSet->innerLayerDisplacementOffset, 0.f, 3.f, "%.3f")) { + wasEdited = true; + } + ImGui::TreePop(); + } + if (ImGui::TreeNodeEx("Glint")) { + if (ImGui::Checkbox("Enabled", &selectedPbrTextureSet->glintParameters.enabled)) { + wasEdited = true; + } + if (selectedPbrTextureSet->glintParameters.enabled) { + if (ImGui::SliderFloat("Screenspace Scale", &selectedPbrTextureSet->glintParameters.screenSpaceScale, 0.f, 3.f, "%.3f")) { wasEdited = true; } - if (ImGui::SliderFloat("Coat Roughness", &selectedPbrTextureSet->coatRoughness, 0.f, 1.f, "%.3f")) { + if (ImGui::SliderFloat("Log Microfacet Density", &selectedPbrTextureSet->glintParameters.logMicrofacetDensity, 0.f, 40.f, "%.3f")) { wasEdited = true; } - if (ImGui::SliderFloat("Coat Specular Level", &selectedPbrTextureSet->coatSpecularLevel, 0.f, 1.f, "%.3f")) { + if (ImGui::SliderFloat("Microfacet Roughness", &selectedPbrTextureSet->glintParameters.microfacetRoughness, 0.f, 1.f, "%.3f")) { wasEdited = true; } - if (ImGui::SliderFloat("Inner Layer Displacement Offset", &selectedPbrTextureSet->innerLayerDisplacementOffset, 0.f, 3.f, "%.3f")) { + if (ImGui::SliderFloat("Density Randomization", &selectedPbrTextureSet->glintParameters.densityRandomization, 0.f, 5.f, "%.3f")) { wasEdited = true; } - ImGui::TreePop(); } - if (ImGui::TreeNodeEx("Glint")) { - if (ImGui::Checkbox("Enabled", &selectedPbrTextureSet->glintParameters.enabled)) { - wasEdited = true; - } - if (selectedPbrTextureSet->glintParameters.enabled) { - if (ImGui::SliderFloat("Screenspace Scale", &selectedPbrTextureSet->glintParameters.screenSpaceScale, 0.f, 3.f, "%.3f")) { - wasEdited = true; - } - if (ImGui::SliderFloat("Log Microfacet Density", &selectedPbrTextureSet->glintParameters.logMicrofacetDensity, 0.f, 40.f, "%.3f")) { - wasEdited = true; - } - if (ImGui::SliderFloat("Microfacet Roughness", &selectedPbrTextureSet->glintParameters.microfacetRoughness, 0.f, 1.f, "%.3f")) { - wasEdited = true; - } - if (ImGui::SliderFloat("Density Randomization", &selectedPbrTextureSet->glintParameters.densityRandomization, 0.f, 5.f, "%.3f")) { - wasEdited = true; - } + ImGui::TreePop(); + } + if (wasEdited) { + for (auto& [material, extensions] : BSLightingShaderMaterialPBR::All) { + if (extensions.textureSetData == selectedPbrTextureSet) { + material->ApplyTextureSetData(*extensions.textureSetData); } - ImGui::TreePop(); } - if (wasEdited) { - for (auto& [material, extensions] : BSLightingShaderMaterialPBR::All) { - if (extensions.textureSetData == selectedPbrTextureSet) { - material->ApplyTextureSetData(*extensions.textureSetData); - } - } - for (auto& [material, textureSets] : BSLightingShaderMaterialPBRLandscape::All) { - for (uint32_t textureSetIndex = 0; textureSetIndex < BSLightingShaderMaterialPBRLandscape::NumTiles; ++textureSetIndex) { - if (textureSets[textureSetIndex] == selectedPbrTextureSet) { - SetupPBRLandscapeTextureParameters(*material, *textureSets[textureSetIndex], textureSetIndex); - } + for (auto& [material, textureSets] : BSLightingShaderMaterialPBRLandscape::All) { + for (uint32_t textureSetIndex = 0; textureSetIndex < BSLightingShaderMaterialPBRLandscape::NumTiles; ++textureSetIndex) { + if (textureSets[textureSetIndex] == selectedPbrTextureSet) { + SetupPBRLandscapeTextureParameters(*material, *textureSets[textureSetIndex], textureSetIndex); } } } - if (selectedPbrTextureSet != nullptr) { - if (ImGui::Button("Save")) { - PNState::SavePBRRecordConfig("Data\\PBRTextureSets", selectedPbrTextureSetName, *selectedPbrTextureSet); - } + } + if (selectedPbrTextureSet != nullptr) { + if (ImGui::Button("Save")) { + PNState::SavePBRRecordConfig("Data\\PBRTextureSets", selectedPbrTextureSetName, *selectedPbrTextureSet); } } - ImGui::TreePop(); } + ImGui::TreePop(); + } - if (ImGui::TreeNodeEx("Material Object Settings", ImGuiTreeNodeFlags_DefaultOpen)) { - if (Util::SearchableCombo("Material Object", selectedPbrMaterialObjectName, pbrMaterialObjects)) { - selectedPbrMaterialObject = &pbrMaterialObjects[selectedPbrMaterialObjectName]; - } - - if (selectedPbrMaterialObject != nullptr) { - bool wasEdited = false; - if (ImGui::TreeNodeEx("Base Color Scale", ImGuiTreeNodeFlags_DefaultOpen)) { - if (ImGui::Button("Reset to 1.0##BaseColorScale")) { - selectedPbrMaterialObject->baseColorScale = { 1.f, 1.f, 1.f }; - wasEdited = true; - } + if (ImGui::TreeNodeEx("Material Object Settings", ImGuiTreeNodeFlags_DefaultOpen)) { + if (Util::SearchableCombo("Material Object", selectedPbrMaterialObjectName, pbrMaterialObjects)) { + selectedPbrMaterialObject = &pbrMaterialObjects[selectedPbrMaterialObjectName]; + } - const float indent = ImGui::GetCursorPosX(); - const float defaultItemWidth = ImGui::CalcItemWidth(); - const float letterColWidth = ImGui::CalcTextSize("Green").x + ImGui::GetStyle().ItemSpacing.x; - const float sliderStartX = indent + letterColWidth; - const float sliderWidth = defaultItemWidth - (sliderStartX - ImGui::GetStyle().ItemSpacing.x); - const float colorLabelStartX = sliderStartX - ImGui::GetStyle().ItemSpacing.x - letterColWidth; - - ImGui::AlignTextToFramePadding(); - ImGui::SetCursorPosX(colorLabelStartX); - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.3f, 0.3f, 1.0f)); - ImGui::Text("Red"); - ImGui::PopStyleColor(); - ImGui::SameLine(sliderStartX); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.4f, 0.1f, 0.1f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.9f, 0.3f, 0.3f, 1.0f)); - ImGui::SetNextItemWidth(sliderWidth); - if (ImGui::SliderFloat("##BaseColorScaleR", &selectedPbrMaterialObject->baseColorScale[0], 0.f, 10.f, "%.3f")) { - wasEdited = true; - } - ImGui::PopStyleColor(2); - - ImGui::AlignTextToFramePadding(); - ImGui::SetCursorPosX(colorLabelStartX); - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3f, 0.9f, 0.3f, 1.0f)); - ImGui::Text("Green"); - ImGui::PopStyleColor(); - ImGui::SameLine(sliderStartX); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.1f, 0.4f, 0.1f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.3f, 0.9f, 0.3f, 1.0f)); - ImGui::SetNextItemWidth(sliderWidth); - if (ImGui::SliderFloat("##BaseColorScaleG", &selectedPbrMaterialObject->baseColorScale[1], 0.f, 10.f, "%.3f")) { - wasEdited = true; - } - ImGui::PopStyleColor(2); - - ImGui::AlignTextToFramePadding(); - ImGui::SetCursorPosX(colorLabelStartX); - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3f, 0.3f, 0.9f, 1.0f)); - ImGui::Text("Blue"); - ImGui::PopStyleColor(); - ImGui::SameLine(sliderStartX); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.1f, 0.1f, 0.4f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.3f, 0.3f, 0.9f, 1.0f)); - ImGui::SetNextItemWidth(sliderWidth); - if (ImGui::SliderFloat("##BaseColorScaleB", &selectedPbrMaterialObject->baseColorScale[2], 0.f, 10.f, "%.3f")) { - wasEdited = true; - } - ImGui::PopStyleColor(2); + if (selectedPbrMaterialObject != nullptr) { + bool wasEdited = false; + if (ImGui::TreeNodeEx("Base Color Scale", ImGuiTreeNodeFlags_DefaultOpen)) { + if (ImGui::Button("Reset to 1.0##BaseColorScale")) { + selectedPbrMaterialObject->baseColorScale = { 1.f, 1.f, 1.f }; + wasEdited = true; + } - ImGui::TreePop(); + const float indent = ImGui::GetCursorPosX(); + const float defaultItemWidth = ImGui::CalcItemWidth(); + const float letterColWidth = ImGui::CalcTextSize("Green").x + ImGui::GetStyle().ItemSpacing.x; + const float sliderStartX = indent + letterColWidth; + const float sliderWidth = defaultItemWidth - (sliderStartX - ImGui::GetStyle().ItemSpacing.x); + const float colorLabelStartX = sliderStartX - ImGui::GetStyle().ItemSpacing.x - letterColWidth; + + ImGui::AlignTextToFramePadding(); + ImGui::SetCursorPosX(colorLabelStartX); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.3f, 0.3f, 1.0f)); + ImGui::Text("Red"); + ImGui::PopStyleColor(); + ImGui::SameLine(sliderStartX); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.4f, 0.1f, 0.1f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.9f, 0.3f, 0.3f, 1.0f)); + ImGui::SetNextItemWidth(sliderWidth); + if (ImGui::SliderFloat("##BaseColorScaleR", &selectedPbrMaterialObject->baseColorScale[0], 0.f, 10.f, "%.3f")) { + wasEdited = true; } - if (ImGui::SliderFloat("Roughness", &selectedPbrMaterialObject->roughness, 0.f, 1.f, "%.3f")) { + ImGui::PopStyleColor(2); + + ImGui::AlignTextToFramePadding(); + ImGui::SetCursorPosX(colorLabelStartX); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3f, 0.9f, 0.3f, 1.0f)); + ImGui::Text("Green"); + ImGui::PopStyleColor(); + ImGui::SameLine(sliderStartX); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.1f, 0.4f, 0.1f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.3f, 0.9f, 0.3f, 1.0f)); + ImGui::SetNextItemWidth(sliderWidth); + if (ImGui::SliderFloat("##BaseColorScaleG", &selectedPbrMaterialObject->baseColorScale[1], 0.f, 10.f, "%.3f")) { wasEdited = true; } - if (ImGui::SliderFloat("Specular Level", &selectedPbrMaterialObject->specularLevel, 0.f, 1.f, "%.3f")) { + ImGui::PopStyleColor(2); + + ImGui::AlignTextToFramePadding(); + ImGui::SetCursorPosX(colorLabelStartX); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3f, 0.3f, 0.9f, 1.0f)); + ImGui::Text("Blue"); + ImGui::PopStyleColor(); + ImGui::SameLine(sliderStartX); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.1f, 0.1f, 0.4f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.3f, 0.3f, 0.9f, 1.0f)); + ImGui::SetNextItemWidth(sliderWidth); + if (ImGui::SliderFloat("##BaseColorScaleB", &selectedPbrMaterialObject->baseColorScale[2], 0.f, 10.f, "%.3f")) { wasEdited = true; } - if (ImGui::TreeNodeEx("Glint")) { - if (ImGui::Checkbox("Enabled", &selectedPbrMaterialObject->glintParameters.enabled)) { + ImGui::PopStyleColor(2); + + ImGui::TreePop(); + } + if (ImGui::SliderFloat("Roughness", &selectedPbrMaterialObject->roughness, 0.f, 1.f, "%.3f")) { + wasEdited = true; + } + if (ImGui::SliderFloat("Specular Level", &selectedPbrMaterialObject->specularLevel, 0.f, 1.f, "%.3f")) { + wasEdited = true; + } + if (ImGui::TreeNodeEx("Glint")) { + if (ImGui::Checkbox("Enabled", &selectedPbrMaterialObject->glintParameters.enabled)) { + wasEdited = true; + } + if (selectedPbrMaterialObject->glintParameters.enabled) { + if (ImGui::SliderFloat("Screenspace Scale", &selectedPbrMaterialObject->glintParameters.screenSpaceScale, 0.f, 3.f, "%.3f")) { wasEdited = true; } - if (selectedPbrMaterialObject->glintParameters.enabled) { - if (ImGui::SliderFloat("Screenspace Scale", &selectedPbrMaterialObject->glintParameters.screenSpaceScale, 0.f, 3.f, "%.3f")) { - wasEdited = true; - } - if (ImGui::SliderFloat("Log Microfacet Density", &selectedPbrMaterialObject->glintParameters.logMicrofacetDensity, 0.f, 40.f, "%.3f")) { - wasEdited = true; - } - if (ImGui::SliderFloat("Microfacet Roughness", &selectedPbrMaterialObject->glintParameters.microfacetRoughness, 0.f, 1.f, "%.3f")) { - wasEdited = true; - } - if (ImGui::SliderFloat("Density Randomization", &selectedPbrMaterialObject->glintParameters.densityRandomization, 0.f, 5.f, "%.3f")) { - wasEdited = true; - } + if (ImGui::SliderFloat("Log Microfacet Density", &selectedPbrMaterialObject->glintParameters.logMicrofacetDensity, 0.f, 40.f, "%.3f")) { + wasEdited = true; } - ImGui::TreePop(); - } - if (wasEdited) { - for (auto& [material, extensions] : BSLightingShaderMaterialPBR::All) { - if (extensions.materialObjectData == selectedPbrMaterialObject) { - material->ApplyMaterialObjectData(*extensions.materialObjectData); - } + if (ImGui::SliderFloat("Microfacet Roughness", &selectedPbrMaterialObject->glintParameters.microfacetRoughness, 0.f, 1.f, "%.3f")) { + wasEdited = true; + } + if (ImGui::SliderFloat("Density Randomization", &selectedPbrMaterialObject->glintParameters.densityRandomization, 0.f, 5.f, "%.3f")) { + wasEdited = true; } } - if (selectedPbrMaterialObject != nullptr) { - if (ImGui::Button("Save")) { - PNState::SavePBRRecordConfig("Data\\PBRMaterialObjects", selectedPbrMaterialObjectName, *selectedPbrMaterialObject); + ImGui::TreePop(); + } + if (wasEdited) { + for (auto& [material, extensions] : BSLightingShaderMaterialPBR::All) { + if (extensions.materialObjectData == selectedPbrMaterialObject) { + material->ApplyMaterialObjectData(*extensions.materialObjectData); } } } - ImGui::TreePop(); + if (selectedPbrMaterialObject != nullptr) { + if (ImGui::Button("Save")) { + PNState::SavePBRRecordConfig("Data\\PBRMaterialObjects", selectedPbrMaterialObjectName, *selectedPbrMaterialObject); + } + } } + ImGui::TreePop(); } } @@ -308,8 +306,10 @@ void TruePBR::SetupResources() SetupMaterialObjectData(); } -void TruePBR::PrePass() +void TruePBR::Prepass() { + SetupDefaultPBRLandTextureSet(); + auto context = globals::d3d::context; if (!glintsNoiseTexture) SetupGlintsTexture(); @@ -395,11 +395,6 @@ void TruePBR::SetupGlintsTexture() noiseGenProgram->Release(); } -void TruePBR::SetupFrame() -{ - SetupDefaultPBRLandTextureSet(); -} - void TruePBR::SetupTextureSetData() { logger::info("[TruePBR] loading PBR texture set configs"); @@ -1091,7 +1086,7 @@ void SetupLandscapeTexture(BSLightingShaderMaterialPBRLandscape& material, RE::T return; } - auto truePBR = globals::truePBR; + auto truePBR = &globals::features::truePBR; auto* textureSetData = truePBR->GetPBRTextureSetData(textureSet); const bool isPbr = textureSetData != nullptr; @@ -1124,7 +1119,7 @@ bool TruePBR::TESObjectLAND_SetupMaterial(RE::TESObjectLAND* land) return false; } - auto singleton = globals::truePBR; + auto singleton = &globals::features::truePBR; bool isPbr = false; if (land->loadedData != nullptr) { @@ -1228,7 +1223,7 @@ struct TESForm_GetFormEditorID { static const char* thunk(const RE::TESForm* form) { - auto* singleton = globals::truePBR; + auto* singleton = &globals::features::truePBR; auto it = singleton->editorIDs.find(form->GetFormID()); if (it == singleton->editorIDs.cend()) { return ""; @@ -1242,7 +1237,7 @@ struct TESForm_SetFormEditorID { static bool thunk(RE::TESForm* form, const char* editorId) { - auto* singleton = globals::truePBR; + auto* singleton = &globals::features::truePBR; singleton->editorIDs[form->GetFormID()] = editorId; return true; } @@ -1254,7 +1249,7 @@ struct BSTempEffectSimpleDecal_SetupGeometry static void thunk(RE::BSTempEffectSimpleDecal* decal, RE::BSGeometry* geometry, RE::BGSTextureSet* textureSet, bool blended) { func(decal, geometry, textureSet, blended); - auto* singleton = globals::truePBR; + auto* singleton = &globals::features::truePBR; auto unknownProperty = geometry->GetGeometryRuntimeData().shaderProperty.get(); if (auto shaderProperty = unknownProperty->GetRTTI() == globals::rtti::BSLightingShaderPropertyRTTI.get() ? static_cast(unknownProperty) : nullptr; shaderProperty != nullptr && singleton->IsPBRTextureSet(textureSet)) { @@ -1291,7 +1286,7 @@ struct BSTempEffectGeometryDecal_Initialize static void thunk(RE::BSTempEffectGeometryDecal* decal) { func(decal); - auto* singleton = globals::truePBR; + auto* singleton = &globals::features::truePBR; if (decal->decal != nullptr && singleton->IsPBRTextureSet(decal->texSet)) { auto shaderProperty = static_cast(RE::MemoryManager::GetSingleton()->Allocate(sizeof(RE::BSLightingShaderProperty), 0, false)); @@ -1336,7 +1331,7 @@ struct TESBoundObject_Clone3D { static RE::NiAVObject* thunk(RE::TESBoundObject* object, RE::TESObjectREFR* ref, bool arg3) { - auto truePBR = globals::truePBR; + auto truePBR = &globals::features::truePBR; auto* result = func(object, ref, arg3); if (result != nullptr && ref != nullptr && ref->data.objectReference != nullptr && ref->data.objectReference->formType == RE::FormType::Static) { auto* stat = static_cast(ref->data.objectReference); @@ -1424,7 +1419,7 @@ struct BGSTextureSet_ToShaderTextureSet { static RE::BSShaderTextureSet* thunk(RE::BGSTextureSet* textureSet) { - auto truePBR = globals::truePBR; + auto truePBR = &globals::features::truePBR; truePBR->currentTextureSet = textureSet; return func(textureSet); @@ -1438,27 +1433,55 @@ struct BSLightingShaderProperty_OnLoadTextureSet { func(property, a2); - auto truePBR = globals::truePBR; + auto truePBR = &globals::features::truePBR; truePBR->currentTextureSet = nullptr; } static inline REL::Relocation func; }; +struct PBR_TESObjectLAND_SetupMaterial +{ + static bool thunk(RE::TESObjectLAND* land) + { + bool vanillaResult = func(land); + + if (globals::features::truePBR.TESObjectLAND_SetupMaterial(land)) { + return true; + } + + return vanillaResult; + } + static inline REL::Relocation func; +}; + +struct PBR_BSLightingShader_SetupMaterial +{ + static void thunk(RE::BSLightingShader* shader, RE::BSLightingShaderMaterialBase const* material) + { + if (globals::features::truePBR.BSLightingShader_SetupMaterial(shader, material)) { + return; + } + + func(shader, material); + } + static inline REL::Relocation func; +}; + void TruePBR::PostPostLoad() { - logger::info("Hooking BGSTextureSet"); + logger::info("[TruePBR] Hooking BGSTextureSet"); stl::detour_thunk(REL::RelocationID(20905, 21361)); - logger::info("Hooking BSLightingShaderProperty"); + logger::info("[TruePBR] Hooking BSLightingShaderProperty"); stl::write_vfunc<0x18, BSLightingShaderProperty_LoadBinary>(RE::VTABLE_BSLightingShaderProperty[0]); stl::write_vfunc<0x2A, BSLightingShaderProperty_GetRenderPasses>(RE::VTABLE_BSLightingShaderProperty[0]); stl::detour_thunk(REL::RelocationID(99865, 106510)); - logger::info("Hooking BSLightingShader"); + logger::info("[TruePBR] Hooking BSLightingShader"); stl::write_vfunc<0x6, BSLightingShader_SetupGeometry>(RE::VTABLE_BSLightingShader[0]); stl::detour_thunk_ignore_func(REL::RelocationID(101633, 108700)); - logger::info("Hooking TESLandTexture"); + logger::info("[TruePBR] Hooking TESLandTexture"); stl::write_vfunc<0x32, TESForm_GetFormEditorID>(RE::VTABLE_TESLandTexture[0]); stl::write_vfunc<0x33, TESForm_SetFormEditorID>(RE::VTABLE_TESLandTexture[0]); stl::write_vfunc<0x32, TESForm_GetFormEditorID>(RE::VTABLE_BGSTextureSet[0]); @@ -1470,14 +1493,20 @@ void TruePBR::PostPostLoad() stl::write_vfunc<0x32, TESForm_GetFormEditorID>(RE::VTABLE_TESWeather[0]); stl::write_vfunc<0x33, TESForm_SetFormEditorID>(RE::VTABLE_TESWeather[0]); - logger::info("Hooking BSTempEffectSimpleDecal"); + logger::info("[TruePBR] Hooking BSTempEffectSimpleDecal"); stl::detour_thunk(REL::RelocationID(29253, 30108)); - logger::info("Hooking BSTempEffectGeometryDecal"); + logger::info("[TruePBR] Hooking BSTempEffectGeometryDecal"); stl::write_vfunc<0x25, BSTempEffectGeometryDecal_Initialize>(RE::VTABLE_BSTempEffectGeometryDecal[0]); - logger::info("Hooking TESObjectSTAT"); + logger::info("[TruePBR] Hooking TESObjectSTAT"); stl::write_vfunc<0x4A, TESBoundObject_Clone3D>(RE::VTABLE_TESObjectSTAT[0]); + + logger::info("[TruePBR] Hooking TESObjectLAND"); + stl::detour_thunk(REL::RelocationID(18368, 18791)); + + logger::info("[TruePBR] Hooking BSLightingShader::SetupMaterial"); + stl::write_vfunc<0x4, PBR_BSLightingShader_SetupMaterial>(RE::VTABLE_BSLightingShader[0]); } void TruePBR::DataLoaded() diff --git a/src/TruePBR.h b/src/TruePBR.h index 2ead82c6e4..782d9a9498 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "Feature.h" struct GlintParameters { @@ -11,27 +11,42 @@ struct GlintParameters float densityRandomization = 2.f; }; -struct TruePBR +struct TruePBR : Feature { public: - static TruePBR* GetSingleton() + virtual std::string GetName() override { return "True PBR"; } + virtual std::string GetShortName() override { return "TruePBR"; } + virtual std::string_view GetCategory() const override { return FeatureCategories::kMaterials; } + virtual bool IsCore() const override { return true; } + virtual bool SupportsVR() override { return true; } + virtual bool IsInMenu() const override { return true; } + virtual bool DrawFailLoadMessage() const override { return false; } + + virtual std::pair> GetFeatureSummary() override { - static TruePBR singleton; - return &singleton; + return std::make_pair( + "True PBR replaces Skyrim's legacy material system with physically-based rendering. " + "Mod authors can supply PBR texture sets (roughness, metallic, displacement, etc.) " + "that are interpreted in a physically correct BRDF, producing realistic surface " + "response to lighting across all weather and time-of-day conditions.", + std::vector{ + "Physically-based BRDF (energy-conserving specular & diffuse)", + "Roughness, metallic, and displacement map support", + "Clearcoat, subsurface scattering, and fuzz layers", + "Procedural glint rendering for sparkle effects", + "Full landscape and decal PBR support" }); } - inline std::string GetShortName() { return "TruePBR"; } - - void DrawSettings(); - void SetupResources(); - void PrePass(); - void PostPostLoad(); - void DataLoaded(); + virtual void DrawSettings() override; + virtual void SetupResources() override; + virtual void Prepass() override; + virtual void PostPostLoad() override; + virtual void DataLoaded() override; bool TESObjectLAND_SetupMaterial(RE::TESObjectLAND* land); bool BSLightingShader_SetupMaterial(RE::BSLightingShader* shader, RE::BSLightingShaderMaterialBase const* material); void SetShaderResouces(ID3D11DeviceContext* a_context); - void GenerateShaderPermutations(RE::BSShader* shader); + virtual void GenerateShaderPermutations(RE::BSShader* shader) override; void SetupGlintsTexture(); eastl::unique_ptr glintsNoiseTexture = nullptr; @@ -59,8 +74,6 @@ struct TruePBR GlintParameters glintParameters; }; - void SetupFrame(); - void SetupTextureSetData(); void ReloadTextureSetData(); PBRTextureSetData* GetPBRTextureSetData(const RE::TESForm* textureSet); diff --git a/src/TruePBR/BSLightingShaderMaterialPBR.cpp b/src/TruePBR/BSLightingShaderMaterialPBR.cpp index 8b0be7f3de..30729d7514 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBR.cpp +++ b/src/TruePBR/BSLightingShaderMaterialPBR.cpp @@ -185,12 +185,12 @@ void BSLightingShaderMaterialPBR::OnLoadTextureSet(std::uint64_t arg1, RE::BSTex textureSet->SetTexture(FeaturesTexture0, featuresTexture0); textureSet->SetTexture(FeaturesTexture1, featuresTexture1); - auto* bgsTextureSet = globals::truePBR->currentTextureSet; + auto* bgsTextureSet = globals::features::truePBR.currentTextureSet; if (bgsTextureSet == nullptr) { bgsTextureSet = skyrim_cast(inTextureSet); } if (bgsTextureSet) { - if (auto* textureSetData = globals::truePBR->GetPBRTextureSetData(bgsTextureSet)) { + if (auto* textureSetData = globals::features::truePBR.GetPBRTextureSetData(bgsTextureSet)) { ApplyTextureSetData(*textureSetData); All[this].textureSetData = textureSetData; } diff --git a/src/XSEPlugin.cpp b/src/XSEPlugin.cpp index d8a4f2e81d..f1d7f6ac98 100644 --- a/src/XSEPlugin.cpp +++ b/src/XSEPlugin.cpp @@ -8,7 +8,6 @@ #include "SceneSettingsManager.h" #include "ShaderCache.h" #include "State.h" -#include "TruePBR.h" #include "ENB/ENBSeriesAPI.h" @@ -82,7 +81,6 @@ void MessageHandler(SKSE::MessagingInterface::Message* message) { if (errors.empty()) { Deferred::Hooks::Install(); - globals::truePBR->PostPostLoad(); Hooks::Install(); EngineFix::InstallOnPostPostLoadFixes(); FrameAnnotations::OnPostPostLoad(); @@ -132,7 +130,6 @@ void MessageHandler(SKSE::MessagingInterface::Message* message) shaderCache->WriteDiskCacheInfo(); } - globals::truePBR->DataLoaded(); Feature::ForEachLoadedFeature("DataLoaded", [](Feature* feature) { feature->DataLoaded(); }); }