Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: cloud shadows blend state reset #199

Merged
merged 2 commits into from
Mar 6, 2024
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
2 changes: 1 addition & 1 deletion package/Shaders/Sky.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct PS_OUTPUT
float2 MotionVectors : SV_Target1;
float4 Normal : SV_Target2;
#if defined(CLOUD_SHADOWS) && defined(CLOUDS)
float4 CloudShadows : SV_Target7;
float4 CloudShadows : SV_Target3;
#endif
};

Expand Down
65 changes: 43 additions & 22 deletions src/Features/CloudShadows.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "CloudShadows.h"

#include "State.h"

#include "Util.h"

#include "magic_enum_flags.hpp"
Expand All @@ -13,19 +15,17 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
TransparencyPower,
AbsorptionAmbient)

class FrameChecker
enum class SkyShaderTechniques
{
private:
uint32_t last_frame = UINT32_MAX;

public:
inline bool isNewFrame(uint32_t frame)
{
bool retval = last_frame != frame;
last_frame = frame;
return retval;
}
inline bool isNewFrame() { return isNewFrame(RE::BSGraphics::State::GetSingleton()->uiFrameCount); }
SunOcclude = 0,
SunGlare = 1,
MoonAndStarsMask = 2,
Stars = 3,
Clouds = 4,
CloudsLerp = 5,
CloudsFade = 6,
Texture = 7,
Sky = 8,
};

void CloudShadows::DrawSettings()
Expand Down Expand Up @@ -70,7 +70,7 @@ void CloudShadows::DrawSettings()

void CloudShadows::CheckResourcesSide(int side)
{
static FrameChecker frame_checker[6];
static Util::FrameChecker frame_checker[6];
if (!frame_checker[side].isNewFrame())
return;

Expand Down Expand Up @@ -136,14 +136,15 @@ void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor)
context->OMSetRenderTargets(4, rtvs, depthStencil);

// blend states
ID3D11BlendState* blendState;
FLOAT blendFactor[4];
UINT sampleMask;

ID3D11BlendState* blendState = nullptr;
FLOAT blendFactor[4] = { 0 };
UINT sampleMask = 0;

context->OMGetBlendState(&blendState, blendFactor, &sampleMask);

if (!mappedBlendStates.contains(blendState)) {
if (!modifiedBlendStates.contains(blendState)) {
if (modifiedBlendStates.contains(blendState)) {
D3D11_BLEND_DESC blendDesc;
blendState->GetDesc(&blendDesc);

Expand All @@ -155,8 +156,9 @@ void CloudShadows::ModifySky(const RE::BSShader*, const uint32_t descriptor)
mappedBlendStates.insert(modifiedBlendState);
modifiedBlendStates.insert({ blendState, modifiedBlendState });
}
blendState = modifiedBlendStates[blendState];
context->OMSetBlendState(blendState, blendFactor, sampleMask);
context->OMSetBlendState(modifiedBlendStates[blendState], blendFactor, sampleMask);

resetBlendState = blendState;
}
}
}
Expand All @@ -168,7 +170,7 @@ void CloudShadows::ModifyLighting()
auto shadowState = RE::BSGraphics::RendererShadowState::GetSingleton();
auto cubeMapRenderTarget = !REL::Module::IsVR() ? shadowState->GetRuntimeData().cubeMapRenderTarget : shadowState->GetVRRuntimeData().cubeMapRenderTarget;
if (cubeMapRenderTarget != RE::RENDER_TARGETS_CUBEMAP::kREFLECTIONS) {
static FrameChecker frame_checker;
static Util::FrameChecker frame_checker;
if (frame_checker.isNewFrame())
context->GenerateMips(texCubemapCloudOcc->srv.get());

Expand All @@ -186,7 +188,7 @@ void CloudShadows::ModifyLighting()

void CloudShadows::Draw(const RE::BSShader* shader, const uint32_t descriptor)
{
static FrameChecker frame_checker;
static Util::FrameChecker frame_checker;
if (frame_checker.isNewFrame()) {
// update settings buffer
auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context;
Expand Down Expand Up @@ -283,4 +285,23 @@ void CloudShadows::SetupResources()
void CloudShadows::RestoreDefaultSettings()
{
settings = {};
}
}

void CloudShadows::Hooks::BSBatchRenderer__RenderPassImmediately::thunk(RE::BSRenderPass* Pass, uint32_t Technique, bool AlphaTest, uint32_t RenderFlags)
{
auto feat = GetSingleton();
auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context;

func(Pass, Technique, AlphaTest, RenderFlags);

if (feat->resetBlendState) {
ID3D11BlendState* blendState = nullptr;
FLOAT blendFactor[4] = { 0 };
UINT sampleMask = 0;

context->OMGetBlendState(&blendState, blendFactor, &sampleMask);
context->OMSetBlendState(feat->resetBlendState, blendFactor, sampleMask);

feat->resetBlendState = nullptr;
}
}
40 changes: 29 additions & 11 deletions src/Features/CloudShadows.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ struct CloudShadows : Feature
return &singleton;
}

virtual inline std::string GetName() { return "Cloud Shadows"; }
virtual inline std::string GetShortName() { return "CloudShadows"; }
virtual inline std::string_view GetShaderDefineName() { return "CLOUD_SHADOWS"; }
virtual inline bool HasShaderDefine(RE::BSShader::Type) { return true; }
virtual inline std::string GetName() override { return "Cloud Shadows"; }
virtual inline std::string GetShortName() override { return "CloudShadows"; }
virtual inline std::string_view GetShaderDefineName() override { return "CLOUD_SHADOWS"; }
virtual inline bool HasShaderDefine(RE::BSShader::Type) override { return true; }

struct Settings
{
Expand All @@ -39,25 +39,43 @@ struct CloudShadows : Feature
};
std::unique_ptr<Buffer> perPass = nullptr;

bool isCubemapPass = false;
ID3D11BlendState* resetBlendState = nullptr;
std::set<ID3D11BlendState*> mappedBlendStates;
std::map<ID3D11BlendState*, ID3D11BlendState*> modifiedBlendStates;

Texture2D* texCubemapCloudOcc = nullptr;
ID3D11RenderTargetView* cubemapCloudOccRTVs[6] = { nullptr };
ID3D11ShaderResourceView* cubemapCloudOccDebugSRV = nullptr;

virtual void SetupResources();
virtual inline void Reset() {}
virtual void SetupResources() override;
virtual inline void Reset() override {}

virtual void DrawSettings();
virtual void DrawSettings() override;

void CheckResourcesSide(int side);
void ModifySky(const RE::BSShader* shader, const uint32_t descriptor);
void ModifyLighting();
virtual void Draw(const RE::BSShader* shader, const uint32_t descriptor);
virtual void Draw(const RE::BSShader* shader, const uint32_t descriptor) override;

virtual void Load(json& o_json);
virtual void Save(json& o_json);
virtual void Load(json& o_json) override;
virtual void Save(json& o_json) override;

virtual void RestoreDefaultSettings();
virtual void RestoreDefaultSettings() override;

virtual inline void PostPostLoad() override { Hooks::Install(); }

struct Hooks
{
struct BSBatchRenderer__RenderPassImmediately
{
static void thunk(RE::BSRenderPass* Pass, uint32_t Technique, bool AlphaTest, uint32_t RenderFlags);
static inline REL::Relocation<decltype(thunk)> func;
};

static void Install()
{
stl::write_thunk_call<BSBatchRenderer__RenderPassImmediately>(REL::RelocationID(100877, 107630).address() + REL::Relocate(0x1E5, 0xFD)); // need SE addr
}
};
};
Loading