130 lines
4.5 KiB
Plaintext
130 lines
4.5 KiB
Plaintext
Shader "GAME/BuildGhost"
|
|
{
|
|
Properties
|
|
{
|
|
[Header(Ghost Tint set to green when placeable red when blocked)][Space]
|
|
[HDR] _BaseColor("Ghost Color", Color) = (0.2, 1.0, 0.35, 1)
|
|
_FillOpacity("Fill Opacity (body see through amount)", Range(0,1)) = 0.15
|
|
|
|
[Header(Fresnel Rim glowing silhouette edge)][Space]
|
|
_RimPower("Rim Power (higher = thinner edge)", Range(0.5,12)) = 2.5
|
|
_RimIntensity("Rim Intensity", Range(0,8)) = 2.5
|
|
|
|
[Header(Scan Pulse gentle breathing glow)][Space]
|
|
_PulseSpeed("Pulse Speed", Float) = 2.5
|
|
_PulseMin("Pulse Min", Range(0,2)) = 0.7
|
|
_PulseMax("Pulse Max", Range(0,2)) = 1.15
|
|
|
|
[Header(Rendering)][Space]
|
|
[Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 2
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags
|
|
{
|
|
"RenderType" = "Transparent"
|
|
"RenderPipeline" = "UniversalPipeline"
|
|
"Queue" = "Transparent"
|
|
"IgnoreProjector" = "True"
|
|
}
|
|
|
|
// Shared declarations for every pass.
|
|
HLSLINCLUDE
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
half4 _BaseColor;
|
|
half _FillOpacity;
|
|
half _RimPower;
|
|
half _RimIntensity;
|
|
float _PulseSpeed;
|
|
half _PulseMin;
|
|
half _PulseMax;
|
|
CBUFFER_END
|
|
ENDHLSL
|
|
|
|
// =====================================================================
|
|
// Ghost — unlit, additive-ish transparent body with a bright fresnel
|
|
// rim so the silhouette reads clearly. The whole look is driven by the
|
|
// single _BaseColor tint, so placement code just swaps green <-> red.
|
|
// =====================================================================
|
|
Pass
|
|
{
|
|
Name "Ghost"
|
|
Tags { "LightMode" = "UniversalForward" }
|
|
|
|
Blend SrcAlpha OneMinusSrcAlpha
|
|
ZWrite Off
|
|
ZTest LEqual
|
|
Cull [_Cull]
|
|
|
|
HLSLPROGRAM
|
|
#pragma target 3.0
|
|
#pragma vertex GhostVertex
|
|
#pragma fragment GhostFragment
|
|
#pragma multi_compile_instancing
|
|
#pragma multi_compile_fog
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float3 normalOS : NORMAL;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float3 positionWS : TEXCOORD0;
|
|
half3 normalWS : TEXCOORD1;
|
|
float fogFactor : TEXCOORD2;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
Varyings GhostVertex(Attributes IN)
|
|
{
|
|
Varyings OUT = (Varyings)0;
|
|
UNITY_SETUP_INSTANCE_ID(IN);
|
|
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
|
|
|
VertexPositionInputs posInput = GetVertexPositionInputs(IN.positionOS.xyz);
|
|
VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normalOS);
|
|
|
|
OUT.positionCS = posInput.positionCS;
|
|
OUT.positionWS = posInput.positionWS;
|
|
OUT.normalWS = normalInput.normalWS;
|
|
OUT.fogFactor = ComputeFogFactor(posInput.positionCS.z);
|
|
return OUT;
|
|
}
|
|
|
|
half4 GhostFragment(Varyings IN) : SV_Target
|
|
{
|
|
UNITY_SETUP_INSTANCE_ID(IN);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
|
|
|
|
half3 normalWS = normalize(IN.normalWS);
|
|
half3 viewDirWS = normalize(GetWorldSpaceViewDir(IN.positionWS));
|
|
|
|
// Fresnel rim: bright on grazing angles so the edge glows.
|
|
half fresnel = pow(1.0 - saturate(dot(normalWS, viewDirWS)), _RimPower);
|
|
half rim = fresnel * _RimIntensity;
|
|
|
|
// Breathing pulse so the ghost feels alive without moving.
|
|
half pulse = lerp(_PulseMin, _PulseMax, sin(_Time.y * _PulseSpeed) * 0.5 + 0.5);
|
|
|
|
half3 color = _BaseColor.rgb * pulse;
|
|
half alpha = saturate(_FillOpacity + rim) * pulse * _BaseColor.a;
|
|
|
|
color = MixFog(color, IN.fogFactor);
|
|
return half4(color, saturate(alpha));
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
|
|
FallBack Off
|
|
}
|