diff options
| author | yum <yum.food.vr@gmail.com> | 2025-06-03 18:24:43 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-06-03 18:25:12 -0700 |
| commit | a8d6d469d57349da515759270eb31a242c795951 (patch) | |
| tree | 814c86255ff287749df60100453d2b4e10945cd6 | |
| parent | 1dca0fed44b9c8eb8a6f3131f54c10f1323ed5a8 (diff) | |
Begin work on SSAO - very buggy!
| -rw-r--r-- | 2ner.cginc | 2 | ||||
| -rw-r--r-- | 2ner.shader | 12 | ||||
| -rw-r--r-- | audiolink.cginc | 2 | ||||
| -rw-r--r-- | cnlohr.cginc | 46 | ||||
| -rw-r--r-- | features.cginc | 4 | ||||
| -rw-r--r-- | glitter.cginc | 2 | ||||
| -rw-r--r-- | globals.cginc | 14 | ||||
| -rw-r--r-- | tessellation.cginc | 2 | ||||
| -rw-r--r-- | yum_lighting.cginc | 2 | ||||
| -rw-r--r-- | yum_pbr.cginc | 58 |
10 files changed, 138 insertions, 6 deletions
@@ -147,7 +147,7 @@ v2f vert(appdata v) { #endif
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.objPos = v.vertex;
- o.eyeVec.xyz = normalize(o.worldPos - _WorldSpaceCameraPos);
+ o.eyeVec.xyz = o.worldPos - _WorldSpaceCameraPos;
o.eyeVec.w = 1;
// These are used to convert normals from tangent space to world space.
diff --git a/2ner.shader b/2ner.shader index 42d9b78..258db61 100644 --- a/2ner.shader +++ b/2ner.shader @@ -847,6 +847,18 @@ Shader "yum_food/2ner" [HideInInspector] m_end_False_Color_Visualization("False color", Float) = 0 //endex + //ifex _SSAO_Enabled==0 + [HideInInspector] m_start_SSAO("SSAO", Float) = 0 + [ThryToggle(_SSAO)] _SSAO_Enabled("Enable", Float) = 0 + _SSAO_Radius("Radius", Float) = 1.0 + _SSAO_Samples("Samples", Float) = 5 + _SSAO_Strength("Strength", Float) = 1 + _SSAO_Noise("Noise", 2D) = "black" {} + _SSAO_Bias("Bias", Float) = 0.0 + _SSAO_Frame_Counter("Frame counter", Float) = 0.0 + [HideInInspector] m_end_SSAO("SSAO", Float) = 0 + //endex + //ifex _Letter_Grid_Enabled==0 [HideInInspector] m_start_Letter_Grid("Letter grid", Float) = 0 [ThryToggle(_LETTER_GRID)] _Letter_Grid_Enabled("Enable", Float) = 0 diff --git a/audiolink.cginc b/audiolink.cginc index bb8de54..68ddb60 100644 --- a/audiolink.cginc +++ b/audiolink.cginc @@ -1,7 +1,7 @@ #ifndef __AUDIOLINK #define __AUDIOLINK -#if defined(_SHATTER_WAVE_AUDIOLINK) || defined(_VERTEX_DOMAIN_WARPING_AUDIOLINK) +#if defined(_SHATTER_WAVE_AUDIOLINK) || defined(_VERTEX_DOMAIN_WARPING_AUDIOLINK) || defined(_SSAO) #include "Third_Party/AudioLink.cginc" #endif diff --git a/cnlohr.cginc b/cnlohr.cginc index ce3e883..2a03516 100644 --- a/cnlohr.cginc +++ b/cnlohr.cginc @@ -2,6 +2,7 @@ #define __CNLOHR_INC
#include "globals.cginc"
+#include "interpolators.cginc"
/*
* MIT License
@@ -58,4 +59,49 @@ bool isVR() { #endif
}
+float GetLinearZFromZDepth_WorksWithMirrors(float zDepthFromMap, float2 screenUV)
+{
+ #if defined(UNITY_REVERSED_Z)
+ zDepthFromMap = 1 - zDepthFromMap;
+
+ // When using a mirror, the far plane is whack. This just checks for it and aborts.
+ if( zDepthFromMap >= 1.0 ) return _ProjectionParams.z;
+ #endif
+
+ float4 clipPos = float4(screenUV.xy, zDepthFromMap, 1.0);
+ clipPos.xyz = 2.0f * clipPos.xyz - 1.0f;
+ float4 camPos = mul(unity_CameraInvProjection, clipPos);
+ return -camPos.z / camPos.w;
+}
+
+void GetScreenUVAndPerspectiveFactor(float3 worldPos, float4 clipPos, out float2 screen_uv, out float perspective_factor) {
+ float3 full_vec_eye_to_geometry = worldPos - _WorldSpaceCameraPos;
+ float3 world_dir = normalize(worldPos - _WorldSpaceCameraPos);
+ float perspective_divide = 1.0f / clipPos.w;
+ perspective_factor = length(full_vec_eye_to_geometry * perspective_divide);
+ screen_uv = clipPos.xy * perspective_divide;
+}
+
+#if defined(_SSAO)
+float GetDepthOfWorldPos(float3 worldPos)
+{
+ float3 full_vec_eye_to_geometry = worldPos - _WorldSpaceCameraPos;
+ float4 objPos = mul(unity_WorldToObject, float4(worldPos, 1));
+ float4 clipPos = UnityObjectToClipPos(objPos);
+
+ float2 suv = clipPos * float2(0.5, 0.5 * _ProjectionParams.x);
+ float2 screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * clipPos.w, clipPos.w);
+
+ 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;
+}
+#endif
+
#endif // __CNLOHR_INC
diff --git a/features.cginc b/features.cginc index 4bb5594..5fcdfbf 100644 --- a/features.cginc +++ b/features.cginc @@ -204,6 +204,10 @@ #pragma shader_feature_local _3D_SDF //endex +//ifex _SSAO_Enabled==0 +#pragma shader_feature_local _SSAO +//endex + //ifex _False_Color_Visualization_Enabled==0 #pragma shader_feature_local _FALSE_COLOR_VISUALIZATION //endex diff --git a/glitter.cginc b/glitter.cginc index e31bc5c..a8e6aad 100644 --- a/glitter.cginc +++ b/glitter.cginc @@ -69,7 +69,7 @@ float4 getGlitter(v2f i, GlitterParams params, float3 normal) { c_acc = c + (1 - c) * c_acc;
}
#if defined(_GLITTER_ANGLE_LIMIT)
- float VdotN = dot(-i.eyeVec.xyz, normal);
+ float VdotN = dot(-normalize(i.eyeVec.xyz), normal);
float angle_mask = smoothstep(
cos(params.angle_limit * PI),
cos(params.angle_limit * (1 - params.angle_limit_transition_width) * PI),
diff --git a/globals.cginc b/globals.cginc index aeedad5..1d9f291 100644 --- a/globals.cginc +++ b/globals.cginc @@ -3,6 +3,11 @@ #include "features.cginc"
+#if defined(_SSAO)
+UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
+float4 _CameraDepthTexture_TexelSize;
+#endif
+
SamplerState point_repeat_s;
SamplerState linear_repeat_s;
SamplerState linear_clamp_s;
@@ -521,4 +526,13 @@ float _Custom30_BasicPlatform_Core_D; float3 _Custom30_BasicPlatform_Chamfer_Size;
#endif // _CUSTOM30_BASICPLATFORM_CHAMFER
+#if defined(_SSAO)
+float _SSAO_Radius;
+float _SSAO_Samples;
+float _SSAO_Strength;
+texture2D _SSAO_Noise;
+float4 _SSAO_Noise_TexelSize;
+float _SSAO_Bias;
+#endif // _SSAO
+
#endif // __GLOBALS_INC
diff --git a/tessellation.cginc b/tessellation.cginc index 526d2e3..3665558 100644 --- a/tessellation.cginc +++ b/tessellation.cginc @@ -149,7 +149,7 @@ v2f domain( o.pos = UnityObjectToClipPos(o.objPos); o.worldPos = mul(unity_ObjectToWorld, o.objPos).xyz; - o.eyeVec.xyz = normalize(o.worldPos - _WorldSpaceCameraPos); + o.eyeVec.xyz = o.worldPos - _WorldSpaceCameraPos; o.eyeVec.w = 1; // TODO what about UNITY_LIGHTING_COORDS(7,8) and instance id and shit? diff --git a/yum_lighting.cginc b/yum_lighting.cginc index d7afcef..dab631a 100644 --- a/yum_lighting.cginc +++ b/yum_lighting.cginc @@ -234,7 +234,7 @@ YumLighting GetYumLighting(v2f i, YumPbr pbr) { YumLighting light = (YumLighting) 0;
// normalize has no visibile impact in test scene
- light.view_dir = -i.eyeVec.xyz;
+ light.view_dir = -normalize(i.eyeVec.xyz);
light.dir = getDirectLightDirection(i);
diff --git a/yum_pbr.cginc b/yum_pbr.cginc index e1928f4..6fa12bb 100644 --- a/yum_pbr.cginc +++ b/yum_pbr.cginc @@ -1,6 +1,8 @@ #ifndef __YUM_PBR #define __YUM_PBR +#include "audiolink.cginc" +#include "cnlohr.cginc" #include "decals.cginc" #include "features.cginc" #include "filamented.cginc" @@ -133,9 +135,63 @@ YumPbr GetYumPbr(v2f i) { applyDecals(i, result.albedo, normal_tangent, result.metallic, result.smoothness); propagateRoughness(result.smoothness, result.roughness_perceptual, result.roughness); - float3x3 tangentToWorld = float3x3(i.tangent, i.binormal, i.normal); + 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; |
