diff --git a/package/Shaders/Common/GBuffer.hlsli b/package/Shaders/Common/GBuffer.hlsli index 5d308f5d09..d2f018869e 100644 --- a/package/Shaders/Common/GBuffer.hlsli +++ b/package/Shaders/Common/GBuffer.hlsli @@ -1,24 +1,40 @@ #ifndef __GBUFFER_DEPENDENCY_HLSL__ #define __GBUFFER_DEPENDENCY_HLSL__ +// https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/ + namespace GBuffer { + float2 OctWrap(float2 v) + { + return (1.0 - abs(v.yx)) * (v.xy >= 0.0 ? 1.0 : -1.0); + } + float2 EncodeNormal(float3 n) { - n.z = max(0.001, sqrt(8.0 - 8.0 * n.z)); - n.xy /= n.z; - return n.xy + 0.5; + n = -n; + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = n.z >= 0.0 ? n.xy : OctWrap(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; } - float3 DecodeNormal(float2 enc) + float3 DecodeNormal(float2 f) { - float2 fenc = enc * 4.0 - 2.0; - float f = dot(fenc, fenc); - float3 n; - n.xy = fenc * sqrt(1.0 - f / 4.0); - n.z = f / 2.0 - 1.0; - return n; + f = f * 2.0 - 1.0; + // https://twitter.com/Stubbesaurus/status/937994790553227264 + float3 n = float3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y)); + float t = saturate(-n.z); + n.xy += n.xy >= 0.0 ? -t : t; + return -normalize(n); + } + + float2 EncodeNormalVanilla(float3 n) + { + n.z = max(1.0 / 1000.0, sqrt(8.0 + -8.0 * n.z)); + n.xy /= n.z; + return n.xy + 0.5; } } diff --git a/package/Shaders/DeferredCompositePS.hlsl b/package/Shaders/DeferredCompositePS.hlsl index 3edc890fac..93c2142be3 100644 --- a/package/Shaders/DeferredCompositePS.hlsl +++ b/package/Shaders/DeferredCompositePS.hlsl @@ -97,7 +97,7 @@ struct PS_INPUT struct PS_OUTPUT { float4 Main: SV_Target0; - float4 NormalRoughness: SV_Target1; + float4 Normal: SV_Target1; }; PS_OUTPUT main(PS_INPUT input) @@ -115,9 +115,10 @@ PS_OUTPUT main(PS_INPUT input) float3 specularColor = SpecularTexture[pixCoord]; float3 linDiffuseColor = Color::IrradianceToLinear(diffuseColor); -#if defined(SSGI) || defined(DYNAMIC_CUBEMAPS) float3 normalGlossiness = NormalRoughnessTexture[pixCoord].xyz; float3 normalVS = GBuffer::DecodeNormal(normalGlossiness.xy); + +#if defined(SSGI) || defined(DYNAMIC_CUBEMAPS) float3 normalWS = normalize(mul(FrameBuffer::CameraViewInverse[eyeIndex], float4(normalVS, 0)).xyz); float depth = DepthTexture[pixCoord]; @@ -311,11 +312,6 @@ PS_OUTPUT main(PS_INPUT input) #if defined(DEBUG) -# if !defined(SSGI) && !defined(DYNAMIC_CUBEMAPS) - float3 normalGlossiness = NormalRoughnessTexture[pixCoord]; - float3 normalVS = GBuffer::DecodeNormal(normalGlossiness.xy); -# endif - # if !defined(SSGI) float3 albedo = AlbedoTexture[pixCoord]; # endif @@ -342,6 +338,6 @@ PS_OUTPUT main(PS_INPUT input) PS_OUTPUT output; output.Main = float4(color, 1.0); - output.NormalRoughness = 0; + output.Normal = float4(GBuffer::EncodeNormalVanilla(normalVS), 0.0, 0.0); return output; } diff --git a/src/Deferred.cpp b/src/Deferred.cpp index 8372b7ec70..a069c5142b 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -140,7 +140,7 @@ void Deferred::SetupResources() D3D11_BLEND_DESC blendDesc{}; blendDesc.IndependentBlendEnable = TRUE; blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - blendDesc.RenderTarget[1].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_BLUE; + blendDesc.RenderTarget[1].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; DX::ThrowIfFailed(device->CreateBlendState(&blendDesc, compositeBlendState.put())); Util::SetResourceName(compositeBlendState.get(), "Deferred::CompositeBlendState"); diff --git a/src/Hooks.cpp b/src/Hooks.cpp index eef88299cb..7398145934 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -596,6 +596,28 @@ namespace Hooks static inline REL::Relocation func; }; + struct CreateRenderTarget_Normals + { + static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) + { + RE::BSGraphics::RenderTargetProperties properties = *a_properties; + properties.format.set(RE::BSGraphics::Format::kR10G10B10A2_UNORM); + func(This, a_target, &properties); + } + static inline REL::Relocation func; + }; + + struct CreateRenderTarget_NormalsSwap + { + static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) + { + RE::BSGraphics::RenderTargetProperties properties = *a_properties; + properties.format.set(RE::BSGraphics::Format::kR10G10B10A2_UNORM); + func(This, a_target, &properties); + } + static inline REL::Relocation func; + }; + struct CreateRenderTarget_RefractionNormals { static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) @@ -953,7 +975,8 @@ namespace Hooks logger::info("Hooking BSShaderRenderTargets::Create::CreateRenderTarget(s)"); stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x3F0, 0x3F3, 0x548)); stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x4F0, 0x4EF, 0x64E)); - + stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x458, 0x45B, 0x5B0)); + stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x46B, 0x46E, 0x5C3)); stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x503, 0x502, 0x661)); stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0xB19, 0xB19, 0xE06));