Advertisement
Sunspider

PSX Inverse Hull Rim Light Shader

Oct 12th, 2024
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OpenGL Shading 14.02 KB | Source Code | 0 0
  1. Shader "psx/RimClipStencil"
  2. {
  3.     Properties
  4.     {
  5.         _MainTex ("Texture", 2D) = "white" {}
  6.         _Color ("Base Color", Color) = (1.0, 1.0, 1.0, 1.0)
  7.         _Light ("Base Light", Color) = (0.0, 0.0, 0.0, 1.0)
  8.         _LightAmp("Light Amplification", Range(0,10)) = 1.0
  9.         _SnapSize ("Snap Size", Float) = 1.0
  10.         _FogStrength("Fog Strength", Range(0,1)) = 1.0
  11.  
  12.         // Outline settings
  13.         _OutlineSize("Outline Size", Range(0,0.1)) = 0.006666667
  14.         _OutlineOffset("Outline Offset", Range(0,0.1)) = 0.006666667
  15.         _OutlineIntensity("Outline Intensity", Range(0.0,10.0)) = 1.0
  16.         _OutlineBlend("Outline Texture Blend", Range(0.0,1.0)) = 0.8
  17.         [IntRange] _OutlineStencilIndex("Outline Stencil ID", Range(0,255)) = 0
  18.  
  19.         //Shader feature toggles
  20.         //[Toggle(OUTLINE_SHARED_OFFSET)] _OutlineSharedOffset ("Outline Offset from Shared Origin", Float) = 0.0
  21.         [Toggle(OUTLINE_FROM_NORMALS)] _OutlineFromNormals ("Outline Normals use Surface Normals", Float) = 0.0
  22.     }
  23.     SubShader
  24.     {
  25.         Tags { "RenderType"="Opaque" "LightMode"="Vertex" }
  26.         LOD 100
  27.  
  28.         Pass
  29.         {
  30.             Name "BasePass"
  31.             Cull Back
  32.  
  33.             // This stencil buffer writes the given Stencil ID to all pixels occupied by the model, so meshes with the given index share a contiguous outline
  34.             Stencil
  35.             {
  36.                 Ref [_OutlineStencilIndex]
  37.                 Comp Always
  38.                 Pass Replace
  39.             }
  40.  
  41.             CGPROGRAM
  42.             #pragma vertex vert
  43.             #pragma fragment frag
  44.  
  45.             #include "UnityCG.cginc"
  46.  
  47.             // Static configurable values
  48.             static const int MAX_LIGHTS = 8; // How many lights affect objects. RANGE: 0 to 8
  49.             static const half LIGHT_BIAS = 0.15; // Sharpening factor for attenuation. RANGE: 0.0 to 0.5
  50.  
  51.             int _OutlineStencilIndex;
  52.  
  53.             sampler2D _MainTex;
  54.             float4 _MainTex_ST;
  55.  
  56.             float4 _Color;
  57.             float4 _Light;
  58.             float _LightAmp;
  59.             float _SnapSize;
  60.  
  61.             float _FogStrength;
  62.             uniform half4 unity_FogStart;
  63.             uniform half4 unity_FogEnd;
  64.  
  65.             struct appdata
  66.             {
  67.                 float4 vertex : POSITION;
  68.                 float4 normal : NORMAL;
  69.                 fixed4 vertex_color : COLOR;
  70.                 float2 uv : TEXCOORD0;
  71.             };
  72.  
  73.             struct v2f
  74.             {
  75.                 float4 vertex : SV_POSITION;
  76.                 float4 color : COLOR0;
  77.                 float4 fog_color : COLOR1;
  78.                 noperspective float2 uv : TEXCOORD0;
  79.             };
  80.            
  81.             v2f vert (appdata v)
  82.             {
  83.                 v2f o;
  84.  
  85.                 float4 clip_pos = UnityObjectToClipPos (v.vertex);
  86.                 float3 view_pos = UnityObjectToViewPos (v.vertex.xyz);
  87.                 float view_distance = length( mul(UNITY_MATRIX_MV, v.vertex) );
  88.  
  89.                 // Calculate vertex snapping in clip space terms
  90.                 float snap_factor = 1 / _SnapSize;
  91.                 float4 snapped_pos = clip_pos;
  92.                 snapped_pos.xyz = clip_pos.xyz / clip_pos.w;
  93.                 snapped_pos.x = floor(160 * snap_factor * snapped_pos.x) / (160 * snap_factor);
  94.                 snapped_pos.y = floor(120 * snap_factor * snapped_pos.y) / (120 * snap_factor);
  95.                 snapped_pos.xyz *= clip_pos.w;
  96.                 o.vertex = snapped_pos;
  97.  
  98.                 // Wrapped vertex lighting, brightest to darkest, which ignores normals
  99.                 float3 light_color = unity_AmbientSky.rgb;
  100.  
  101.                 for(int light_id = 0; light_id < MAX_LIGHTS; light_id++)
  102.                 {
  103.                     // Calculate directional light vector, or vector to point light source
  104.                     float3 to_light = unity_LightPosition[light_id].xyz - view_pos.xyz * unity_LightPosition[light_id].w;
  105.                     float length_sq = dot (to_light, to_light);
  106.  
  107.                     // Skip this light if not directional and outside range
  108.                     if (unity_LightPosition[light_id].w && length_sq > unity_LightAtten[light_id].w)
  109.                     {
  110.                         continue;
  111.                     }
  112.                    
  113.                     // Prevents NaNs when overlapping light position
  114.                     length_sq = max(length_sq, 0.00001);
  115.                     to_light *= rsqrt(length_sq);
  116.  
  117.                     // Calculate and apply light attenuation, sharpened with LIGHT_BIAS
  118.                     float attenuation = 1.0 / (1.0 + length_sq * unity_LightAtten[light_id].z);
  119.                     float biased_atten = smoothstep(LIGHT_BIAS, 1.0 - LIGHT_BIAS, attenuation);
  120.                     light_color += unity_LightColor[light_id].rgb * biased_atten * _LightAmp;
  121.                 }
  122.  
  123.                 // Surface is lit to the maximum of base light or environmental light
  124.                 o.color = _Color;
  125.                 o.color.rgb *= max(light_color, _Light.rgb * _LightAmp);
  126.  
  127.                 // Fog with vertex cutout
  128.                 float4 fog_color = unity_FogColor;
  129.                 float fog_density = (unity_FogEnd - view_distance) / (unity_FogEnd - unity_FogStart);
  130.                 o.fog_color = fog_color;
  131.                 o.fog_color.a = saturate(fog_density) * _FogStrength;
  132.  
  133.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  134.                 return o;
  135.             }
  136.  
  137.             fixed4 frag (v2f i) : SV_Target
  138.             {
  139.                 // sample the texture, and modulate by light color
  140.                 fixed4 col = tex2D(_MainTex, i.uv);
  141.                 fixed4 final_col = col * i.color;
  142.  
  143.                 // apply fog color
  144.                 float fog_blend = (_FogStrength - i.fog_color.a) * _FogStrength;
  145.                 final_col.rgb = lerp(final_col.rgb, i.fog_color.rgb, fog_blend);
  146.  
  147.                 return final_col;
  148.             }
  149.             ENDCG
  150.         }
  151.  
  152.         Pass
  153.         {
  154.             Name "OutlinePass"
  155.             Cull Back
  156.  
  157.             Stencil
  158.             {
  159.                 Ref [_OutlineStencilIndex]
  160.                 Comp Greater
  161.             }
  162.  
  163.             CGPROGRAM
  164.                 #pragma shader_feature OUTLINE_FROM_NORMALS
  165.                 #pragma vertex vert
  166.                 #pragma fragment frag
  167.                 #include "UnityCG.cginc"
  168.  
  169.                 static const int MAX_LIGHTS = 8;
  170.                 static const half OUTLINE_FALLOFF = 0.5;
  171.  
  172.                 float4 _Color;
  173.                 float4 _Light;
  174.                 float _LightAmp;
  175.  
  176.                 half _OutlineSize;
  177.                 half _OutlineOffset;
  178.                 half _OutlineIntensity;
  179.                 half _OutlineBlend;
  180.  
  181.                 half4 _OutlineTestNormal;
  182.  
  183.                 sampler2D _MainTex;
  184.                 float4 _MainTex_ST;
  185.  
  186.                 float _SnapSize;
  187.                
  188.                 float _FogStrength;
  189.                 uniform half4 unity_FogStart;
  190.                 uniform half4 unity_FogEnd;
  191.  
  192.                 struct appdata
  193.                 {
  194.                     float4 vertex : POSITION;
  195.                     float3 normal : NORMAL;
  196.                     half4 vertex_color : COLOR;
  197.                     float2 uv : TEXCOORD0;
  198.                 };
  199.  
  200.                 struct v2f
  201.                 {
  202.                     // noperspective keyword prevents modern affine warping correction
  203.                     float4 vertex : SV_POSITION;
  204.                     half4 color : COLOR0;
  205.                     float4 fog_color : COLOR1;
  206.                     noperspective float2 uv : TEXCOORD0;
  207.                 };
  208.  
  209.                 v2f vert (appdata v)
  210.                 {
  211.                     v2f o;
  212.  
  213.                     float3 view_pos = UnityObjectToViewPos (v.vertex);
  214.                     float4 clip_pos = UnityObjectToClipPos (v.vertex);
  215.                     float view_distance = length( mul(UNITY_MATRIX_MV, v.vertex) );
  216.                    
  217.                     half3 light_color = unity_AmbientSky.rgb;
  218.                     float3 swizzled_normal = v.normal;
  219.                    
  220.                     #if (!OUTLINE_FROM_NORMALS)
  221.                     {
  222.                         // Remap and swizzle Blender-style baked normals to Unity normals in range -1 to +1
  223.                         swizzled_normal.rgb = normalize(v.vertex_color.gbr * 2.0 - 1.0);
  224.                         swizzled_normal.r *= -1.0;
  225.                         swizzled_normal.b *= -1.0;
  226.                     }
  227.                     #endif
  228.  
  229.                     // Calculate distance and direction based light factors, for offsetting rimlight
  230.                     float3 avg_light_normal = float3(0.0, 0.0, 0.0);
  231.                     float max_light_atten = 0.0;
  232.                     float total_luminance = 0.0;
  233.                     float valid_lights = 0;
  234.  
  235.                     // For each light, add vertex light intensity at object's origin
  236.                     for(int light_id = 0; light_id < MAX_LIGHTS; light_id++)
  237.                     {
  238.                         float3 to_light = unity_LightPosition[light_id].xyz - view_pos.xyz * unity_LightPosition[light_id].w;
  239.                         //float3 to_light = clip_light_pos.xyz - view_pos.xyz * clip_light_pos.w;
  240.                         float length_sq = dot (to_light, to_light);
  241.  
  242.                         // Skip this light if not directional and outside range
  243.                         if (unity_LightPosition[light_id].w && length_sq > unity_LightAtten[light_id].w)
  244.                         {
  245.                             continue;
  246.                         }
  247.  
  248.                         // Prevents NaNs when overlapping light position
  249.                         length_sq = max(length_sq, 0.00001);
  250.                         to_light *= rsqrt(length_sq);
  251.  
  252.                         // Calculate and apply light attenuation, sharpened with OUTLINE_FALLOFF
  253.                         float light_quad_atten = unity_LightAtten[light_id].z;
  254.  
  255.                         float attenuation = 1.0 / (1.0 + length_sq * unity_LightAtten[light_id].z);
  256.                         float biased_atten = smoothstep(0.0, OUTLINE_FALLOFF, attenuation);
  257.                        
  258.                         valid_lights += 1;
  259.                         max_light_atten = max(max_light_atten, attenuation);
  260.                         avg_light_normal += to_light * attenuation;
  261.  
  262.                         light_color += unity_LightColor[light_id].rgb * biased_atten * _LightAmp * _OutlineIntensity;
  263.                         total_luminance += Luminance(unity_LightColor[light_id].rgb * attenuation);
  264.                     }
  265.  
  266.                     total_luminance = saturate(total_luminance);
  267.  
  268.                     float3 outline_normal = UnityObjectToWorldNormal(swizzled_normal);
  269.                     float3 clip_normal = mul((float3x3) UNITY_MATRIX_VP, mul((float3x3) UNITY_MATRIX_M, swizzled_normal));
  270.  
  271.                     float clip_aspect = _ScreenParams.x / _ScreenParams.y;
  272.                     float2 clip_scale_offset = normalize(clip_normal.xy) * total_luminance * _OutlineSize * clip_pos.w;
  273.                     clip_scale_offset.y *= clip_aspect;
  274.                     clip_pos.xy += clip_scale_offset;
  275.  
  276.                     //avg_light_normal = _OutlineTestNormal;
  277.                     float3 clip_light_normal = mul((float3x3) UNITY_MATRIX_P, avg_light_normal);
  278.                     //float3 clip_light_normal = mul((float3x3) UNITY_MATRIX_VP, mul((float3x3) UNITY_MATRIX_M, avg_light_normal));
  279.  
  280.                     float2 clip_light_offset = normalize(clip_light_normal.xy) * total_luminance * _OutlineOffset * clip_pos.w;
  281.                     clip_light_offset.y *= clip_aspect;
  282.                     clip_pos.xy += clip_light_offset;
  283.  
  284.                     avg_light_normal = normalize(avg_light_normal);
  285.                     avg_light_normal = mul(avg_light_normal, (float3x3)UNITY_MATRIX_IT_MV);
  286.  
  287.                     float3 scale_offset = normalize(outline_normal) * max_light_atten * _OutlineSize; // - normalize(outline_normal) * 0.01;
  288.                     float3 light_offset = normalize(avg_light_normal) * max_light_atten * _OutlineOffset;
  289.                     float3 offset_pos = scale_offset + light_offset;
  290.  
  291.                     v.vertex.xyz += offset_pos;
  292.  
  293.                     // Calculate vertex snapping in clip space terms
  294.                     float snap_factor = 1 / _SnapSize;
  295.                     float4 snapped_pos = clip_pos;
  296.                     snapped_pos.xyz = clip_pos.xyz / clip_pos.w;
  297.                     snapped_pos.x = floor(160 * snap_factor * snapped_pos.x) / (160 * snap_factor);
  298.                     snapped_pos.y = floor(120 * snap_factor * snapped_pos.y) / (120 * snap_factor);
  299.                     snapped_pos.xyz *= clip_pos.w;
  300.  
  301.                     o.vertex = snapped_pos;
  302.  
  303.                     // Surface is lit to the maximum of base light or environmental light
  304.                     o.color = _Color;
  305.                     o.color.rgb *= max(light_color, _Light.rgb * _LightAmp * _OutlineIntensity);
  306.  
  307.                     // Fog with vertex cutout
  308.                     float4 fog_color = unity_FogColor;
  309.                     float fog_density = (unity_FogEnd - view_distance) / (unity_FogEnd - unity_FogStart);
  310.                     o.fog_color = fog_color;
  311.                     o.fog_color.a = saturate(fog_density) * _FogStrength;
  312.  
  313.                     o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  314.                     return o;
  315.                 }
  316.  
  317.                 fixed4 frag (v2f i) : SV_Target
  318.                 {
  319.                     // sample the texture
  320.                     fixed4 col = tex2D(_MainTex, i.uv);
  321.                    
  322.                     // Interpolate pure light color with recolored texture
  323.                     fixed4 final_col = lerp(i.color, col * i.color, _OutlineBlend);
  324.  
  325.                     // apply fog color
  326.                     float fog_blend = (_FogStrength - i.fog_color.a) * _FogStrength;
  327.                     final_col.rgb = lerp(final_col.rgb, i.fog_color.rgb, fog_blend);
  328.  
  329.                     return final_col;
  330.                 }
  331.             ENDCG
  332.         }
  333.     }
  334. }
  335.  
Tags: Shader hlsl
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement