summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-06-03 18:24:43 -0700
committeryum <yum.food.vr@gmail.com>2025-06-03 18:25:12 -0700
commita8d6d469d57349da515759270eb31a242c795951 (patch)
tree814c86255ff287749df60100453d2b4e10945cd6
parent1dca0fed44b9c8eb8a6f3131f54c10f1323ed5a8 (diff)
Begin work on SSAO - very buggy!
-rw-r--r--2ner.cginc2
-rw-r--r--2ner.shader12
-rw-r--r--audiolink.cginc2
-rw-r--r--cnlohr.cginc46
-rw-r--r--features.cginc4
-rw-r--r--glitter.cginc2
-rw-r--r--globals.cginc14
-rw-r--r--tessellation.cginc2
-rw-r--r--yum_lighting.cginc2
-rw-r--r--yum_pbr.cginc58
10 files changed, 138 insertions, 6 deletions
diff --git a/2ner.cginc b/2ner.cginc
index c0f2ac1..6cea852 100644
--- a/2ner.cginc
+++ b/2ner.cginc
@@ -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;