280 lines
12 KiB
Plaintext
280 lines
12 KiB
Plaintext
Shader "HighlightPlus/Geometry/Overlay" {
|
|
Properties {
|
|
_MainTex ("Texture", Any) = "white" {}
|
|
_Color ("Color", Color) = (1,1,1) // not used; dummy property to avoid inspector warning "material has no _Color property"
|
|
_OverlayColor ("Overlay Color", Color) = (1,1,1,1)
|
|
_OverlayBackColor ("Overlay Back Color", Color) = (1,1,1,1)
|
|
_OverlayData("Overlay Data", Vector) = (1,0.5,1,1)
|
|
_OverlayHitPosData("Overlay Hit Pos Data", Vector) = (0,0,0,0)
|
|
_OverlayHitStartTime("Overlay Hit Start Time", Float) = 0
|
|
_OverlayTexture("Overlay Texture", 2D) = "white" {}
|
|
_CutOff("CutOff", Float ) = 0.5
|
|
_Cull ("Cull Mode", Int) = 2
|
|
_OverlayZTest("ZTest", Int) = 4
|
|
_OverlayPatternScrolling("Pattern Scrolling", Vector) = (0,0,0,0)
|
|
_OverlayPatternData("Pattern Data", Vector) = (0,0,0,0)
|
|
_OverlayBlendDst("Overlay Blend Dst", Int) = 10
|
|
}
|
|
SubShader
|
|
{
|
|
Tags { "Queue"="Transparent+121" "RenderType"="Transparent" "DisableBatching"="True" }
|
|
|
|
// Overlay
|
|
Pass
|
|
{
|
|
Name "Overlay"
|
|
Stencil {
|
|
Ref 4
|
|
ReadMask 4
|
|
Comp NotEqual
|
|
Pass keep
|
|
}
|
|
Blend SrcAlpha [_OverlayBlendDst]
|
|
ZWrite Off
|
|
Cull [_Cull]
|
|
Offset -1, -1 // avoid issues on Quest 2 standalone when using with other render features (ie. Liquid Volume Pro 2 irregular topology)
|
|
ZTest [_OverlayZTest]
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma multi_compile_local _ HP_ALPHACLIP
|
|
#pragma multi_compile_local _ HP_TEXTURE_TRIPLANAR HP_TEXTURE_TRIPLANAR_LOCAL HP_TEXTURE_SCREENSPACE HP_TEXTURE_OBJECTSPACE
|
|
#pragma multi_compile_local _ HP_PATTERN_POLKADOTS HP_PATTERN_GRID HP_PATTERN_STAGGERED_LINES HP_PATTERN_ZIGZAG
|
|
|
|
#include "UnityCG.cginc"
|
|
#include "CustomVertexTransform.cginc"
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float3 norm : NORMAL;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float3 wpos : TEXCOORD1;
|
|
#if HP_TEXTURE_TRIPLANAR
|
|
float3 wnorm : TEXCOORD2;
|
|
#elif HP_TEXTURE_TRIPLANAR_LOCAL
|
|
float3 lnorm : TEXCOORD2;
|
|
float3 lpos : TEXCOORD4;
|
|
#endif
|
|
#if HP_TEXTURE_SCREENSPACE
|
|
float4 scrPos : TEXCOORD3;
|
|
#endif
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
fixed4 _OverlayColor;
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
fixed4 _OverlayBackColor;
|
|
fixed4 _OverlayData; // x = speed, y = MinIntensity, z = blend, w = texture scale
|
|
float4 _OverlayHitPosData;
|
|
float _OverlayHitStartTime;
|
|
fixed _CutOff;
|
|
sampler2D _OverlayTexture;
|
|
float2 _OverlayTextureScrolling;
|
|
|
|
float2 _OverlayPatternScrolling;
|
|
float4 _OverlayPatternData;
|
|
#define PATTERN_SCALE (_OverlayPatternData.x)
|
|
#define PATTERN_SIZE (_OverlayPatternData.y)
|
|
#define PATTERN_SOFTNESS (_OverlayPatternData.z)
|
|
#define PATTERN_ROTATION (_OverlayPatternData.w)
|
|
|
|
v2f vert (appdata v)
|
|
{
|
|
v2f o;
|
|
UNITY_SETUP_INSTANCE_ID(v);
|
|
UNITY_INITIALIZE_OUTPUT(v2f, o);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
|
o.pos = ComputeVertexPosition(v.vertex);
|
|
#if HP_TEXTURE_SCREENSPACE
|
|
o.scrPos = ComputeScreenPos(o.pos);
|
|
o.scrPos.x *= _ScreenParams.x / _ScreenParams.y;
|
|
#endif
|
|
o.wpos = mul(unity_ObjectToWorld, v.vertex).xyz;
|
|
#if HP_TEXTURE_TRIPLANAR
|
|
o.wnorm = UnityObjectToWorldNormal(v.norm);
|
|
#elif HP_TEXTURE_TRIPLANAR_LOCAL
|
|
o.lpos = v.vertex.xyz;
|
|
o.lnorm = v.norm;
|
|
#endif
|
|
o.uv = TRANSFORM_TEX (v.uv, _MainTex);
|
|
return o;
|
|
}
|
|
|
|
// Helper to rotate UVs by angle in degrees
|
|
float2 rotateUV(float2 uv, float angleDeg) {
|
|
float angleRad = radians(angleDeg);
|
|
float s = sin(angleRad);
|
|
float c = cos(angleRad);
|
|
float2 center = float2(0.5, 0.5);
|
|
uv -= center;
|
|
float2 rotated = float2(
|
|
uv.x * c - uv.y * s,
|
|
uv.x * s + uv.y * c
|
|
);
|
|
return rotated + center;
|
|
}
|
|
|
|
// Function to create antialiased polka dot pattern
|
|
float polkaDotPattern(float2 uv) {
|
|
float2 scrolledUV = uv + _OverlayPatternScrolling * _Time.y;
|
|
float2 rotatedUV = rotateUV(scrolledUV, PATTERN_ROTATION);
|
|
float2 localUV = rotatedUV;
|
|
// Offset every other row
|
|
localUV.x += 0.5 / PATTERN_SCALE * (floor(rotatedUV.y * PATTERN_SCALE) % 2.0);
|
|
float2 scaledUV = localUV * PATTERN_SCALE;
|
|
float2 gridPos = frac(scaledUV) - 0.5;
|
|
float dist = length(gridPos);
|
|
float alpha = smoothstep(PATTERN_SIZE + PATTERN_SOFTNESS, PATTERN_SIZE - PATTERN_SOFTNESS, dist);
|
|
return saturate(alpha);
|
|
}
|
|
|
|
// Function to create antialiased grid pattern
|
|
float gridPattern(float2 uv) {
|
|
float2 scrolledUV = uv + _OverlayPatternScrolling * _Time.y;
|
|
float2 rotatedUV = rotateUV(scrolledUV, PATTERN_ROTATION);
|
|
float2 scaledUV = rotatedUV * PATTERN_SCALE;
|
|
float2 grid = abs(frac(scaledUV) - 0.5);
|
|
float lin = min(grid.x, grid.y);
|
|
float alpha = smoothstep(PATTERN_SIZE + PATTERN_SOFTNESS, PATTERN_SIZE - PATTERN_SOFTNESS, lin);
|
|
return saturate(alpha);
|
|
}
|
|
|
|
// Function to create antialiased staggered horizontal dashed lines
|
|
float staggeredLinePattern(float2 uv) {
|
|
float2 scrolledUV = uv + _OverlayPatternScrolling * _Time.y;
|
|
float2 rotatedUV = rotateUV(scrolledUV, PATTERN_ROTATION);
|
|
float2 scaledUV = rotatedUV * PATTERN_SCALE;
|
|
|
|
// Row index for staggering the dash pattern
|
|
float row = floor(scaledUV.y);
|
|
float dashOffset = (row % 2.0) * 0.5; // Stagger by half a pattern period along X
|
|
float staggeredX = scaledUV.x + dashOffset;
|
|
|
|
// Calculate visibility for the horizontal line itself.
|
|
// Thickness is controlled by PATTERN_SIZE.
|
|
// hline_alpha = 1 if on the line, 0 if in the gap between lines.
|
|
float hline_alpha = smoothstep(PATTERN_SIZE + PATTERN_SOFTNESS, PATTERN_SIZE - PATTERN_SOFTNESS, abs(frac(scaledUV.y) - 0.5));
|
|
|
|
// Calculate visibility for the dash segments along the X-axis.
|
|
// Let's use a fixed 50% duty cycle for dashes (dash length = gap length).
|
|
// For a 50% duty cycle, the effective "size" parameter for the dash segment is 0.25.
|
|
// (because abs(frac(X)-0.5) goes from 0 to 0.5; visible for 0 to 0.25 means 0.25*2=0.5 of the period).
|
|
float dash_segment_parameter = 0.25;
|
|
float dash_alpha = smoothstep(dash_segment_parameter + PATTERN_SOFTNESS, dash_segment_parameter - PATTERN_SOFTNESS, abs(frac(staggeredX) - 0.5));
|
|
|
|
// Final alpha: The pixel is visible if it's on a horizontal line AND on a dash segment of that line.
|
|
float final_alpha = hline_alpha * dash_alpha;
|
|
return saturate(final_alpha);
|
|
}
|
|
|
|
// Function to create antialiased zigzag pattern
|
|
float zigZagPattern(float2 uv) {
|
|
float2 scrolledUV = uv + _OverlayPatternScrolling * _Time.y;
|
|
float2 rotatedUV = rotateUV(scrolledUV, PATTERN_ROTATION);
|
|
float2 scaledUV = rotatedUV * PATTERN_SCALE;
|
|
|
|
// y_center_norm is a triangle wave ^ shape, ranging from 0 to 1, based on scaledUV.x
|
|
// It represents the normalized y-coordinate of the zigzag centerline within a vertical cell.
|
|
float y_center_norm = abs(frac(scaledUV.x) - 0.5) * 2.0;
|
|
|
|
// y_pixel_norm is the normalized y-coordinate of the current pixel within a vertical cell.
|
|
float y_pixel_norm = frac(scaledUV.y);
|
|
|
|
// dist is the vertical distance from the pixel's normalized y to the zigzag centerline's normalized y.
|
|
float dist = abs(y_pixel_norm - y_center_norm);
|
|
|
|
// PATTERN_SIZE defines half the thickness of the line in normalized cell coordinates.
|
|
// Alpha is 1 if dist is small (within PATTERN_SIZE), 0 if dist is large.
|
|
float alpha = smoothstep(PATTERN_SIZE + PATTERN_SOFTNESS, PATTERN_SIZE - PATTERN_SOFTNESS, dist);
|
|
return saturate(alpha);
|
|
}
|
|
|
|
fixed4 SampleOverlayTexture(float2 uv) {
|
|
float2 uvOffset = _OverlayTextureScrolling * _Time.y;
|
|
fixed4 tex = tex2D(_OverlayTexture, uv * _OverlayData.w + uvOffset);
|
|
#if HP_PATTERN_POLKADOTS
|
|
tex.a *= polkaDotPattern(uv);
|
|
#endif
|
|
#if HP_PATTERN_GRID
|
|
tex.a *= gridPattern(uv);
|
|
#endif
|
|
#if HP_PATTERN_STAGGERED_LINES
|
|
tex.a *= staggeredLinePattern(uv);
|
|
#endif
|
|
#if HP_PATTERN_ZIGZAG
|
|
tex.a *= zigZagPattern(uv);
|
|
#endif
|
|
return tex;
|
|
}
|
|
|
|
fixed4 frag (v2f i) : SV_Target
|
|
{
|
|
fixed4 color = tex2D(_MainTex, i.uv);
|
|
#if HP_ALPHACLIP
|
|
clip(color.a - _CutOff);
|
|
#endif
|
|
float time = _Time.y % 1000;
|
|
fixed t = _OverlayData.y + (1.0 - _OverlayData.y) * 2.0 * abs(0.5 - frac(time * _OverlayData.x));
|
|
fixed4 col = lerp(_OverlayColor, color * _OverlayBackColor * _OverlayColor, _OverlayData.z);
|
|
col.a *= t;
|
|
|
|
if (_OverlayHitPosData.w>0) {
|
|
float elapsed = _Time.y - _OverlayHitStartTime;
|
|
float hitDist = distance(i.wpos, _OverlayHitPosData.xyz);
|
|
float atten = saturate( min(elapsed, _OverlayHitPosData.w) / hitDist );
|
|
col.a *= atten;
|
|
}
|
|
|
|
#if HP_TEXTURE_TRIPLANAR
|
|
half3 triblend = saturate(pow(i.wnorm, 4));
|
|
triblend /= max(dot(triblend, half3(1,1,1)), 0.0001);
|
|
|
|
// triplanar uvs
|
|
float3 tpos = i.wpos;
|
|
float2 uvX = tpos.zy;
|
|
float2 uvY = tpos.xz;
|
|
float2 uvZ = tpos.xy;
|
|
|
|
// albedo textures
|
|
fixed4 colX = SampleOverlayTexture(uvX);
|
|
fixed4 colY = SampleOverlayTexture(uvY);
|
|
fixed4 colZ = SampleOverlayTexture(uvZ);
|
|
fixed4 tex = colX * triblend.x + colY * triblend.y + colZ * triblend.z;
|
|
col *= tex;
|
|
#elif HP_TEXTURE_TRIPLANAR_LOCAL
|
|
half3 triblend = saturate(pow(i.lnorm, 4));
|
|
triblend /= max(dot(triblend, half3(1,1,1)), 0.0001);
|
|
|
|
float3 tpos = i.lpos;
|
|
float2 uvX = tpos.zy;
|
|
float2 uvY = tpos.xz;
|
|
float2 uvZ = tpos.xy;
|
|
|
|
fixed4 colX = SampleOverlayTexture(uvX);
|
|
fixed4 colY = SampleOverlayTexture(uvY);
|
|
fixed4 colZ = SampleOverlayTexture(uvZ);
|
|
fixed4 tex = colX * triblend.x + colY * triblend.y + colZ * triblend.z;
|
|
col *= tex;
|
|
#elif HP_TEXTURE_SCREENSPACE
|
|
col *= SampleOverlayTexture(i.scrPos.xy / i.scrPos.w);
|
|
#elif HP_TEXTURE_OBJECTSPACE
|
|
col *= SampleOverlayTexture(i.uv);
|
|
#endif
|
|
|
|
return col;
|
|
}
|
|
ENDCG
|
|
}
|
|
|
|
}
|
|
} |