From a13a00f2a28a2ea024dcc93eadd87ecf707f3ab4 Mon Sep 17 00:00:00 2001 From: yum Date: Wed, 4 Jun 2025 13:26:27 -0700 Subject: fix ssao --- 2ner.cginc | 11 ++++++++++- 2ner.shader | 2 +- cnlohr.cginc | 23 ++++++++++------------- custom30.cginc | 36 ++++++++++++++++++++++++++++++------ fog.cginc | 6 +++--- math.cginc | 19 +++++++++++++++++++ ssao.cginc | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yum_brdf.cginc | 12 ++++++------ yum_pbr.cginc | 58 +--------------------------------------------------------- 9 files changed, 138 insertions(+), 87 deletions(-) create mode 100644 ssao.cginc diff --git a/2ner.cginc b/2ner.cginc index 284b2b2..fe01972 100644 --- a/2ner.cginc +++ b/2ner.cginc @@ -19,6 +19,7 @@ #include "math.cginc" #include "poi.cginc" #include "shatter_wave.cginc" +#include "ssao.cginc" #include "ssfd.cginc" #include "tessellation.cginc" #include "unigram_letter_grid.cginc" @@ -188,6 +189,7 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace i.normal = UnityObjectToWorldNormal(i.normal); i.tangent = UnityObjectToWorldNormal(i.tangent); i.binormal = UnityObjectToWorldNormal(i.binormal); + const float3x3 tangentToWorld = float3x3(i.tangent, i.binormal, i.normal); #if defined(_RAYMARCHED_FOG) && defined(FORWARD_BASE_PASS) { @@ -249,6 +251,12 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace i.uv01.xy = eye_effect_00.uv; #endif + float ssao = 1; +#if defined(_SSAO) + float2 debug; + ssao = get_ssao(i, tangentToWorld, debug); +#endif + #if defined(_CUSTOM30) && defined(FORWARD_BASE_PASS) || (!defined(_DEPTH_PREPASS) && defined(SHADOW_CASTER_PASS)) #if defined(_CUSTOM30_BASICCUBE) Custom30Output basic_cube_output = BasicCube(i); @@ -278,7 +286,8 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace #endif #endif - YumPbr pbr = GetYumPbr(i); + YumPbr pbr = GetYumPbr(i, tangentToWorld); + pbr.ao *= ssao; #if defined(_HARNACK_TRACING) HarnackTracingOutput harnack_output = HarnackTracing(i); diff --git a/2ner.shader b/2ner.shader index 471c84c..e92c65d 100644 --- a/2ner.shader +++ b/2ner.shader @@ -1929,7 +1929,7 @@ Shader "yum_food/2ner" } SubShader { - Tags { "RenderType" = "Opaque" "Queue" = "Geometry" "VRCFallback" = "Standard" } + Tags { "RenderType" = "Opaque" "Queue" = "Geometry" "VRCFallback" = "Standard" "DisableBatching" = "True" } //ifex _Depth_Prepass_Enabled==0 Pass { diff --git a/cnlohr.cginc b/cnlohr.cginc index b01bbce..cd98f08 100644 --- a/cnlohr.cginc +++ b/cnlohr.cginc @@ -82,24 +82,21 @@ void GetScreenUVAndPerspectiveFactor(float3 worldPos, float4 clipPos, out float2 } #if defined(_SSAO) -float GetDepthOfWorldPos(float3 worldPos) +float GetDepthOfWorldPos(float3 worldPos, out float2 debug) { float3 full_vec_eye_to_geometry = worldPos - _WorldSpaceCameraPos; - float4 objPos = mul(unity_WorldToObject, float4(worldPos, 1)); + float3 objPos = mul(unity_WorldToObject, float4(worldPos, 1)); float4 clipPos = UnityObjectToClipPos(objPos); + float4 screenPos = ComputeScreenPos(clipPos); - float2 suv = clipPos * float2(0.5, 0.5 * _ProjectionParams.x); - float2 screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * clipPos.w, clipPos.w); + const float2 screen_uv = screenPos.xy / screenPos.w; + float zDepthFromMap = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv); + float linearZ = + GetLinearZFromZDepth_WorksWithMirrors(zDepthFromMap, screen_uv); + linearZ = min(1E3, linearZ); - float perspective_divide = 1.0f / clipPos.w; - float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide); - float2 screen_uv = screenPos.xy * perspective_divide; - - float eye_depth_world = - GetLinearZFromZDepth_WorksWithMirrors( - SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv), - screen_uv) * perspective_factor; - return eye_depth_world; + debug = screen_uv; + return linearZ; } #endif diff --git a/custom30.cginc b/custom30.cginc index 2d407ca..be4bd4c 100644 --- a/custom30.cginc +++ b/custom30.cginc @@ -2,6 +2,7 @@ #define __CUSTOM30_INC #include "globals.cginc" +#include "math.cginc" #include "pema99.cginc" #include "quilez.cginc" #include "interpolators.cginc" @@ -47,9 +48,29 @@ float cut_with_box(float3 p, float d, float3 box_size) { return d; } +float distance_from_hex_comb( + float3 p, + float3 period, + float hex_sc, + float zoff, + float count) { + float3 p_hex = cart_to_hex(p.xy); + + float half_period = period * 0.5; + float3 which = abs(floor((p_hex + half_period) / period)); + p_hex = glsl_mod(p_hex + half_period, period) - half_period; + + p.xy = hex_to_cart(p_hex); + + float hex_d = distance_from_hex_prism(p - + float3(0, 0, zoff), hex_sc); + hex_d = any(which > count) ? 1E9 : hex_d; + return hex_d; +} + float distance_from_hex_grid( float3 p, - float period, + float2 period, float hex_sc, float zoff, float count) { @@ -82,8 +103,8 @@ float BasicCube_map(float3 p) { float hex_grip_scale = scale * 10; [branch] if (hex_grip_scale < 1) { - float period = 0.05; - float hex_sc = period * 0.4; + float period = 0.1; + float hex_sc = period * 0.2; float count = 13; float zoff = core_dim - (hex_sc * 0.2) - hex_grip_scale * hex_sc; @@ -92,7 +113,10 @@ float BasicCube_map(float3 p) { pp = pp.z > pp.x && pp.z > pp.y ? pp.xyz : pp; pp = pp.y > pp.x && pp.y > pp.z ? pp.zxy : pp; pp = pp.x > pp.y && pp.x > pp.z ? pp.yzx : pp; - d = min(d, distance_from_hex_grid(pp, period, hex_sc, zoff, count)); + + float hex_d = distance_from_hex_comb(pp, period, hex_sc, zoff, count); + hex_d = any(pp.xy > 0.85) ? 1E9 : hex_d; + d = min(d, hex_d); } #endif @@ -118,7 +142,7 @@ float BasicCube_map(float3 p) { } float3 BasicCube_normal(float3 p) { - float epsilon = 1E-3; + float epsilon = 5E-3; float center_d = BasicCube_map(p); float3 n = float3( BasicCube_map(p + float3(epsilon, 0, 0)) - center_d, @@ -139,7 +163,7 @@ Custom30Output BasicCube(v2f i) { float d; float d_acc = 0; - float epsilon = 5E-3; + float epsilon = 1E-3; // 1.73... = sqrt(3) // our cube has an edge length of 2, so mult by 2 float max_d = 1.73205081f * 2.0f; diff --git a/fog.cginc b/fog.cginc index c71fa97..ed99927 100644 --- a/fog.cginc +++ b/fog.cginc @@ -40,7 +40,7 @@ FogResult raymarched_fog(v2f i, FogParams p) const float ro_epsilon = 1E-3; ro += rd * ro_epsilon; - float2 screen_uv = (i.pos.xy + 0.5) / _ScreenParams.xy; + const float2 screen_uv = (i.pos.xy + 0.5) / _ScreenParams.xy; float zDepthFromMap = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv); float linearZ = GetLinearZFromZDepth_WorksWithMirrors(zDepthFromMap, screen_uv); @@ -96,10 +96,10 @@ FogResult raymarched_fog(v2f i, FogParams p) } FogResult r; - r.color.rgb = _Raymarched_Fog_Color; + //r.color.rgb = _Raymarched_Fog_Color; //r.color.rgb = saturate(log(linearZ) / 5.0); + r.color.rgb = float3(screen_uv, 0); r.color.a = d; - //r.color.a = 1; r.depth = 0.0001; // Very small depth value to render in front return r; } diff --git a/math.cginc b/math.cginc index 8ada893..bb01823 100644 --- a/math.cginc +++ b/math.cginc @@ -283,4 +283,23 @@ float3 cmykToRgb(float4 cmyk) { (1 - cmyk[2]) * (1 - cmyk[3])); } +// Cartesian to cube hexagonal coordinates. +// Based on this: https://backdrifting.net/post/064_hex_grids +#define TWO_OVER_THREE 0.6666666666666666f +#define SQRT_3_OVER_2 0.8660254037844386f + +float3 cart_to_hex(float2 cart) { + float p = cart.x; + float q = dot(cart, float2(0.5f, SQRT_3_OVER_2)); + float r = dot(cart, float2(0.5f, -SQRT_3_OVER_2)); + + return float3(p, q, r) * TWO_OVER_THREE; +} + +float2 hex_to_cart(float3 cart) { + return float2( + cart[0] + (cart[1] + cart[2]) * 0.5f, + (cart[1] - cart[2]) * SQRT_3_OVER_2); +} + #endif // __MATH_INC diff --git a/ssao.cginc b/ssao.cginc new file mode 100644 index 0000000..060b2da --- /dev/null +++ b/ssao.cginc @@ -0,0 +1,58 @@ +#ifndef __SSAO_INC +#define __SSAO_INC + +#include "audiolink.cginc" +#include "globals.cginc" +#include "interpolators.cginc" + +#if defined(_SSAO) +float get_ssao(v2f i, float3x3 tangentToWorld, out float2 debug) { + const float fragment_depth = GetDepthOfWorldPos(i.worldPos, debug); + const float2 screen_px = (i.pos.xy + 0.5); + const float2 screen_uv = (i.pos.xy + 0.5) / _ScreenParams.xy; + const float ssao_theta = _SSAO_Noise.SampleLevel(point_repeat_s, screen_px * _SSAO_Noise_TexelSize.xy, 0) * TAU; + const float2x2 ssao_rot = float2x2( + cos(ssao_theta), -sin(ssao_theta), + sin(ssao_theta), cos(ssao_theta)); + + const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x); + + float ssao_occlusion = 0; + const float ssao_eps = 1E-5; + [loop] + for (uint ii = 0; ii < _SSAO_Samples; ii++) { + // Compute random vector in tangent space. + // Get the index of the current pixels, on the range [0, screen_width] x + // [0, screen_height]. + // Map that onto the noise texture's pixels. Add an offset for each + // index. + float2 noise_uv = (float2(ii % _ScreenParams.x, ii * (_ScreenParams.z - 1.0f))) * _SSAO_Noise_TexelSize.xy; + float3 sample_point = _SSAO_Noise.SampleLevel(point_repeat_s, noise_uv, 0).rgb; + // Use a low discrepancy sequence to transform each sample over time. + //sample_point = frac(sample_point + PHI * frame); + sample_point.xy = 2.0 * sample_point.xy - 1.0; + sample_point.xy = mul(ssao_rot, sample_point.xy); + + // Remap to world space. + sample_point = mul(sample_point, tangentToWorld); + float scale = (ii * 1.0f) / _SSAO_Samples; + sample_point *= lerp(0.1f, 1.0f, scale * scale) * _SSAO_Radius; + + sample_point += i.worldPos; + + float sample_depth = GetDepthOfWorldPos(sample_point, debug); + + // Depth values we're working with indicate how far you have to go along + // the view vector before you hit the object in question. Therefore, we + // care when the sample is *closer* to us than the object. + float occlusion_amount = saturate((fragment_depth - sample_depth) - _SSAO_Bias); + + ssao_occlusion += occlusion_amount; + } + + return saturate(1.0 - _SSAO_Strength * ssao_occlusion / _SSAO_Samples); +} +#endif + +#endif // __SSAO_INC + diff --git a/yum_brdf.cginc b/yum_brdf.cginc index 9e44626..fde2aae 100644 --- a/yum_brdf.cginc +++ b/yum_brdf.cginc @@ -103,8 +103,8 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { const float3 energy_compensation = energyCompensation(dfg, f0); float3 Fd = pbr.albedo / PI; - Fd *= (1.0 - pbr.metallic) * light.attenuation; - float3 Fr = specularLobe(pbr, f0, h, LoH, NoH, NoV, NoL_wrapped_s); + Fd *= (1.0 - pbr.metallic) * light.attenuation * pbr.ao; + float3 Fr = specularLobe(pbr, f0, h, LoH, NoH, NoV, NoL_wrapped_s) * pbr.ao; float3 color = Fd * NoL_wrapped_d + Fr * energy_compensation * NoL_wrapped_s; direct_standard = color * light.direct; @@ -118,12 +118,12 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { // makers suck shit and don't use enough reflection probes. float3 Fr = _Cloth_Sheen_Color * light.specular * light.diffuse_luminance; float3 Fd = pbr.albedo * light.diffuse * pbr.ao; - + #if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE) // Apply subsurface color to indirect diffuse Fd *= _Cloth_Subsurface_Color; #endif - + indirect_cloth = (Fr + Fd) * _Cloth_Indirect_Multiplier; } #endif @@ -136,9 +136,9 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { const float3 E = specularDFG(dfg, f0); const float3 energy_compensation = energyCompensation(dfg, f0); - float3 Fr = E * light.specular * energy_compensation; + float3 Fr = E * light.specular * energy_compensation * pbr.ao; float3 Fd = pbr.albedo * light.diffuse * (1.0 - E) * (1.0 - pbr.metallic) * pbr.ao; - + indirect_standard = Fr + Fd; } diff --git a/yum_pbr.cginc b/yum_pbr.cginc index 6fa12bb..c3f5c4a 100644 --- a/yum_pbr.cginc +++ b/yum_pbr.cginc @@ -1,7 +1,6 @@ #ifndef __YUM_PBR #define __YUM_PBR -#include "audiolink.cginc" #include "cnlohr.cginc" #include "decals.cginc" #include "features.cginc" @@ -29,7 +28,7 @@ void propagateRoughness(in float smoothness, out float roughness_perceptual, out roughness = roughness_perceptual * roughness_perceptual; } -YumPbr GetYumPbr(v2f i) { +YumPbr GetYumPbr(v2f i, float3x3 tangentToWorld) { YumPbr result; float2 raw_uv = i.uv01.xy; @@ -135,63 +134,8 @@ YumPbr GetYumPbr(v2f i) { applyDecals(i, result.albedo, normal_tangent, result.metallic, result.smoothness); propagateRoughness(result.smoothness, result.roughness_perceptual, result.roughness); - const float3x3 tangentToWorld = float3x3(i.tangent, i.binormal, i.normal); result.normal = normalize(mul(normal_tangent, tangentToWorld)); -#if defined(_SSAO) - { - const float fragment_depth = GetDepthOfWorldPos(i.worldPos); - - float2 screen_uv; - float perspective_factor; - GetScreenUVAndPerspectiveFactor(i.worldPos, i.pos, screen_uv, perspective_factor); - - const float2 screen_px = screen_uv * _ScreenParams.xy; - const float ssao_theta = _SSAO_Noise.SampleLevel(point_repeat_s, screen_px * _SSAO_Noise_TexelSize.xy, 0) * TAU; - const float2x2 ssao_rot = float2x2( - cos(ssao_theta), -sin(ssao_theta), - sin(ssao_theta), cos(ssao_theta)); - - const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x); - - float ssao_occlusion = 0; - const float ssao_eps = 1E-5; - [loop] - for (uint ii = 0; ii < _SSAO_Samples; ii++) { - // Compute random vector in tangent space. - // Get the index of the current pixels, on the range [0, screen_width] x - // [0, screen_height]. - // Map that onto the noise texture's pixels. Add an offset for each - // index. - float2 noise_uv = (float2(ii % _ScreenParams.x, ii * (_ScreenParams.z - 1.0f))) * _SSAO_Noise_TexelSize.xy; - float3 sample_point = _SSAO_Noise.SampleLevel(point_repeat_s, noise_uv, 0).rgb; - // Use a low discrepancy sequence to transform each sample over time. - //sample_point = frac(sample_point + PHI * frame); - sample_point.xy = 2.0 * sample_point.xy - 1.0; - sample_point.xy = mul(ssao_rot, sample_point.xy); - - // Remap to world space. - sample_point = mul(sample_point, tangentToWorld); - float scale = (ii * 1.0f) / _SSAO_Samples; - sample_point *= lerp(0.1f, 1.0f, scale * scale) * _SSAO_Radius; - - sample_point += i.worldPos; - - float sample_depth = GetDepthOfWorldPos(sample_point); - - // Depth values we're working with indicate how far you have to go along - // the view vector before you hit the object in question. Therefore, we - // care when the sample is *closer* to us than the object. - float occlusion_amount = saturate((fragment_depth - sample_depth) - _SSAO_Bias); - - ssao_occlusion += occlusion_amount; - } - - //result.albedo.xyz *= saturate(1.0 - _SSAO_Strength * ssao_occlusion / _SSAO_Samples); - result.albedo.xyz = saturate(1.0 - _SSAO_Strength * ssao_occlusion / _SSAO_Samples); - } -#endif - #if (defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS)) && defined(_GLITTER) GlitterParams glitter_p; glitter_p.color = _Glitter_Color; -- cgit v1.2.3