summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-01-24 16:54:26 -0800
committeryum <yum.food.vr@gmail.com>2026-01-24 16:54:26 -0800
commitd0c27e80cefa593641f3525ef23e7fc5631b136b (patch)
tree2894d04cac14f1403f49d52f8a742440cb8cfbf1
parent4885fb42bd42f5dfb7fdc198bd0cc42be7959aaf (diff)
Add anisotropic reflections
-rw-r--r--2ner.cginc1200
-rw-r--r--2ner.shader42
-rw-r--r--UnityStandardMeta.cginc3
-rw-r--r--data.cginc3
-rw-r--r--features.cginc4
-rw-r--r--filamented.cginc21
-rw-r--r--globals.cginc4
-rw-r--r--interpolators.cginc2
-rw-r--r--yum_brdf.cginc27
-rw-r--r--yum_lighting.cginc9
-rw-r--r--yum_pbr.cginc4
11 files changed, 692 insertions, 627 deletions
diff --git a/2ner.cginc b/2ner.cginc
index c886fe6..87d9d29 100644
--- a/2ner.cginc
+++ b/2ner.cginc
@@ -1,600 +1,600 @@
-#ifndef __2NER_INC
-#define __2NER_INC
-
-#define HANDLE_SHADOWS_BLENDING_IN_GI
-
-#include "UnityStandardCoreMinimal.cginc"
-#include "UnityCG.cginc"
-#include "UnityLightingCommon.cginc"
-#include "AutoLight.cginc"
-
-#include "custom30.cginc"
-#include "eyes.cginc"
-#include "face_me.cginc"
-#include "false_color_visualization.cginc"
-#include "features.cginc"
-#include "fog.cginc"
-#include "globals.cginc"
-#include "harnack_tracing.cginc"
-#include "interpolators.cginc"
-#include "letter_grid.cginc"
-#include "matcaps.cginc"
-#include "math.cginc"
-#include "poi.cginc"
-#include "shatter_wave.cginc"
-#include "ssao.cginc"
-#include "ssfd.cginc"
-#include "tessellation.cginc"
-#include "trochoid.cginc"
-#include "unigram_letter_grid.cginc"
-#include "vertex_domain_warping.cginc"
-#include "yum_brdf.cginc"
-#include "yum_pbr.cginc"
-#include "yum_lighting.cginc"
-
-v2f vert(appdata v) {
-#if defined(OUTLINE_PASS) && !defined(_OUTLINES)
- // The outline pass will be entirely elided when locked. This just lets us
- // hide outlines when not locked.
- return (v2f) (0.0/0.0);
-#endif
-#if defined(_RAYMARCHED_FOG) && !defined(FORWARD_BASE_PASS)
- return (v2f) (0.0/0.0);
-#endif
-#if defined(DEPTH_PREPASS) && !defined(_DEPTH_PREPASS)
- return (v2f) (0.0/0.0);
-#endif
-#if defined(EXTRA_STENCIL_COLOR_PASS) && !defined(_EXTRA_STENCIL_COLOR_PASS)
- return (v2f) (0.0/0.0);
-#endif
-#if defined(MASKED_STENCIL1_PASS)
-#if !defined(_MASKED_STENCIL1)
- return (v2f) (0.0/0.0);
-#endif
- float masked_stencil1_mask = _Masked_Stencil1_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
- [branch]
- if (masked_stencil1_mask < 0.5) {
- return (v2f) (0.0/0.0);
- }
-#endif
-#if defined(MASKED_STENCIL2_PASS)
-#if !defined(_MASKED_STENCIL2)
- return (v2f) (0.0/0.0);
-#endif
- float masked_stencil2_mask = _Masked_Stencil2_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
- [branch]
- if (masked_stencil2_mask < 0.5) {
- return (v2f) (0.0/0.0);
- }
-#endif
-#if defined(MASKED_STENCIL3_PASS)
-#if !defined(_MASKED_STENCIL3)
- return (v2f) (0.0/0.0);
-#endif
- float masked_stencil3_mask = _Masked_Stencil3_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
- [branch]
- if (masked_stencil3_mask < 0.5) {
- return (v2f) (0.0/0.0);
- }
-#endif
-#if defined(MASKED_STENCIL4_PASS)
-#if !defined(_MASKED_STENCIL4)
- return (v2f) (0.0/0.0);
-#endif
- float masked_stencil4_mask = _Masked_Stencil4_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
- [branch]
- if (masked_stencil4_mask < 0.5) {
- return (v2f) (0.0/0.0);
- }
-#endif
-#if defined(EXTRA_STENCIL_COLOR_PASS) && !defined(_EXTRA_STENCIL_COLOR_PASS)
- return (v2f) (0.0/0.0);
-#endif
-#if defined(FORWARD_ADD_PASS) & defined(_UNLIT)
- return (v2f) (0.0/0.0);
-#endif
-
- v2f o;
-
- UNITY_SETUP_INSTANCE_ID(v);
- UNITY_INITIALIZE_OUTPUT(v2f, o);
- UNITY_TRANSFER_INSTANCE_ID(v, o);
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
-
-#if defined(_SPHERIZE)
- {
- float3 tgt_normal = normalize(o.objPos.xyz);
- float3 tgt_tangent = normalize(float3(tgt_normal.y, -tgt_normal.x, 0));
- float3 tgt_pos = tgt_normal * _Spherize_Radius;
- v.normal = normalize(lerp(v.normal, tgt_normal, _Spherize_Strength));
- v.vertex.xyz = lerp(v.vertex.xyz, tgt_pos, _Spherize_Strength);
- }
-#endif
-#if !defined(_TESSELLATION) && defined(_SHATTER_WAVE)
- shatterWaveVert(v.vertex.xyz, v.normal, v.tangent);
-#endif
-
-#if defined(_VERTEX_DOMAIN_WARPING)
- v.vertex.xyz = domainWarpVertexPosition(v.vertex.xyz);
-#endif
-
-#if defined(_TROCHOID)
- o.orig_pos = v.vertex.xyz;
- v.vertex.xyz = trochoid_map(v.vertex.xyz);
-#endif
-
-#if defined(OUTLINE_PASS)
- [branch]
- if (!_Outlines_Enabled_Dynamic) {
- return (v2f) (0.0/0.0);
- }
-#if defined(_OUTLINE_MASK)
- float thickness = _Outline_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
- thickness = (_Outline_Mask_Invert == 0 ? thickness : 1 - thickness);
-#else
- float thickness = 1;
-#endif
- v.vertex.xyz += _Outline_Width * v.normal * thickness;
- v.normal *= -1;
- v.tangent *= -1;
-#endif // OUTLINE_PASS
-
-#if defined(_FACE_ME)
- face_me(v);
-#endif
-
-#if defined(_FOCAL_LENGTH_CONTROL)
- [branch]
- if (_Focal_Length_Enabled_Dynamic) {
- float4 fl_worldPos_unscaled = mul(unity_ObjectToWorld, v.vertex);
- float4 fl_viewPos_unscaled = mul(UNITY_MATRIX_V, fl_worldPos_unscaled);
-
- float4 fl_objPos = float4(v.vertex.xyz * _Focal_Length_Multiplier, v.vertex.w);
- float4 fl_worldPos = mul(unity_ObjectToWorld, fl_objPos);
- float4 fl_viewPos = mul(UNITY_MATRIX_V, fl_worldPos);
- fl_viewPos.xy /= _Focal_Length_Multiplier;
-
- float2 fl_compensation = fl_viewPos_unscaled.xy - fl_viewPos.xy;
- fl_viewPos.xy += fl_compensation;
-
- o.pos = mul(UNITY_MATRIX_P, fl_viewPos);
- } else {
- o.pos = UnityObjectToClipPos(v.vertex);
- }
-#else
- o.pos = UnityObjectToClipPos(v.vertex);
-#endif
-
-#if defined(_TESSELLATION)
- o.tpos = v.vertex;
-#endif
- o.uv01.xy = v.uv0;
-#if defined(LIGHTMAP_ON)
- o.uv01.zw = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;
-#else
- o.uv01.zw = v.uv1;
-#endif
- o.uv23.xy = v.uv2;
- o.uv23.zw = v.uv3;
-#if defined(_MIRROR_UVS_IN_MIRROR)
- [branch]
- if (isInMirror()) {
- o.uv01.x = 1.0 - o.uv01.x;
- o.uv01.z = 1.0 - o.uv01.z;
- o.uv23.x = 1.0 - o.uv23.x;
- o.uv23.z = 1.0 - o.uv23.z;
- }
-#endif
- o.objPos = v.vertex;
-
- // These are used to convert normals from tangent space to world space.
- o.normal = v.normal;
- o.tangent = v.tangent.xyz;
-
- UNITY_TRANSFER_LIGHTING(o, v.uv1);
- UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o, o.pos);
- TRANSFER_SHADOW(o);
-#if defined(SHADOW_CASTER_PASS)
- TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
-#endif
-
-#if defined(V2F_COLOR)
- // Vertex color
- o.color = v.color;
-#endif
-
- // Calculate vertex lights
- #ifdef VERTEXLIGHT_ON
- float3 worldPos = mul(unity_ObjectToWorld, v.vertex);
- #if defined(_WRAPPED_LIGHTING)
- o.vertexLight = Shade4PointLightsWrapped(
- unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
- unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
- unity_4LightAtten0, worldPos, o.normal, _Wrap_NoL_Diffuse_Strength);
- #else
- o.vertexLight = Shade4PointLights(
- unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
- unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
- unity_4LightAtten0, worldPos, o.normal);
- #endif
- #else
- o.vertexLight = 0;
- #endif
-
- return o;
-}
-
-//ifex _Fur_Enabled==0
-[maxvertexcount(30)]
-void geom(triangle v2f input[3], inout TriangleStream<v2f> stream) {
-#if defined(_FUR)
-#if defined(_FUR_MASK)
- float fur_mask = _Fur_Mask.SampleLevel(bilinear_repeat_s, input[0].uv01.xy * _Fur_Mask_ST.xy, 0);
-#else
- float fur_mask = 1;
-#endif
-
- stream.Append(input[0]);
- stream.Append(input[1]);
- stream.Append(input[2]);
- stream.RestartStrip();
-
- [branch]
- if (fur_mask < 0.5) {
- return;
- }
-
- float3 gravDirObj = normalize(mul(unity_WorldToObject, float3(0, -1, 0)));
-
- // Compute gravity direction minus component that would compress this shell.
- // Could compute average normal but this is probably good enough.
- float3 gravDirNoRegress = gravDirObj - min(0, input[0].normal * dot(gravDirObj, input[0].normal));
-
- float3 worldPos = mul(unity_ObjectToWorld, input[0].objPos).xyz;
- float radius = length(_WorldSpaceCameraPos - worldPos);
- uint fur_layers = lerp(_Fur_Layers - 3, 5, saturate((radius - _Fur_Min_Dist) / (_Fur_Max_Dist - _Fur_Min_Dist)));
-
- [loop]
- for (uint layer = 0; layer < fur_layers; layer++) {
- float t = (float) layer / (float) max(fur_layers - 4, 1);
-
- float offset = t * _Fur_Thickness;
-
- v2f o = input[layer % 3];
- float3 normal_ws = UnityObjectToWorldNormal(o.normal);
-
- float3 dir = lerp(o.normal, gravDirNoRegress, t * t * _Fur_Gravity_Strength);
-
- o.objPos.xyz += dir * offset;
-
- float3 worldPos = mul(unity_ObjectToWorld, o.objPos).xyz;
- o.pos = UnityWorldToClipPos(worldPos);
- o.vertexLight.w = t;
- stream.Append(o);
- }
-#else
- stream.Append(input[0]);
- stream.Append(input[1]);
- stream.Append(input[2]);
- stream.RestartStrip();
-#endif // _FUR
-}
-//endex
-
-float4 frag(v2f i, uint facing : SV_IsFrontFace
-#if defined(_HARNACK_TRACING) || defined(_SHATTER_WAVE) || defined(_VERTEX_DOMAIN_WARPING) || (defined(_CUSTOM30) && !defined(_DEPTH_PREPASS)) || defined(_RAYMARCHED_FOG) || defined(_TESSELLATION_HEIGHTMAP)
- , out float depth : SV_DepthLessEqual
-#endif
-) : SV_Target {
-
- UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy);
- UNITY_SETUP_INSTANCE_ID(i);
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
-
-#if defined(_CUSTOM30) && defined(_DEPTH_PREPASS) && !defined(FORWARD_BASE_PASS)
- return 0;
-#endif
-
- i.normal *= facing ? 1 : -1;
- i.normal = UnityObjectToWorldNormal(i.normal);
- i.tangent = UnityObjectToWorldNormal(i.tangent);
-
- // Not necessarily normalized after interpolation
- i.normal = normalize(i.normal);
- i.tangent = normalize(i.tangent);
-
- f2f f = (f2f) 0;
- f.worldPos = mul(unity_ObjectToWorld, i.objPos);
- f.binormal = cross(i.tangent, i.normal);
- f.eyeVec = f.worldPos - _WorldSpaceCameraPos;
- f.viewDir = normalize(f.eyeVec);
- f.tbn = float3x3(
- i.tangent,
- f.binormal,
- i.normal
- );
-
-#if defined(_RAYMARCHED_FOG)
- {
- // Many fields are overspecified as .rgb or .xyz. This is because thry's
- // shader locker will inline those fields (incorrectly) as float4. Unity's
- // shader compiler doesn't like that, demanding exact type correspondence.
- // Overspecifying gets around the issue.
-
- FogParams fog_params = {
- _Raymarched_Fog_Color.rgb,
- _Raymarched_Fog_Direct_Light_Intensity,
- _Raymarched_Fog_Indirect_Light_Intensity,
- _Raymarched_Fog_Steps,
- _Raymarched_Fog_Y_Cutoff,
- _Raymarched_Fog_Dithering_Noise,
- _Raymarched_Fog_Dithering_Noise_TexelSize,
- _Raymarched_Fog_Density_Noise,
- _Raymarched_Fog_Density_Noise_Scale,
- _Raymarched_Fog_Velocity.xyz,
- _Raymarched_Fog_Mean_Free_Path,
- _Raymarched_Fog_Albedo,
- _Raymarched_Fog_G,
- _Raymarched_Fog_Height_Scale,
- _Raymarched_Fog_Height_Offset,
- _Raymarched_Fog_Turbulence,
- _Raymarched_Fog_Step_Size,
- _Raymarched_Fog_Step_Growth,
- #if defined(_RAYMARCHED_FOG_EMITTER_TEXTURE)
- _Raymarched_Fog_Emitter_Texture,
- _Raymarched_Fog_Emitter_Texture_TexelSize,
- _Raymarched_Fog_Emitter_Texture_World_Pos.xyz,
- normalize(_Raymarched_Fog_Emitter_Texture_World_Normal).xyz,
- normalize(_Raymarched_Fog_Emitter_Texture_World_Tangent).xyz,
- normalize(cross(_Raymarched_Fog_Emitter_Texture_World_Normal, _Raymarched_Fog_Emitter_Texture_World_Tangent)).xyz,
- _Raymarched_Fog_Emitter_Texture_World_Scale.xy,
- 1.0f / _Raymarched_Fog_Emitter_Texture_World_Scale.xy,
- _Raymarched_Fog_Emitter_Texture_Luminance,
- _Raymarched_Fog_Emitter_Texture_Intensity,
- #endif
- #if defined(_RAYMARCHED_FOG_EMITTER_TEXTURE_WARPING)
- _Raymarched_Fog_Emitter_Texture_Warping_Octaves,
- _Raymarched_Fog_Emitter_Texture_Warping_Strength,
- _Raymarched_Fog_Emitter_Texture_Warping_Scale,
- _Raymarched_Fog_Emitter_Texture_Warping_Speed,
- #endif
- #if defined(_RAYMARCHED_FOG_DENSITY_EXPONENT)
- _Raymarched_Fog_Density_Exponent,
- #endif
- };
- FogResult fog_result = raymarched_fog(i, f, fog_params);
- depth = fog_result.depth;
- return fog_result.color;
- }
-#endif
-
-#if defined(_SHATTER_WAVE) || defined(_SCREEN_SPACE_NORMALS)
- calcNormalInScreenSpace(i.normal, i.objPos);
- i.normal = UnityObjectToWorldNormal(i.normal);
-#endif
-
-#if defined(_SHATTER_WAVE) || defined(_VERTEX_DOMAIN_WARPING) || defined(_TESSELLATION_HEIGHTMAP)
- {
- [branch]
- if (
- false
-#if defined(_SHATTER_WAVE)
- || any(_Shatter_Wave_Amplitude > 1E-4)
-#endif
-#if defined(_VERTEX_DOMAIN_WARPING)
- || _Vertex_Domain_Warping_Octaves > 0.1
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_0)
- || _Tessellation_Heightmap_0_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_1)
- || _Tessellation_Heightmap_1_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_2)
- || _Tessellation_Heightmap_2_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_3)
- || _Tessellation_Heightmap_3_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_4)
- || _Tessellation_Heightmap_4_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_5)
- || _Tessellation_Heightmap_5_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_6)
- || _Tessellation_Heightmap_6_Scale > 1E-4
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_7)
- || _Tessellation_Heightmap_7_Scale > 1E-4
-#endif
- ) {
- float4 clip_pos = UnityObjectToClipPos(i.objPos);
- depth = clip_pos.z / clip_pos.w;
- } else {
- // Perspective division takes place before the fragment shader, so we
- // don't have to divide again.
- depth = i.pos.z;
- }
- }
-#endif
-
-#if defined(_EYE_EFFECT_00)
- EyeEffectOutput eye_effect_00 = EyeEffect_00(i);
- i.uv01.xy = eye_effect_00.uv;
-#endif
-
-#if defined(_CUSTOM30)
-#if defined(FORWARD_BASE_PASS) || (!defined(_DEPTH_PREPASS) && defined(SHADOW_CASTER_PASS))
-#if defined(_CUSTOM30_BASICCUBE)
- Custom30Output c30_out = BasicCube(i);
-#elif defined(_CUSTOM30_BASICWEDGE)
- Custom30Output c30_out = BasicWedge(i);
-#elif defined(_CUSTOM30_BASICPLATFORM)
- Custom30Output c30_out = BasicPlatform(i);
-#elif defined(_CUSTOM30_RAINBOW)
- Custom30Output c30_out = Rainbow(i);
-#else
- Custom30Output c30_out = (Custom30Output) 0;
-#endif
- i.normal = c30_out.normal;
- float4 c30_clipPos = UnityObjectToClipPos(i.objPos);
- float4 c30_screenPos = ComputeScreenPos(c30_clipPos);
- i.pos = c30_screenPos;
-#if !defined(_DEPTH_PREPASS)
- depth = c30_out.depth;
-#endif
-#endif
-#endif
-
- float ssao = 1;
-#if defined(_SSAO)
- float2 debug;
- ssao = get_ssao(i, f, debug);
-#endif
- YumPbr pbr = GetYumPbr(i, f);
- pbr.albedo.rgb *= ssao;
-
-#if defined(META_PASS)
-#if defined(_EMISSION)
- return pbr.emission;
-#else
- return 0;
-#endif
-#endif
-
-#if defined(_TROCHOID)
- float3 normal_obj = trochoid_normal(i.orig_pos);
-
- // We need tangents that are perpendicular to the new normal.
- // A common way to generate them is to cross with a fixed "up" vector.
- float3 tangent_obj = normalize(cross(normal_obj, float3(0, 1, 0)));
- float3 binormal_obj = cross(normal_obj, tangent_obj);
-
- i.normal = UnityObjectToWorldNormal(normal_obj);
- i.tangent = float4(normalize(mul((float3x3)unity_ObjectToWorld, tangent_obj)), 1);
- i.binormal = normalize(mul((float3x3)unity_ObjectToWorld, binormal_obj));
- i.normal *= facing ? 1 : -1;
-
- float theta = 1 - atan2(i.orig_pos.y, i.orig_pos.x) / PI;
- float3 color = _Trochoid_Color_Ramp.SampleLevel(linear_clamp_s, float2(theta, 0.5), 0).rgb;
- pbr.albedo.xyz = color;
-#endif
-
-#if defined(_HARNACK_TRACING)
- HarnackTracingOutput harnack_output = HarnackTracing(i);
- pbr.albedo = float4(1, 1, 1, 0.2);
- pbr.smoothness = 0.95;
- pbr.roughness_perceptual = 0.05;
- pbr.roughness = pbr.roughness_perceptual * pbr.roughness_perceptual;
- pbr.metallic = 0;
-#endif
-
-#if defined(_SSFD)
- float ssfd_mask = ssfd(i.uv01.xy, _SSFD_Scale, _SSFD_Max_Fwidth, 0, _SSFD_Noise);
- pbr.albedo *= (ssfd_mask > _SSFD_Threshold);
-#endif
-
-#if defined(OUTLINE_PASS)
- pbr.smoothness = 0;
- pbr.roughness = 1;
- pbr.roughness_perceptual = 1;
- pbr.metallic = 0;
-#endif
-
-#if defined(_EYE_EFFECT_00)
- pbr.normal = eye_effect_00.normal;
-#endif
-
-#if defined(_LETTER_GRID)
- LetterGridOutput letter_grid_output = LetterGrid(i);
- pbr.albedo.rgb = lerp(pbr.albedo.rgb, letter_grid_output.albedo, letter_grid_output.albedo.a);
- pbr.metallic = lerp(pbr.metallic, letter_grid_output.metallic, letter_grid_output.albedo.a);
- pbr.roughness = lerp(pbr.roughness, letter_grid_output.roughness, letter_grid_output.albedo.a);
-#endif
-
-#if defined(_UNIGRAM_LETTER_GRID)
- UnigramLetterGridOutput unigram_letter_grid_output = UnigramLetterGrid(i, facing);
- pbr.albedo.rgb = lerp(pbr.albedo.rgb, unigram_letter_grid_output.albedo,
- unigram_letter_grid_output.albedo.a);
- pbr.metallic = lerp(pbr.metallic, unigram_letter_grid_output.metallic,
- unigram_letter_grid_output.albedo.a);
- pbr.roughness = lerp(pbr.roughness, unigram_letter_grid_output.roughness,
- unigram_letter_grid_output.albedo.a);
-#endif
-
- [branch]
- if (_Mode == 1) {
- clip(pbr.albedo.a - _Clip);
- pbr.albedo.a = 1;
- }
-
-#if defined(EXTRA_STENCIL_COLOR_PASS) && defined(_EXTRA_STENCIL_COLOR_PASS)
- pbr.albedo = _ExtraStencilColor;
-#endif
-
-#if defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS) || defined(OUTLINE_PASS) || defined(EXTRA_STENCIL_COLOR_PASS)
- YumLighting l = GetYumLighting(i, f, pbr);
-
-#if defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS)
- applyMatcapsAndRimLighting(i, f, pbr, l);
- l.diffuse = max(0, l.diffuse);
- l.specular = max(0, l.specular);
-#endif
-
- pbr.albedo.rgb = visualizeInFalseColor(pbr.albedo.rgb);
- pbr.albedo.rgb = applyQuasiShadows(pbr.albedo.rgb, l);
-
-#if defined(_UNLIT)
- float4 lit = pbr.albedo;
-#else
- float4 lit = YumBRDF(i, f, l, pbr);
-#endif
-
-#if defined(_HARNACK_TRACING)
- pbr.albedo = harnack_output.color;
- pbr.smoothness = 0;
- pbr.roughness = 1;
- pbr.roughness_perceptual = 1;
- pbr.metallic = 0;
- pbr.normal = harnack_output.normal;
- l.NoL = saturate(dot(pbr.normal, l.dir));
- l.NoL_wrapped_s = l.NoL;
- l.NoL_wrapped_d = l.NoL;
- float4 harnack_lit = YumBRDF(i, l, pbr);
- //lit = alphaBlend(harnack_lit, lit);
- lit = harnack_lit;
- {
- float4 clip_pos = mul(UNITY_MATRIX_VP, float4(harnack_output.worldPos, 1.0));
- depth = clip_pos.z / clip_pos.w;
- }
-#endif
-
-#if defined(_EMISSION) || (defined(_GLITTER) && defined(FORWARD_BASE_PASS)) || defined(OUTLINE_PASS)
- lit.rgb += pbr.emission;
-#endif
-#if defined(_LETTER_GRID)
- lit.rgb += letter_grid_output.emission * letter_grid_output.albedo.a;
-#endif
-#if defined(_UNIGRAM_LETTER_GRID)
- lit.rgb += unigram_letter_grid_output.emission * unigram_letter_grid_output.albedo.a;
-#endif
-
- UNITY_EXTRACT_FOG_FROM_EYE_VEC(i);
- UNITY_APPLY_FOG(_unity_fogCoord, lit.rgb);
-
- return lit;
-#elif defined(SHADOW_CASTER_PASS)
- // Apply dithering for LOD if needed
- #ifdef LOD_FADE_CROSSFADE
- UnityApplyDitherCrossFade(i.pos.xy);
- #endif
-
- // Output proper shadow data
- SHADOW_CASTER_FRAGMENT(i)
-#elif defined(MASKED_STENCIL1_PASS) || defined(MASKED_STENCIL2_PASS) || defined(MASKED_STENCIL3_PASS) || defined(MASKED_STENCIL4_PASS) || defined(DEPTH_PREPASS)
- return 0;
-#endif
-}
-
-#endif // __2NER_INC
+#ifndef __2NER_INC
+#define __2NER_INC
+
+#define HANDLE_SHADOWS_BLENDING_IN_GI
+
+#include "UnityCG.cginc"
+#include "UnityStandardCoreMinimal.cginc"
+#include "UnityLightingCommon.cginc"
+#include "AutoLight.cginc"
+
+#include "custom30.cginc"
+#include "eyes.cginc"
+#include "face_me.cginc"
+#include "false_color_visualization.cginc"
+#include "features.cginc"
+#include "fog.cginc"
+#include "globals.cginc"
+#include "harnack_tracing.cginc"
+#include "interpolators.cginc"
+#include "letter_grid.cginc"
+#include "matcaps.cginc"
+#include "math.cginc"
+#include "poi.cginc"
+#include "shatter_wave.cginc"
+#include "ssao.cginc"
+#include "ssfd.cginc"
+#include "tessellation.cginc"
+#include "trochoid.cginc"
+#include "unigram_letter_grid.cginc"
+#include "vertex_domain_warping.cginc"
+#include "yum_brdf.cginc"
+#include "yum_pbr.cginc"
+#include "yum_lighting.cginc"
+
+v2f vert(appdata v) {
+#if defined(OUTLINE_PASS) && !defined(_OUTLINES)
+ // The outline pass will be entirely elided when locked. This just lets us
+ // hide outlines when not locked.
+ return (v2f) (0.0/0.0);
+#endif
+#if defined(_RAYMARCHED_FOG) && !defined(FORWARD_BASE_PASS)
+ return (v2f) (0.0/0.0);
+#endif
+#if defined(DEPTH_PREPASS) && !defined(_DEPTH_PREPASS)
+ return (v2f) (0.0/0.0);
+#endif
+#if defined(EXTRA_STENCIL_COLOR_PASS) && !defined(_EXTRA_STENCIL_COLOR_PASS)
+ return (v2f) (0.0/0.0);
+#endif
+#if defined(MASKED_STENCIL1_PASS)
+#if !defined(_MASKED_STENCIL1)
+ return (v2f) (0.0/0.0);
+#endif
+ float masked_stencil1_mask = _Masked_Stencil1_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
+ [branch]
+ if (masked_stencil1_mask < 0.5) {
+ return (v2f) (0.0/0.0);
+ }
+#endif
+#if defined(MASKED_STENCIL2_PASS)
+#if !defined(_MASKED_STENCIL2)
+ return (v2f) (0.0/0.0);
+#endif
+ float masked_stencil2_mask = _Masked_Stencil2_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
+ [branch]
+ if (masked_stencil2_mask < 0.5) {
+ return (v2f) (0.0/0.0);
+ }
+#endif
+#if defined(MASKED_STENCIL3_PASS)
+#if !defined(_MASKED_STENCIL3)
+ return (v2f) (0.0/0.0);
+#endif
+ float masked_stencil3_mask = _Masked_Stencil3_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
+ [branch]
+ if (masked_stencil3_mask < 0.5) {
+ return (v2f) (0.0/0.0);
+ }
+#endif
+#if defined(MASKED_STENCIL4_PASS)
+#if !defined(_MASKED_STENCIL4)
+ return (v2f) (0.0/0.0);
+#endif
+ float masked_stencil4_mask = _Masked_Stencil4_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
+ [branch]
+ if (masked_stencil4_mask < 0.5) {
+ return (v2f) (0.0/0.0);
+ }
+#endif
+#if defined(EXTRA_STENCIL_COLOR_PASS) && !defined(_EXTRA_STENCIL_COLOR_PASS)
+ return (v2f) (0.0/0.0);
+#endif
+#if defined(FORWARD_ADD_PASS) & defined(_UNLIT)
+ return (v2f) (0.0/0.0);
+#endif
+
+ v2f o;
+
+ UNITY_SETUP_INSTANCE_ID(v);
+ UNITY_INITIALIZE_OUTPUT(v2f, o);
+ UNITY_TRANSFER_INSTANCE_ID(v, o);
+ UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
+
+#if defined(_SPHERIZE)
+ {
+ float3 tgt_normal = normalize(o.objPos.xyz);
+ float3 tgt_tangent = normalize(float3(tgt_normal.y, -tgt_normal.x, 0));
+ float3 tgt_pos = tgt_normal * _Spherize_Radius;
+ v.normal = normalize(lerp(v.normal, tgt_normal, _Spherize_Strength));
+ v.vertex.xyz = lerp(v.vertex.xyz, tgt_pos, _Spherize_Strength);
+ }
+#endif
+#if !defined(_TESSELLATION) && defined(_SHATTER_WAVE)
+ shatterWaveVert(v.vertex.xyz, v.normal, v.tangent);
+#endif
+
+#if defined(_VERTEX_DOMAIN_WARPING)
+ v.vertex.xyz = domainWarpVertexPosition(v.vertex.xyz);
+#endif
+
+#if defined(_TROCHOID)
+ o.orig_pos = v.vertex.xyz;
+ v.vertex.xyz = trochoid_map(v.vertex.xyz);
+#endif
+
+#if defined(OUTLINE_PASS)
+ [branch]
+ if (!_Outlines_Enabled_Dynamic) {
+ return (v2f) (0.0/0.0);
+ }
+#if defined(_OUTLINE_MASK)
+ float thickness = _Outline_Mask.SampleLevel(linear_repeat_s, v.uv0, 0);
+ thickness = (_Outline_Mask_Invert == 0 ? thickness : 1 - thickness);
+#else
+ float thickness = 1;
+#endif
+ v.vertex.xyz += _Outline_Width * v.normal * thickness;
+ v.normal *= -1;
+ v.tangent *= -1;
+#endif // OUTLINE_PASS
+
+#if defined(_FACE_ME)
+ face_me(v);
+#endif
+
+#if defined(_FOCAL_LENGTH_CONTROL)
+ [branch]
+ if (_Focal_Length_Enabled_Dynamic) {
+ float4 fl_worldPos_unscaled = mul(unity_ObjectToWorld, v.vertex);
+ float4 fl_viewPos_unscaled = mul(UNITY_MATRIX_V, fl_worldPos_unscaled);
+
+ float4 fl_objPos = float4(v.vertex.xyz * _Focal_Length_Multiplier, v.vertex.w);
+ float4 fl_worldPos = mul(unity_ObjectToWorld, fl_objPos);
+ float4 fl_viewPos = mul(UNITY_MATRIX_V, fl_worldPos);
+ fl_viewPos.xy /= _Focal_Length_Multiplier;
+
+ float2 fl_compensation = fl_viewPos_unscaled.xy - fl_viewPos.xy;
+ fl_viewPos.xy += fl_compensation;
+
+ o.pos = mul(UNITY_MATRIX_P, fl_viewPos);
+ } else {
+ o.pos = UnityObjectToClipPos(v.vertex);
+ }
+#else
+ o.pos = UnityObjectToClipPos(v.vertex);
+#endif
+
+#if defined(_TESSELLATION)
+ o.tpos = v.vertex;
+#endif
+ o.uv01.xy = v.uv0;
+#if defined(LIGHTMAP_ON)
+ o.uv01.zw = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;
+#else
+ o.uv01.zw = v.uv1;
+#endif
+ o.uv23.xy = v.uv2;
+ o.uv23.zw = v.uv3;
+#if defined(_MIRROR_UVS_IN_MIRROR)
+ [branch]
+ if (isInMirror()) {
+ o.uv01.x = 1.0 - o.uv01.x;
+ o.uv01.z = 1.0 - o.uv01.z;
+ o.uv23.x = 1.0 - o.uv23.x;
+ o.uv23.z = 1.0 - o.uv23.z;
+ }
+#endif
+ o.objPos = v.vertex;
+
+ // These are used to convert normals from tangent space to world space.
+ o.normal = v.normal;
+ o.tangent = v.tangent;
+
+ UNITY_TRANSFER_LIGHTING(o, v.uv1);
+ UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o, o.pos);
+ TRANSFER_SHADOW(o);
+#if defined(SHADOW_CASTER_PASS)
+ TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
+#endif
+
+#if defined(V2F_COLOR)
+ // Vertex color
+ o.color = v.color;
+#endif
+
+ // Calculate vertex lights
+ #ifdef VERTEXLIGHT_ON
+ float3 worldPos = mul(unity_ObjectToWorld, v.vertex);
+ #if defined(_WRAPPED_LIGHTING)
+ o.vertexLight = Shade4PointLightsWrapped(
+ unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
+ unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
+ unity_4LightAtten0, worldPos, o.normal, _Wrap_NoL_Diffuse_Strength);
+ #else
+ o.vertexLight = Shade4PointLights(
+ unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
+ unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
+ unity_4LightAtten0, worldPos, o.normal);
+ #endif
+ #else
+ o.vertexLight = 0;
+ #endif
+
+ return o;
+}
+
+//ifex _Fur_Enabled==0
+[maxvertexcount(30)]
+void geom(triangle v2f input[3], inout TriangleStream<v2f> stream) {
+#if defined(_FUR)
+#if defined(_FUR_MASK)
+ float fur_mask = _Fur_Mask.SampleLevel(bilinear_repeat_s, input[0].uv01.xy * _Fur_Mask_ST.xy, 0);
+#else
+ float fur_mask = 1;
+#endif
+
+ stream.Append(input[0]);
+ stream.Append(input[1]);
+ stream.Append(input[2]);
+ stream.RestartStrip();
+
+ [branch]
+ if (fur_mask < 0.5) {
+ return;
+ }
+
+ float3 gravDirObj = normalize(mul(unity_WorldToObject, float3(0, -1, 0)));
+
+ // Compute gravity direction minus component that would compress this shell.
+ // Could compute average normal but this is probably good enough.
+ float3 gravDirNoRegress = gravDirObj - min(0, input[0].normal * dot(gravDirObj, input[0].normal));
+
+ float3 worldPos = mul(unity_ObjectToWorld, input[0].objPos).xyz;
+ float radius = length(_WorldSpaceCameraPos - worldPos);
+ uint fur_layers = lerp(_Fur_Layers - 3, 5, saturate((radius - _Fur_Min_Dist) / (_Fur_Max_Dist - _Fur_Min_Dist)));
+
+ [loop]
+ for (uint layer = 0; layer < fur_layers; layer++) {
+ float t = (float) layer / (float) max(fur_layers - 4, 1);
+
+ float offset = t * _Fur_Thickness;
+
+ v2f o = input[layer % 3];
+ float3 normal_ws = UnityObjectToWorldNormal(o.normal);
+
+ float3 dir = lerp(o.normal, gravDirNoRegress, t * t * _Fur_Gravity_Strength);
+
+ o.objPos.xyz += dir * offset;
+
+ float3 worldPos = mul(unity_ObjectToWorld, o.objPos).xyz;
+ o.pos = UnityWorldToClipPos(worldPos);
+ o.vertexLight.w = t;
+ stream.Append(o);
+ }
+#else
+ stream.Append(input[0]);
+ stream.Append(input[1]);
+ stream.Append(input[2]);
+ stream.RestartStrip();
+#endif // _FUR
+}
+//endex
+
+float4 frag(v2f i, uint facing : SV_IsFrontFace
+#if defined(_HARNACK_TRACING) || defined(_SHATTER_WAVE) || defined(_VERTEX_DOMAIN_WARPING) || (defined(_CUSTOM30) && !defined(_DEPTH_PREPASS)) || defined(_RAYMARCHED_FOG) || defined(_TESSELLATION_HEIGHTMAP)
+ , out float depth : SV_DepthLessEqual
+#endif
+) : SV_Target {
+
+ UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy);
+ UNITY_SETUP_INSTANCE_ID(i);
+ UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
+
+#if defined(_CUSTOM30) && defined(_DEPTH_PREPASS) && !defined(FORWARD_BASE_PASS)
+ return 0;
+#endif
+
+ i.normal *= facing ? 1 : -1;
+ i.normal = UnityObjectToWorldNormal(i.normal);
+ i.tangent.xyz = UnityObjectToWorldNormal(i.tangent.xyz);
+
+ // Not necessarily normalized after interpolation
+ i.normal = normalize(i.normal);
+ i.tangent.xyz = normalize(i.tangent.xyz);
+
+ f2f f = (f2f) 0;
+ f.worldPos = mul(unity_ObjectToWorld, i.objPos);
+ f.binormal = cross(i.normal, i.tangent.xyz) * i.tangent.w;
+ f.eyeVec = f.worldPos - _WorldSpaceCameraPos;
+ f.viewDir = normalize(f.eyeVec);
+ f.tbn = float3x3(
+ i.tangent.xyz,
+ f.binormal,
+ i.normal
+ );
+
+#if defined(_RAYMARCHED_FOG)
+ {
+ // Many fields are overspecified as .rgb or .xyz. This is because thry's
+ // shader locker will inline those fields (incorrectly) as float4. Unity's
+ // shader compiler doesn't like that, demanding exact type correspondence.
+ // Overspecifying gets around the issue.
+
+ FogParams fog_params = {
+ _Raymarched_Fog_Color.rgb,
+ _Raymarched_Fog_Direct_Light_Intensity,
+ _Raymarched_Fog_Indirect_Light_Intensity,
+ _Raymarched_Fog_Steps,
+ _Raymarched_Fog_Y_Cutoff,
+ _Raymarched_Fog_Dithering_Noise,
+ _Raymarched_Fog_Dithering_Noise_TexelSize,
+ _Raymarched_Fog_Density_Noise,
+ _Raymarched_Fog_Density_Noise_Scale,
+ _Raymarched_Fog_Velocity.xyz,
+ _Raymarched_Fog_Mean_Free_Path,
+ _Raymarched_Fog_Albedo,
+ _Raymarched_Fog_G,
+ _Raymarched_Fog_Height_Scale,
+ _Raymarched_Fog_Height_Offset,
+ _Raymarched_Fog_Turbulence,
+ _Raymarched_Fog_Step_Size,
+ _Raymarched_Fog_Step_Growth,
+ #if defined(_RAYMARCHED_FOG_EMITTER_TEXTURE)
+ _Raymarched_Fog_Emitter_Texture,
+ _Raymarched_Fog_Emitter_Texture_TexelSize,
+ _Raymarched_Fog_Emitter_Texture_World_Pos.xyz,
+ normalize(_Raymarched_Fog_Emitter_Texture_World_Normal).xyz,
+ normalize(_Raymarched_Fog_Emitter_Texture_World_Tangent).xyz,
+ normalize(cross(_Raymarched_Fog_Emitter_Texture_World_Normal, _Raymarched_Fog_Emitter_Texture_World_Tangent)).xyz,
+ _Raymarched_Fog_Emitter_Texture_World_Scale.xy,
+ 1.0f / _Raymarched_Fog_Emitter_Texture_World_Scale.xy,
+ _Raymarched_Fog_Emitter_Texture_Luminance,
+ _Raymarched_Fog_Emitter_Texture_Intensity,
+ #endif
+ #if defined(_RAYMARCHED_FOG_EMITTER_TEXTURE_WARPING)
+ _Raymarched_Fog_Emitter_Texture_Warping_Octaves,
+ _Raymarched_Fog_Emitter_Texture_Warping_Strength,
+ _Raymarched_Fog_Emitter_Texture_Warping_Scale,
+ _Raymarched_Fog_Emitter_Texture_Warping_Speed,
+ #endif
+ #if defined(_RAYMARCHED_FOG_DENSITY_EXPONENT)
+ _Raymarched_Fog_Density_Exponent,
+ #endif
+ };
+ FogResult fog_result = raymarched_fog(i, f, fog_params);
+ depth = fog_result.depth;
+ return fog_result.color;
+ }
+#endif
+
+#if defined(_SHATTER_WAVE) || defined(_SCREEN_SPACE_NORMALS)
+ calcNormalInScreenSpace(i.normal, i.objPos);
+ i.normal = UnityObjectToWorldNormal(i.normal);
+#endif
+
+#if defined(_SHATTER_WAVE) || defined(_VERTEX_DOMAIN_WARPING) || defined(_TESSELLATION_HEIGHTMAP)
+ {
+ [branch]
+ if (
+ false
+#if defined(_SHATTER_WAVE)
+ || any(_Shatter_Wave_Amplitude > 1E-4)
+#endif
+#if defined(_VERTEX_DOMAIN_WARPING)
+ || _Vertex_Domain_Warping_Octaves > 0.1
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_0)
+ || _Tessellation_Heightmap_0_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_1)
+ || _Tessellation_Heightmap_1_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_2)
+ || _Tessellation_Heightmap_2_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_3)
+ || _Tessellation_Heightmap_3_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_4)
+ || _Tessellation_Heightmap_4_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_5)
+ || _Tessellation_Heightmap_5_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_6)
+ || _Tessellation_Heightmap_6_Scale > 1E-4
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_7)
+ || _Tessellation_Heightmap_7_Scale > 1E-4
+#endif
+ ) {
+ float4 clip_pos = UnityObjectToClipPos(i.objPos);
+ depth = clip_pos.z / clip_pos.w;
+ } else {
+ // Perspective division takes place before the fragment shader, so we
+ // don't have to divide again.
+ depth = i.pos.z;
+ }
+ }
+#endif
+
+#if defined(_EYE_EFFECT_00)
+ EyeEffectOutput eye_effect_00 = EyeEffect_00(i);
+ i.uv01.xy = eye_effect_00.uv;
+#endif
+
+#if defined(_CUSTOM30)
+#if defined(FORWARD_BASE_PASS) || (!defined(_DEPTH_PREPASS) && defined(SHADOW_CASTER_PASS))
+#if defined(_CUSTOM30_BASICCUBE)
+ Custom30Output c30_out = BasicCube(i);
+#elif defined(_CUSTOM30_BASICWEDGE)
+ Custom30Output c30_out = BasicWedge(i);
+#elif defined(_CUSTOM30_BASICPLATFORM)
+ Custom30Output c30_out = BasicPlatform(i);
+#elif defined(_CUSTOM30_RAINBOW)
+ Custom30Output c30_out = Rainbow(i);
+#else
+ Custom30Output c30_out = (Custom30Output) 0;
+#endif
+ i.normal = c30_out.normal;
+ float4 c30_clipPos = UnityObjectToClipPos(i.objPos);
+ float4 c30_screenPos = ComputeScreenPos(c30_clipPos);
+ i.pos = c30_screenPos;
+#if !defined(_DEPTH_PREPASS)
+ depth = c30_out.depth;
+#endif
+#endif
+#endif
+
+ float ssao = 1;
+#if defined(_SSAO)
+ float2 debug;
+ ssao = get_ssao(i, f, debug);
+#endif
+ YumPbr pbr = GetYumPbr(i, f);
+ pbr.albedo.rgb *= ssao;
+
+#if defined(META_PASS)
+#if defined(_EMISSION)
+ return pbr.emission;
+#else
+ return 0;
+#endif
+#endif
+
+#if defined(_TROCHOID)
+ float3 normal_obj = trochoid_normal(i.orig_pos);
+
+ // We need tangents that are perpendicular to the new normal.
+ // A common way to generate them is to cross with a fixed "up" vector.
+ float3 tangent_obj = normalize(cross(normal_obj, float3(0, 1, 0)));
+ float3 binormal_obj = cross(normal_obj, tangent_obj);
+
+ i.normal = UnityObjectToWorldNormal(normal_obj);
+ i.tangent = float4(normalize(mul((float3x3)unity_ObjectToWorld, tangent_obj)), 1);
+ i.binormal = normalize(mul((float3x3)unity_ObjectToWorld, binormal_obj));
+ i.normal *= facing ? 1 : -1;
+
+ float theta = 1 - atan2(i.orig_pos.y, i.orig_pos.x) / PI;
+ float3 color = _Trochoid_Color_Ramp.SampleLevel(linear_clamp_s, float2(theta, 0.5), 0).rgb;
+ pbr.albedo.xyz = color;
+#endif
+
+#if defined(_HARNACK_TRACING)
+ HarnackTracingOutput harnack_output = HarnackTracing(i);
+ pbr.albedo = float4(1, 1, 1, 0.2);
+ pbr.smoothness = 0.95;
+ pbr.roughness_perceptual = 0.05;
+ pbr.roughness = pbr.roughness_perceptual * pbr.roughness_perceptual;
+ pbr.metallic = 0;
+#endif
+
+#if defined(_SSFD)
+ float ssfd_mask = ssfd(i.uv01.xy, _SSFD_Scale, _SSFD_Max_Fwidth, 0, _SSFD_Noise);
+ pbr.albedo *= (ssfd_mask > _SSFD_Threshold);
+#endif
+
+#if defined(OUTLINE_PASS)
+ pbr.smoothness = 0;
+ pbr.roughness = 1;
+ pbr.roughness_perceptual = 1;
+ pbr.metallic = 0;
+#endif
+
+#if defined(_EYE_EFFECT_00)
+ pbr.normal = eye_effect_00.normal;
+#endif
+
+#if defined(_LETTER_GRID)
+ LetterGridOutput letter_grid_output = LetterGrid(i);
+ pbr.albedo.rgb = lerp(pbr.albedo.rgb, letter_grid_output.albedo, letter_grid_output.albedo.a);
+ pbr.metallic = lerp(pbr.metallic, letter_grid_output.metallic, letter_grid_output.albedo.a);
+ pbr.roughness = lerp(pbr.roughness, letter_grid_output.roughness, letter_grid_output.albedo.a);
+#endif
+
+#if defined(_UNIGRAM_LETTER_GRID)
+ UnigramLetterGridOutput unigram_letter_grid_output = UnigramLetterGrid(i, facing);
+ pbr.albedo.rgb = lerp(pbr.albedo.rgb, unigram_letter_grid_output.albedo,
+ unigram_letter_grid_output.albedo.a);
+ pbr.metallic = lerp(pbr.metallic, unigram_letter_grid_output.metallic,
+ unigram_letter_grid_output.albedo.a);
+ pbr.roughness = lerp(pbr.roughness, unigram_letter_grid_output.roughness,
+ unigram_letter_grid_output.albedo.a);
+#endif
+
+ [branch]
+ if (_Mode == 1) {
+ clip(pbr.albedo.a - _Clip);
+ pbr.albedo.a = 1;
+ }
+
+#if defined(EXTRA_STENCIL_COLOR_PASS) && defined(_EXTRA_STENCIL_COLOR_PASS)
+ pbr.albedo = _ExtraStencilColor;
+#endif
+
+#if defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS) || defined(OUTLINE_PASS) || defined(EXTRA_STENCIL_COLOR_PASS)
+ YumLighting l = GetYumLighting(i, f, pbr);
+
+#if defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS)
+ applyMatcapsAndRimLighting(i, f, pbr, l);
+ l.diffuse = max(0, l.diffuse);
+ l.specular = max(0, l.specular);
+#endif
+
+ pbr.albedo.rgb = visualizeInFalseColor(pbr.albedo.rgb);
+ pbr.albedo.rgb = applyQuasiShadows(pbr.albedo.rgb, l);
+
+#if defined(_UNLIT)
+ float4 lit = pbr.albedo;
+#else
+ float4 lit = YumBRDF(i, f, l, pbr);
+#endif
+
+#if defined(_HARNACK_TRACING)
+ pbr.albedo = harnack_output.color;
+ pbr.smoothness = 0;
+ pbr.roughness = 1;
+ pbr.roughness_perceptual = 1;
+ pbr.metallic = 0;
+ pbr.normal = harnack_output.normal;
+ l.NoL = saturate(dot(pbr.normal, l.dir));
+ l.NoL_wrapped_s = l.NoL;
+ l.NoL_wrapped_d = l.NoL;
+ float4 harnack_lit = YumBRDF(i, l, pbr);
+ //lit = alphaBlend(harnack_lit, lit);
+ lit = harnack_lit;
+ {
+ float4 clip_pos = mul(UNITY_MATRIX_VP, float4(harnack_output.worldPos, 1.0));
+ depth = clip_pos.z / clip_pos.w;
+ }
+#endif
+
+#if defined(_EMISSION) || (defined(_GLITTER) && defined(FORWARD_BASE_PASS)) || defined(OUTLINE_PASS)
+ lit.rgb += pbr.emission;
+#endif
+#if defined(_LETTER_GRID)
+ lit.rgb += letter_grid_output.emission * letter_grid_output.albedo.a;
+#endif
+#if defined(_UNIGRAM_LETTER_GRID)
+ lit.rgb += unigram_letter_grid_output.emission * unigram_letter_grid_output.albedo.a;
+#endif
+
+ UNITY_EXTRACT_FOG_FROM_EYE_VEC(i);
+ UNITY_APPLY_FOG(_unity_fogCoord, lit.rgb);
+
+ return lit;
+#elif defined(SHADOW_CASTER_PASS)
+ // Apply dithering for LOD if needed
+ #ifdef LOD_FADE_CROSSFADE
+ UnityApplyDitherCrossFade(i.pos.xy);
+ #endif
+
+ // Output proper shadow data
+ SHADOW_CASTER_FRAGMENT(i)
+#elif defined(MASKED_STENCIL1_PASS) || defined(MASKED_STENCIL2_PASS) || defined(MASKED_STENCIL3_PASS) || defined(MASKED_STENCIL4_PASS) || defined(DEPTH_PREPASS)
+ return 0;
+#endif
+}
+
+#endif // __2NER_INC
diff --git a/2ner.shader b/2ner.shader
index ae966d1..0ea5b2c 100644
--- a/2ner.shader
+++ b/2ner.shader
@@ -72,24 +72,32 @@ Shader "yum_food/2ner"
//endex
//ifex _Metallics_Enabled==0
- [HideInInspector] m_reflectionOptions("Reflections", Float) = 0
- [HideInInspector] m_start_Metallic("Metallics", Float) = 0
- [ThryToggle(_METALLICS)]_Metallics_Enabled("Enable", Float) = 0
- _Metallic("Metallic", Range(0, 1)) = 0
- _Smoothness("Smoothness", Range(0, 1)) = 0
- _MetallicGlossMap("Metallic gloss map", 2D) = "white" {}
- [HideInInspector] m_end_Metallic("Metallics", Float) = 0
- //endex
+ [HideInInspector] m_start_Reflections("Reflections", Float) = 0
+ [HideInInspector] m_start_Metallic("Metallics", Float) = 0
+ [ThryToggle(_METALLICS)]_Metallics_Enabled("Enable", Float) = 0
+ _Metallic("Metallic", Range(0, 1)) = 0
+ _Smoothness("Smoothness", Range(0, 1)) = 0
+ _MetallicGlossMap("Metallic gloss map", 2D) = "white" {}
+ [HideInInspector] m_end_Metallic("Metallics", Float) = 0
+ //endex
- //ifex _Clearcoat_Enabled==0
- [HideInInspector] m_start_Clearcoat("Clearcoat", Float) = 0
- [ThryToggle(_CLEARCOAT)]_Clearcoat_Enabled("Enable", Float) = 0
- [ThryToggle(_CLEARCOAT_GEOMETRIC_NORMALS)]_Clearcoat_Geometric_Normals_Enabled("Use geometric normals", Float) = 1
- _Clearcoat_Mask("Mask", 2D) = "white" {}
- _Clearcoat_Strength("Strength", Range(0, 10)) = 1
- _Clearcoat_Roughness("Roughness", Range(0.089, 1)) = 0.089
- [HideInInspector] m_end_Clearcoat("Clearcoat", Float) = 0
- //endex
+ //ifex _Clearcoat_Enabled==0
+ [HideInInspector] m_start_Clearcoat("Clearcoat", Float) = 0
+ [ThryToggle(_CLEARCOAT)]_Clearcoat_Enabled("Enable", Float) = 0
+ [ThryToggle(_CLEARCOAT_GEOMETRIC_NORMALS)]_Clearcoat_Geometric_Normals_Enabled("Use geometric normals", Float) = 1
+ _Clearcoat_Mask("Mask", 2D) = "white" {}
+ _Clearcoat_Strength("Strength", Range(0, 10)) = 1
+ _Clearcoat_Roughness("Roughness", Range(0.089, 1)) = 0.089
+ [HideInInspector] m_end_Clearcoat("Clearcoat", Float) = 0
+ //endex
+
+ //ifex _Anisotropy_Enabled==0
+ [HideInInspector] m_start_Anisotropy("Anisotropy", Float) = 0
+ [ThryToggle(_ANISOTROPY)]_Anisotropy_Enabled("Enable", Float) = 0
+ _Anisotropy_Strength("Strength", Range(-1, 1)) = 0
+ [HideInInspector] m_end_Anisotropy("Anisotropy", Float) = 0
+ //endex
+ [HideInInspector] m_end_Reflections("Reflections", Float) = 0
[HideInInspector] m_gimmicks("Gimmicks", Float) = 0
//ifex _Outlines_Enabled==0
diff --git a/UnityStandardMeta.cginc b/UnityStandardMeta.cginc
index 60eedc9..95fe193 100644
--- a/UnityStandardMeta.cginc
+++ b/UnityStandardMeta.cginc
@@ -101,7 +101,6 @@ float4 frag_meta (v2f_meta i) : SV_Target
v2f pbr_input;
pbr_input.uv01 = i.uv01;
pbr_input.uv23 = i.uv23;
- pbr_input.worldPos = i.worldPos;
pbr_input.objPos = float4(i.objPos, 1.0);
pbr_input.normal = i.normal;
pbr_input.tangent = i.tangent;
@@ -114,7 +113,7 @@ float4 frag_meta (v2f_meta i) : SV_Target
f.eyeVec = i.worldPos - _WorldSpaceCameraPos;
f.viewDir = normalize(f.eyeVec);
- YumPbr pbr = GetYumPbr(pbr_input, f, tangentToWorld);
+ YumPbr pbr = GetYumPbr(pbr_input, f);
#if defined(_CUSTOM30)
#if defined(_CUSTOM30_BASICCUBE)
diff --git a/data.cginc b/data.cginc
index 9b6ea10..2e765e6 100644
--- a/data.cginc
+++ b/data.cginc
@@ -10,6 +10,9 @@ struct YumPbr {
float roughness_perceptual;
float metallic;
float ao;
+#if defined(_ANISOTROPY)
+ float3 binormal;
+#endif
};
#endif // __DATA_INC
diff --git a/features.cginc b/features.cginc
index ab45306..12a89a0 100644
--- a/features.cginc
+++ b/features.cginc
@@ -63,6 +63,10 @@
#pragma shader_feature_local _CLEARCOAT_GEOMETRIC_NORMALS
//endex
+//ifex _Anisotropy_Enabled==0
+#pragma shader_feature_local _ANISOTROPY
+//endex
+
//ifex _Metallics_Enabled==0
#pragma shader_feature_local _METALLICS
//endex
diff --git a/filamented.cginc b/filamented.cginc
index b66baf2..ecf697f 100644
--- a/filamented.cginc
+++ b/filamented.cginc
@@ -889,6 +889,19 @@ float D_GGX(float roughness, float NoH, const float3 h) {
return d;
}
+// t = tangent vector, b = bitangent vector
+float D_GGX_Anisotropic(float at, float ab, float NoH,
+ const float3 h,
+ const float3 t, const float3 b) {
+ float ToH = dot(t, h);
+ float BoH = dot(b, h);
+ float a2 = at * ab;
+ float3 v = float3(ab * ToH, at * BoH, a2 * NoH);
+ float v2 = dot(v, v);
+ float w2 = a2 / v2;
+ return a2 * w2 * w2 * (1.0 / PI);
+}
+
float F_Schlick(float f0, float VoH) {
return f0 + (1.0 - f0) * pow5(1.0 - VoH);
}
@@ -935,6 +948,14 @@ float V_SmithGGXCorrelated_Fast(float roughness, float NoV, float NoL) {
return v;
}
+float V_SmithGGXCorrelated_Anisotropic(float at, float ab, float ToV, float BoV,
+ float ToL, float BoL, float NoV, float NoL) {
+ float lambdaV = NoL * length(float3(at * ToV, ab * BoV, NoV));
+ float lambdaL = NoV * length(float3(at * ToL, ab * BoL, NoL));
+ float v = 0.5 / (lambdaV + lambdaL);
+ return saturate(v);
+}
+
float perceptualRoughnessToRoughness(float perceptualRoughness) {
return perceptualRoughness * perceptualRoughness;
}
diff --git a/globals.cginc b/globals.cginc
index d374c2d..e6e7423 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -132,6 +132,10 @@ float _Clearcoat_Strength;
float _Clearcoat_Roughness;
#endif
+#if defined(_ANISOTROPY)
+float _Anisotropy_Strength;
+#endif
+
#if defined(OUTLINE_PASS)
float _Outlines_Enabled_Dynamic;
float4 _Outline_Color;
diff --git a/interpolators.cginc b/interpolators.cginc
index 6a632d1..89fae91 100644
--- a/interpolators.cginc
+++ b/interpolators.cginc
@@ -25,7 +25,7 @@ struct v2f {
float4 uv23 : TEXCOORD1; // just one more uv slot bro please
float4 objPos : TEXCOORD2;
float3 normal : TEXCOORD3;
- float3 tangent : TEXCOORD4;
+ float4 tangent : TEXCOORD4;
float4 vertexLight : TEXCOORD5; // vertexLight.xyz | furLayer
UNITY_LIGHTING_COORDS(6,7)
diff --git a/yum_brdf.cginc b/yum_brdf.cginc
index 347c31d..a12e667 100644
--- a/yum_brdf.cginc
+++ b/yum_brdf.cginc
@@ -33,8 +33,8 @@ float V_Cloth(float NoV, float NoL) {
return 1.0 / (4.0 * (NoL + NoV - NoL * NoV));
}
-float3 specularLobe(YumPbr pbr, float3 f0,
- float3 h, float LoH, float NoH, float NoV, float NoL)
+float3 specularLobe(v2f i, f2f f, YumPbr pbr, YumLighting light,
+ float3 f0, float3 h, float LoH, float NoH, float NoV, float NoL)
{
#if defined(_MATERIAL_TYPE_CLOTH)
float D = D_Charlie(pbr.roughness, NoH);
@@ -49,10 +49,25 @@ float3 specularLobe(YumPbr pbr, float3 f0,
float f90 = saturate(dot(f0, (50.0 * 0.33)));
const float3 F = F_Schlick(f0, f90, LoH);
#endif
- // Normal distribution function
+
+#if defined(_ANISOTROPY)
+ float anisotropy = _Anisotropy_Strength;
+ // Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"
+ float3 b = pbr.binormal;
+ float3 t = i.tangent.xyz;
+ float at = max(pbr.roughness * (1.0 + anisotropy), 0.001);
+ float ab = max(pbr.roughness * (1.0 - anisotropy), 0.001);
+ float D = D_GGX_Anisotropic(at, ab, NoH, h, t, b);
+ float ToV = dot(t, light.view_dir);
+ float BoV = dot(b, light.view_dir);
+ float ToL = dot(t, light.dir);
+ float BoL = dot(b, light.dir);
+ float V = V_SmithGGXCorrelated_Anisotropic(at, ab,
+ ToV, BoV, ToL, BoL, NoV, NoL);
+#else
float D = D_GGX(pbr.roughness, NoH, h);
- // Geometric shadowing
float V = V_SmithGGXCorrelated_Fast(pbr.roughness, NoV, NoL);
+#endif
return (D * V) * F;
#endif
}
@@ -118,7 +133,7 @@ float4 YumBRDF(v2f i, f2f f, const YumLighting light, YumPbr pbr) {
#endif
// Cloth specular BRDF - multiply by PI to match Unity intensities
- float3 Fr = specularLobe(pbr, float3(0.04, 0.04, 0.04), h, LoH, NoH, NoV, NoL_wrapped_s) * PI * light.attenuation;
+ float3 Fr = specularLobe(i, f, pbr, light, float3(0.04, 0.04, 0.04), h, LoH, NoH, NoV, NoL_wrapped_s) * PI * light.attenuation;
#if defined(_MATERIAL_TYPE_CLOTH_SUBSURFACE)
// No need to multiply by NoL when using subsurface scattering
@@ -163,7 +178,7 @@ float4 YumBRDF(v2f i, f2f f, const YumLighting light, YumPbr pbr) {
Fd *= light.attenuation * pbr.ao * remainder;
// Multiply by PI to match Unity intensities (same as Filament's implementation)
- float3 Fr = specularLobe(pbr, f0, h, LoH, NoH, NoV, NoL_wrapped_s) * PI * light.attenuation * remainder;
+ float3 Fr = specularLobe(i, f, pbr, light, f0, h, LoH, NoH, NoV, NoL_wrapped_s) * PI * light.attenuation * remainder;
// Apply energy compensation to specular term
float3 color = Fd * NoL_wrapped_d + Fr * energy_compensation * NoL_wrapped_s;
diff --git a/yum_lighting.cginc b/yum_lighting.cginc
index 7f2d922..a1bef47 100644
--- a/yum_lighting.cginc
+++ b/yum_lighting.cginc
@@ -166,7 +166,14 @@ float GetLodRoughness(float roughness) {
}
float3 getIndirectSpecular(v2f i, f2f f, YumPbr pbr, float3 view_dir, float diffuse_luminance) {
+#if defined(_ANISOTROPY)
+ float3 aniso_tangent = cross(view_dir, pbr.binormal);
+ float3 aniso_normal = -normalize(cross(aniso_tangent, pbr.binormal));
+ float3 refl_normal = normalize(lerp(pbr.normal, aniso_normal, _Anisotropy_Strength));
+ float3 reflect_dir = reflect(-view_dir, refl_normal);
+#else
float3 reflect_dir = reflect(-view_dir, pbr.normal);
+#endif
UnityGIInput data;
data.worldPos = f.worldPos;
@@ -349,7 +356,7 @@ YumLighting GetYumLighting(v2f i, f2f f, YumPbr pbr) {
light.attenuation = getShadowAttenuation(i, f);
float3 tangentNormal = mul(f.tbn, pbr.normal);
- float3x3 tangentToWorld = float3x3(i.tangent, f.binormal, i.normal);
+ float3x3 tangentToWorld = float3x3(i.tangent.xyz, f.binormal, i.normal);
// Use Bakery-aware irradiance function
#if defined(LIGHTMAP_ON)
diff --git a/yum_pbr.cginc b/yum_pbr.cginc
index 6049b35..2b746d5 100644
--- a/yum_pbr.cginc
+++ b/yum_pbr.cginc
@@ -327,6 +327,10 @@ YumPbr GetYumPbr(v2f i, f2f f) {
result.emission += glitter_albedo.rgb * glitter_albedo.a * _Glitter_Emission;
#endif
+#if defined(_ANISOTROPY)
+ result.binormal = normalize(cross(result.normal, i.tangent.xyz) * i.tangent.w);
+#endif
+
return result;
}