From ed578777cba3e324a80217e5d34eae27c1abf10f Mon Sep 17 00:00:00 2001 From: Ilya Perapechka Date: Sat, 10 Aug 2024 19:45:24 +0300 Subject: [PATCH 01/13] fix: switched to using in-game imagespace shader defines. --- package/Shaders/ISBlur.hlsl | 39 +++-- package/Shaders/ISCopy.hlsl | 6 +- package/Shaders/ISDepthOfField.hlsl | 4 +- package/Shaders/ISDownsample.hlsl | 6 +- package/Shaders/ISHDR.hlsl | 16 +- package/Shaders/ISIBLensFlare.hlsl | 2 +- package/Shaders/ISLightingComposite.hlsl | 2 +- package/Shaders/ISRadialBlur.hlsl | 4 +- package/Shaders/ISSAOMinify.hlsl | 2 +- package/Shaders/ISSimpleColor.hlsl | 4 +- package/Shaders/ISWaterDisplacement.hlsl | 16 +- package/Shaders/ISWorldMap.hlsl | 2 +- src/ShaderCache.cpp | 203 ++--------------------- src/ShaderCache.h | 2 +- src/State.cpp | 2 +- 15 files changed, 71 insertions(+), 239 deletions(-) diff --git a/package/Shaders/ISBlur.hlsl b/package/Shaders/ISBlur.hlsl index 9c665aca2e..c3b5c755a3 100644 --- a/package/Shaders/ISBlur.hlsl +++ b/package/Shaders/ISBlur.hlsl @@ -24,34 +24,43 @@ cbuffer PerGeometry : register(b2) float4 BlurOffsets[16] : packoffset(c3); }; +float4 GetImageColor(float2 texCoord, float blurScale) +{ + return ImageTex.Sample(ImageSampler, texCoord) * float4(blurScale.xxx, 1); +} + PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; - float4 color = 0.0.xxxx; - - float blurRadius = BLUR_RADIUS; - float2 blurScale = BlurScale.zw; -# if BLUR_RADIUS == 0 - blurRadius = BlurRadius; + float4 color = 0; + +# if defined(TEXTAP) + int blurRadius = TEXTAP; +# else + uint blurRadius = asuint(BlurRadius); # endif -# if BLUR_RADIUS == 0 || defined(BLUR_NON_HDR) - blurScale = 1.0.xx; + float2 blurScale = BlurScale.zw; +# if !defined(TEXTAP) || !defined(COLORRANGE) + blurScale = 1; # endif for (int blurIndex = 0; blurIndex < blurRadius; ++blurIndex) { float2 screenPosition = BlurOffsets[blurIndex].xy + input.TexCoord.xy; - if (BlurScale.x < 0.5) { - screenPosition = GetDynamicResolutionAdjustedScreenPosition(screenPosition); - } - float4 imageColor = ImageTex.Sample(ImageSampler, screenPosition) * float4(blurScale.yyy, 1); -# if defined(BLUR_BRIGHT_PASS) - imageColor = BlurBrightPass.y * max(0.0.xxxx, -BlurBrightPass.x + imageColor); + float4 imageColor = 0; + [branch] if (BlurScale.x < 0.5) { + imageColor = GetImageColor(GetDynamicResolutionAdjustedScreenPosition(screenPosition), blurScale.y); + } + else { + imageColor = GetImageColor(screenPosition, blurScale.y); + } +# if defined(BRIGHTPASS) + imageColor = BlurBrightPass.y * max(0, -BlurBrightPass.x + imageColor); # endif color += imageColor * BlurOffsets[blurIndex].z; } -# if defined(BLUR_BRIGHT_PASS) +# if defined(BRIGHTPASS) float avgLum = RGBToLuminance(AvgLumTex.Sample(AvgLumSampler, input.TexCoord.xy).xyz); color.w = avgLum; # endif diff --git a/package/Shaders/ISCopy.hlsl b/package/Shaders/ISCopy.hlsl index 36616cb06d..bf6aa532b6 100644 --- a/package/Shaders/ISCopy.hlsl +++ b/package/Shaders/ISCopy.hlsl @@ -24,7 +24,7 @@ PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; -# if !defined(DYNAMIC_FETCH_DISABLED) +# if !defined(DISABLE_DYNAMIC) float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); # else float2 screenPosition = input.TexCoord; @@ -32,9 +32,9 @@ PS_OUTPUT main(PS_INPUT input) float4 color = ImageTex.Sample(ImageSampler, screenPosition); -# if defined(GRAY_SCALE) +# if defined(GREYSCALE) color = float4(dot(color, ColorSelect).xxx, color.w); -# elif defined(TEXTURE_MASK) +# elif defined(MASK) color.w = 1 - color.x; # endif diff --git a/package/Shaders/ISDepthOfField.hlsl b/package/Shaders/ISDepthOfField.hlsl index 2d6c8bb198..951b25c53d 100644 --- a/package/Shaders/ISDepthOfField.hlsl +++ b/package/Shaders/ISDepthOfField.hlsl @@ -121,9 +121,9 @@ PS_OUTPUT main(PS_INPUT input) finalDepth = GetFinalDepth(depth, near, far); float dofStrength = 0; -# if defined(DISTANT_BLUR) +# if defined(DISTANT) dofStrength = (finalDepth - focusDistance) / dofBlurRange.y; -# elif defined(DOF) +# else if ((focusDistance > finalDepth || mask == 0) && dofParams2.y != 0) { dofStrength = (focusDistance - finalDepth) / dofBlurRange.y; } else if (finalDepth > focusDistance && dofParams2.z != 0) { diff --git a/package/Shaders/ISDownsample.hlsl b/package/Shaders/ISDownsample.hlsl index 8164cdc14d..a3e942b6ae 100644 --- a/package/Shaders/ISDownsample.hlsl +++ b/package/Shaders/ISDownsample.hlsl @@ -34,11 +34,11 @@ PS_OUTPUT main(PS_INPUT input) float luminance = 0; for (uint sampleIndex = 0; sampleIndex < asuint(SamplesCount); ++sampleIndex) { float2 texCoord = OffsetsAndWeights[sampleIndex].xy * TexelSize.xy + input.TexCoord; -# if defined(IGNORE_BRIGHTEST) +# if defined(DYNAMIC_SOURCE) texCoord = GetDynamicResolutionAdjustedScreenPosition(texCoord); # endif float4 sourceColor = SourceTex.Sample(SourceSampler, texCoord); -# if defined(IGNORE_BRIGHTEST) +# if defined(DYNAMIC_SOURCE) downsampledColor += sourceColor; # else float sampleLuminance = RGBToLuminanceAlternative(sourceColor.xyz); @@ -48,7 +48,7 @@ PS_OUTPUT main(PS_INPUT input) } # endif } -# if defined(IGNORE_BRIGHTEST) +# if defined(DYNAMIC_SOURCE) psout.Color = downsampledColor / asuint(SamplesCount); # else if (CompensateJittering) { diff --git a/package/Shaders/ISHDR.hlsl b/package/Shaders/ISHDR.hlsl index 756e08374d..858aca2084 100644 --- a/package/Shaders/ISHDR.hlsl +++ b/package/Shaders/ISHDR.hlsl @@ -13,7 +13,7 @@ struct PS_OUTPUT SamplerState ImageSampler : register(s0); # if defined(DOWNSAMPLE) SamplerState AdaptSampler : register(s1); -# elif defined(TONEMAP) +# elif defined(BLEND) SamplerState BlendSampler : register(s1); # endif SamplerState AvgSampler : register(s2); @@ -21,7 +21,7 @@ SamplerState AvgSampler : register(s2); Texture2D ImageTex : register(t0); # if defined(DOWNSAMPLE) Texture2D AdaptTex : register(t1); -# elif defined(TONEMAP) +# elif defined(BLEND) Texture2D BlendTex : register(t1); # endif Texture2D AvgTex : register(t2); @@ -56,20 +56,20 @@ PS_OUTPUT main(PS_INPUT input) # if defined(DOWNSAMPLE) float3 downsampledColor = 0; - for (int sampleIndex = 0; sampleIndex < SAMPLES_COUNT; ++sampleIndex) { + for (int sampleIndex = 0; sampleIndex < DOWNSAMPLE; ++sampleIndex) { float2 texCoord = BlurOffsets[sampleIndex].xy * BlurScale.xy + input.TexCoord; if (Flags.x > 0.5) { texCoord = GetDynamicResolutionAdjustedScreenPosition(texCoord); } float3 imageColor = ImageTex.Sample(ImageSampler, texCoord).xyz; -# if defined(LUM) - imageColor = imageColor.x; -# elif defined(RGB2LUM) +# if defined(RGB2LUM) imageColor = RGBToLuminance(imageColor); +# elif (defined(LUM) || defined(LUMCLAMP)) && !defined(DOWNADAPT) + imageColor = imageColor.x; # endif downsampledColor += imageColor * BlurOffsets[sampleIndex].z; } -# if defined(LIGHT_ADAPT) +# if defined(DOWNADAPT) float2 adaptValue = AdaptTex.Sample(AdaptSampler, input.TexCoord).xy; if (isnan(downsampledColor.x) || isnan(downsampledColor.y) || isnan(downsampledColor.z)) { downsampledColor.xy = adaptValue; @@ -82,7 +82,7 @@ PS_OUTPUT main(PS_INPUT input) # endif psout.Color = float4(downsampledColor, BlurScale.z); -# elif defined(TONEMAP) +# elif defined(BLEND) float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); float3 blendColor = BlendTex.Sample(BlendSampler, adjustedTexCoord).xyz; float3 imageColor = 0; diff --git a/package/Shaders/ISIBLensFlare.hlsl b/package/Shaders/ISIBLensFlare.hlsl index ee242c6921..8d62e948cb 100644 --- a/package/Shaders/ISIBLensFlare.hlsl +++ b/package/Shaders/ISIBLensFlare.hlsl @@ -32,7 +32,7 @@ cbuffer PerGeometry : register(b2) float haloFetch : packoffset(c2.z); float haloWidthPow : packoffset(c2.w); float dynamicSource : packoffset(c3.x); - float globalIntensity : packoffset(c3.y); + float globalIntensity : packoffset(c4.x); }; float4 GetSampleColor(float2 texCoord) diff --git a/package/Shaders/ISLightingComposite.hlsl b/package/Shaders/ISLightingComposite.hlsl index 7a180d183f..36006631eb 100644 --- a/package/Shaders/ISLightingComposite.hlsl +++ b/package/Shaders/ISLightingComposite.hlsl @@ -40,7 +40,7 @@ PS_OUTPUT main(PS_INPUT input) float4 specular = SpecularTex.Sample(SpecularSampler, input.TexCoord); float4 albedo = AlbedoTex.Sample(AlbedoSampler, input.TexCoord); -# if !defined(NO_DIRECTIONAL_LIGHT) +# if defined(DIRECTIONALLIGHT) float4 dirDiffuse = DirDiffuseTex.Sample(DirDiffuseSampler, input.TexCoord); float4 dirSpecular = DirSpecularTex.Sample(DirSpecularSampler, input.TexCoord); # else diff --git a/package/Shaders/ISRadialBlur.hlsl b/package/Shaders/ISRadialBlur.hlsl index a2931e17b3..ba457c32a7 100644 --- a/package/Shaders/ISRadialBlur.hlsl +++ b/package/Shaders/ISRadialBlur.hlsl @@ -40,13 +40,13 @@ PS_OUTPUT main(PS_INPUT input) GetCircleParam(centerDistance, Center.z, Params.w))); float4 color = 0; - for (float sampleIndex = -SAMPLES_COUNT; sampleIndex <= SAMPLES_COUNT; ++sampleIndex) { + for (float sampleIndex = -NUM_STEPS; sampleIndex <= NUM_STEPS; ++sampleIndex) { float2 texCoord = input.TexCoord + sampleDelta * sampleIndex; float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(texCoord); float4 currentColor = ImageTex.SampleLevel(ImageSampler, adjustedTexCoord, 0); color += currentColor; } - color *= (1. / (2. * SAMPLES_COUNT + 1.)); + color *= (1. / (2. * NUM_STEPS + 1.)); psout.Color = color; diff --git a/package/Shaders/ISSAOMinify.hlsl b/package/Shaders/ISSAOMinify.hlsl index 3e4cf84312..a7c6d577b2 100644 --- a/package/Shaders/ISSAOMinify.hlsl +++ b/package/Shaders/ISSAOMinify.hlsl @@ -51,7 +51,7 @@ PS_OUTPUT main(PS_INPUT input) float4 color = sourceTex.Sample(sourceSampler, finalTexCoord); -# if defined(CONTRAST) +# if defined(APPLY_CENTER_CONTRAST) int contrastIndex = (int)(5 * input.TexCoord.x) + (int)(5 * input.TexCoord.y) * 5; float contrastFactor = ContrastValues[contrastIndex] * g_ContrastParams.x; color *= contrastFactor; diff --git a/package/Shaders/ISSimpleColor.hlsl b/package/Shaders/ISSimpleColor.hlsl index 1072a633a4..dbd1897d89 100644 --- a/package/Shaders/ISSimpleColor.hlsl +++ b/package/Shaders/ISSimpleColor.hlsl @@ -1,6 +1,6 @@ #if defined(DISPLAY_DEPTH) # include "Common/DummyVSTexCoord.hlsl" -#elif defined(SIMPLE_COLOR) +#else # include "Common/DummyVS.hlsl" #endif @@ -41,7 +41,7 @@ PS_OUTPUT main(PS_INPUT input) float screenDepth = saturate((-Color.x + depth) / (Color.y - Color.x)); psout.Color.xyz = (screenDepth * -2 + 3) * (screenDepth * screenDepth); psout.Color.w = 1; -# elif defined(SIMPLE_COLOR) +# else psout.Color = Color; # endif diff --git a/package/Shaders/ISWaterDisplacement.hlsl b/package/Shaders/ISWaterDisplacement.hlsl index 449a416185..9b4f090e7c 100644 --- a/package/Shaders/ISWaterDisplacement.hlsl +++ b/package/Shaders/ISWaterDisplacement.hlsl @@ -1,4 +1,4 @@ -#if defined(SMOOTH_HEIGHTMAP) || defined(RAIN_HEIGHTMAP) || defined(WADING_HEIGHTMAP) +#if defined(HEIGHTMAP_SMOOTH) || defined(HEIGHTMAP_RAIN) || defined(HEIGHTMAP_WADING) # define HEIGHTMAP #endif @@ -51,7 +51,7 @@ SamplerState HeightMap01Sampler : register(s0); SamplerState HeightMap02Sampler : register(s1); # elif defined(NORMALS) SamplerState DisplaceMapSampler : register(s0); -# elif defined(TEX_OFFSET) +# elif defined(TEXCOORD_OFFSET) SamplerState DisplaySamplerSampler : register(s0); # elif defined(HEIGHTMAP) SamplerState HeightMapSampler : register(s0); @@ -62,7 +62,7 @@ Texture2D HeightMap01Tex : register(t0); Texture2D HeightMap02Tex : register(t1); # elif defined(NORMALS) Texture2D DisplaceMapTex : register(t0); -# elif defined(TEX_OFFSET) +# elif defined(TEXCOORD_OFFSET) Texture2D DisplaySamplerTex : register(t0); # elif defined(HEIGHTMAP) Texture2D HeightMapTex : register(t0); @@ -142,18 +142,18 @@ PS_OUTPUT main(PS_INPUT input) psout.Color = float4(normalize(float3(-valueRL, valueTB, 1)), 1) * 0.5 + 0.5; -# elif defined(RAIN_RIPPLE) || defined(WADING_RIPPLE) +# elif defined(RIPPLE_MAKER_RAIN) || defined(RIPPLE_MAKER_WADING) psout.Color = float4(1, 0.5, 0.5, 0.5); -# elif defined(TEX_OFFSET) +# elif defined(TEXCOORD_OFFSET) float lerpFactor = saturate(10 * (-0.4 + length(input.TexCoord - 0.5))); float4 displayColor = DisplaySamplerTex.Sample(DisplaySamplerSampler, TextureOffset + input.TexCoord); psout.Color.xy = displayColor.xy; psout.Color.zw = lerp(displayColor.zw, 0.5, lerpFactor); -# elif defined(SMOOTH_HEIGHTMAP) +# elif defined(HEIGHTMAP_SMOOTH) psout.Color = HeightMapTex.Sample(HeightMapSampler, input.TexCoord); -# elif defined(RAIN_HEIGHTMAP) +# elif defined(HEIGHTMAP_RAIN) psout.Color = GetHeight(input, RainVars); -# elif defined(WADING_HEIGHTMAP) +# elif defined(HEIGHTMAP_WADING) psout.Color = GetHeight(input, WadingVars); # endif diff --git a/package/Shaders/ISWorldMap.hlsl b/package/Shaders/ISWorldMap.hlsl index f269427a68..0bc3c72948 100644 --- a/package/Shaders/ISWorldMap.hlsl +++ b/package/Shaders/ISWorldMap.hlsl @@ -32,7 +32,7 @@ PS_OUTPUT main(PS_INPUT input) float depthFactor = DepthParams.w / ((1 - depth) * DepthParams.z + DepthParams.y); float offsetDelta = min(TexelSize.y, TexelSize.z * abs(depthFactor - TexelSize.x)); -# if defined(NO_SKY_BLUR) +# if defined(NO_SKY) if (1 - depth <= 1e-4) { offsetDelta = 0; } diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index 3a691f12c4..0fcbce51d9 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -17,7 +17,7 @@ namespace SIE { namespace SShaderCache { - static void GetShaderDefines(RE::BSShader::Type, uint32_t, D3D_SHADER_MACRO*); + static void GetShaderDefines(const RE::BSShader&, uint32_t, D3D_SHADER_MACRO*); static std::string GetShaderString(ShaderClass, const RE::BSShader&, uint32_t, bool = false); /** @brief Get the BSShader::Type from the ShaderString @@ -622,195 +622,18 @@ namespace SIE defines[0] = { nullptr, nullptr }; } - static void GetImagespaceShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) + static void GetImagespaceShaderDefines(const RE::BSShader& shader, D3D_SHADER_MACRO* defines) { - using enum RE::ImageSpaceManager::ImageSpaceEffectEnum; - - const auto descEnum = - static_cast(descriptor); - if ((descriptor >= static_cast(ISBlur3) && - descriptor <= static_cast(ISBrightPassBlur15)) || - descEnum == ISBlur) { - if (descEnum == ISBlur) { - defines[0] = { "BLUR_RADIUS", "0" }; - ++defines; - } else { - static constexpr std::array blurRadiusDefines = { { "3", "5", - "7", "9", "11", "13", "15" } }; - const size_t blurRadius = static_cast( - (descriptor - static_cast(ISBlur3)) % blurRadiusDefines.size()); - defines[0] = { "BLUR_RADIUS", blurRadiusDefines[blurRadius] }; - ++defines; - const size_t blurType = static_cast( - (descriptor - static_cast(ISBlur3)) / blurRadiusDefines.size()); - if (blurType == 1) { - defines[0] = { "BLUR_NON_HDR", nullptr }; - ++defines; - } else if (blurType == 2) { - defines[0] = { "BLUR_BRIGHT_PASS", nullptr }; - ++defines; - } - } - } else if (descEnum == ISDisplayDepth) { - defines[0] = { "DISPLAY_DEPTH", nullptr }; - ++defines; - } else if (descEnum == ISSimpleColor) { - defines[0] = { "SIMPLE_COLOR", nullptr }; - ++defines; - } else if (descEnum == ISCopyDynamicFetchDisabled) { - defines[0] = { "DYNAMIC_FETCH_DISABLED", nullptr }; - ++defines; - } else if (descEnum == ISCopyGrayScale) { - defines[0] = { "GRAY_SCALE", nullptr }; - ++defines; - } else if (descEnum == ISCopyTextureMask) { - defines[0] = { "TEXTURE_MASK", nullptr }; - ++defines; - } else if (descEnum == ISCompositeLensFlare) { - defines[0] = { "VOLUMETRIC_LIGHTING", nullptr }; - ++defines; - } else if (descEnum == ISCompositeVolumetricLighting) { - defines[0] = { "LENS_FLARE", nullptr }; - ++defines; - } else if (descEnum == ISCompositeLensFlareVolumetricLighting) { - defines[0] = { "VOLUMETRIC_LIGHTING", nullptr }; - ++defines; - defines[0] = { "LENS_FLARE", nullptr }; - ++defines; - } else if (descriptor >= static_cast(ISDepthOfField) && - descriptor <= static_cast(ISDistantBlurMaskedFogged)) { - if (descriptor >= static_cast(ISDepthOfField) && - descriptor <= static_cast(ISDepthOfFieldMaskedFogged)) - - { - defines[0] = { "DOF", nullptr }; - ++defines; - } else { - defines[0] = { "DISTANT_BLUR", nullptr }; - ++defines; - } - if (descEnum != ISDepthOfField && descEnum != ISDistantBlur) { - defines[0] = { "FOGGED", nullptr }; - ++defines; - } - if (descEnum == ISDepthOfFieldMaskedFogged || descEnum == ISDistantBlurMaskedFogged) { - defines[0] = { "MASKED", nullptr }; - ++defines; - } - } else if (descEnum == ISDownsampleIgnoreBrightest) { - defines[0] = { "IGNORE_BRIGHTEST", nullptr }; - ++defines; - } else if (descEnum == ISHDRTonemapBlendCinematic) { - defines[0] = { "TONEMAP", nullptr }; - ++defines; - } else if (descEnum == ISHDRTonemapBlendCinematicFade) { - defines[0] = { "TONEMAP", nullptr }; - ++defines; - defines[0] = { "FADE", nullptr }; - ++defines; - } else if (descriptor >= static_cast(ISHDRDownSample16) && - descriptor <= static_cast(ISHDRDownSample16LightAdapt)) { - defines[0] = { "DOWNSAMPLE", nullptr }; - ++defines; - if (descEnum == ISHDRDownSample16 || descEnum == ISHDRDownSample16Lum || - descEnum == ISHDRDownSample16LightAdapt || - descEnum == ISHDRDownSample16LumClamp) { - defines[0] = { "SAMPLES_COUNT", "16" }; - ++defines; - } else { - defines[0] = { "SAMPLES_COUNT", "4" }; - ++defines; - } - if (descEnum == ISHDRDownSample4RGB2Lum) { - defines[0] = { "RGB2LUM", nullptr }; - ++defines; - } else if (descEnum == ISHDRDownSample16Lum || descEnum == ISHDRDownSample16LumClamp) { - defines[0] = { "LUM", nullptr }; - ++defines; - } else if (descEnum == ISHDRDownSample16LightAdapt || - descEnum == ISHDRDownSample4LightAdapt) { - defines[0] = { "LIGHT_ADAPT", nullptr }; - ++defines; - } - } else if (descEnum == ISLightingCompositeMenu) { - defines[0] = { "MENU", nullptr }; - ++defines; - } else if (descEnum == ISLightingCompositeNoDirectionalLight) { - defines[0] = { "NO_DIRECTIONAL_LIGHT", nullptr }; - ++defines; - } else if (descEnum == ISWaterBlendHeightmaps) { - defines[0] = { "BLEND_HEIGHTMAPS", nullptr }; - ++defines; - } else if (descEnum == ISWaterDisplacementClearSimulation) { - defines[0] = { "CLEAR_SIMULATION", nullptr }; - ++defines; - } else if (descEnum == ISWaterDisplacementNormals) { - defines[0] = { "NORMALS", nullptr }; - ++defines; - } else if (descEnum == ISWaterDisplacementRainRipple) { - defines[0] = { "RAIN_RIPPLE", nullptr }; - ++defines; - } else if (descEnum == ISWaterDisplacementTexOffset) { - defines[0] = { "TEX_OFFSET", nullptr }; - ++defines; - } else if (descEnum == ISWaterSmoothHeightmap) { - defines[0] = { "SMOOTH_HEIGHTMAP", nullptr }; - ++defines; - } else if (descEnum == ISWaterRainHeightmap) { - defines[0] = { "RAIN_HEIGHTMAP", nullptr }; - ++defines; - } else if (descEnum == ISWaterWadingHeightmap) { - defines[0] = { "WADING_HEIGHTMAP", nullptr }; - ++defines; - } else if (descEnum == ISWorldMapNoSkyBlur) { - defines[0] = { "NO_SKY_BLUR", nullptr }; - ++defines; - } else if (descEnum == ISMinifyContrast) { - defines[0] = { "CONTRAST", nullptr }; - ++defines; - } else if (descEnum == ISNoiseNormalmap) { - defines[0] = { "NORMALMAP", nullptr }; - ++defines; - } else if (descEnum == ISNoiseScrollAndBlend) { - defines[0] = { "SCROLL_AND_BLEND", nullptr }; - ++defines; - } else if (descEnum == ISRadialBlur) { - defines[0] = { "SAMPLES_COUNT", "2" }; - ++defines; - } else if (descEnum == ISRadialBlurHigh) { - defines[0] = { "SAMPLES_COUNT", "10" }; - ++defines; - } else if (descEnum == ISRadialBlurMedium) { - defines[0] = { "SAMPLES_COUNT", "6" }; - ++defines; - } else if (descEnum == ISSAOCompositeSAO) { - defines[0] = { "APPLY_SAO", nullptr }; - ++defines; - } else if (descEnum == ISSAOCompositeFog) { - defines[0] = { "APPLY_FOG", nullptr }; - ++defines; - } else if (descEnum == ISSAOCompositeSAOFog) { - defines[0] = { "APPLY_SAO", nullptr }; - ++defines; - defines[0] = { "APPLY_FOG", nullptr }; - ++defines; - } else if (descEnum == ISSAOBlurH) { - defines[0] = { "AXIS_H", nullptr }; - ++defines; - } else if (descEnum == ISSAOBlurV) { - defines[0] = { "AXIS_V", nullptr }; - ++defines; - } else if (descEnum == ISUnderwaterMask) { - defines[0] = { "UNDERWATERMASK", nullptr }; - ++defines; - } - defines[0] = { nullptr, nullptr }; + auto& isShader = const_cast(static_cast(shader)); + auto getDefines = reinterpret_cast(&RE::BSImagespaceShader::Unk_0D); + (isShader.*getDefines)(defines); + return; } - static void GetShaderDefines(RE::BSShader::Type type, uint32_t descriptor, + static void GetShaderDefines(const RE::BSShader& shader, uint32_t descriptor, D3D_SHADER_MACRO* defines) { - switch (type) { + switch (shader.shaderType.get()) { case RE::BSShader::Type::Grass: GetGrassShaderDefines(descriptor, defines); break; @@ -824,7 +647,7 @@ namespace SIE GetBloodSplaterShaderDefines(descriptor, defines); break; case RE::BSShader::Type::ImageSpace: - GetImagespaceShaderDefines(descriptor, defines); + GetImagespaceShaderDefines(shader, defines); break; case RE::BSShader::Type::Lighting: GetLightingShaderDefines(descriptor, defines); @@ -1473,7 +1296,7 @@ namespace SIE { auto sourceShaderFile = shader.fxpFilename; std::array defines{}; - SIE::SShaderCache::GetShaderDefines(shader.shaderType.get(), descriptor, &defines[0]); + SIE::SShaderCache::GetShaderDefines(shader, descriptor, &defines[0]); std::string result; if (hashkey) // generate hashkey so don't include descriptor result = fmt::format("{}:{}:{}", sourceShaderFile, magic_enum::enum_name(shaderClass), SIE::SShaderCache::MergeDefinesString(defines, true)); @@ -1550,7 +1373,7 @@ namespace SIE defines[lastIndex++] = { shaderDefines->at(i).first.c_str(), shaderDefines->at(i).second.c_str() }; } defines[lastIndex] = { nullptr, nullptr }; // do final entry - GetShaderDefines(type, descriptor, &defines[lastIndex]); + GetShaderDefines(shader, descriptor, &defines[lastIndex]); const std::wstring path = GetShaderPath( shader.shaderType == RE::BSShader::Type::ImageSpace ? @@ -2352,10 +2175,10 @@ namespace SIE return nullptr; } - std::string ShaderCache::GetDefinesString(RE::BSShader::Type enumType, uint32_t descriptor) + std::string ShaderCache::GetDefinesString(const RE::BSShader& shader, uint32_t descriptor) { std::array defines{}; - SIE::SShaderCache::GetShaderDefines(enumType, descriptor, &defines[0]); + SIE::SShaderCache::GetShaderDefines(shader, descriptor, &defines[0]); return SIE::SShaderCache::MergeDefinesString(defines, true); } diff --git a/src/ShaderCache.h b/src/ShaderCache.h index ad1ac9b878..868677c9ef 100644 --- a/src/ShaderCache.h +++ b/src/ShaderCache.h @@ -184,7 +184,7 @@ namespace SIE RE::BSGraphics::PixelShader* MakeAndAddPixelShader(const RE::BSShader& shader, uint32_t descriptor); - static std::string GetDefinesString(RE::BSShader::Type enumType, uint32_t descriptor); + static std::string GetDefinesString(const RE::BSShader& shader, uint32_t descriptor); uint64_t GetCachedHitTasks(); uint64_t GetCompletedTasks(); diff --git a/src/State.cpp b/src/State.cpp index a5bf211aca..06cf5d9ef2 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -67,7 +67,7 @@ void State::Draw() if (IsDeveloperMode()) { BeginPerfEvent(std::format("Draw: CS {}::{:x}", magic_enum::enum_name(currentShader->shaderType.get()), currentPixelDescriptor)); - SetPerfMarker(std::format("Defines: {}", SIE::ShaderCache::GetDefinesString(currentShader->shaderType.get(), currentPixelDescriptor))); + SetPerfMarker(std::format("Defines: {}", SIE::ShaderCache::GetDefinesString(*currentShader, currentPixelDescriptor))); EndPerfEvent(); } } From 215d6e2dba9948308eeb27330ccc7634c60c8691 Mon Sep 17 00:00:00 2001 From: Ilya Perapechka Date: Sat, 10 Aug 2024 22:17:41 +0300 Subject: [PATCH 02/13] feat: support for glint parameters in pbr meshes and texture sets. --- package/Shaders/Common/PBR.hlsli | 66 ++- package/Shaders/Lighting.hlsl | 63 ++- package/Shaders/RunGrass.hlsl | 13 +- package/Shaders/SnowSparkles/Glints2023.hlsli | 520 ++++++++++++++++++ package/Shaders/SnowSparkles/noisegen.cs.hlsl | 130 +++++ src/ShaderCache.cpp | 12 + src/TruePBR.cpp | 42 +- src/TruePBR.h | 11 + src/TruePBR/BSLightingShaderMaterialPBR.cpp | 25 +- src/TruePBR/BSLightingShaderMaterialPBR.h | 8 + .../BSLightingShaderMaterialPBRLandscape.cpp | 1 + .../BSLightingShaderMaterialPBRLandscape.h | 4 + 12 files changed, 860 insertions(+), 35 deletions(-) create mode 100644 package/Shaders/SnowSparkles/Glints2023.hlsli create mode 100644 package/Shaders/SnowSparkles/noisegen.cs.hlsl diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index b8c1c42647..b40e454921 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -1,3 +1,5 @@ +#include "SnowSparkles/Glints2023.hlsli" + #define TruePBR_HasEmissive (1 << 0) #define TruePBR_HasDisplacement (1 << 1) #define TruePBR_HasFeatureTexture0 (1 << 2) @@ -8,7 +10,9 @@ #define TruePBR_InterlayerParallax (1 << 7) #define TruePBR_CoatNormal (1 << 8) #define TruePBR_Fuzz (1 << 9) -#define TruePBR_HairMarschner (1 << 9) +#define TruePBR_HairMarschner (1 << 10) +#define TruePBR_Glint (1 << 11) + #define TruePBR_LandTile0PBR (1 << 0) #define TruePBR_LandTile1PBR (1 << 1) #define TruePBR_LandTile2PBR (1 << 2) @@ -21,6 +25,13 @@ #define TruePBR_LandTile3HasDisplacement (1 << 9) #define TruePBR_LandTile4HasDisplacement (1 << 10) #define TruePBR_LandTile5HasDisplacement (1 << 11) +#define TruePBR_LandGlint (1 << 12) +#define TruePBR_LandTile0HasGlint (1 << 13) +#define TruePBR_LandTile1HasGlint (1 << 14) +#define TruePBR_LandTile2HasGlint (1 << 15) +#define TruePBR_LandTile3HasGlint (1 << 16) +#define TruePBR_LandTile4HasGlint (1 << 17) +#define TruePBR_LandTile5HasGlint (1 << 18) namespace PBR { @@ -39,7 +50,39 @@ namespace PBR float3 CoatF0; float3 FuzzColor; float FuzzWeight; + float GlintScreenSpaceScale; + float GlintLogMicrofacetDensity; + float GlintMicrofacetRoughness; + float GlintDensityRandomization; }; + + SurfaceProperties InitSurfaceProperties() + { + SurfaceProperties surfaceProperties; + + surfaceProperties.Roughness = 1; + surfaceProperties.Metallic = 0; + surfaceProperties.AO = 1; + surfaceProperties.F0 = 0.04; + + surfaceProperties.SubsurfaceColor = 0; + surfaceProperties.Thickness = 0; + + surfaceProperties.CoatColor = 0; + surfaceProperties.CoatStrength = 0; + surfaceProperties.CoatRoughness = 0; + surfaceProperties.CoatF0 = 0.04; + + surfaceProperties.FuzzColor = 0; + surfaceProperties.FuzzWeight = 0; + + surfaceProperties.GlintScreenSpaceScale = 0; + surfaceProperties.GlintLogMicrofacetDensity = 0; + surfaceProperties.GlintMicrofacetRoughness = 0; + surfaceProperties.GlintDensityRandomization = 0; + + return surfaceProperties; + } float3 AdjustDirectionalLightColor(float3 lightColor) { @@ -110,9 +153,18 @@ namespace PBR return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI); } - float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, out float3 F) + float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float3 H, float NdotL, float NdotV, float NdotH, float VdotH, float2 uv, out float3 F) { float D = GetNormalDistributionFunctionGGX(roughness, NdotH); +#if defined(LANDSCAPE) + [branch] if (PBRFlags & TruePBR_LandGlint) +#else + [branch] if (PBRFlags & TruePBR_Glint) +#endif + { + float D_max = GetNormalDistributionFunctionGGX(roughness, 1); + D = SampleGlints2023NDF(H, D, D_max, uv, ddx(uv), ddy(uv)); + } float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); F = GetFresnelFactorSchlick(specularColor, VdotH); @@ -312,7 +364,8 @@ namespace PBR return color; } - void GetDirectLightInput(out float3 diffuse, out float3 coatDiffuse, out float3 transmission, out float3 specular, float3 N, float3 coatN, float3 V, float3 coatV, float3 L, float3 coatL, float3 lightColor, float3 coatLightColor, SurfaceProperties surfaceProperties) + void GetDirectLightInput(out float3 diffuse, out float3 coatDiffuse, out float3 transmission, out float3 specular, float3 N, float3 coatN, float3 V, float3 coatV, float3 L, float3 coatL, float3 lightColor, float3 coatLightColor, SurfaceProperties surfaceProperties, + float3x3 tbn, float2 uv) { diffuse = 0; coatDiffuse = 0; @@ -320,6 +373,7 @@ namespace PBR specular = 0; float3 H = normalize(V + L); + float3 localH = mul(H, tbn); float NdotL = dot(N, L); float NdotV = dot(N, V); @@ -344,7 +398,7 @@ namespace PBR diffuse += lightColor * satNdotL; float3 F; - specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, F) * lightColor * satNdotL; + specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, H, satNdotL, satNdotV, satNdotH, satVdotH, uv, F) * lightColor * satNdotL; float2 specularBRDF = 0; [branch] if (pbrSettings.UseMultipleScattering) @@ -390,7 +444,7 @@ namespace PBR } float3 coatF; - float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, coatF) * coatLightColor * coatNdotL; + float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, H, coatNdotL, coatNdotV, coatNdotH, coatVdotH, uv, coatF) * coatLightColor * coatNdotL; float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; diffuse *= layerAttenuation; @@ -415,7 +469,7 @@ namespace PBR float VdotH = saturate(dot(V, H)); float3 wetnessF; - float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, wetnessF) * lightColor * NdotL; + float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, H, NdotL, NdotV, NdotH, VdotH, 0, wetnessF) * lightColor * NdotL; return wetnessSpecular * wetnessStrength; } diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index eafe8c6129..889d3400a9 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -599,12 +599,21 @@ cbuffer PerTechnique : register(b0) cbuffer PerMaterial : register(b1) { float4 LODTexParams : packoffset(c0); // TerrainTexOffset in xy, LodBlendingEnabled in z +# if !(defined(LANDSCAPE) && defined(TRUE_PBR)) float4 TintColor : packoffset(c1); float4 EnvmapData : packoffset(c2); // fEnvmapScale in x, 1 or 0 in y depending of if has envmask float4 ParallaxOccData : packoffset(c3); float4 SpecularColor : packoffset(c4); // Shininess in w, color in xyz float4 SparkleParams : packoffset(c5); float4 MultiLayerParallaxData : packoffset(c6); // Layer thickness in x, refraction scale in y, uv scale in zw +# else + float4 LandscapeTexture1GlintParameters : packoffset(c1); + float4 LandscapeTexture2GlintParameters : packoffset(c2); + float4 LandscapeTexture3GlintParameters : packoffset(c3); + float4 LandscapeTexture4GlintParameters : packoffset(c4); + float4 LandscapeTexture5GlintParameters : packoffset(c5); + float4 LandscapeTexture6GlintParameters : packoffset(c6); +# endif float4 LightingEffectParams : packoffset(c7); // fSubSurfaceLightRolloff in x, fRimLightPower in y float4 IBLParams : packoffset(c8); @@ -1234,6 +1243,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float4 glossiness = 0; float4 rawRMAOS = 0; + + float4 glintParameters = 0; # if defined(LANDSCAPE) if (input.LandBlendWeights1.x > 0.0) { @@ -1284,10 +1295,18 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile0PBR) != 0) { rawRMAOS = input.LandBlendWeights1.x * TexRMAOSSampler.Sample(SampRMAOSSampler, diffuseUv) * float4(PBRParams1.x, 1, 1, PBRParams1.z); + if ((PBRFlags & TruePBR_LandTile0HasGlint) != 0) + { + glintParameters += input.LandBlendWeights1.x * LandscapeTexture1GlintParameters; + } } else { rawRMAOS = input.LandBlendWeights1.x * float4(1 - glossiness.x, 0, 1, 0.04); + if ((PBRFlags & TruePBR_Glint) != 0) + { + glintParameters = MultiLayerParallaxData; + } } # else rawRMAOS = TexRMAOSSampler.Sample(SampRMAOSSampler, diffuseUv) * float4(PBRParams1.x, 1, 1, PBRParams1.z); @@ -1336,6 +1355,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile1PBR) != 0) { rawRMAOS += input.LandBlendWeights1.y * TexLandRMAOS2Sampler.Sample(SampLandRMAOS2Sampler, uv) * float4(LandscapeTexture2PBRParams.x, 1, 1, LandscapeTexture2PBRParams.z); + if ((PBRFlags & TruePBR_LandTile1HasGlint) != 0) + { + glintParameters += input.LandBlendWeights1.y * LandscapeTexture2GlintParameters; + } } else { @@ -1360,6 +1383,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile2PBR) != 0) { rawRMAOS += input.LandBlendWeights1.z * TexLandRMAOS3Sampler.Sample(SampLandRMAOS3Sampler, uv) * float4(LandscapeTexture3PBRParams.x, 1, 1, LandscapeTexture3PBRParams.z); + if ((PBRFlags & TruePBR_LandTile2HasGlint) != 0) + { + glintParameters += input.LandBlendWeights1.z * LandscapeTexture3GlintParameters; + } } else { @@ -1384,6 +1411,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile3PBR) != 0) { rawRMAOS += input.LandBlendWeights1.w * TexLandRMAOS4Sampler.Sample(SampLandRMAOS4Sampler, uv) * float4(LandscapeTexture4PBRParams.x, 1, 1, LandscapeTexture4PBRParams.z); + if ((PBRFlags & TruePBR_LandTile3HasGlint) != 0) + { + glintParameters += input.LandBlendWeights1.w * LandscapeTexture4GlintParameters; + } } else { @@ -1408,6 +1439,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile4PBR) != 0) { rawRMAOS += input.LandBlendWeights2.x * TexLandRMAOS5Sampler.Sample(SampLandRMAOS5Sampler, uv) * float4(LandscapeTexture5PBRParams.x, 1, 1, LandscapeTexture5PBRParams.z); + if ((PBRFlags & TruePBR_LandTile4HasGlint) != 0) + { + glintParameters += input.LandBlendWeights2.x * LandscapeTexture5GlintParameters; + } } else { @@ -1432,6 +1467,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile5PBR) != 0) { rawRMAOS += input.LandBlendWeights2.y * TexLandRMAOS6Sampler.Sample(SampLandRMAOS6Sampler, uv) * float4(LandscapeTexture6PBRParams.x, 1, 1, LandscapeTexture6PBRParams.z); + if ((PBRFlags & TruePBR_LandTile5HasGlint) != 0) + { + glintParameters += input.LandBlendWeights2.y * LandscapeTexture6GlintParameters; + } } else { @@ -1580,23 +1619,17 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 screenSpaceNormal = normalize(WorldToView(worldSpaceNormal, false, eyeIndex)); # if defined(TRUE_PBR) - PBR::SurfaceProperties pbrSurfaceProperties; + PBR::SurfaceProperties pbrSurfaceProperties = PBR::InitSurfaceProperties(); pbrSurfaceProperties.Roughness = saturate(rawRMAOS.x); pbrSurfaceProperties.Metallic = saturate(rawRMAOS.y); pbrSurfaceProperties.AO = rawRMAOS.z; pbrSurfaceProperties.F0 = lerp(saturate(rawRMAOS.w), baseColor.xyz, pbrSurfaceProperties.Metallic); - - pbrSurfaceProperties.SubsurfaceColor = 0; - pbrSurfaceProperties.Thickness = 0; - - pbrSurfaceProperties.CoatColor = 0; - pbrSurfaceProperties.CoatStrength = 0; - pbrSurfaceProperties.CoatRoughness = 0; - pbrSurfaceProperties.CoatF0 = 0.04; - - pbrSurfaceProperties.FuzzColor = 0; - pbrSurfaceProperties.FuzzWeight = 0; + + pbrSurfaceProperties.GlintScreenSpaceScale = glintParameters.x; + pbrSurfaceProperties.GlintLogMicrofacetDensity = glintParameters.y; + pbrSurfaceProperties.GlintMicrofacetRoughness = glintParameters.z; + pbrSurfaceProperties.GlintDensityRandomization = glintParameters.w; baseColor.xyz *= 1 - pbrSurfaceProperties.Metallic; @@ -1904,7 +1937,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 coatFinalLightColor = coatShadowDirLightColorMultiplier * pbrDirLightColor; float3 dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor; - PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedDirLightDirection, DirLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties); + PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedDirLightDirection, DirLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties, tbn, uvOriginal); lightsDiffuseColor += dirDiffuseColor; coatLightsDiffuseColor += coatDirDiffuseColor; transmissionColor += dirTransmissionColor; @@ -1986,7 +2019,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace refractedLightDirection = -refract(-normalizedLightDirection, coatModelNormal, eta); } float3 pbrLightColor = PBR::AdjustPointLightColor(lightColor); - PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedLightDirection, normalizedLightDirection, pbrLightColor, pbrLightColor, pbrSurfaceProperties); + PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedLightDirection, normalizedLightDirection, pbrLightColor, pbrLightColor, pbrSurfaceProperties, tbn, uvOriginal); lightsDiffuseColor += pointDiffuseColor; coatLightsDiffuseColor += coatPointDiffuseColor; transmissionColor += pointTransmissionColor; @@ -2125,7 +2158,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } float3 pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor; - PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, worldSpaceNormal.xyz, coatWorldNormal, refractedViewDirectionWS, worldSpaceViewDirection, refractedLightDirection, normalizedLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties); + PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, worldSpaceNormal.xyz, coatWorldNormal, refractedViewDirectionWS, worldSpaceViewDirection, refractedLightDirection, normalizedLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties, tbn, uvOriginal); lightsDiffuseColor += pointDiffuseColor; coatLightsDiffuseColor += coatPointDiffuseColor; transmissionColor += pointTransmissionColor; diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 9d7f2c150d..895f2f1a37 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -474,24 +474,13 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # if defined(TRUE_PBR) float4 rawRMAOS = TexRMAOSSampler.Sample(SampRMAOSSampler, input.TexCoord.xy) * float4(PBRParams1.x, 1, 1, PBRParams1.y); - PBR::SurfaceProperties pbrSurfaceProperties; + PBR::SurfaceProperties pbrSurfaceProperties = PBR::InitSurfaceProperties(); pbrSurfaceProperties.Roughness = saturate(rawRMAOS.x); pbrSurfaceProperties.Metallic = saturate(rawRMAOS.y); pbrSurfaceProperties.AO = rawRMAOS.z; pbrSurfaceProperties.F0 = lerp(saturate(rawRMAOS.w), baseColor.xyz, pbrSurfaceProperties.Metallic); - pbrSurfaceProperties.SubsurfaceColor = 0; - pbrSurfaceProperties.Thickness = 0; - - pbrSurfaceProperties.CoatColor = 0; - pbrSurfaceProperties.CoatStrength = 0; - pbrSurfaceProperties.CoatRoughness = 0; - pbrSurfaceProperties.CoatF0 = 0.04; - - pbrSurfaceProperties.FuzzColor = 0; - pbrSurfaceProperties.FuzzWeight = 0; - baseColor.xyz *= 1 - pbrSurfaceProperties.Metallic; pbrSurfaceProperties.BaseColor = baseColor.xyz; diff --git a/package/Shaders/SnowSparkles/Glints2023.hlsli b/package/Shaders/SnowSparkles/Glints2023.hlsli new file mode 100644 index 0000000000..ce07499680 --- /dev/null +++ b/package/Shaders/SnowSparkles/Glints2023.hlsli @@ -0,0 +1,520 @@ +static const float DEG2RAD = 0.01745329251; +static const float RAD2DEG = 57.2957795131; + +Texture2D _Glint2023NoiseMap : register(t28); + +//======================================================================================= +// TOOLS +//======================================================================================= +float erfinv(float x) +{ + float w, p; + w = -log((1.0 - x) * (1.0 + x)); + if (w < 5.000000) { + w = w - 2.500000; + p = 2.81022636e-08; + p = 3.43273939e-07 + p * w; + p = -3.5233877e-06 + p * w; + p = -4.39150654e-06 + p * w; + p = 0.00021858087 + p * w; + p = -0.00125372503 + p * w; + p = -0.00417768164 + p * w; + p = 0.246640727 + p * w; + p = 1.50140941 + p * w; + } else { + w = sqrt(w) - 3.000000; + p = -0.000200214257; + p = 0.000100950558 + p * w; + p = 0.00134934322 + p * w; + p = -0.00367342844 + p * w; + p = 0.00573950773 + p * w; + p = -0.0076224613 + p * w; + p = 0.00943887047 + p * w; + p = 1.00167406 + p * w; + p = 2.83297682 + p * w; + } + return p * x; +} + +float3 sampleNormalDistribution(float3 u, float mu, float sigma) +{ + //return mu + sigma * (sqrt(-2.0 * log(u.x))* cos(2.0 * pi * u.y)); + float x0 = sigma * 1.414213f * erfinv(2.0 * u.x - 1.0) + mu; + float x1 = sigma * 1.414213f * erfinv(2.0 * u.y - 1.0) + mu; + float x2 = sigma * 1.414213f * erfinv(2.0 * u.z - 1.0) + mu; + return float3(x0, x1, x2); +} + +float4 sampleNormalDistribution(float4 u, float mu, float sigma) +{ + //return mu + sigma * (sqrt(-2.0 * log(u.x))* cos(2.0 * pi * u.y)); + float x0 = sigma * 1.414213f * erfinv(2.0 * u.x - 1.0) + mu; + float x1 = sigma * 1.414213f * erfinv(2.0 * u.y - 1.0) + mu; + float x2 = sigma * 1.414213f * erfinv(2.0 * u.z - 1.0) + mu; + float x3 = sigma * 1.414213f * erfinv(2.0 * u.w - 1.0) + mu; + return float4(x0, x1, x2, x3); +} + +float3 pcg3dFloat(uint3 v) +{ + v = v * 1664525u + 1013904223u; + + v.x += v.y * v.z; + v.y += v.z * v.x; + v.z += v.x * v.y; + + v ^= v >> 16u; + + v.x += v.y * v.z; + v.y += v.z * v.x; + v.z += v.x * v.y; + + return v * (1.0 / 4294967296.0); +} + +float HashWithoutSine13(float3 p3) +{ + p3 = frac(p3 * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return frac((p3.x + p3.y) * p3.z); +} + +float2x2 Inverse(float2x2 A) +{ + return float2x2(A[1][1], -A[0][1], -A[1][0], A[0][0]) / determinant(A); +} + +void GetGradientEllipse(float2 duvdx, float2 duvdy, out float2 ellipseMajor, out float2 ellipseMinor) +{ + float2x2 J = float2x2(duvdx, duvdy); + J = Inverse(J); + J = mul(J, transpose(J)); + + float a = J[0][0]; + float b = J[0][1]; + float c = J[1][0]; + float d = J[1][1]; + + float T = a + d; + float D = a * d - b * c; + float L1 = T / 2.0 - pow(T * T / 3.99999 - D, 0.5); + float L2 = T / 2.0 + pow(T * T / 3.99999 - D, 0.5); + + float2 A0 = float2(L1 - d, c); + float2 A1 = float2(L2 - d, c); + float r0 = 1.0 / sqrt(L1); + float r1 = 1.0 / sqrt(L2); + ellipseMajor = normalize(A0) * r0; + ellipseMinor = normalize(A1) * r1; +} + +float2 VectorToSlope(float3 v) +{ + return float2(-v.x / v.z, -v.y / v.z); +} + +float3 SlopeToVector(float2 s) +{ + float z = 1 / sqrt(s.x * s.x + s.y * s.y + 1); + float x = s.x * z; + float y = s.y * z; + return float3(x, y, z); +} + +float2 RotateUV(float2 uv, float rotation, float2 mid) +{ + return float2( + cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x, + cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y); +} + +float BilinearLerp(float4 values, float2 valuesLerp) +{ + // Values XY = float4(00, 01, 10, 11) + float resultX = lerp(values.x, values.z, valuesLerp.x); + float resultY = lerp(values.y, values.w, valuesLerp.x); + float result = lerp(resultX, resultY, valuesLerp.y); + return result; +} + +float4 BilinearLerpParallel4(float4 values00, float4 values01, float4 values10, float4 values11, float4 valuesLerpX, float4 valuesLerpY) +{ + // Values XY = float4(00, 01, 10, 11) + float4 resultX = lerp(values00, values10, valuesLerpX); + float4 resultY = lerp(values01, values11, valuesLerpX); + float4 result = lerp(resultX, resultY, valuesLerpY); + return result; +} + +float Remap(float s, float a1, float a2, float b1, float b2) +{ + return b1 + (s - a1) * (b2 - b1) / (a2 - a1); +} + +float Remap01To(float s, float b1, float b2) +{ + return b1 + s * (b2 - b1); +} + +float RemapTo01(float s, float a1, float a2) +{ + return (s - a1) / (a2 - a1); +} + +float4 RemapTo01(float4 s, float4 a1, float4 a2) +{ + return (s - a1) / (a2 - a1); +} + +float3 GetBarycentricWeights(float2 p, float2 a, float2 b, float2 c) +{ + /*float2 v0 = b - a; + float2 v1 = c - a; + float2 v2 = p - a; + float d00 = dot(v0, v0); + float d01 = dot(v0, v1); + float d11 = dot(v1, v1); + float d20 = dot(v2, v0); + float d21 = dot(v2, v1); + float denom = d00 * d11 - d01 * d01; + float v = (d11 * d20 - d01 * d21) / denom; + float w = (d00 * d21 - d01 * d20) / denom; + float u = 1.0 - v - w; + return float3(u, v, w);*/ + + float2 v0 = b - a; + float2 v1 = c - a; + float2 v2 = p - a; + float den = v0.x * v1.y - v1.x * v0.y; + float v = (v2.x * v1.y - v1.x * v2.y) / den; + float w = (v0.x * v2.y - v2.x * v0.y) / den; + float u = 1.0f - v - w; + return float3(u, v, w); +} + +float4 GetBarycentricWeightsTetrahedron(float3 p, float3 v1, float3 v2, float3 v3, float3 v4) +{ + float3 c11 = v1 - v4, c21 = v2 - v4, c31 = v3 - v4, c41 = v4 - p; + + float2 m1 = c31.yz / c31.x; + float2 c12 = c11.yz - c11.x * m1, c22 = c21.yz - c21.x * m1, c32 = c41.yz - c41.x * m1; + + float4 uvwk = 0.0.rrrr; + float m2 = c22.y / c22.x; + uvwk.x = (c32.x * m2 - c32.y) / (c12.y - c12.x * m2); + uvwk.y = -(c32.x + c12.x * uvwk.x) / c22.x; + uvwk.z = -(c41.x + c21.x * uvwk.y + c11.x * uvwk.x) / c31.x; + uvwk.w = 1.0 - uvwk.z - uvwk.y - uvwk.x; + + return uvwk; +} + +void UnpackFloat(float input, out float a, out float b) +{ + uint uintInput = asuint(input); + a = f16tof32(uintInput >> 16); + b = f16tof32(uintInput); +} + +void UnpackFloatParallel4(float4 input, out float4 a, out float4 b) +{ + uint4 uintInput = asuint(input); + a = f16tof32(uintInput >> 16); + b = f16tof32(uintInput); +} + +//======================================================================================= +// GLINTS TEST NOVEMBER 2022 +//======================================================================================= +void CustomRand4Texture(float2 slope, float2 slopeRandOffset, out float4 outUniform, out float4 outGaussian, out float2 slopeLerp) +{ + int2 size = snowSettings.Glint2023NoiseMapSize.rr; + float2 slope2 = abs(slope) / snowSettings.MicrofacetRoughness; + slope2 = slope2 + (slopeRandOffset * size); + slopeLerp = frac(slope2); + int2 slopeCoord = int2(floor(slope2)) % size; + + float4 packedRead = _Glint2023NoiseMap[slopeCoord]; + UnpackFloatParallel4(packedRead, outUniform, outGaussian); +} + +float GenerateAngularBinomialValueForSurfaceCell(float4 randB, float4 randG, float2 slopeLerp, float footprintOneHitProba, float binomialSmoothWidth, float footprintMean, float footprintSTD, float microfacetCount) +{ + float4 gating; + if (binomialSmoothWidth > 0.0000001) + gating = saturate(RemapTo01(randB, footprintOneHitProba + binomialSmoothWidth, footprintOneHitProba - binomialSmoothWidth)); + else + gating = randB < footprintOneHitProba; + + float4 gauss = randG * footprintSTD + footprintMean; + gauss = clamp(floor(gauss), 0, microfacetCount); + float4 results = gating * (1.0 + gauss); + float result = BilinearLerp(results, slopeLerp); + return result; +} + +float SampleGlintGridSimplex(float2 uv, uint gridSeed, float2 slope, float footprintArea, float targetNDF, float gridWeight) +{ + // Get surface space glint simplex grid cell + const float2x2 gridToSkewedGrid = float2x2(1.0, -0.57735027, 0.0, 1.15470054); + float2 skewedCoord = mul(gridToSkewedGrid, uv); + int2 baseId = int2(floor(skewedCoord)); + float3 temp = float3(frac(skewedCoord), 0.0); + temp.z = 1.0 - temp.x - temp.y; + float s = step(0.0, -temp.z); + float s2 = 2.0 * s - 1.0; + int2 glint0 = baseId + int2(s, s); + int2 glint1 = baseId + int2(s, 1.0 - s); + int2 glint2 = baseId + int2(1.0 - s, s); + float3 barycentrics = float3(-temp.z * s2, s - temp.y * s2, s - temp.x * s2); + + // Generate per surface cell random numbers + float3 rand0 = pcg3dFloat(uint3(glint0 + 2147483648, gridSeed)); // TODO : optimize away manual seeds + float3 rand1 = pcg3dFloat(uint3(glint1 + 2147483648, gridSeed)); + float3 rand2 = pcg3dFloat(uint3(glint2 + 2147483648, gridSeed)); + + // Get per surface cell per slope cell random numbers + float4 rand0SlopesB, rand1SlopesB, rand2SlopesB, rand0SlopesG, rand1SlopesG, rand2SlopesG; + float2 slopeLerp0, slopeLerp1, slopeLerp2; + CustomRand4Texture(slope, rand0.yz, rand0SlopesB, rand0SlopesG, slopeLerp0); + CustomRand4Texture(slope, rand1.yz, rand1SlopesB, rand1SlopesG, slopeLerp1); + CustomRand4Texture(slope, rand2.yz, rand2SlopesB, rand2SlopesG, slopeLerp2); + + // Compute microfacet count with randomization + float3 logDensityRand = clamp(sampleNormalDistribution(float3(rand0.x, rand1.x, rand2.x), snowSettings.LogMicrofacetDensity.r, snowSettings.DensityRandomization), 0.0, 50.0); // TODO : optimize sampleNormalDist + float3 microfacetCount = max(0.0.rrr, footprintArea.rrr * exp(logDensityRand)); + float3 microfacetCountBlended = microfacetCount * gridWeight; + + // Compute binomial properties + float hitProba = snowSettings.MicrofacetRoughness * targetNDF; // probability of hitting desired half vector in NDF distribution + float3 footprintOneHitProba = (1.0 - pow(1.0 - hitProba.rrr, microfacetCountBlended)); // probability of hitting at least one microfacet in footprint + float3 footprintMean = (microfacetCountBlended - 1.0) * hitProba.rrr; // Expected value of number of hits in the footprint given already one hit + float3 footprintSTD = sqrt((microfacetCountBlended - 1.0) * hitProba.rrr * (1.0 - hitProba.rrr)); // Standard deviation of number of hits in the footprint given already one hit + float3 binomialSmoothWidth = 0.1 * clamp(footprintOneHitProba * 10, 0.0, 1.0) * clamp((1.0 - footprintOneHitProba) * 10, 0.0, 1.0); + + // Generate numbers of reflecting microfacets + float result0, result1, result2; + result0 = GenerateAngularBinomialValueForSurfaceCell(rand0SlopesB, rand0SlopesG, slopeLerp0, footprintOneHitProba.x, binomialSmoothWidth.x, footprintMean.x, footprintSTD.x, microfacetCountBlended.x); + result1 = GenerateAngularBinomialValueForSurfaceCell(rand1SlopesB, rand1SlopesG, slopeLerp1, footprintOneHitProba.y, binomialSmoothWidth.y, footprintMean.y, footprintSTD.y, microfacetCountBlended.y); + result2 = GenerateAngularBinomialValueForSurfaceCell(rand2SlopesB, rand2SlopesG, slopeLerp2, footprintOneHitProba.z, binomialSmoothWidth.z, footprintMean.z, footprintSTD.z, microfacetCountBlended.z); + + // Interpolate result for glint grid cell + float3 results = float3(result0, result1, result2) / microfacetCount.xyz; + float result = dot(results, barycentrics); + return result; +} + +void GetAnisoCorrectingGridTetrahedron(bool centerSpecialCase, inout float thetaBinLerp, float ratioLerp, float lodLerp, out float3 p0, out float3 p1, out float3 p2, out float3 p3) +{ + [branch] if (centerSpecialCase == true) // SPECIAL CASE (no anisotropy, center of blending pattern, different triangulation) + { + float3 a = float3(0, 1, 0); + float3 b = float3(0, 0, 0); + float3 c = float3(1, 1, 0); + float3 d = float3(0, 1, 1); + float3 e = float3(0, 0, 1); + float3 f = float3(1, 1, 1); + [branch] if (lodLerp > 1.0 - ratioLerp) // Upper pyramid + { + [branch] if (RemapTo01(lodLerp, 1.0 - ratioLerp, 1.0) > thetaBinLerp) // Left-up tetrahedron (a, e, d, f) + { + p0 = a; + p1 = e; + p2 = d; + p3 = f; + } + else // Right-down tetrahedron (f, e, c, a) + { + p0 = f; + p1 = e; + p2 = c; + p3 = a; + } + } + else // Lower tetrahedron (b, a, c, e) + { + p0 = b; + p1 = a; + p2 = c; + p3 = e; + } + } + else // NORMAL CASE + { + float3 a = float3(0, 1, 0); + float3 b = float3(0, 0, 0); + float3 c = float3(0.5, 1, 0); + float3 d = float3(1, 0, 0); + float3 e = float3(1, 1, 0); + float3 f = float3(0, 1, 1); + float3 g = float3(0, 0, 1); + float3 h = float3(0.5, 1, 1); + float3 i = float3(1, 0, 1); + float3 j = float3(1, 1, 1); + [branch] if (thetaBinLerp < 0.5 && thetaBinLerp * 2.0 < ratioLerp) // Prism A + { + [branch] if (lodLerp > 1.0 - ratioLerp) // Upper pyramid + { + [branch] if (RemapTo01(lodLerp, 1.0 - ratioLerp, 1.0) > RemapTo01(thetaBinLerp * 2.0, 0.0, ratioLerp)) // Left-up tetrahedron (a, f, h, g) + { + p0 = a; + p1 = f; + p2 = h; + p3 = g; + } + else // Right-down tetrahedron (c, a, h, g) + { + p0 = c; + p1 = a; + p2 = h; + p3 = g; + } + } + else // Lower tetrahedron (b, a, c, g) + { + p0 = b; + p1 = a; + p2 = c; + p3 = g; + } + } + else if (1.0 - ((thetaBinLerp - 0.5) * 2.0) > ratioLerp) // Prism B + { + [branch] if (lodLerp < 1.0 - ratioLerp) // Lower pyramid + { + [branch] if (RemapTo01(lodLerp, 0.0, 1.0 - ratioLerp) > RemapTo01(thetaBinLerp, 0.5 - (1.0 - ratioLerp) * 0.5, 0.5 + (1.0 - ratioLerp) * 0.5)) // Left-up tetrahedron (b, g, i, c) + { + p0 = b; + p1 = g; + p2 = i; + p3 = c; + } + else // Right-down tetrahedron (d, b, c, i) + { + p0 = d; + p1 = b; + p2 = c; + p3 = i; + } + } + else // Upper tetrahedron (c, g, h, i) + { + p0 = c; + p1 = g; + p2 = h; + p3 = i; + } + } + else // Prism C + { + [branch] if (lodLerp > 1.0 - ratioLerp) // Upper pyramid + { + [branch] if (RemapTo01(lodLerp, 1.0 - ratioLerp, 1.0) > RemapTo01((thetaBinLerp - 0.5) * 2.0, 1.0 - ratioLerp, 1.0)) // Left-up tetrahedron (c, j, h, i) + { + p0 = c; + p1 = j; + p2 = h; + p3 = i; + } + else // Right-down tetrahedron (e, i, c, j) + { + p0 = e; + p1 = i; + p2 = c; + p3 = j; + } + } + else // Lower tetrahedron (d, e, c, i) + { + p0 = d; + p1 = e; + p2 = c; + p3 = i; + } + } + } + + return; +} + +float4 SampleGlints2023NDF(float3 localHalfVector, float targetNDF, float maxNDF, float2 uv, float2 duvdx, float2 duvdy) +{ + // ACCURATE PIXEL FOOTPRINT ELLIPSE + float2 ellipseMajor, ellipseMinor; + GetGradientEllipse(duvdx, duvdy, ellipseMajor, ellipseMinor); + float ellipseRatio = length(ellipseMajor) / length(ellipseMinor); + + // SHARED GLINT NDF VALUES + float halfScreenSpaceScaler = snowSettings.ScreenSpaceScale * 0.5; + float footprintArea = length(ellipseMajor) * halfScreenSpaceScaler * length(ellipseMinor) * halfScreenSpaceScaler * 4.0; + float2 slope = localHalfVector.xy; // Orthogrtaphic slope projected grid + float rescaledTargetNDF = targetNDF / maxNDF; + + // MANUAL LOD COMPENSATION + float lod = log2(length(ellipseMinor) * halfScreenSpaceScaler); + float lod0 = (int)lod; //lod >= 0.0 ? (int)(lod) : (int)(lod - 1.0); + float lod1 = lod0 + 1; + float divLod0 = pow(2.0, lod0); + float divLod1 = pow(2.0, lod1); + float lodLerp = frac(lod); + float footprintAreaLOD0 = pow(exp2(lod0), 2.0); + float footprintAreaLOD1 = pow(exp2(lod1), 2.0); + + // MANUAL ANISOTROPY RATIO COMPENSATION + float ratio0 = max(pow(2.0, (int)log2(ellipseRatio)), 1.0); + float ratio1 = ratio0 * 2.0; + float ratioLerp = clamp(Remap(ellipseRatio, ratio0, ratio1, 0.0, 1.0), 0.0, 1.0); + + // MANUAL ANISOTROPY ROTATION COMPENSATION + float2 v1 = float2(0.0, 1.0); + float2 v2 = normalize(ellipseMajor); + float theta = atan2(v1.x * v2.y - v1.y * v2.x, v1.x * v2.x + v1.y * v2.y) * RAD2DEG; + float thetaGrid = 90.0 / max(ratio0, 2.0); + float thetaBin = (int)(theta / thetaGrid) * thetaGrid; + thetaBin = thetaBin + (thetaGrid / 2.0); + float thetaBin0 = theta < thetaBin ? thetaBin - thetaGrid / 2.0 : thetaBin; + float thetaBinH = thetaBin0 + thetaGrid / 4.0; + float thetaBin1 = thetaBin0 + thetaGrid / 2.0; + float thetaBinLerp = Remap(theta, thetaBin0, thetaBin1, 0.0, 1.0); + thetaBin0 = thetaBin0 <= 0.0 ? 180.0 + thetaBin0 : thetaBin0; + + // TETRAHEDRONIZATION OF ROTATION + RATIO + LOD GRID + bool centerSpecialCase = (ratio0.x == 1.0); + float2 divLods = float2(divLod0, divLod1); + float2 footprintAreas = float2(footprintAreaLOD0, footprintAreaLOD1); + float2 ratios = float2(ratio0, ratio1); + float4 thetaBins = float4(thetaBin0, thetaBinH, thetaBin1, 0.0); // added 0.0 for center singularity case + float3 tetraA, tetraB, tetraC, tetraD; + GetAnisoCorrectingGridTetrahedron(centerSpecialCase, thetaBinLerp, ratioLerp, lodLerp, tetraA, tetraB, tetraC, tetraD); + if (centerSpecialCase == true) // Account for center singularity in barycentric computation + thetaBinLerp = Remap01To(thetaBinLerp, 0.0, ratioLerp); + float4 tetraBarycentricWeights = GetBarycentricWeightsTetrahedron(float3(thetaBinLerp, ratioLerp, lodLerp), tetraA, tetraB, tetraC, tetraD); // Compute barycentric coordinates within chosen tetrahedron + + // PREPARE NEEDED ROTATIONS + tetraA.x *= 2; + tetraB.x *= 2; + tetraC.x *= 2; + tetraD.x *= 2; + if (centerSpecialCase == true) // Account for center singularity (if center vertex => no rotation) + { + tetraA.x = (tetraA.y == 0) ? 3 : tetraA.x; + tetraB.x = (tetraB.y == 0) ? 3 : tetraB.x; + tetraC.x = (tetraC.y == 0) ? 3 : tetraC.x; + tetraD.x = (tetraD.y == 0) ? 3 : tetraD.x; + } + float2 uvRotA = RotateUV(uv, thetaBins[tetraA.x] * DEG2RAD, 0.0.rr); + float2 uvRotB = RotateUV(uv, thetaBins[tetraB.x] * DEG2RAD, 0.0.rr); + float2 uvRotC = RotateUV(uv, thetaBins[tetraC.x] * DEG2RAD, 0.0.rr); + float2 uvRotD = RotateUV(uv, thetaBins[tetraD.x] * DEG2RAD, 0.0.rr); + + // SAMPLE GLINT GRIDS + uint gridSeedA = HashWithoutSine13(float3(log2(divLods[tetraA.z]), thetaBins[tetraA.x] % 360, ratios[tetraA.y])) * 4294967296.0; + uint gridSeedB = HashWithoutSine13(float3(log2(divLods[tetraB.z]), thetaBins[tetraB.x] % 360, ratios[tetraB.y])) * 4294967296.0; + uint gridSeedC = HashWithoutSine13(float3(log2(divLods[tetraC.z]), thetaBins[tetraC.x] % 360, ratios[tetraC.y])) * 4294967296.0; + uint gridSeedD = HashWithoutSine13(float3(log2(divLods[tetraD.z]), thetaBins[tetraD.x] % 360, ratios[tetraD.y])) * 4294967296.0; + float sampleA = SampleGlintGridSimplex(uvRotA / divLods[tetraA.z] / float2(1.0, ratios[tetraA.y]), gridSeedA, slope, ratios[tetraA.y] * footprintAreas[tetraA.z], rescaledTargetNDF, tetraBarycentricWeights.x); + float sampleB = SampleGlintGridSimplex(uvRotB / divLods[tetraB.z] / float2(1.0, ratios[tetraB.y]), gridSeedB, slope, ratios[tetraB.y] * footprintAreas[tetraB.z], rescaledTargetNDF, tetraBarycentricWeights.y); + float sampleC = SampleGlintGridSimplex(uvRotC / divLods[tetraC.z] / float2(1.0, ratios[tetraC.y]), gridSeedC, slope, ratios[tetraC.y] * footprintAreas[tetraC.z], rescaledTargetNDF, tetraBarycentricWeights.z); + float sampleD = SampleGlintGridSimplex(uvRotD / divLods[tetraD.z] / float2(1.0, ratios[tetraD.y]), gridSeedD, slope, ratios[tetraD.y] * footprintAreas[tetraD.z], rescaledTargetNDF, tetraBarycentricWeights.w); + return (sampleA + sampleB + sampleC + sampleD) * (1.0 / snowSettings.MicrofacetRoughness) * maxNDF; +} \ No newline at end of file diff --git a/package/Shaders/SnowSparkles/noisegen.cs.hlsl b/package/Shaders/SnowSparkles/noisegen.cs.hlsl new file mode 100644 index 0000000000..31f9ad9409 --- /dev/null +++ b/package/Shaders/SnowSparkles/noisegen.cs.hlsl @@ -0,0 +1,130 @@ +RWTexture2D tex_noise : register(u0); + +static const float GAUSSIAN_AVG = 0.0; +static const float GAUSSIAN_STD = 1.0; + +uint CoordToFlatId(uint2 coord, uint width) +{ + return coord.y * width + coord.x; +} + +float PackFloats(float a, float b) +{ + uint a16 = f32tof16(a); + uint b16 = f32tof16(b); + uint abPacked = (a16 << 16) | b16; + return asfloat(abPacked); +} + +uint WangHash(uint seed) +{ + seed = (seed ^ 61) ^ (seed >> 16); + seed *= 9; + seed = seed ^ (seed >> 4); + seed *= 0x27d4eb2d; + seed = seed ^ (seed >> 15); + return seed; +} + +void RandXorshift(inout uint rngState) +{ + // Xorshift algorithm from George Marsaglia's paper + rngState ^= (rngState << 13); + rngState ^= (rngState >> 17); + rngState ^= (rngState << 5); +} + +float RandXorshiftFloat(inout uint rngState) +{ + RandXorshift(rngState); + float res = float(rngState) * (1.0 / 4294967296.0); + return res; +} + +float Erf(float x) +{ + // Save the sign of x + int sign = 1; + if (x < 0) + sign = -1; + x = abs(x); + + // A&S formula 7.1.26 + float t = 1.0 / (1.0 + 0.3275911 * x); + float y = 1.0 - (((((1.061405429 * t + -1.453152027) * t) + 1.421413741) * t + -0.284496736) * t + 0.254829592) * t * exp(-x * x); + + return sign * y; +} + +float ErfInv(float x) +{ + float w, p; + w = -log((1.0f - x) * (1.0f + x)); + if (w < 5.000000f) { + w = w - 2.500000; + p = 2.81022636e-08; + p = 3.43273939e-07 + p * w; + p = -3.5233877e-06 + p * w; + p = -4.39150654e-06 + p * w; + p = 0.00021858087 + p * w; + p = -0.00125372503 + p * w; + p = -0.00417768164 + p * w; + p = 0.246640727 + p * w; + p = 1.50140941 + p * w; + } else { + w = sqrt(w) - 3.000000; + p = -0.000200214257; + p = 0.000100950558 + p * w; + p = 0.00134934322 + p * w; + p = -0.00367342844 + p * w; + p = 0.00573950773 + p * w; + p = -0.0076224613 + p * w; + p = 0.00943887047 + p * w; + p = 1.00167406 + p * w; + p = 2.83297682 + p * w; + } + return p * x; +} + +float CDF(float x, float mu, float sigma) +{ + float U = 0.5 * (1 + Erf((x - mu) / (sigma * sqrt(2.0)))); + return U; +} + +float InvCDF(float U, float mu, float sigma) +{ + float x = sigma * sqrt(2.0) * ErfInv(2.0 * U - 1.0) + mu; + return x; +} + +[numthreads(32, 32, 1)] void main(const uint2 tid + : SV_DispatchThreadID) { + uint2 size; + tex_noise.GetDimensions(size.x, size.y); + int offset = size.x * size.y * 0x69420; + + // Generate random numbers for this cell and the next ones in X and Y + int2 pixelCoord00 = tid.xy; + uint rngState00 = WangHash(CoordToFlatId(pixelCoord00 * 123, size.x) + offset); + float u00 = RandXorshiftFloat(rngState00); + float g00 = InvCDF(RandXorshiftFloat(rngState00), GAUSSIAN_AVG, GAUSSIAN_STD); + + int2 pixelCoord01 = (pixelCoord00 + int2(0, 1)) % size; + uint rngState01 = WangHash(CoordToFlatId(pixelCoord01 * 123, size.x) + offset); + float u01 = RandXorshiftFloat(rngState01); + float g01 = InvCDF(RandXorshiftFloat(rngState01), GAUSSIAN_AVG, GAUSSIAN_STD); + + int2 pixelCoord10 = (pixelCoord00 + int2(1, 0)) % size; + uint rngState10 = WangHash(CoordToFlatId(pixelCoord10 * 123, size.x) + offset); + float u10 = RandXorshiftFloat(rngState10); + float g10 = InvCDF(RandXorshiftFloat(rngState10), GAUSSIAN_AVG, GAUSSIAN_STD); + + int2 pixelCoord11 = (pixelCoord00 + int2(1, 1)) % size; + uint rngState11 = WangHash(CoordToFlatId(pixelCoord11 * 123, size.x) + offset); + float u11 = RandXorshiftFloat(rngState11); + float g11 = InvCDF(RandXorshiftFloat(rngState11), GAUSSIAN_AVG, GAUSSIAN_STD); + + // Pack 8 values into 4 + tex_noise[tid.xy] = float4(PackFloats(u00, g00), PackFloats(u01, g01), PackFloats(u10, g10), PackFloats(u11, g11)); +} \ No newline at end of file diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index 0fcbce51d9..25a127b2c3 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -760,6 +760,12 @@ namespace SIE { "LandscapeTexture5PBRParams", 49 }, { "LandscapeTexture6PBRParams", 50 }, { "PBRParams2", 51 }, + { "LandscapeTexture1GlintParameters", 52 }, + { "LandscapeTexture2GlintParameters", 53 }, + { "LandscapeTexture3GlintParameters", 54 }, + { "LandscapeTexture4GlintParameters", 55 }, + { "LandscapeTexture5GlintParameters", 56 }, + { "LandscapeTexture6GlintParameters", 57 }, }); } else { lightingPS.insert({ @@ -790,6 +796,12 @@ namespace SIE { "LandscapeTexture5PBRParams", 41 }, { "LandscapeTexture6PBRParams", 42 }, { "PBRParams2", 43 }, + { "LandscapeTexture1GlintParameters", 44 }, + { "LandscapeTexture2GlintParameters", 45 }, + { "LandscapeTexture3GlintParameters", 46 }, + { "LandscapeTexture4GlintParameters", 47 }, + { "LandscapeTexture5GlintParameters", 48 }, + { "LandscapeTexture6GlintParameters", 49 }, }); } diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 7a9b7598aa..d7cd42e2f5 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -41,6 +41,16 @@ namespace PNState return true; } } + if constexpr (std::is_same_v) { + if (section.is_object()) { + result.enabled = section["enabled"]; + result.screenSpaceScale = section["screenSpaceScale"]; + result.logMicrofacetDensity = section["logMicrofacetDensity"]; + result.microfacetRoughness = section["microfacetRoughness"]; + result.densityRandomization = section["densityRandomization"]; + return true; + } + } return false; } @@ -248,6 +258,7 @@ void TruePBR::SetupTextureSetData() PNState::Read(config, "innerLayerDisplacementOffset", textureSetData.innerLayerDisplacementOffset); PNState::Read(config, "fuzzColor", textureSetData.fuzzColor); PNState::Read(config, "fuzzWeight", textureSetData.fuzzWeight); + PNState::Read(config, "glintParameters", textureSetData.glintParameters); pbrTextureSets.insert_or_assign(editorId, textureSetData); }); @@ -648,10 +659,12 @@ struct BSLightingShaderProperty_LoadBinary } if (property->flags.any(kSoftLighting)) { pbrMaterial->pbrFlags.set(PBRFlags::Fuzz); + } else if (property->flags.any(kFitSlope)) { + pbrMaterial->pbrFlags.set(PBRFlags::Glint); } } property->flags.set(kVertexLighting); - property->flags.reset(kMenuScreen, kSpecular, kGlowMap, kEnvMap, kMultiLayerParallax, kSoftLighting, kRimLighting, kBackLighting, kAnisotropicLighting, kEffectLighting); + property->flags.reset(kMenuScreen, kSpecular, kGlowMap, kEnvMap, kMultiLayerParallax, kSoftLighting, kRimLighting, kBackLighting, kAnisotropicLighting, kEffectLighting, kFitSlope); } } static inline REL::Relocation func; @@ -754,6 +767,14 @@ struct BSLightingShader_SetupMaterial if (pbrMaterial->landscapeDisplacementTextures[textureIndex] != nullptr && pbrMaterial->landscapeDisplacementTextures[textureIndex] != RE::BSGraphics::State::GetSingleton()->GetRuntimeData().defaultTextureBlack) { flags |= (1 << (BSLightingShaderMaterialPBRLandscape::NumTiles + textureIndex)); } + bool hasGlint = false; + if (pbrMaterial->glintParameters[textureIndex].enabled) { + hasGlint = true; + flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles + 1 + textureIndex)); + } + if (hasGlint) { + flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles)); + } } } shadowState->SetPSConstant(flags, RE::BSGraphics::ConstantGroupLevel::PerMaterial, 36); @@ -761,6 +782,7 @@ struct BSLightingShader_SetupMaterial { constexpr size_t PBRParamsStartIndex = 37; + constexpr size_t GlintParametersStartIndex = 44; for (uint32_t textureIndex = 0; textureIndex < BSLightingShaderMaterialPBRLandscape::NumTiles; ++textureIndex) { std::array PBRParams; @@ -768,6 +790,13 @@ struct BSLightingShader_SetupMaterial PBRParams[1] = pbrMaterial->displacementScales[textureIndex]; PBRParams[2] = pbrMaterial->specularLevels[textureIndex]; shadowState->SetPSConstant(PBRParams, RE::BSGraphics::ConstantGroupLevel::PerMaterial, PBRParamsStartIndex + textureIndex); + + std::array glintParameters; + glintParameters[0] = pbrMaterial->glintParameters[textureIndex].screenSpaceScale; + glintParameters[1] = pbrMaterial->glintParameters[textureIndex].logMicrofacetDensity; + glintParameters[2] = pbrMaterial->glintParameters[textureIndex].microfacetRoughness; + glintParameters[3] = pbrMaterial->glintParameters[textureIndex].densityRandomization; + shadowState->SetPSConstant(PBRParams, RE::BSGraphics::ConstantGroupLevel::PerMaterial, GlintParametersStartIndex + textureIndex); } } @@ -843,6 +872,15 @@ struct BSLightingShader_SetupMaterial PBRParams3[2] = pbrMaterial->GetFuzzColor().blue; PBRParams3[3] = pbrMaterial->GetFuzzWeight(); shadowState->SetPSConstant(PBRParams3, RE::BSGraphics::ConstantGroupLevel::PerMaterial, 27); + } else if (pbrMaterial->pbrFlags.any(PBRFlags::Glint)) { + shaderFlags.set(PBRShaderFlags::Glint); + + std::array GlintParameters; + GlintParameters[0] = pbrMaterial->GetGlintParameters().screenSpaceScale; + GlintParameters[0] = pbrMaterial->GetGlintParameters().logMicrofacetDensity; + GlintParameters[0] = pbrMaterial->GetGlintParameters().microfacetRoughness; + GlintParameters[0] = pbrMaterial->GetGlintParameters().densityRandomization; + shadowState->SetPSConstant(GlintParameters, RE::BSGraphics::ConstantGroupLevel::PerMaterial, 27); } } @@ -1009,6 +1047,8 @@ void SetupLandscapeTexture(BSLightingShaderMaterialPBRLandscape& material, RE::T material.displacementScales[textureIndex] = textureSetData->displacementScale; material.roughnessScales[textureIndex] = textureSetData->roughnessScale; material.specularLevels[textureIndex] = textureSetData->specularLevel; + + material.glintParameters[textureIndex] = textureSetData->glintParameters; } material.isPbr[textureIndex] = isPbr; diff --git a/src/TruePBR.h b/src/TruePBR.h index 930bf82bae..33ecbeaf05 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -1,5 +1,14 @@ #pragma once +struct GlintParameters +{ + bool enabled = false; + float screenSpaceScale = 1.f; + float logMicrofacetDensity = 1.f; + float microfacetRoughness = 1.f; + float densityRandomization = 1.f; +}; + struct TruePBR { public: @@ -55,6 +64,8 @@ struct TruePBR RE::NiColor fuzzColor; float fuzzWeight = 0.f; + + GlintParameters glintParameters; }; void SetupFrame(); diff --git a/src/TruePBR/BSLightingShaderMaterialPBR.cpp b/src/TruePBR/BSLightingShaderMaterialPBR.cpp index 4bdcafc957..2a6c7561ed 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBR.cpp +++ b/src/TruePBR/BSLightingShaderMaterialPBR.cpp @@ -27,6 +27,7 @@ void BSLightingShaderMaterialPBR::CopyMembers(RE::BSShaderMaterial* that) coatSpecularLevel = pbrThat->coatSpecularLevel; fuzzColor = pbrThat->fuzzColor; fuzzWeight = pbrThat->fuzzWeight; + glintParameters = pbrThat->glintParameters; projectedMaterialBaseColorScale = pbrThat->projectedMaterialBaseColorScale; projectedMaterialRoughness = pbrThat->projectedMaterialRoughness; projectedMaterialSpecularLevel = pbrThat->projectedMaterialSpecularLevel; @@ -46,7 +47,11 @@ std::uint32_t BSLightingShaderMaterialPBR::ComputeCRC32(uint32_t srcHash) float coatRoughness = 0.f; float coatSpecularLevel = 0.f; std::array fuzzColor = { 0.f, 0.f, 0.f }; - float fuzzWeight = 0.; + float fuzzWeight = 0.f; + float screenSpaceScale = 0.f; + float logMicrofacetDensity = 0.f; + float microfacetRoughness = 0.f; + float densityRandomization = 0.f; std::array projectedMaterialBaseColorScale = { 0.f, 0.f, 0.f }; float projectedMaterialRoughness = 0.f; float projectedMaterialSpecularLevel = 0.f; @@ -65,6 +70,10 @@ std::uint32_t BSLightingShaderMaterialPBR::ComputeCRC32(uint32_t srcHash) hashes.fuzzColor[1] = fuzzColor[1] * 100.f; hashes.fuzzColor[2] = fuzzColor[2] * 100.f; hashes.fuzzWeight = fuzzWeight * 100.f; + hashes.screenSpaceScale = glintParameters.screenSpaceScale * 100.f; + hashes.logMicrofacetDensity = glintParameters.logMicrofacetDensity * 100.f; + hashes.microfacetRoughness = glintParameters.microfacetRoughness * 100.f; + hashes.densityRandomization = glintParameters.densityRandomization * 100.f; hashes.projectedMaterialBaseColorScale[0] = projectedMaterialBaseColorScale[0] * 100.f; hashes.projectedMaterialBaseColorScale[1] = projectedMaterialBaseColorScale[1] * 100.f; hashes.projectedMaterialBaseColorScale[2] = projectedMaterialBaseColorScale[2] * 100.f; @@ -134,6 +143,10 @@ void BSLightingShaderMaterialPBR::OnLoadTextureSet(std::uint64_t arg1, RE::BSTex fuzzWeight = textureSetData->fuzzWeight; } } + + if (pbrFlags.any(PBRFlags::Glint)) { + glintParameters = textureSetData->glintParameters; + } } } } @@ -226,6 +239,11 @@ void BSLightingShaderMaterialPBR::LoadBinary(RE::NiStream& stream) parameters[2] }; fuzzWeight = parameters[3]; + glintParameters.screenSpaceScale = parameters[0]; + glintParameters.logMicrofacetDensity = parameters[1]; + glintParameters.microfacetRoughness = parameters[2]; + glintParameters.densityRandomization = parameters[3]; + if (stream.header.version > 0x4A) { float dummy; stream.iStr->read(&dummy, 1); @@ -301,4 +319,9 @@ const RE::NiColor& BSLightingShaderMaterialPBR::GetFuzzColor() const float BSLightingShaderMaterialPBR::GetFuzzWeight() const { return fuzzWeight; +} + +const GlintParameters& BSLightingShaderMaterialPBR::GetGlintParameters() const +{ + return glintParameters; } \ No newline at end of file diff --git a/src/TruePBR/BSLightingShaderMaterialPBR.h b/src/TruePBR/BSLightingShaderMaterialPBR.h index bacc25a341..065e6e6335 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBR.h +++ b/src/TruePBR/BSLightingShaderMaterialPBR.h @@ -1,5 +1,7 @@ #pragma once +#include "TruePBR.h" + enum class PBRFlags : uint32_t { Subsurface = 1 << 0, @@ -9,6 +11,7 @@ enum class PBRFlags : uint32_t CoatNormal = 1 << 4, Fuzz = 1 << 5, HairMarschner = 1 << 6, + Glint = 1 << 7, }; enum class PBRShaderFlags : uint32_t @@ -24,6 +27,7 @@ enum class PBRShaderFlags : uint32_t CoatNormal = 1 << 8, Fuzz = 1 << 9, HairMarschner = 1 << 10, + Glint = 1 << 11, }; class BSLightingShaderMaterialPBR : public RE::BSLightingShaderMaterialBase @@ -72,6 +76,8 @@ class BSLightingShaderMaterialPBR : public RE::BSLightingShaderMaterialBase const RE::NiColor& GetFuzzColor() const; float GetFuzzWeight() const; + const GlintParameters& GetGlintParameters() const; + // members RE::BSShaderMaterial::Feature loadedWithFeature = RE::BSShaderMaterial::Feature::kDefault; @@ -87,6 +93,8 @@ class BSLightingShaderMaterialPBR : public RE::BSLightingShaderMaterialBase float projectedMaterialRoughness = 1.f; float projectedMaterialSpecularLevel = 0.04f; + GlintParameters glintParameters; + // Roughness in r, metallic in g, AO in b, nonmetal reflectance in a RE::NiPointer rmaosTexture; diff --git a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp index 7826c748a8..edc662e400 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp +++ b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp @@ -45,6 +45,7 @@ void BSLightingShaderMaterialPBRLandscape::CopyMembers(RE::BSShaderMaterial* tha pbrThat->terrainTexOffsetX = terrainTexOffsetX; pbrThat->terrainTexOffsetY = terrainTexOffsetY; pbrThat->terrainTexFade = terrainTexFade; + pbrThat->glintParameters = glintParameters; } RE::BSShaderMaterial::Feature BSLightingShaderMaterialPBRLandscape::GetFeature() const diff --git a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h index 45c07ac404..7c848fd229 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h +++ b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h @@ -1,5 +1,7 @@ #pragma once +#include "TruePBR.h" + class BSLightingShaderMaterialPBRLandscape : public RE::BSLightingShaderMaterialBase { public: @@ -48,6 +50,8 @@ class BSLightingShaderMaterialPBRLandscape : public RE::BSLightingShaderMaterial std::array, NumTiles> landscapeRMAOSTextures; std::array displacementScales; std::array specularLevels; + + std::array glintParameters; }; static_assert(offsetof(BSLightingShaderMaterialPBRLandscape, terrainOverlayTexture) == offsetof(RE::BSLightingShaderMaterialLandscape, terrainOverlayTexture)); static_assert(offsetof(BSLightingShaderMaterialPBRLandscape, terrainNoiseTexture) == offsetof(RE::BSLightingShaderMaterialLandscape, terrainNoiseTexture)); From ca642a680cf8e3a507afcafee922d356ffa7816e Mon Sep 17 00:00:00 2001 From: Jonahex Date: Sat, 10 Aug 2024 19:18:15 +0000 Subject: [PATCH 03/13] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20clang-for?= =?UTF-8?q?mat=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/Shaders/Common/PBR.hlsli | 26 ++++++++++----------- package/Shaders/ISBlur.hlsl | 20 ++++++++-------- package/Shaders/Lighting.hlsl | 39 +++++++++++++------------------- 3 files changed, 40 insertions(+), 45 deletions(-) diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index b40e454921..500788c163 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -55,34 +55,34 @@ namespace PBR float GlintMicrofacetRoughness; float GlintDensityRandomization; }; - + SurfaceProperties InitSurfaceProperties() - { - SurfaceProperties surfaceProperties; - + { + SurfaceProperties surfaceProperties; + surfaceProperties.Roughness = 1; surfaceProperties.Metallic = 0; surfaceProperties.AO = 1; surfaceProperties.F0 = 0.04; - + surfaceProperties.SubsurfaceColor = 0; surfaceProperties.Thickness = 0; - + surfaceProperties.CoatColor = 0; surfaceProperties.CoatStrength = 0; surfaceProperties.CoatRoughness = 0; surfaceProperties.CoatF0 = 0.04; - + surfaceProperties.FuzzColor = 0; surfaceProperties.FuzzWeight = 0; - + surfaceProperties.GlintScreenSpaceScale = 0; surfaceProperties.GlintLogMicrofacetDensity = 0; surfaceProperties.GlintMicrofacetRoughness = 0; surfaceProperties.GlintDensityRandomization = 0; - - return surfaceProperties; - } + + return surfaceProperties; + } float3 AdjustDirectionalLightColor(float3 lightColor) { @@ -161,10 +161,10 @@ namespace PBR #else [branch] if (PBRFlags & TruePBR_Glint) #endif - { + { float D_max = GetNormalDistributionFunctionGGX(roughness, 1); D = SampleGlints2023NDF(H, D, D_max, uv, ddx(uv), ddy(uv)); - } + } float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); F = GetFresnelFactorSchlick(specularColor, VdotH); diff --git a/package/Shaders/ISBlur.hlsl b/package/Shaders/ISBlur.hlsl index c3b5c755a3..9380c230ba 100644 --- a/package/Shaders/ISBlur.hlsl +++ b/package/Shaders/ISBlur.hlsl @@ -34,11 +34,11 @@ PS_OUTPUT main(PS_INPUT input) PS_OUTPUT psout; float4 color = 0; - + # if defined(TEXTAP) int blurRadius = TEXTAP; # else - uint blurRadius = asuint(BlurRadius); + uint blurRadius = asuint(BlurRadius); # endif float2 blurScale = BlurScale.zw; # if !defined(TEXTAP) || !defined(COLORRANGE) @@ -47,13 +47,15 @@ PS_OUTPUT main(PS_INPUT input) for (int blurIndex = 0; blurIndex < blurRadius; ++blurIndex) { float2 screenPosition = BlurOffsets[blurIndex].xy + input.TexCoord.xy; - float4 imageColor = 0; - [branch] if (BlurScale.x < 0.5) { - imageColor = GetImageColor(GetDynamicResolutionAdjustedScreenPosition(screenPosition), blurScale.y); - } - else { - imageColor = GetImageColor(screenPosition, blurScale.y); - } + float4 imageColor = 0; + [branch] if (BlurScale.x < 0.5) + { + imageColor = GetImageColor(GetDynamicResolutionAdjustedScreenPosition(screenPosition), blurScale.y); + } + else + { + imageColor = GetImageColor(screenPosition, blurScale.y); + } # if defined(BRIGHTPASS) imageColor = BlurBrightPass.y * max(0, -BlurBrightPass.x + imageColor); # endif diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 889d3400a9..a1f510e399 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -614,7 +614,7 @@ cbuffer PerMaterial : register(b1) float4 LandscapeTexture5GlintParameters : packoffset(c5); float4 LandscapeTexture6GlintParameters : packoffset(c6); # endif - float4 LightingEffectParams : packoffset(c7); // fSubSurfaceLightRolloff in x, fRimLightPower in y + float4 LightingEffectParams : packoffset(c7); // fSubSurfaceLightRolloff in x, fRimLightPower in y float4 IBLParams : packoffset(c8); # if !defined(TRUE_PBR) @@ -1243,8 +1243,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float4 glossiness = 0; float4 rawRMAOS = 0; - - float4 glintParameters = 0; + + float4 glintParameters = 0; # if defined(LANDSCAPE) if (input.LandBlendWeights1.x > 0.0) { @@ -1295,16 +1295,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile0PBR) != 0) { rawRMAOS = input.LandBlendWeights1.x * TexRMAOSSampler.Sample(SampRMAOSSampler, diffuseUv) * float4(PBRParams1.x, 1, 1, PBRParams1.z); - if ((PBRFlags & TruePBR_LandTile0HasGlint) != 0) - { + if ((PBRFlags & TruePBR_LandTile0HasGlint) != 0) { glintParameters += input.LandBlendWeights1.x * LandscapeTexture1GlintParameters; } } else { rawRMAOS = input.LandBlendWeights1.x * float4(1 - glossiness.x, 0, 1, 0.04); - if ((PBRFlags & TruePBR_Glint) != 0) - { + if ((PBRFlags & TruePBR_Glint) != 0) { glintParameters = MultiLayerParallaxData; } } @@ -1355,8 +1353,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile1PBR) != 0) { rawRMAOS += input.LandBlendWeights1.y * TexLandRMAOS2Sampler.Sample(SampLandRMAOS2Sampler, uv) * float4(LandscapeTexture2PBRParams.x, 1, 1, LandscapeTexture2PBRParams.z); - if ((PBRFlags & TruePBR_LandTile1HasGlint) != 0) - { + if ((PBRFlags & TruePBR_LandTile1HasGlint) != 0) { glintParameters += input.LandBlendWeights1.y * LandscapeTexture2GlintParameters; } } @@ -1383,8 +1380,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile2PBR) != 0) { rawRMAOS += input.LandBlendWeights1.z * TexLandRMAOS3Sampler.Sample(SampLandRMAOS3Sampler, uv) * float4(LandscapeTexture3PBRParams.x, 1, 1, LandscapeTexture3PBRParams.z); - if ((PBRFlags & TruePBR_LandTile2HasGlint) != 0) - { + if ((PBRFlags & TruePBR_LandTile2HasGlint) != 0) { glintParameters += input.LandBlendWeights1.z * LandscapeTexture3GlintParameters; } } @@ -1411,8 +1407,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile3PBR) != 0) { rawRMAOS += input.LandBlendWeights1.w * TexLandRMAOS4Sampler.Sample(SampLandRMAOS4Sampler, uv) * float4(LandscapeTexture4PBRParams.x, 1, 1, LandscapeTexture4PBRParams.z); - if ((PBRFlags & TruePBR_LandTile3HasGlint) != 0) - { + if ((PBRFlags & TruePBR_LandTile3HasGlint) != 0) { glintParameters += input.LandBlendWeights1.w * LandscapeTexture4GlintParameters; } } @@ -1439,8 +1434,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile4PBR) != 0) { rawRMAOS += input.LandBlendWeights2.x * TexLandRMAOS5Sampler.Sample(SampLandRMAOS5Sampler, uv) * float4(LandscapeTexture5PBRParams.x, 1, 1, LandscapeTexture5PBRParams.z); - if ((PBRFlags & TruePBR_LandTile4HasGlint) != 0) - { + if ((PBRFlags & TruePBR_LandTile4HasGlint) != 0) { glintParameters += input.LandBlendWeights2.x * LandscapeTexture5GlintParameters; } } @@ -1467,8 +1461,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace [branch] if ((PBRFlags & TruePBR_LandTile5PBR) != 0) { rawRMAOS += input.LandBlendWeights2.y * TexLandRMAOS6Sampler.Sample(SampLandRMAOS6Sampler, uv) * float4(LandscapeTexture6PBRParams.x, 1, 1, LandscapeTexture6PBRParams.z); - if ((PBRFlags & TruePBR_LandTile5HasGlint) != 0) - { + if ((PBRFlags & TruePBR_LandTile5HasGlint) != 0) { glintParameters += input.LandBlendWeights2.y * LandscapeTexture6GlintParameters; } } @@ -1619,17 +1612,17 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 screenSpaceNormal = normalize(WorldToView(worldSpaceNormal, false, eyeIndex)); # if defined(TRUE_PBR) - PBR::SurfaceProperties pbrSurfaceProperties = PBR::InitSurfaceProperties(); + PBR::SurfaceProperties pbrSurfaceProperties = PBR::InitSurfaceProperties(); pbrSurfaceProperties.Roughness = saturate(rawRMAOS.x); pbrSurfaceProperties.Metallic = saturate(rawRMAOS.y); pbrSurfaceProperties.AO = rawRMAOS.z; pbrSurfaceProperties.F0 = lerp(saturate(rawRMAOS.w), baseColor.xyz, pbrSurfaceProperties.Metallic); - - pbrSurfaceProperties.GlintScreenSpaceScale = glintParameters.x; - pbrSurfaceProperties.GlintLogMicrofacetDensity = glintParameters.y; - pbrSurfaceProperties.GlintMicrofacetRoughness = glintParameters.z; - pbrSurfaceProperties.GlintDensityRandomization = glintParameters.w; + + pbrSurfaceProperties.GlintScreenSpaceScale = glintParameters.x; + pbrSurfaceProperties.GlintLogMicrofacetDensity = glintParameters.y; + pbrSurfaceProperties.GlintMicrofacetRoughness = glintParameters.z; + pbrSurfaceProperties.GlintDensityRandomization = glintParameters.w; baseColor.xyz *= 1 - pbrSurfaceProperties.Metallic; From 92f1b55e0a5cd084cbe6d01c8701cf66515774c6 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Sat, 10 Aug 2024 23:36:30 +0100 Subject: [PATCH 04/13] fix: trying to fix --- .../Glints}/Glints2023.hlsli | 65 +++++++++------ .../Glints}/noisegen.cs.hlsl | 0 package/Shaders/Common/PBR.hlsli | 47 +++++++---- src/Deferred.cpp | 3 + src/TruePBR.cpp | 80 +++++++++++++++++++ src/TruePBR.h | 17 ++-- 6 files changed, 167 insertions(+), 45 deletions(-) rename package/Shaders/{SnowSparkles => Common/Glints}/Glints2023.hlsli (85%) rename package/Shaders/{SnowSparkles => Common/Glints}/noisegen.cs.hlsl (100%) diff --git a/package/Shaders/SnowSparkles/Glints2023.hlsli b/package/Shaders/Common/Glints/Glints2023.hlsli similarity index 85% rename from package/Shaders/SnowSparkles/Glints2023.hlsli rename to package/Shaders/Common/Glints/Glints2023.hlsli index ce07499680..b7d2382aad 100644 --- a/package/Shaders/SnowSparkles/Glints2023.hlsli +++ b/package/Shaders/Common/Glints/Glints2023.hlsli @@ -1,6 +1,3 @@ -static const float DEG2RAD = 0.01745329251; -static const float RAD2DEG = 57.2957795131; - Texture2D _Glint2023NoiseMap : register(t28); //======================================================================================= @@ -226,10 +223,25 @@ void UnpackFloatParallel4(float4 input, out float4 a, out float4 b) //======================================================================================= // GLINTS TEST NOVEMBER 2022 //======================================================================================= -void CustomRand4Texture(float2 slope, float2 slopeRandOffset, out float4 outUniform, out float4 outGaussian, out float2 slopeLerp) + +struct GlintInput { - int2 size = snowSettings.Glint2023NoiseMapSize.rr; - float2 slope2 = abs(slope) / snowSettings.MicrofacetRoughness; + bool enabled; + float3 H; + float2 uv; + float2 duvdx; + float2 duvdy; + + float ScreenSpaceScale; + float LogMicrofacetDensity; + float MicrofacetRoughness; + float DensityRandomization; +}; + +void CustomRand4Texture(GlintInput params, float2 slope, float2 slopeRandOffset, out float4 outUniform, out float4 outGaussian, out float2 slopeLerp) +{ + int2 size = 512; + float2 slope2 = abs(slope) / params.MicrofacetRoughness; slope2 = slope2 + (slopeRandOffset * size); slopeLerp = frac(slope2); int2 slopeCoord = int2(floor(slope2)) % size; @@ -253,7 +265,7 @@ float GenerateAngularBinomialValueForSurfaceCell(float4 randB, float4 randG, flo return result; } -float SampleGlintGridSimplex(float2 uv, uint gridSeed, float2 slope, float footprintArea, float targetNDF, float gridWeight) +float SampleGlintGridSimplex(GlintInput params, float2 uv, uint gridSeed, float2 slope, float footprintArea, float targetNDF, float gridWeight) { // Get surface space glint simplex grid cell const float2x2 gridToSkewedGrid = float2x2(1.0, -0.57735027, 0.0, 1.15470054); @@ -276,17 +288,17 @@ float SampleGlintGridSimplex(float2 uv, uint gridSeed, float2 slope, float footp // Get per surface cell per slope cell random numbers float4 rand0SlopesB, rand1SlopesB, rand2SlopesB, rand0SlopesG, rand1SlopesG, rand2SlopesG; float2 slopeLerp0, slopeLerp1, slopeLerp2; - CustomRand4Texture(slope, rand0.yz, rand0SlopesB, rand0SlopesG, slopeLerp0); - CustomRand4Texture(slope, rand1.yz, rand1SlopesB, rand1SlopesG, slopeLerp1); - CustomRand4Texture(slope, rand2.yz, rand2SlopesB, rand2SlopesG, slopeLerp2); + CustomRand4Texture(params, slope, rand0.yz, rand0SlopesB, rand0SlopesG, slopeLerp0); + CustomRand4Texture(params, slope, rand1.yz, rand1SlopesB, rand1SlopesG, slopeLerp1); + CustomRand4Texture(params, slope, rand2.yz, rand2SlopesB, rand2SlopesG, slopeLerp2); // Compute microfacet count with randomization - float3 logDensityRand = clamp(sampleNormalDistribution(float3(rand0.x, rand1.x, rand2.x), snowSettings.LogMicrofacetDensity.r, snowSettings.DensityRandomization), 0.0, 50.0); // TODO : optimize sampleNormalDist + float3 logDensityRand = clamp(sampleNormalDistribution(float3(rand0.x, rand1.x, rand2.x), params.LogMicrofacetDensity.r, params.DensityRandomization), 0.0, 50.0); // TODO : optimize sampleNormalDist float3 microfacetCount = max(0.0.rrr, footprintArea.rrr * exp(logDensityRand)); float3 microfacetCountBlended = microfacetCount * gridWeight; // Compute binomial properties - float hitProba = snowSettings.MicrofacetRoughness * targetNDF; // probability of hitting desired half vector in NDF distribution + float hitProba = params.MicrofacetRoughness * targetNDF; // probability of hitting desired half vector in NDF distribution float3 footprintOneHitProba = (1.0 - pow(1.0 - hitProba.rrr, microfacetCountBlended)); // probability of hitting at least one microfacet in footprint float3 footprintMean = (microfacetCountBlended - 1.0) * hitProba.rrr; // Expected value of number of hits in the footprint given already one hit float3 footprintSTD = sqrt((microfacetCountBlended - 1.0) * hitProba.rrr * (1.0 - hitProba.rrr)); // Standard deviation of number of hits in the footprint given already one hit @@ -437,17 +449,20 @@ void GetAnisoCorrectingGridTetrahedron(bool centerSpecialCase, inout float theta return; } -float4 SampleGlints2023NDF(float3 localHalfVector, float targetNDF, float maxNDF, float2 uv, float2 duvdx, float2 duvdy) +float4 SampleGlints2023NDF(GlintInput params, float targetNDF, float maxNDF) { + static const float DEG2RAD = 0.01745329251; + static const float RAD2DEG = 57.2957795131; + // ACCURATE PIXEL FOOTPRINT ELLIPSE float2 ellipseMajor, ellipseMinor; - GetGradientEllipse(duvdx, duvdy, ellipseMajor, ellipseMinor); + GetGradientEllipse(params.duvdx, params.duvdy, ellipseMajor, ellipseMinor); float ellipseRatio = length(ellipseMajor) / length(ellipseMinor); // SHARED GLINT NDF VALUES - float halfScreenSpaceScaler = snowSettings.ScreenSpaceScale * 0.5; + float halfScreenSpaceScaler = params.ScreenSpaceScale * 0.5; float footprintArea = length(ellipseMajor) * halfScreenSpaceScaler * length(ellipseMinor) * halfScreenSpaceScaler * 4.0; - float2 slope = localHalfVector.xy; // Orthogrtaphic slope projected grid + float2 slope = params.H.xy; // Orthogrtaphic slope projected grid float rescaledTargetNDF = targetNDF / maxNDF; // MANUAL LOD COMPENSATION @@ -502,19 +517,19 @@ float4 SampleGlints2023NDF(float3 localHalfVector, float targetNDF, float maxNDF tetraC.x = (tetraC.y == 0) ? 3 : tetraC.x; tetraD.x = (tetraD.y == 0) ? 3 : tetraD.x; } - float2 uvRotA = RotateUV(uv, thetaBins[tetraA.x] * DEG2RAD, 0.0.rr); - float2 uvRotB = RotateUV(uv, thetaBins[tetraB.x] * DEG2RAD, 0.0.rr); - float2 uvRotC = RotateUV(uv, thetaBins[tetraC.x] * DEG2RAD, 0.0.rr); - float2 uvRotD = RotateUV(uv, thetaBins[tetraD.x] * DEG2RAD, 0.0.rr); + float2 uvRotA = RotateUV(params.uv, thetaBins[tetraA.x] * DEG2RAD, 0.0.rr); + float2 uvRotB = RotateUV(params.uv, thetaBins[tetraB.x] * DEG2RAD, 0.0.rr); + float2 uvRotC = RotateUV(params.uv, thetaBins[tetraC.x] * DEG2RAD, 0.0.rr); + float2 uvRotD = RotateUV(params.uv, thetaBins[tetraD.x] * DEG2RAD, 0.0.rr); // SAMPLE GLINT GRIDS uint gridSeedA = HashWithoutSine13(float3(log2(divLods[tetraA.z]), thetaBins[tetraA.x] % 360, ratios[tetraA.y])) * 4294967296.0; uint gridSeedB = HashWithoutSine13(float3(log2(divLods[tetraB.z]), thetaBins[tetraB.x] % 360, ratios[tetraB.y])) * 4294967296.0; uint gridSeedC = HashWithoutSine13(float3(log2(divLods[tetraC.z]), thetaBins[tetraC.x] % 360, ratios[tetraC.y])) * 4294967296.0; uint gridSeedD = HashWithoutSine13(float3(log2(divLods[tetraD.z]), thetaBins[tetraD.x] % 360, ratios[tetraD.y])) * 4294967296.0; - float sampleA = SampleGlintGridSimplex(uvRotA / divLods[tetraA.z] / float2(1.0, ratios[tetraA.y]), gridSeedA, slope, ratios[tetraA.y] * footprintAreas[tetraA.z], rescaledTargetNDF, tetraBarycentricWeights.x); - float sampleB = SampleGlintGridSimplex(uvRotB / divLods[tetraB.z] / float2(1.0, ratios[tetraB.y]), gridSeedB, slope, ratios[tetraB.y] * footprintAreas[tetraB.z], rescaledTargetNDF, tetraBarycentricWeights.y); - float sampleC = SampleGlintGridSimplex(uvRotC / divLods[tetraC.z] / float2(1.0, ratios[tetraC.y]), gridSeedC, slope, ratios[tetraC.y] * footprintAreas[tetraC.z], rescaledTargetNDF, tetraBarycentricWeights.z); - float sampleD = SampleGlintGridSimplex(uvRotD / divLods[tetraD.z] / float2(1.0, ratios[tetraD.y]), gridSeedD, slope, ratios[tetraD.y] * footprintAreas[tetraD.z], rescaledTargetNDF, tetraBarycentricWeights.w); - return (sampleA + sampleB + sampleC + sampleD) * (1.0 / snowSettings.MicrofacetRoughness) * maxNDF; + float sampleA = SampleGlintGridSimplex(params, uvRotA / divLods[tetraA.z] / float2(1.0, ratios[tetraA.y]), gridSeedA, slope, ratios[tetraA.y] * footprintAreas[tetraA.z], rescaledTargetNDF, tetraBarycentricWeights.x); + float sampleB = SampleGlintGridSimplex(params, uvRotB / divLods[tetraB.z] / float2(1.0, ratios[tetraB.y]), gridSeedB, slope, ratios[tetraB.y] * footprintAreas[tetraB.z], rescaledTargetNDF, tetraBarycentricWeights.y); + float sampleC = SampleGlintGridSimplex(params, uvRotC / divLods[tetraC.z] / float2(1.0, ratios[tetraC.y]), gridSeedC, slope, ratios[tetraC.y] * footprintAreas[tetraC.z], rescaledTargetNDF, tetraBarycentricWeights.z); + float sampleD = SampleGlintGridSimplex(params, uvRotD / divLods[tetraD.z] / float2(1.0, ratios[tetraD.y]), gridSeedD, slope, ratios[tetraD.y] * footprintAreas[tetraD.z], rescaledTargetNDF, tetraBarycentricWeights.w); + return (sampleA + sampleB + sampleC + sampleD) * (1.0 / params.MicrofacetRoughness) * maxNDF; } \ No newline at end of file diff --git a/package/Shaders/SnowSparkles/noisegen.cs.hlsl b/package/Shaders/Common/Glints/noisegen.cs.hlsl similarity index 100% rename from package/Shaders/SnowSparkles/noisegen.cs.hlsl rename to package/Shaders/Common/Glints/noisegen.cs.hlsl diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 500788c163..b619e40a9d 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -1,4 +1,4 @@ -#include "SnowSparkles/Glints2023.hlsli" +#include "Common/Glints/Glints2023.hlsli" #define TruePBR_HasEmissive (1 << 0) #define TruePBR_HasDisplacement (1 << 1) @@ -76,10 +76,10 @@ namespace PBR surfaceProperties.FuzzColor = 0; surfaceProperties.FuzzWeight = 0; - surfaceProperties.GlintScreenSpaceScale = 0; - surfaceProperties.GlintLogMicrofacetDensity = 0; - surfaceProperties.GlintMicrofacetRoughness = 0; - surfaceProperties.GlintDensityRandomization = 0; + surfaceProperties.GlintScreenSpaceScale = 1.5; + surfaceProperties.GlintLogMicrofacetDensity = 18.0; + surfaceProperties.GlintMicrofacetRoughness = 0.015; + surfaceProperties.GlintDensityRandomization = 2.0; return surfaceProperties; } @@ -153,17 +153,13 @@ namespace PBR return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI); } - float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float3 H, float NdotL, float NdotV, float NdotH, float VdotH, float2 uv, out float3 F) + float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, GlintInput glintInput, out float3 F) { float D = GetNormalDistributionFunctionGGX(roughness, NdotH); -#if defined(LANDSCAPE) - [branch] if (PBRFlags & TruePBR_LandGlint) -#else - [branch] if (PBRFlags & TruePBR_Glint) -#endif + [branch] if (glintInput.enabled) { float D_max = GetNormalDistributionFunctionGGX(roughness, 1); - D = SampleGlints2023NDF(H, D, D_max, uv, ddx(uv), ddy(uv)); + D = SampleGlints2023NDF(glintInput, D, D_max); } float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); F = GetFresnelFactorSchlick(specularColor, VdotH); @@ -397,8 +393,26 @@ namespace PBR { diffuse += lightColor * satNdotL; + GlintInput glintInput; +#if defined(LANDSCAPE) + glintInput.enabled = PBRFlags & TruePBR_LandGlint; +#else + glintInput.enabled = PBRFlags & TruePBR_Glint; +#endif + [branch] if (glintInput.enabled) + { + glintInput.H = H; + glintInput.uv = uv; + glintInput.duvdx = ddx(uv); + glintInput.duvdy = ddy(uv); + glintInput.ScreenSpaceScale = surfaceProperties.GlintScreenSpaceScale; + glintInput.LogMicrofacetDensity = surfaceProperties.GlintLogMicrofacetDensity; + glintInput.MicrofacetRoughness = surfaceProperties.GlintMicrofacetRoughness; + glintInput.DensityRandomization = surfaceProperties.GlintDensityRandomization; + } + float3 F; - specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, H, satNdotL, satNdotV, satNdotH, satVdotH, uv, F) * lightColor * satNdotL; + specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, glintInput, F) * lightColor * satNdotL; float2 specularBRDF = 0; [branch] if (pbrSettings.UseMultipleScattering) @@ -444,7 +458,8 @@ namespace PBR } float3 coatF; - float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, H, coatNdotL, coatNdotV, coatNdotH, coatVdotH, uv, coatF) * coatLightColor * coatNdotL; + glintInput.H = coatH; + float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, glintInput, coatF) * coatLightColor * coatNdotL; float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; diffuse *= layerAttenuation; @@ -468,8 +483,10 @@ namespace PBR float NdotH = saturate(dot(N, H)); float VdotH = saturate(dot(V, H)); + GlintInput glintInput; + glintInput.enabled = false; float3 wetnessF; - float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, H, NdotL, NdotV, NdotH, VdotH, 0, wetnessF) * lightColor * NdotL; + float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, glintInput, wetnessF) * lightColor * NdotL; return wetnessSpecular * wetnessStrength; } diff --git a/src/Deferred.cpp b/src/Deferred.cpp index 4ec49719f3..e61cf54807 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -2,8 +2,10 @@ #include "ShaderCache.h" #include "State.h" +#include "TruePBR.h" #include "Util.h" + #include "Features/DynamicCubemaps.h" #include "Features/ScreenSpaceGI.h" #include "Features/Skylighting.h" @@ -265,6 +267,7 @@ void Deferred::PrepassPasses() stateUpdateFlags.set(RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET); // Run OMSetRenderTargets again + TruePBR::GetSingleton()->PrePass(); for (auto* feature : Feature::GetFeatureList()) { if (feature->loaded) { feature->Prepass(); diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index d7cd42e2f5..1bece848d0 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -8,6 +8,7 @@ #include "Hooks.h" #include "ShaderCache.h" #include "State.h" +#include "Util.h" namespace PNState { @@ -202,6 +203,15 @@ void TruePBR::SaveSettings(json& o_json) o_json["Ambient Light Color Multiplier"] = globalPBRAmbientLightColorMultiplier; } +void TruePBR::PrePass() +{ + auto context = State::GetSingleton()->context; + if (context && glintsNoiseTexture) { + ID3D11ShaderResourceView* srv = glintsNoiseTexture->srv.get(); + context->PSSetShaderResources(28, 1, &srv); + } +} + void TruePBR::SetupFrame() { float newDirectionalLightScale = 1.f; @@ -237,6 +247,76 @@ void TruePBR::SetupFrame() settings.ambientLightColorMultiplier = globalPBRAmbientLightColorMultiplier * weatherPBRDirectionalAmbientLightColorMultiplier; } +void TruePBR::SetupGlintsTexture() +{ + constexpr uint noiseTexSize = 512; + + D3D11_TEXTURE2D_DESC tex_desc{ + .Width = noiseTexSize, + .Height = noiseTexSize, + .MipLevels = 1, + .ArraySize = 1, + .Format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .SampleDesc = { .Count = 1, .Quality = 0 }, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS, + .CPUAccessFlags = 0, + .MiscFlags = 0 + }; + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = { + .Format = tex_desc.Format, + .ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D, + .Texture2D = { + .MostDetailedMip = 0, + .MipLevels = 1 } + }; + D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = { + .Format = tex_desc.Format, + .ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D, + .Texture2D = { .MipSlice = 0 } + }; + + glintsNoiseTexture = eastl::make_unique(tex_desc); + glintsNoiseTexture->CreateSRV(srv_desc); + glintsNoiseTexture->CreateUAV(uav_desc); + + // Compile + auto noiseGenProgram = reinterpret_cast(Util::CompileShader(L"Data\\Shaders\\Common\\Glints\\noisegen.cs.hlsl", {}, "cs_5_0")); + if (!noiseGenProgram) { + logger::error("Failed to compile glints noise generation shader!"); + return; + } + + // Generate the noise + { + auto context = State::GetSingleton()->context; + + struct OldState + { + ID3D11ComputeShader* shader; + ID3D11UnorderedAccessView* uav[1]; + ID3D11ClassInstance* instance; + UINT numInstances; + }; + + OldState newer{}, old{}; + context->CSGetShader(&old.shader, &old.instance, &old.numInstances); + context->CSGetUnorderedAccessViews(0, ARRAYSIZE(old.uav), old.uav); + + { + newer.uav[0] = glintsNoiseTexture->uav.get(); + context->CSSetShader(noiseGenProgram, nullptr, 0); + context->CSSetUnorderedAccessViews(0, ARRAYSIZE(newer.uav), newer.uav, nullptr); + context->Dispatch((noiseTexSize + 31) >> 5, (noiseTexSize + 31) >> 5, 1); + } + + context->CSSetShader(old.shader, &old.instance, old.numInstances); + context->CSSetUnorderedAccessViews(0, ARRAYSIZE(old.uav), old.uav, nullptr); + } + + noiseGenProgram->Release(); +} + void TruePBR::SetupTextureSetData() { logger::info("[TruePBR] loading PBR texture set configs"); diff --git a/src/TruePBR.h b/src/TruePBR.h index 33ecbeaf05..b8a61287e4 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -1,12 +1,14 @@ #pragma once +#include "Buffer.h" + struct GlintParameters { bool enabled = false; - float screenSpaceScale = 1.f; - float logMicrofacetDensity = 1.f; - float microfacetRoughness = 1.f; - float densityRandomization = 1.f; + float screenSpaceScale = 1.5f; + float logMicrofacetDensity = 18.f; + float microfacetRoughness = .015f; + float densityRandomization = 2.f; }; struct TruePBR @@ -24,11 +26,15 @@ struct TruePBR void SetupResources(); void LoadSettings(json& o_json); void SaveSettings(json& o_json); + void PrePass(); void PostPostLoad(); void SetShaderResouces(); void GenerateShaderPermutations(RE::BSShader* shader); + void SetupGlintsTexture(); + eastl::unique_ptr glintsNoiseTexture = nullptr; + std::unordered_map editorIDs; float globalPBRDirectLightColorMultiplier = 1.f; @@ -37,7 +43,7 @@ struct TruePBR float weatherPBRDirectionalLightColorMultiplier = 1.f; float weatherPBRDirectionalAmbientLightColorMultiplier = 1.f; - struct alignas(16) Settings + struct Settings { float directionalLightColorMultiplier = 1.f; float pointLightColorMultiplier = 1.f; @@ -46,6 +52,7 @@ struct TruePBR uint32_t useMultiBounceAO = true; uint32_t pad[3]; } settings{}; + static_assert(sizeof(Settings) % 16 == 0); struct PBRTextureSetData { From 8037f681d71d1a2e076fd6b16ca044fc7a223d25 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Sat, 10 Aug 2024 22:36:56 +0000 Subject: [PATCH 05/13] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20clang-for?= =?UTF-8?q?mat=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Deferred.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Deferred.cpp b/src/Deferred.cpp index e61cf54807..fa8a8cdc96 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -5,7 +5,6 @@ #include "TruePBR.h" #include "Util.h" - #include "Features/DynamicCubemaps.h" #include "Features/ScreenSpaceGI.h" #include "Features/Skylighting.h" From cb58ba66eef376fe3299b6c7c159170d717f8a34 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Sun, 11 Aug 2024 12:12:35 +0100 Subject: [PATCH 06/13] fix: use local H --- package/Shaders/Common/PBR.hlsli | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index b619e40a9d..9caaf1b3cb 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -369,7 +369,6 @@ namespace PBR specular = 0; float3 H = normalize(V + L); - float3 localH = mul(H, tbn); float NdotL = dot(N, L); float NdotV = dot(N, V); @@ -401,7 +400,7 @@ namespace PBR #endif [branch] if (glintInput.enabled) { - glintInput.H = H; + glintInput.H = mul(H, tbn); glintInput.uv = uv; glintInput.duvdx = ddx(uv); glintInput.duvdy = ddy(uv); @@ -458,7 +457,7 @@ namespace PBR } float3 coatF; - glintInput.H = coatH; + glintInput.H = mul(coatH, tbn); float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, glintInput, coatF) * coatLightColor * coatNdotL; float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; From 6eeac1883771f3e41c735d5ad8acadb08a61b32c Mon Sep 17 00:00:00 2001 From: Ilya Perapechka Date: Sun, 11 Aug 2024 18:05:02 +0300 Subject: [PATCH 07/13] fix: fixed shader compilation with glint. Reworked pbr parameters serialization. Hidden glint under define. --- package/Shaders/Common/PBR.hlsli | 20 +- package/Shaders/Lighting.hlsl | 16 +- package/Shaders/RunGrass.hlsl | 9 +- src/ShaderCache.cpp | 3 + src/ShaderCache.h | 2 +- src/TruePBR.cpp | 172 +++++++----------- src/TruePBR.h | 19 ++ .../BSLightingShaderMaterialPBRLandscape.cpp | 12 ++ .../BSLightingShaderMaterialPBRLandscape.h | 2 + 9 files changed, 140 insertions(+), 115 deletions(-) diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 9caaf1b3cb..81ded8c7a0 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -1,4 +1,6 @@ +#if defined(GLINT) #include "Common/Glints/Glints2023.hlsli" +#endif #define TruePBR_HasEmissive (1 << 0) #define TruePBR_HasDisplacement (1 << 1) @@ -83,6 +85,10 @@ namespace PBR return surfaceProperties; } + +#if !defined(GLINT) + struct GlintInput {}; +#endif float3 AdjustDirectionalLightColor(float3 lightColor) { @@ -156,11 +162,13 @@ namespace PBR float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, GlintInput glintInput, out float3 F) { float D = GetNormalDistributionFunctionGGX(roughness, NdotH); +#if defined(GLINT) [branch] if (glintInput.enabled) { float D_max = GetNormalDistributionFunctionGGX(roughness, 1); D = SampleGlints2023NDF(glintInput, D, D_max); } +#endif float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); F = GetFresnelFactorSchlick(specularColor, VdotH); @@ -393,11 +401,12 @@ namespace PBR diffuse += lightColor * satNdotL; GlintInput glintInput; -#if defined(LANDSCAPE) +#if defined(GLINT) +# if defined(LANDSCAPE) glintInput.enabled = PBRFlags & TruePBR_LandGlint; -#else +# else glintInput.enabled = PBRFlags & TruePBR_Glint; -#endif +# endif [branch] if (glintInput.enabled) { glintInput.H = mul(H, tbn); @@ -409,6 +418,7 @@ namespace PBR glintInput.MicrofacetRoughness = surfaceProperties.GlintMicrofacetRoughness; glintInput.DensityRandomization = surfaceProperties.GlintDensityRandomization; } +#endif float3 F; specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, glintInput, F) * lightColor * satNdotL; @@ -457,7 +467,9 @@ namespace PBR } float3 coatF; +#if defined(GLINT) glintInput.H = mul(coatH, tbn); +#endif float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, glintInput, coatF) * coatLightColor * coatNdotL; float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; @@ -483,7 +495,9 @@ namespace PBR float VdotH = saturate(dot(V, H)); GlintInput glintInput; +#if defined(GLINT) glintInput.enabled = false; +#endif float3 wetnessF; float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, glintInput, wetnessF) * lightColor * NdotL; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index a1f510e399..f5f5aaa9bd 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -705,10 +705,12 @@ float GetRimLightMultiplier(float3 L, float3 V, float3 N) return exp2(LightingEffectParams.y * log2(1 - NdotV)) * saturate(dot(V, -L)); } +#if !defined(TRUE_PBR) float ProcessSparkleColor(float color) { return exp2(SparkleParams.y * log2(min(1, abs(color)))); } +#endif float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float3 lightColor, float shininess, float2 uv) { @@ -1023,11 +1025,13 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif // defined (SKINNED) || !defined (MODELSPACENORMALS) -# if defined(LANDSCAPE) && !defined(TRUE_PBR) +# if !defined(TRUE_PBR) +# if defined(LANDSCAPE) float shininess = dot(input.LandBlendWeights1, LandscapeTexture1to4IsSpecPower) + input.LandBlendWeights2.x * LandscapeTexture5to6IsSpecPower.x + input.LandBlendWeights2.y * LandscapeTexture5to6IsSpecPower.y; -# else +# else float shininess = SpecularColor.w; -# endif // defined (LANDSCAPE) +# endif // defined (LANDSCAPE) +# endif float3 viewPosition = mul(CameraView[eyeIndex], float4(input.WorldPosition.xyz, 1)).xyz; float2 screenUV = ViewToUV(viewPosition, true, eyeIndex); @@ -1302,12 +1306,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace else { rawRMAOS = input.LandBlendWeights1.x * float4(1 - glossiness.x, 0, 1, 0.04); - if ((PBRFlags & TruePBR_Glint) != 0) { - glintParameters = MultiLayerParallaxData; - } } # else rawRMAOS = TexRMAOSSampler.Sample(SampRMAOSSampler, diffuseUv) * float4(PBRParams1.x, 1, 1, PBRParams1.z); + if ((PBRFlags & TruePBR_Glint) != 0) { + glintParameters = MultiLayerParallaxData; + } # endif # endif diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 895f2f1a37..da5c56bad8 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -455,6 +455,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace normal = -normal; normal = normalize(lerp(normal, normalize(input.SphereNormal.xyz), input.SphereNormal.w)); + + float3x3 tbn = 0; # if !defined(TRUE_PBR) if (complex) @@ -463,7 +465,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 normalColor = GrassLighting::TransformNormal(specColor.xyz); // world-space -> tangent-space -> world-space. // This is because we don't have pre-computed tangents. - normal = normalize(mul(normalColor, GrassLighting::CalculateTBN(normal, -input.WorldPosition.xyz, input.TexCoord.xy))); + tbn = GrassLighting::CalculateTBN(normal, -input.WorldPosition.xyz, input.TexCoord.xy); + normal = normalize(mul(normalColor, tbn)); } # if !defined(TRUE_PBR) @@ -543,7 +546,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 pbrDirLightColor = PBR::AdjustDirectionalLightColor(DirLightColorShared.xyz) * dirLightColorMultiplier * dirShadow; float3 dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor; - PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, normal, normal, viewDirection, viewDirection, DirLightDirection, DirLightDirection, pbrDirLightColor, pbrDirLightColor, pbrSurfaceProperties); + PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, normal, normal, viewDirection, viewDirection, DirLightDirection, DirLightDirection, pbrDirLightColor, pbrDirLightColor, pbrSurfaceProperties, tbn, input.TexCoord.xy); lightsDiffuseColor += dirDiffuseColor; transmissionColor += dirTransmissionColor; specularColorPBR += dirSpecularColor; @@ -599,7 +602,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace { float3 pointDiffuseColor, coatDirDiffuseColor, pointTransmissionColor, pointSpecularColor; float3 pbrLightColor = PBR::AdjustPointLightColor(lightColor * intensityMultiplier); - PBR::GetDirectLightInput(pointDiffuseColor, coatDirDiffuseColor, pointTransmissionColor, pointSpecularColor, normal, normal, viewDirection, viewDirection, normalizedLightDirection, normalizedLightDirection, pbrLightColor, pbrLightColor, pbrSurfaceProperties); + PBR::GetDirectLightInput(pointDiffuseColor, coatDirDiffuseColor, pointTransmissionColor, pointSpecularColor, normal, normal, viewDirection, viewDirection, normalizedLightDirection, normalizedLightDirection, pbrLightColor, pbrLightColor, pbrSurfaceProperties, tbn, input.TexCoord.xy); lightsDiffuseColor += pointDiffuseColor; transmissionColor += pointTransmissionColor; specularColorPBR += pointSpecularColor; diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index 25a127b2c3..7741e25fa1 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -65,6 +65,9 @@ namespace SIE } if ((descriptor & static_cast(ShaderCache::LightingShaderFlags::TruePbr)) != 0) { defines[lastIndex++] = { "TRUE_PBR", nullptr }; + if ((descriptor & static_cast(ShaderCache::LightingShaderFlags::AnisoLighting)) != 0) { + defines[lastIndex++] = { "GLINT", nullptr }; + } } for (auto* feature : Feature::GetFeatureList()) { diff --git a/src/ShaderCache.h b/src/ShaderCache.h index 868677c9ef..71c0a3e262 100644 --- a/src/ShaderCache.h +++ b/src/ShaderCache.h @@ -246,7 +246,7 @@ namespace SIE ShadowDir = 1 << 13, DefShadow = 1 << 14, ProjectedUV = 1 << 15, - AnisoLighting = 1 << 16, + AnisoLighting = 1 << 16, // Reused for glint with PBR AmbientSpecular = 1 << 17, WorldMap = 1 << 18, BaseObjectIsSnow = 1 << 19, diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 1bece848d0..fc7a58933e 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -12,49 +12,6 @@ namespace PNState { - template - bool Read(const json& config, const std::string_view& key, ResultType& result) - { - if (!config.is_object()) { - return false; - } - - auto it = config.find(key); - if (it == config.end()) { - return false; - } - - const json& section = it.value(); - - if constexpr (std::is_same_v> || std::is_same_v) { - if (section.is_array() && section.size() == 3 && - section[0].is_number_float() && section[1].is_number_float() && - section[2].is_number_float()) { - result[0] = section[0]; - result[1] = section[1]; - result[2] = section[2]; - return true; - } - } - if constexpr (std::is_same_v) { - if (section.is_number_float()) { - result = section; - return true; - } - } - if constexpr (std::is_same_v) { - if (section.is_object()) { - result.enabled = section["enabled"]; - result.screenSpaceScale = section["screenSpaceScale"]; - result.logMicrofacetDensity = section["logMicrofacetDensity"]; - result.microfacetRoughness = section["microfacetRoughness"]; - result.densityRandomization = section["densityRandomization"]; - return true; - } - } - return false; - } - void ReadPBRRecordConfigs(const std::string& rootPath, std::function recordReader) { if (std::filesystem::exists(rootPath)) { @@ -109,6 +66,27 @@ namespace PNState } } +namespace nlohmann +{ + void to_json(json& section, const RE::NiColor& result) + { + section = { result[0], + result[1], + result[2] }; + } + + void from_json(const json& section, RE::NiColor& result) + { + if (section.is_array() && section.size() == 3 && + section[0].is_number_float() && section[1].is_number_float() && + section[2].is_number_float()) { + result[0] = section[0]; + result[1] = section[1]; + result[2] = section[2]; + } + } +} + void TruePBR::DrawSettings() { if (ImGui::TreeNodeEx("PBR", ImGuiTreeNodeFlags_DefaultOpen)) { @@ -324,23 +302,11 @@ void TruePBR::SetupTextureSetData() pbrTextureSets.clear(); PNState::ReadPBRRecordConfigs("Data\\PBRTextureSets", [this](const std::string& editorId, const json& config) { - PBRTextureSetData textureSetData; - - PNState::Read(config, "roughnessScale", textureSetData.roughnessScale); - PNState::Read(config, "displacementScale", textureSetData.displacementScale); - PNState::Read(config, "specularLevel", textureSetData.specularLevel); - PNState::Read(config, "subsurfaceColor", textureSetData.subsurfaceColor); - PNState::Read(config, "subsurfaceOpacity", textureSetData.subsurfaceOpacity); - PNState::Read(config, "coatColor", textureSetData.coatColor); - PNState::Read(config, "coatStrength", textureSetData.coatStrength); - PNState::Read(config, "coatRoughness", textureSetData.coatRoughness); - PNState::Read(config, "coatSpecularLevel", textureSetData.coatSpecularLevel); - PNState::Read(config, "innerLayerDisplacementOffset", textureSetData.innerLayerDisplacementOffset); - PNState::Read(config, "fuzzColor", textureSetData.fuzzColor); - PNState::Read(config, "fuzzWeight", textureSetData.fuzzWeight); - PNState::Read(config, "glintParameters", textureSetData.glintParameters); - - pbrTextureSets.insert_or_assign(editorId, textureSetData); + try { + pbrTextureSets.insert_or_assign(editorId, config); + } catch (const std::exception& e) { + logger::error("Failed to deserialize config for {}: {}.", editorId, e.what()); + } }); } @@ -369,13 +335,11 @@ void TruePBR::SetupMaterialObjectData() pbrMaterialObjects.clear(); PNState::ReadPBRRecordConfigs("Data\\PBRMaterialObjects", [this](const std::string& editorId, const json& config) { - PBRMaterialObjectData materialObjectData; - - PNState::Read(config, "baseColorScale", materialObjectData.baseColorScale); - PNState::Read(config, "roughness", materialObjectData.roughness); - PNState::Read(config, "specularLevel", materialObjectData.specularLevel); - - pbrMaterialObjects.insert_or_assign(editorId, materialObjectData); + try { + pbrMaterialObjects.insert_or_assign(editorId, config); + } catch (const std::exception& e) { + logger::error("Failed to deserialize config for {}: {}.", editorId, e.what()); + } }); } @@ -404,12 +368,11 @@ void TruePBR::SetupLightingTemplateData() pbrLightingTemplates.clear(); PNState::ReadPBRRecordConfigs("Data\\PBRLightingTemplates", [this](const std::string& editorId, const json& config) { - PBRLightingTemplateData lightingTemplateData; - - PNState::Read(config, "directionalLightColorScale", lightingTemplateData.directionalLightColorScale); - PNState::Read(config, "directionalAmbientLightColorScale", lightingTemplateData.directionalAmbientLightColorScale); - - pbrLightingTemplates.insert_or_assign(editorId, lightingTemplateData); + try { + pbrLightingTemplates.insert_or_assign(editorId, config); + } catch (const std::exception& e) { + logger::error("Failed to deserialize config for {}: {}.", editorId, e.what()); + } }); } @@ -434,12 +397,11 @@ bool TruePBR::IsPBRLightingTemplate(const RE::TESForm* lightingTemplate) void TruePBR::SavePBRLightingTemplateData(const std::string& editorId) { const auto& pbrLightingTemplateData = pbrLightingTemplates[editorId]; - - json config; - config["directionalLightColorScale"] = pbrLightingTemplateData.directionalLightColorScale; - config["directionalAmbientLightColorScale"] = pbrLightingTemplateData.directionalAmbientLightColorScale; - - PNState::SavePBRRecordConfig("Data\\PBRLightingTemplates\\", editorId, config); + try { + PNState::SavePBRRecordConfig("Data\\PBRLightingTemplates\\", editorId, pbrLightingTemplateData); + } catch (const std::exception& e) { + logger::error("Failed to serialize config for {}: {}.", editorId, e.what()); + } } void TruePBR::SetupWeatherData() @@ -449,12 +411,11 @@ void TruePBR::SetupWeatherData() pbrWeathers.clear(); PNState::ReadPBRRecordConfigs("Data\\PBRWeathers", [this](const std::string& editorId, const json& config) { - PBRWeatherData weatherData; - - PNState::Read(config, "directionalLightColorScale", weatherData.directionalLightColorScale); - PNState::Read(config, "directionalAmbientLightColorScale", weatherData.directionalAmbientLightColorScale); - - pbrWeathers.insert_or_assign(editorId, weatherData); + try { + pbrWeathers.insert_or_assign(editorId, config); + } catch (const std::exception& e) { + logger::error("Failed to deserialize config for {}: {}.", editorId, e.what()); + } }); } @@ -479,12 +440,11 @@ bool TruePBR::IsPBRWeather(const RE::TESForm* weather) void TruePBR::SavePBRWeatherData(const std::string& editorId) { const auto& pbrWeatherData = pbrWeathers[editorId]; - - json config; - config["directionalLightColorScale"] = pbrWeatherData.directionalLightColorScale; - config["directionalAmbientLightColorScale"] = pbrWeatherData.directionalAmbientLightColorScale; - - PNState::SavePBRRecordConfig("Data\\PBRWeathers\\", editorId, config); + try { + PNState::SavePBRRecordConfig("Data\\PBRWeathers\\", editorId, pbrWeatherData); + } catch (const std::exception& e) { + logger::error("Failed to serialize config for {}: {}.", editorId, e.what()); + } } namespace Permutations @@ -741,6 +701,7 @@ struct BSLightingShaderProperty_LoadBinary pbrMaterial->pbrFlags.set(PBRFlags::Fuzz); } else if (property->flags.any(kFitSlope)) { pbrMaterial->pbrFlags.set(PBRFlags::Glint); + pbrMaterial->glintParameters.enabled = true; } } property->flags.set(kVertexLighting); @@ -775,6 +736,19 @@ struct BSLightingShaderProperty_GetRenderPasses lightingFlags &= ~0b111000u; if (isPbr) { lightingFlags |= static_cast(SIE::ShaderCache::LightingShaderFlags::TruePbr); + if (property->flags.any(RE::BSShaderProperty::EShaderPropertyFlag::kMultiTextureLandscape)) { + auto* material = static_cast(property->material); + if (material->HasGlint()) { + lightingFlags |= static_cast(SIE::ShaderCache::LightingShaderFlags::AnisoLighting); + } + } + else + { + auto* material = static_cast(property->material); + if (material->pbrFlags.any(PBRFlags::Glint)) { + lightingFlags |= static_cast(SIE::ShaderCache::LightingShaderFlags::AnisoLighting); + } + } } lightingTechnique = (static_cast(lightingType) << 24) | lightingFlags; currentPass->passEnum = lightingTechnique + LightingTechniqueStart; @@ -847,12 +821,10 @@ struct BSLightingShader_SetupMaterial if (pbrMaterial->landscapeDisplacementTextures[textureIndex] != nullptr && pbrMaterial->landscapeDisplacementTextures[textureIndex] != RE::BSGraphics::State::GetSingleton()->GetRuntimeData().defaultTextureBlack) { flags |= (1 << (BSLightingShaderMaterialPBRLandscape::NumTiles + textureIndex)); } - bool hasGlint = false; if (pbrMaterial->glintParameters[textureIndex].enabled) { - hasGlint = true; flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles + 1 + textureIndex)); } - if (hasGlint) { + if (pbrMaterial->HasGlint()) { flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles)); } } @@ -876,7 +848,7 @@ struct BSLightingShader_SetupMaterial glintParameters[1] = pbrMaterial->glintParameters[textureIndex].logMicrofacetDensity; glintParameters[2] = pbrMaterial->glintParameters[textureIndex].microfacetRoughness; glintParameters[3] = pbrMaterial->glintParameters[textureIndex].densityRandomization; - shadowState->SetPSConstant(PBRParams, RE::BSGraphics::ConstantGroupLevel::PerMaterial, GlintParametersStartIndex + textureIndex); + shadowState->SetPSConstant(glintParameters, RE::BSGraphics::ConstantGroupLevel::PerMaterial, GlintParametersStartIndex + textureIndex); } } @@ -1070,10 +1042,11 @@ struct BSLightingShader_SetupGeometry { static void thunk(RE::BSLightingShader* shader, RE::BSRenderPass* pass, uint32_t renderFlags) { - const uint32_t originalExtraFlags = shader->currentRawTechnique & 0b111000u; + const auto originalTechnique = shader->currentRawTechnique; if ((shader->currentRawTechnique & static_cast(SIE::ShaderCache::LightingShaderFlags::TruePbr)) != 0) { shader->currentRawTechnique |= static_cast(SIE::ShaderCache::LightingShaderFlags::AmbientSpecular); + shader->currentRawTechnique ^= static_cast(SIE::ShaderCache::LightingShaderFlags::AnisoLighting); } shader->currentRawTechnique &= ~0b111000u; @@ -1081,12 +1054,7 @@ struct BSLightingShader_SetupGeometry func(shader, pass, renderFlags); - shader->currentRawTechnique &= ~0b111000u; - shader->currentRawTechnique |= originalExtraFlags; - - if ((shader->currentRawTechnique & static_cast(SIE::ShaderCache::LightingShaderFlags::TruePbr)) != 0) { - shader->currentRawTechnique &= ~static_cast(SIE::ShaderCache::LightingShaderFlags::AmbientSpecular); - } + shader->currentRawTechnique = originalTechnique; } static inline REL::Relocation func; }; diff --git a/src/TruePBR.h b/src/TruePBR.h index b8a61287e4..9492b3543d 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -9,8 +9,17 @@ struct GlintParameters float logMicrofacetDensity = 18.f; float microfacetRoughness = .015f; float densityRandomization = 2.f; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GlintParameters, enabled, screenSpaceScale, logMicrofacetDensity, + microfacetRoughness, densityRandomization); }; +namespace nlohmann +{ + void to_json(json&, const RE::NiColor&); + void from_json(const json&, RE::NiColor&); +} + struct TruePBR { public: @@ -73,6 +82,10 @@ struct TruePBR float fuzzWeight = 0.f; GlintParameters glintParameters; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(PBRTextureSetData, roughnessScale, displacementScale, specularLevel, + subsurfaceColor, subsurfaceOpacity, coatColor, coatStrength, coatRoughness, coatSpecularLevel, + innerLayerDisplacementOffset, fuzzColor, fuzzWeight, glintParameters); }; void SetupFrame(); @@ -88,6 +101,8 @@ struct TruePBR std::array baseColorScale = { 1.f, 1.f, 1.f }; float roughness = 1.f; float specularLevel = 1.f; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(PBRMaterialObjectData, baseColorScale, roughness, specularLevel); }; void SetupMaterialObjectData(); @@ -100,6 +115,8 @@ struct TruePBR { float directionalLightColorScale = 1.f; float directionalAmbientLightColorScale = 1.f; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(PBRLightingTemplateData, directionalLightColorScale, directionalAmbientLightColorScale); }; void SetupLightingTemplateData(); @@ -113,6 +130,8 @@ struct TruePBR { float directionalLightColorScale = 1.f; float directionalAmbientLightColorScale = 1.f; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(PBRWeatherData, directionalLightColorScale, directionalAmbientLightColorScale); }; void SetupWeatherData(); diff --git a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp index edc662e400..dc01ad9174 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp +++ b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp @@ -130,4 +130,16 @@ uint32_t BSLightingShaderMaterialPBRLandscape::GetTextures(RE::NiSourceTexture** } return textureIndex; +} + +bool BSLightingShaderMaterialPBRLandscape::HasGlint() const +{ + for (uint32_t textureIndex = 0; textureIndex < numLandscapeTextures; ++textureIndex) + { + if (glintParameters[textureIndex].enabled) + { + return true; + } + } + return false; } \ No newline at end of file diff --git a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h index 7c848fd229..98b82fafd7 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h +++ b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.h @@ -27,6 +27,8 @@ class BSLightingShaderMaterialPBRLandscape : public RE::BSLightingShaderMaterial static BSLightingShaderMaterialPBRLandscape* Make(); + bool HasGlint() const; + // members std::uint32_t numLandscapeTextures = 0; From d136d12224df67e4ce471167ca969d62d2f13dae Mon Sep 17 00:00:00 2001 From: Jonahex Date: Sun, 11 Aug 2024 15:05:25 +0000 Subject: [PATCH 08/13] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20clang-for?= =?UTF-8?q?mat=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/Shaders/Common/PBR.hlsli | 11 ++++++----- package/Shaders/Lighting.hlsl | 4 ++-- package/Shaders/RunGrass.hlsl | 2 +- src/ShaderCache.h | 2 +- src/TruePBR.cpp | 4 +--- src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp | 6 ++---- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 81ded8c7a0..8b8a251485 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -1,5 +1,5 @@ #if defined(GLINT) -#include "Common/Glints/Glints2023.hlsli" +# include "Common/Glints/Glints2023.hlsli" #endif #define TruePBR_HasEmissive (1 << 0) @@ -85,9 +85,10 @@ namespace PBR return surfaceProperties; } - + #if !defined(GLINT) - struct GlintInput {}; + struct GlintInput + {}; #endif float3 AdjustDirectionalLightColor(float3 lightColor) @@ -467,9 +468,9 @@ namespace PBR } float3 coatF; -#if defined(GLINT) +# if defined(GLINT) glintInput.H = mul(coatH, tbn); -#endif +# endif float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, glintInput, coatF) * coatLightColor * coatNdotL; float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index f5f5aaa9bd..8fd4ec1dd0 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -705,12 +705,12 @@ float GetRimLightMultiplier(float3 L, float3 V, float3 N) return exp2(LightingEffectParams.y * log2(1 - NdotV)) * saturate(dot(V, -L)); } -#if !defined(TRUE_PBR) +# if !defined(TRUE_PBR) float ProcessSparkleColor(float color) { return exp2(SparkleParams.y * log2(min(1, abs(color)))); } -#endif +# endif float3 GetLightSpecularInput(PS_INPUT input, float3 L, float3 V, float3 N, float3 lightColor, float shininess, float2 uv) { diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index da5c56bad8..24a1627f19 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -455,7 +455,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace normal = -normal; normal = normalize(lerp(normal, normalize(input.SphereNormal.xyz), input.SphereNormal.w)); - + float3x3 tbn = 0; # if !defined(TRUE_PBR) diff --git a/src/ShaderCache.h b/src/ShaderCache.h index 71c0a3e262..6c02e39949 100644 --- a/src/ShaderCache.h +++ b/src/ShaderCache.h @@ -246,7 +246,7 @@ namespace SIE ShadowDir = 1 << 13, DefShadow = 1 << 14, ProjectedUV = 1 << 15, - AnisoLighting = 1 << 16, // Reused for glint with PBR + AnisoLighting = 1 << 16, // Reused for glint with PBR AmbientSpecular = 1 << 17, WorldMap = 1 << 18, BaseObjectIsSnow = 1 << 19, diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index fc7a58933e..46ac7bb83c 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -741,9 +741,7 @@ struct BSLightingShaderProperty_GetRenderPasses if (material->HasGlint()) { lightingFlags |= static_cast(SIE::ShaderCache::LightingShaderFlags::AnisoLighting); } - } - else - { + } else { auto* material = static_cast(property->material); if (material->pbrFlags.any(PBRFlags::Glint)) { lightingFlags |= static_cast(SIE::ShaderCache::LightingShaderFlags::AnisoLighting); diff --git a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp index dc01ad9174..42b79a9df6 100644 --- a/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp +++ b/src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp @@ -134,10 +134,8 @@ uint32_t BSLightingShaderMaterialPBRLandscape::GetTextures(RE::NiSourceTexture** bool BSLightingShaderMaterialPBRLandscape::HasGlint() const { - for (uint32_t textureIndex = 0; textureIndex < numLandscapeTextures; ++textureIndex) - { - if (glintParameters[textureIndex].enabled) - { + for (uint32_t textureIndex = 0; textureIndex < numLandscapeTextures; ++textureIndex) { + if (glintParameters[textureIndex].enabled) { return true; } } From 7db47e6e9effec39975dcc30a3b076ad0b201c1c Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Sun, 11 Aug 2024 18:38:29 +0100 Subject: [PATCH 09/13] fix: trying to fix glints --- .../Shaders/Common/Glints/Glints2023.hlsli | 1 - package/Shaders/Common/PBR.hlsli | 70 ++++++++---------- src/TruePBR.cpp | 74 ++++++++++--------- src/TruePBR.h | 2 +- 4 files changed, 69 insertions(+), 78 deletions(-) diff --git a/package/Shaders/Common/Glints/Glints2023.hlsli b/package/Shaders/Common/Glints/Glints2023.hlsli index b7d2382aad..959d2baf96 100644 --- a/package/Shaders/Common/Glints/Glints2023.hlsli +++ b/package/Shaders/Common/Glints/Glints2023.hlsli @@ -226,7 +226,6 @@ void UnpackFloatParallel4(float4 input, out float4 a, out float4 b) struct GlintInput { - bool enabled; float3 H; float2 uv; float2 duvdx; diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 8b8a251485..29a6b9e902 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -79,18 +79,13 @@ namespace PBR surfaceProperties.FuzzWeight = 0; surfaceProperties.GlintScreenSpaceScale = 1.5; - surfaceProperties.GlintLogMicrofacetDensity = 18.0; + surfaceProperties.GlintLogMicrofacetDensity = 40.0; surfaceProperties.GlintMicrofacetRoughness = 0.015; surfaceProperties.GlintDensityRandomization = 2.0; return surfaceProperties; } -#if !defined(GLINT) - struct GlintInput - {}; -#endif - float3 AdjustDirectionalLightColor(float3 lightColor) { return pbrSettings.DirectionalLightColorMultiplier * sRGB2Lin(lightColor); @@ -160,16 +155,22 @@ namespace PBR return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI); } - float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, GlintInput glintInput, out float3 F) +#if defined(GLINT) + float3 GetSpecularDirectLightMultiplierMicrofacetWithGlint(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, GlintInput glintInput, out float3 F) { float D = GetNormalDistributionFunctionGGX(roughness, NdotH); -#if defined(GLINT) - [branch] if (glintInput.enabled) - { - float D_max = GetNormalDistributionFunctionGGX(roughness, 1); - D = SampleGlints2023NDF(glintInput, D, D_max); - } + float D_max = GetNormalDistributionFunctionGGX(roughness, 1); + D = SampleGlints2023NDF(glintInput, D, D_max); + float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); + F = GetFresnelFactorSchlick(specularColor, VdotH); + + return D * G * F; + } #endif + + float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, out float3 F) + { + float D = GetNormalDistributionFunctionGGX(roughness, NdotH); float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); F = GetFresnelFactorSchlick(specularColor, VdotH); @@ -401,28 +402,24 @@ namespace PBR { diffuse += lightColor * satNdotL; - GlintInput glintInput; #if defined(GLINT) -# if defined(LANDSCAPE) - glintInput.enabled = PBRFlags & TruePBR_LandGlint; -# else - glintInput.enabled = PBRFlags & TruePBR_Glint; -# endif - [branch] if (glintInput.enabled) - { - glintInput.H = mul(H, tbn); - glintInput.uv = uv; - glintInput.duvdx = ddx(uv); - glintInput.duvdy = ddy(uv); - glintInput.ScreenSpaceScale = surfaceProperties.GlintScreenSpaceScale; - glintInput.LogMicrofacetDensity = surfaceProperties.GlintLogMicrofacetDensity; - glintInput.MicrofacetRoughness = surfaceProperties.GlintMicrofacetRoughness; - glintInput.DensityRandomization = surfaceProperties.GlintDensityRandomization; - } + GlintInput glintInput; + glintInput.H = mul(tbn, H); + glintInput.uv = uv; + glintInput.duvdx = ddx(uv); + glintInput.duvdy = ddy(uv); + glintInput.ScreenSpaceScale = max(1, surfaceProperties.GlintScreenSpaceScale); + glintInput.LogMicrofacetDensity = 40 - clamp(surfaceProperties.GlintLogMicrofacetDensity, 0, 40); + glintInput.MicrofacetRoughness = clamp(surfaceProperties.GlintMicrofacetRoughness, 0.005, 0.3); + glintInput.DensityRandomization = clamp(surfaceProperties.GlintDensityRandomization, 0, 5); #endif float3 F; - specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, glintInput, F) * lightColor * satNdotL; +#if defined(GLINT) + specular += PI * GetSpecularDirectLightMultiplierMicrofacetWithGlint(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, glintInput, F) * lightColor * satNdotL; +#else + specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, F) * lightColor * satNdotL; +#endif float2 specularBRDF = 0; [branch] if (pbrSettings.UseMultipleScattering) @@ -468,10 +465,7 @@ namespace PBR } float3 coatF; -# if defined(GLINT) - glintInput.H = mul(coatH, tbn); -# endif - float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, glintInput, coatF) * coatLightColor * coatNdotL; + float3 coatSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, coatF) * coatLightColor * coatNdotL; float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; diffuse *= layerAttenuation; @@ -495,12 +489,8 @@ namespace PBR float NdotH = saturate(dot(N, H)); float VdotH = saturate(dot(V, H)); - GlintInput glintInput; -#if defined(GLINT) - glintInput.enabled = false; -#endif float3 wetnessF; - float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, glintInput, wetnessF) * lightColor * NdotL; + float3 wetnessSpecular = PI * GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, wetnessF) * lightColor * NdotL; return wetnessSpecular * wetnessStrength; } diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 46ac7bb83c..ff136296eb 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -184,47 +184,14 @@ void TruePBR::SaveSettings(json& o_json) void TruePBR::PrePass() { auto context = State::GetSingleton()->context; - if (context && glintsNoiseTexture) { + if (context) { + if (!glintsNoiseTexture) + SetupGlintsTexture(); ID3D11ShaderResourceView* srv = glintsNoiseTexture->srv.get(); context->PSSetShaderResources(28, 1, &srv); } } -void TruePBR::SetupFrame() -{ - float newDirectionalLightScale = 1.f; - float newDirectionalAmbientLightScale = 1.f; - - if (const auto* player = RE::PlayerCharacter::GetSingleton()) { - if (const auto* currentCell = player->GetParentCell()) { - if (currentCell->IsInteriorCell()) { - if (const auto* lightingTemplate = currentCell->GetRuntimeData().lightingTemplate) { - const auto* editorId = lightingTemplate->GetFormEditorID(); - if (auto it = pbrLightingTemplates.find(editorId); it != pbrLightingTemplates.cend()) { - newDirectionalLightScale = it->second.directionalLightColorScale; - newDirectionalAmbientLightScale = it->second.directionalAmbientLightColorScale; - } - } - } else if (RE::Sky* sky = RE::Sky::GetSingleton()) { - if (const auto* weather = sky->currentWeather) { - const auto* editorId = weather->GetFormEditorID(); - if (auto it = pbrWeathers.find(editorId); it != pbrWeathers.cend()) { - newDirectionalLightScale = it->second.directionalLightColorScale; - newDirectionalAmbientLightScale = it->second.directionalAmbientLightColorScale; - } - } - } - } - } - - weatherPBRDirectionalLightColorMultiplier = newDirectionalLightScale; - weatherPBRDirectionalAmbientLightColorMultiplier = newDirectionalAmbientLightScale; - - settings.directionalLightColorMultiplier = globalPBRDirectLightColorMultiplier * weatherPBRDirectionalLightColorMultiplier; - settings.pointLightColorMultiplier = globalPBRDirectLightColorMultiplier; - settings.ambientLightColorMultiplier = globalPBRAmbientLightColorMultiplier * weatherPBRDirectionalAmbientLightColorMultiplier; -} - void TruePBR::SetupGlintsTexture() { constexpr uint noiseTexSize = 512; @@ -295,6 +262,41 @@ void TruePBR::SetupGlintsTexture() noiseGenProgram->Release(); } +void TruePBR::SetupFrame() +{ + float newDirectionalLightScale = 1.f; + float newDirectionalAmbientLightScale = 1.f; + + if (const auto* player = RE::PlayerCharacter::GetSingleton()) { + if (const auto* currentCell = player->GetParentCell()) { + if (currentCell->IsInteriorCell()) { + if (const auto* lightingTemplate = currentCell->GetRuntimeData().lightingTemplate) { + const auto* editorId = lightingTemplate->GetFormEditorID(); + if (auto it = pbrLightingTemplates.find(editorId); it != pbrLightingTemplates.cend()) { + newDirectionalLightScale = it->second.directionalLightColorScale; + newDirectionalAmbientLightScale = it->second.directionalAmbientLightColorScale; + } + } + } else if (RE::Sky* sky = RE::Sky::GetSingleton()) { + if (const auto* weather = sky->currentWeather) { + const auto* editorId = weather->GetFormEditorID(); + if (auto it = pbrWeathers.find(editorId); it != pbrWeathers.cend()) { + newDirectionalLightScale = it->second.directionalLightColorScale; + newDirectionalAmbientLightScale = it->second.directionalAmbientLightColorScale; + } + } + } + } + } + + weatherPBRDirectionalLightColorMultiplier = newDirectionalLightScale; + weatherPBRDirectionalAmbientLightColorMultiplier = newDirectionalAmbientLightScale; + + settings.directionalLightColorMultiplier = globalPBRDirectLightColorMultiplier * weatherPBRDirectionalLightColorMultiplier; + settings.pointLightColorMultiplier = globalPBRDirectLightColorMultiplier; + settings.ambientLightColorMultiplier = globalPBRAmbientLightColorMultiplier * weatherPBRDirectionalAmbientLightColorMultiplier; +} + void TruePBR::SetupTextureSetData() { logger::info("[TruePBR] loading PBR texture set configs"); diff --git a/src/TruePBR.h b/src/TruePBR.h index 9492b3543d..94cd419ba0 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -6,7 +6,7 @@ struct GlintParameters { bool enabled = false; float screenSpaceScale = 1.5f; - float logMicrofacetDensity = 18.f; + float logMicrofacetDensity = 40.f; float microfacetRoughness = .015f; float densityRandomization = 2.f; From 72440f25507967224e642565225b20b1939b0e4f Mon Sep 17 00:00:00 2001 From: Ilya Perapechka Date: Sun, 11 Aug 2024 23:28:22 +0300 Subject: [PATCH 10/13] fix: fixed blowing up specular when blending pbr and non-pbr landscape. --- package/Shaders/Common/PBR.hlsli | 13 ++++++------- package/Shaders/Lighting.hlsl | 10 +++++----- src/TruePBR.cpp | 5 +---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 29a6b9e902..4218e672c0 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -27,13 +27,12 @@ #define TruePBR_LandTile3HasDisplacement (1 << 9) #define TruePBR_LandTile4HasDisplacement (1 << 10) #define TruePBR_LandTile5HasDisplacement (1 << 11) -#define TruePBR_LandGlint (1 << 12) -#define TruePBR_LandTile0HasGlint (1 << 13) -#define TruePBR_LandTile1HasGlint (1 << 14) -#define TruePBR_LandTile2HasGlint (1 << 15) -#define TruePBR_LandTile3HasGlint (1 << 16) -#define TruePBR_LandTile4HasGlint (1 << 17) -#define TruePBR_LandTile5HasGlint (1 << 18) +#define TruePBR_LandTile0HasGlint (1 << 12) +#define TruePBR_LandTile1HasGlint (1 << 13) +#define TruePBR_LandTile2HasGlint (1 << 14) +#define TruePBR_LandTile3HasGlint (1 << 15) +#define TruePBR_LandTile4HasGlint (1 << 16) +#define TruePBR_LandTile5HasGlint (1 << 17) namespace PBR { diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 8fd4ec1dd0..c423c735d7 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1363,7 +1363,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } else { - rawRMAOS += input.LandBlendWeights1.y * float4(1 - landNormal2.w, 0, 1, 1); + rawRMAOS += input.LandBlendWeights1.y * float4(1 - landNormal2.w, 0, 1, 0.04); } # endif } @@ -1390,7 +1390,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } else { - rawRMAOS += input.LandBlendWeights1.z * float4(1 - landNormal3.w, 0, 1, 1); + rawRMAOS += input.LandBlendWeights1.z * float4(1 - landNormal3.w, 0, 1, 0.04); } # endif } @@ -1417,7 +1417,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } else { - rawRMAOS += input.LandBlendWeights1.w * float4(1 - landNormal4.w, 0, 1, 1); + rawRMAOS += input.LandBlendWeights1.w * float4(1 - landNormal4.w, 0, 1, 0.04); } # endif } @@ -1444,7 +1444,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } else { - rawRMAOS += input.LandBlendWeights2.x * float4(1 - landNormal5.w, 0, 1, 1); + rawRMAOS += input.LandBlendWeights2.x * float4(1 - landNormal5.w, 0, 1, 0.04); } # endif } @@ -1471,7 +1471,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } else { - rawRMAOS += input.LandBlendWeights2.y * float4(1 - landNormal6.w, 0, 1, 1); + rawRMAOS += input.LandBlendWeights2.y * float4(1 - landNormal6.w, 0, 1, 0.04); } # endif } diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index ff136296eb..f7df34b1fe 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -822,10 +822,7 @@ struct BSLightingShader_SetupMaterial flags |= (1 << (BSLightingShaderMaterialPBRLandscape::NumTiles + textureIndex)); } if (pbrMaterial->glintParameters[textureIndex].enabled) { - flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles + 1 + textureIndex)); - } - if (pbrMaterial->HasGlint()) { - flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles)); + flags |= (1 << (2 * BSLightingShaderMaterialPBRLandscape::NumTiles + textureIndex)); } } } From 646967752e06cdf5d951c2fb63c9aa2a3c5fed63 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Mon, 12 Aug 2024 23:37:59 +0100 Subject: [PATCH 11/13] fix: prevent glazing angle flashes, correct tbnTr --- .../Shaders/Common/Glints/Glints2023.hlsli | 19 +++++++++-------- package/Shaders/Common/PBR.hlsli | 21 +++++++++++-------- package/Shaders/Lighting.hlsl | 6 +++--- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/package/Shaders/Common/Glints/Glints2023.hlsli b/package/Shaders/Common/Glints/Glints2023.hlsli index 959d2baf96..6b31a4137c 100644 --- a/package/Shaders/Common/Glints/Glints2023.hlsli +++ b/package/Shaders/Common/Glints/Glints2023.hlsli @@ -94,13 +94,14 @@ void GetGradientEllipse(float2 duvdx, float2 duvdy, out float2 ellipseMajor, out float T = a + d; float D = a * d - b * c; - float L1 = T / 2.0 - pow(T * T / 3.99999 - D, 0.5); - float L2 = T / 2.0 + pow(T * T / 3.99999 - D, 0.5); + float SQ = sqrt(abs(T * T / 3.99999 - D)); + float L1 = T / 2.0 - SQ; + float L2 = T / 2.0 + SQ; float2 A0 = float2(L1 - d, c); float2 A1 = float2(L2 - d, c); - float r0 = 1.0 / sqrt(L1); - float r1 = 1.0 / sqrt(L2); + float r0 = rsqrt(L1); + float r1 = rsqrt(L2); ellipseMajor = normalize(A0) * r0; ellipseMinor = normalize(A1) * r1; } @@ -112,7 +113,7 @@ float2 VectorToSlope(float3 v) float3 SlopeToVector(float2 s) { - float z = 1 / sqrt(s.x * s.x + s.y * s.y + 1); + float z = rsqrt(s.x * s.x + s.y * s.y + 1); float x = s.x * z; float y = s.y * z; return float3(x, y, z); @@ -239,11 +240,11 @@ struct GlintInput void CustomRand4Texture(GlintInput params, float2 slope, float2 slopeRandOffset, out float4 outUniform, out float4 outGaussian, out float2 slopeLerp) { - int2 size = 512; + uint2 size = 512; float2 slope2 = abs(slope) / params.MicrofacetRoughness; slope2 = slope2 + (slopeRandOffset * size); slopeLerp = frac(slope2); - int2 slopeCoord = int2(floor(slope2)) % size; + uint2 slopeCoord = uint2(floor(slope2)) % size; float4 packedRead = _Glint2023NoiseMap[slopeCoord]; UnpackFloatParallel4(packedRead, outUniform, outGaussian); @@ -298,7 +299,7 @@ float SampleGlintGridSimplex(GlintInput params, float2 uv, uint gridSeed, float2 // Compute binomial properties float hitProba = params.MicrofacetRoughness * targetNDF; // probability of hitting desired half vector in NDF distribution - float3 footprintOneHitProba = (1.0 - pow(1.0 - hitProba.rrr, microfacetCountBlended)); // probability of hitting at least one microfacet in footprint + float3 footprintOneHitProba = (1.0 - pow(abs(1.0 - hitProba.rrr), microfacetCountBlended)); // probability of hitting at least one microfacet in footprint float3 footprintMean = (microfacetCountBlended - 1.0) * hitProba.rrr; // Expected value of number of hits in the footprint given already one hit float3 footprintSTD = sqrt((microfacetCountBlended - 1.0) * hitProba.rrr * (1.0 - hitProba.rrr)); // Standard deviation of number of hits in the footprint given already one hit float3 binomialSmoothWidth = 0.1 * clamp(footprintOneHitProba * 10, 0.0, 1.0) * clamp((1.0 - footprintOneHitProba) * 10, 0.0, 1.0); @@ -530,5 +531,5 @@ float4 SampleGlints2023NDF(GlintInput params, float targetNDF, float maxNDF) float sampleB = SampleGlintGridSimplex(params, uvRotB / divLods[tetraB.z] / float2(1.0, ratios[tetraB.y]), gridSeedB, slope, ratios[tetraB.y] * footprintAreas[tetraB.z], rescaledTargetNDF, tetraBarycentricWeights.y); float sampleC = SampleGlintGridSimplex(params, uvRotC / divLods[tetraC.z] / float2(1.0, ratios[tetraC.y]), gridSeedC, slope, ratios[tetraC.y] * footprintAreas[tetraC.z], rescaledTargetNDF, tetraBarycentricWeights.z); float sampleD = SampleGlintGridSimplex(params, uvRotD / divLods[tetraD.z] / float2(1.0, ratios[tetraD.y]), gridSeedD, slope, ratios[tetraD.y] * footprintAreas[tetraD.z], rescaledTargetNDF, tetraBarycentricWeights.w); - return (sampleA + sampleB + sampleC + sampleD) * (1.0 / params.MicrofacetRoughness) * maxNDF; + return min((sampleA + sampleB + sampleC + sampleD) * (1.0 / params.MicrofacetRoughness), 40) * maxNDF; // somewhat brute force way of prevent glazing angle extremities } \ No newline at end of file diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 4218e672c0..205f7084ed 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -1,7 +1,3 @@ -#if defined(GLINT) -# include "Common/Glints/Glints2023.hlsli" -#endif - #define TruePBR_HasEmissive (1 << 0) #define TruePBR_HasDisplacement (1 << 1) #define TruePBR_HasFeatureTexture0 (1 << 2) @@ -36,6 +32,10 @@ namespace PBR { +#if defined(GLINT) +# include "Common/Glints/Glints2023.hlsli" +#endif + struct SurfaceProperties { float3 BaseColor; @@ -158,8 +158,11 @@ namespace PBR float3 GetSpecularDirectLightMultiplierMicrofacetWithGlint(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, GlintInput glintInput, out float3 F) { float D = GetNormalDistributionFunctionGGX(roughness, NdotH); - float D_max = GetNormalDistributionFunctionGGX(roughness, 1); - D = SampleGlints2023NDF(glintInput, D, D_max); + [branch] if (glintInput.LogMicrofacetDensity > 1.1) + { + float D_max = GetNormalDistributionFunctionGGX(roughness, 1); + D = SampleGlints2023NDF(glintInput, D, D_max); + } float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); F = GetFresnelFactorSchlick(specularColor, VdotH); @@ -370,7 +373,7 @@ namespace PBR } void GetDirectLightInput(out float3 diffuse, out float3 coatDiffuse, out float3 transmission, out float3 specular, float3 N, float3 coatN, float3 V, float3 coatV, float3 L, float3 coatL, float3 lightColor, float3 coatLightColor, SurfaceProperties surfaceProperties, - float3x3 tbn, float2 uv) + float3x3 tbnTr, float2 uv) { diffuse = 0; coatDiffuse = 0; @@ -403,12 +406,12 @@ namespace PBR #if defined(GLINT) GlintInput glintInput; - glintInput.H = mul(tbn, H); + glintInput.H = mul(tbnTr, H); glintInput.uv = uv; glintInput.duvdx = ddx(uv); glintInput.duvdy = ddy(uv); glintInput.ScreenSpaceScale = max(1, surfaceProperties.GlintScreenSpaceScale); - glintInput.LogMicrofacetDensity = 40 - clamp(surfaceProperties.GlintLogMicrofacetDensity, 0, 40); + glintInput.LogMicrofacetDensity = clamp(surfaceProperties.GlintLogMicrofacetDensity, 1, 40); glintInput.MicrofacetRoughness = clamp(surfaceProperties.GlintMicrofacetRoughness, 0.005, 0.3); glintInput.DensityRandomization = clamp(surfaceProperties.GlintDensityRandomization, 0, 5); #endif diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index c423c735d7..af8e5ddf4d 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1934,7 +1934,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 coatFinalLightColor = coatShadowDirLightColorMultiplier * pbrDirLightColor; float3 dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor; - PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedDirLightDirection, DirLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties, tbn, uvOriginal); + PBR::GetDirectLightInput(dirDiffuseColor, coatDirDiffuseColor, dirTransmissionColor, dirSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedDirLightDirection, DirLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties, tbnTr, uvOriginal); lightsDiffuseColor += dirDiffuseColor; coatLightsDiffuseColor += coatDirDiffuseColor; transmissionColor += dirTransmissionColor; @@ -2016,7 +2016,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace refractedLightDirection = -refract(-normalizedLightDirection, coatModelNormal, eta); } float3 pbrLightColor = PBR::AdjustPointLightColor(lightColor); - PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedLightDirection, normalizedLightDirection, pbrLightColor, pbrLightColor, pbrSurfaceProperties, tbn, uvOriginal); + PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, modelNormal.xyz, coatModelNormal, refractedViewDirection, viewDirection, refractedLightDirection, normalizedLightDirection, pbrLightColor, pbrLightColor, pbrSurfaceProperties, tbnTr, uvOriginal); lightsDiffuseColor += pointDiffuseColor; coatLightsDiffuseColor += coatPointDiffuseColor; transmissionColor += pointTransmissionColor; @@ -2155,7 +2155,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace } float3 pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor; - PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, worldSpaceNormal.xyz, coatWorldNormal, refractedViewDirectionWS, worldSpaceViewDirection, refractedLightDirection, normalizedLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties, tbn, uvOriginal); + PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, worldSpaceNormal.xyz, coatWorldNormal, refractedViewDirectionWS, worldSpaceViewDirection, refractedLightDirection, normalizedLightDirection, mainLayerFinalLightColor, coatFinalLightColor, pbrSurfaceProperties, tbnTr, uvOriginal); lightsDiffuseColor += pointDiffuseColor; coatLightsDiffuseColor += coatPointDiffuseColor; transmissionColor += pointTransmissionColor; From 019cd38b974257ad7ab66892a58af9d1d84de7a3 Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Tue, 13 Aug 2024 14:51:43 +0100 Subject: [PATCH 12/13] fix: blending, more suppression on edgy glints, optimisation --- .../Shaders/Common/Glints/Glints2023.hlsli | 62 ++++++++----------- package/Shaders/Common/PBR.hlsli | 2 +- src/TruePBR.cpp | 4 +- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/package/Shaders/Common/Glints/Glints2023.hlsli b/package/Shaders/Common/Glints/Glints2023.hlsli index 6b31a4137c..0293cfc098 100644 --- a/package/Shaders/Common/Glints/Glints2023.hlsli +++ b/package/Shaders/Common/Glints/Glints2023.hlsli @@ -106,24 +106,14 @@ void GetGradientEllipse(float2 duvdx, float2 duvdy, out float2 ellipseMajor, out ellipseMinor = normalize(A1) * r1; } -float2 VectorToSlope(float3 v) -{ - return float2(-v.x / v.z, -v.y / v.z); -} - -float3 SlopeToVector(float2 s) -{ - float z = rsqrt(s.x * s.x + s.y * s.y + 1); - float x = s.x * z; - float y = s.y * z; - return float3(x, y, z); -} - float2 RotateUV(float2 uv, float rotation, float2 mid) { + float2 rel_uv = uv - mid; + float2 sincos_rot; + sincos(rotation, sincos_rot.y, sincos_rot.x); return float2( - cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x, - cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y); + sincos_rot.x * rel_uv.x + sincos_rot.y * rel_uv.y + mid.x, + sincos_rot.x * rel_uv.y - sincos_rot.y * rel_uv.x + mid.y); } float BilinearLerp(float4 values, float2 valuesLerp) @@ -184,8 +174,9 @@ float3 GetBarycentricWeights(float2 p, float2 a, float2 b, float2 c) float2 v1 = c - a; float2 v2 = p - a; float den = v0.x * v1.y - v1.x * v0.y; - float v = (v2.x * v1.y - v1.x * v2.y) / den; - float w = (v0.x * v2.y - v2.x * v0.y) / den; + float rcpDen = rcp(den); + float v = (v2.x * v1.y - v1.x * v2.y) * rcpDen; + float w = (v0.x * v2.y - v2.x * v0.y) * rcpDen; float u = 1.0f - v - w; return float3(u, v, w); } @@ -294,7 +285,7 @@ float SampleGlintGridSimplex(GlintInput params, float2 uv, uint gridSeed, float2 // Compute microfacet count with randomization float3 logDensityRand = clamp(sampleNormalDistribution(float3(rand0.x, rand1.x, rand2.x), params.LogMicrofacetDensity.r, params.DensityRandomization), 0.0, 50.0); // TODO : optimize sampleNormalDist - float3 microfacetCount = max(0.0.rrr, footprintArea.rrr * exp(logDensityRand)); + float3 microfacetCount = max(1e-8, footprintArea.rrr * exp(logDensityRand)); float3 microfacetCountBlended = microfacetCount * gridWeight; // Compute binomial properties @@ -451,13 +442,10 @@ void GetAnisoCorrectingGridTetrahedron(bool centerSpecialCase, inout float theta float4 SampleGlints2023NDF(GlintInput params, float targetNDF, float maxNDF) { - static const float DEG2RAD = 0.01745329251; - static const float RAD2DEG = 57.2957795131; - // ACCURATE PIXEL FOOTPRINT ELLIPSE float2 ellipseMajor, ellipseMinor; GetGradientEllipse(params.duvdx, params.duvdy, ellipseMajor, ellipseMinor); - float ellipseRatio = length(ellipseMajor) / length(ellipseMinor); + float ellipseRatio = length(ellipseMajor) / (length(ellipseMinor) + 1e-8); // SHARED GLINT NDF VALUES float halfScreenSpaceScaler = params.ScreenSpaceScale * 0.5; @@ -472,26 +460,26 @@ float4 SampleGlints2023NDF(GlintInput params, float targetNDF, float maxNDF) float divLod0 = pow(2.0, lod0); float divLod1 = pow(2.0, lod1); float lodLerp = frac(lod); - float footprintAreaLOD0 = pow(exp2(lod0), 2.0); - float footprintAreaLOD1 = pow(exp2(lod1), 2.0); + float footprintAreaLOD0 = exp2(2.0 * lod0); + float footprintAreaLOD1 = exp2(2.0 * lod1); // MANUAL ANISOTROPY RATIO COMPENSATION float ratio0 = max(pow(2.0, (int)log2(ellipseRatio)), 1.0); float ratio1 = ratio0 * 2.0; - float ratioLerp = clamp(Remap(ellipseRatio, ratio0, ratio1, 0.0, 1.0), 0.0, 1.0); + float ratioLerp = saturate(Remap(ellipseRatio, ratio0, ratio1, 0.0, 1.0)); // MANUAL ANISOTROPY ROTATION COMPENSATION float2 v1 = float2(0.0, 1.0); float2 v2 = normalize(ellipseMajor); - float theta = atan2(v1.x * v2.y - v1.y * v2.x, v1.x * v2.x + v1.y * v2.y) * RAD2DEG; - float thetaGrid = 90.0 / max(ratio0, 2.0); + float theta = atan2(v1.x * v2.y - v1.y * v2.x, v1.x * v2.x + v1.y * v2.y); + float thetaGrid = 1.57079632679 / max(ratio0, 2.0); float thetaBin = (int)(theta / thetaGrid) * thetaGrid; thetaBin = thetaBin + (thetaGrid / 2.0); float thetaBin0 = theta < thetaBin ? thetaBin - thetaGrid / 2.0 : thetaBin; float thetaBinH = thetaBin0 + thetaGrid / 4.0; float thetaBin1 = thetaBin0 + thetaGrid / 2.0; float thetaBinLerp = Remap(theta, thetaBin0, thetaBin1, 0.0, 1.0); - thetaBin0 = thetaBin0 <= 0.0 ? 180.0 + thetaBin0 : thetaBin0; + thetaBin0 = thetaBin0 <= 0.0 ? 3.1415926535 + thetaBin0 : thetaBin0; // TETRAHEDRONIZATION OF ROTATION + RATIO + LOD GRID bool centerSpecialCase = (ratio0.x == 1.0); @@ -517,19 +505,19 @@ float4 SampleGlints2023NDF(GlintInput params, float targetNDF, float maxNDF) tetraC.x = (tetraC.y == 0) ? 3 : tetraC.x; tetraD.x = (tetraD.y == 0) ? 3 : tetraD.x; } - float2 uvRotA = RotateUV(params.uv, thetaBins[tetraA.x] * DEG2RAD, 0.0.rr); - float2 uvRotB = RotateUV(params.uv, thetaBins[tetraB.x] * DEG2RAD, 0.0.rr); - float2 uvRotC = RotateUV(params.uv, thetaBins[tetraC.x] * DEG2RAD, 0.0.rr); - float2 uvRotD = RotateUV(params.uv, thetaBins[tetraD.x] * DEG2RAD, 0.0.rr); + float2 uvRotA = RotateUV(params.uv, thetaBins[tetraA.x], 0.0.rr); + float2 uvRotB = RotateUV(params.uv, thetaBins[tetraB.x], 0.0.rr); + float2 uvRotC = RotateUV(params.uv, thetaBins[tetraC.x], 0.0.rr); + float2 uvRotD = RotateUV(params.uv, thetaBins[tetraD.x], 0.0.rr); // SAMPLE GLINT GRIDS - uint gridSeedA = HashWithoutSine13(float3(log2(divLods[tetraA.z]), thetaBins[tetraA.x] % 360, ratios[tetraA.y])) * 4294967296.0; - uint gridSeedB = HashWithoutSine13(float3(log2(divLods[tetraB.z]), thetaBins[tetraB.x] % 360, ratios[tetraB.y])) * 4294967296.0; - uint gridSeedC = HashWithoutSine13(float3(log2(divLods[tetraC.z]), thetaBins[tetraC.x] % 360, ratios[tetraC.y])) * 4294967296.0; - uint gridSeedD = HashWithoutSine13(float3(log2(divLods[tetraD.z]), thetaBins[tetraD.x] % 360, ratios[tetraD.y])) * 4294967296.0; + uint gridSeedA = HashWithoutSine13(float3(log2(divLods[tetraA.z]), fmod(thetaBins[tetraA.x], 6.28318530718), ratios[tetraA.y])) * 4294967296.0; + uint gridSeedB = HashWithoutSine13(float3(log2(divLods[tetraB.z]), fmod(thetaBins[tetraB.x], 6.28318530718), ratios[tetraB.y])) * 4294967296.0; + uint gridSeedC = HashWithoutSine13(float3(log2(divLods[tetraC.z]), fmod(thetaBins[tetraC.x], 6.28318530718), ratios[tetraC.y])) * 4294967296.0; + uint gridSeedD = HashWithoutSine13(float3(log2(divLods[tetraD.z]), fmod(thetaBins[tetraD.x], 6.28318530718), ratios[tetraD.y])) * 4294967296.0; float sampleA = SampleGlintGridSimplex(params, uvRotA / divLods[tetraA.z] / float2(1.0, ratios[tetraA.y]), gridSeedA, slope, ratios[tetraA.y] * footprintAreas[tetraA.z], rescaledTargetNDF, tetraBarycentricWeights.x); float sampleB = SampleGlintGridSimplex(params, uvRotB / divLods[tetraB.z] / float2(1.0, ratios[tetraB.y]), gridSeedB, slope, ratios[tetraB.y] * footprintAreas[tetraB.z], rescaledTargetNDF, tetraBarycentricWeights.y); float sampleC = SampleGlintGridSimplex(params, uvRotC / divLods[tetraC.z] / float2(1.0, ratios[tetraC.y]), gridSeedC, slope, ratios[tetraC.y] * footprintAreas[tetraC.z], rescaledTargetNDF, tetraBarycentricWeights.z); float sampleD = SampleGlintGridSimplex(params, uvRotD / divLods[tetraD.z] / float2(1.0, ratios[tetraD.y]), gridSeedD, slope, ratios[tetraD.y] * footprintAreas[tetraD.z], rescaledTargetNDF, tetraBarycentricWeights.w); - return min((sampleA + sampleB + sampleC + sampleD) * (1.0 / params.MicrofacetRoughness), 40) * maxNDF; // somewhat brute force way of prevent glazing angle extremities + return min((sampleA + sampleB + sampleC + sampleD) * (1.0 / params.MicrofacetRoughness), 20) * maxNDF; // somewhat brute force way of prevent glazing angle extremities } \ No newline at end of file diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 205f7084ed..f52e8295ec 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -411,7 +411,7 @@ namespace PBR glintInput.duvdx = ddx(uv); glintInput.duvdy = ddy(uv); glintInput.ScreenSpaceScale = max(1, surfaceProperties.GlintScreenSpaceScale); - glintInput.LogMicrofacetDensity = clamp(surfaceProperties.GlintLogMicrofacetDensity, 1, 40); + glintInput.LogMicrofacetDensity = clamp(40.f - surfaceProperties.GlintLogMicrofacetDensity, 1, 40); glintInput.MicrofacetRoughness = clamp(surfaceProperties.GlintMicrofacetRoughness, 0.005, 0.3); glintInput.DensityRandomization = clamp(surfaceProperties.GlintDensityRandomization, 0, 5); #endif diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index f7df34b1fe..e16e3b6a59 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -842,7 +842,7 @@ struct BSLightingShader_SetupMaterial std::array glintParameters; glintParameters[0] = pbrMaterial->glintParameters[textureIndex].screenSpaceScale; - glintParameters[1] = pbrMaterial->glintParameters[textureIndex].logMicrofacetDensity; + glintParameters[1] = 40.f - pbrMaterial->glintParameters[textureIndex].logMicrofacetDensity; glintParameters[2] = pbrMaterial->glintParameters[textureIndex].microfacetRoughness; glintParameters[3] = pbrMaterial->glintParameters[textureIndex].densityRandomization; shadowState->SetPSConstant(glintParameters, RE::BSGraphics::ConstantGroupLevel::PerMaterial, GlintParametersStartIndex + textureIndex); @@ -926,7 +926,7 @@ struct BSLightingShader_SetupMaterial std::array GlintParameters; GlintParameters[0] = pbrMaterial->GetGlintParameters().screenSpaceScale; - GlintParameters[0] = pbrMaterial->GetGlintParameters().logMicrofacetDensity; + GlintParameters[0] = 40.f - pbrMaterial->GetGlintParameters().logMicrofacetDensity; GlintParameters[0] = pbrMaterial->GetGlintParameters().microfacetRoughness; GlintParameters[0] = pbrMaterial->GetGlintParameters().densityRandomization; shadowState->SetPSConstant(GlintParameters, RE::BSGraphics::ConstantGroupLevel::PerMaterial, 27); From ae29748b044e269e29d90332d51ed330fa92b93d Mon Sep 17 00:00:00 2001 From: Pentalimbed Date: Tue, 13 Aug 2024 20:16:59 +0100 Subject: [PATCH 13/13] chore: remove redundant context check --- src/TruePBR.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index e16e3b6a59..9f0f07e743 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -184,12 +184,10 @@ void TruePBR::SaveSettings(json& o_json) void TruePBR::PrePass() { auto context = State::GetSingleton()->context; - if (context) { - if (!glintsNoiseTexture) - SetupGlintsTexture(); - ID3D11ShaderResourceView* srv = glintsNoiseTexture->srv.get(); - context->PSSetShaderResources(28, 1, &srv); - } + if (!glintsNoiseTexture) + SetupGlintsTexture(); + ID3D11ShaderResourceView* srv = glintsNoiseTexture->srv.get(); + context->PSSetShaderResources(28, 1, &srv); } void TruePBR::SetupGlintsTexture()