You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
15 KiB
527 lines
15 KiB
//-------------------------------------------------------------------------------------------------------------------------------- |
|
// Cartoon FX |
|
// (c) 2012-2020 Jean Moreno |
|
//-------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
Shader "Cartoon FX/Remaster/Particle Procedural Ring" |
|
{ |
|
Properties |
|
{ |
|
//# Blending |
|
//# |
|
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Blend Source", Float) = 5 |
|
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Blend Destination", Float) = 10 |
|
|
|
//# -------------------------------------------------------- |
|
|
|
[Toggle(_CFXR_DISSOLVE)] _UseDissolve ("Enable Dissolve", Float) = 0 |
|
//# IF_KEYWORD _CFXR_DISSOLVE |
|
[NoScaleOffset] _DissolveTex ("Dissolve Texture", 2D) = "gray" {} |
|
_DissolveSmooth ("Dissolve Smoothing", Range(0.0001,0.5)) = 0.1 |
|
[ToggleNoKeyword] _InvertDissolveTex ("Invert Dissolve Texture", Float) = 0 |
|
//# END_IF |
|
|
|
//# -------------------------------------------------------- |
|
|
|
//# Textures |
|
//# |
|
|
|
_MainTex ("Texture", 2D) = "white" {} |
|
[Toggle(_CFXR_SINGLE_CHANNEL)] _SingleChannel ("Single Channel Texture", Float) = 0 |
|
|
|
//# -------------------------------------------------------- |
|
|
|
//# Ring |
|
//# |
|
|
|
[Toggle(_CFXR_RADIAL_UV)] _UseRadialUV ("Enable Radial UVs", Float) = 0 |
|
_RingTopOffset ("Ring Offset", float) = 0.05 |
|
[Toggle(_CFXR_WORLD_SPACE_RING)] _WorldSpaceRing ("World Space", Float) = 0 |
|
|
|
//# -------------------------------------------------------- |
|
|
|
[Toggle(_CFXR_HDR_BOOST)] _HdrBoost ("Enable HDR Multiplier", Float) = 0 |
|
//# IF_KEYWORD _CFXR_HDR_BOOST |
|
_HdrMultiply ("HDR Multiplier", Float) = 2 |
|
//# END_IF |
|
|
|
//# -------------------------------------------------------- |
|
|
|
[Toggle(_FADING_ON)] _UseSP ("Soft Particles", Float) = 0 |
|
//# IF_KEYWORD _FADING_ON |
|
_SoftParticlesFadeDistanceNear ("Near Fade", Float) = 0 |
|
_SoftParticlesFadeDistanceFar ("Far Fade", Float) = 1 |
|
//# END_IF |
|
|
|
//# ======================================================== |
|
//# Shadows |
|
//# |
|
|
|
[KeywordEnum(Off,On,CustomTexture)] _CFXR_DITHERED_SHADOWS ("Dithered Shadows", Float) = 0 |
|
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE |
|
_ShadowStrength ("Shadows Strength Max", Range(0,1)) = 1.0 |
|
//# IF_KEYWORD _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE |
|
_DitherCustom ("Dithering 3D Texture", 3D) = "black" {} |
|
//# END_IF |
|
//# END_IF |
|
} |
|
|
|
Category |
|
{ |
|
Tags |
|
{ |
|
"Queue"="Transparent" |
|
"IgnoreProjector"="True" |
|
"RenderType"="Transparent" |
|
} |
|
Blend [_SrcBlend] [_DstBlend] |
|
Cull Off |
|
ZWrite Off |
|
|
|
//================================================================================================================================ |
|
// Includes & Code |
|
|
|
CGINCLUDE |
|
#include "UnityCG.cginc" |
|
#include "UnityStandardUtils.cginc" |
|
|
|
// -------------------------------- |
|
|
|
#include "CFXR_SETTINGS.cginc" |
|
|
|
// -------------------------------- |
|
|
|
CBUFFER_START(UnityPerMaterial) |
|
|
|
sampler2D _MainTex; |
|
float4 _MainTex_ST; |
|
|
|
sampler2D _DissolveTex; |
|
half _InvertDissolveTex; |
|
half _DissolveSmooth; |
|
|
|
half _HdrMultiply; |
|
|
|
float _RingTopOffset; |
|
|
|
half _Cutoff; |
|
|
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture); |
|
half _SoftParticlesFadeDistanceNear; |
|
half _SoftParticlesFadeDistanceFar; |
|
half _EdgeFadePow; |
|
|
|
float _ShadowStrength; |
|
sampler3D _DitherMaskLOD; |
|
sampler3D _DitherCustom; |
|
float4 _DitherCustom_TexelSize; |
|
|
|
CBUFFER_END |
|
|
|
// -------------------------------- |
|
// Input/Output |
|
|
|
struct appdata |
|
{ |
|
float4 vertex : POSITION; |
|
half4 color : COLOR; |
|
float4 texcoord : TEXCOORD0; //uv + particle data |
|
float4 texcoord1 : TEXCOORD1; //additional particle data |
|
float4 texcoord2 : TEXCOORD2; //procedural ring data: x = width, y = smooth, z = rotation, w = particle size |
|
#if PASS_SHADOW_CASTER || _CFXR_WORLD_SPACE_RING |
|
float3 normal : NORMAL; |
|
#endif |
|
UNITY_VERTEX_INPUT_INSTANCE_ID |
|
}; |
|
|
|
// vertex to fragment |
|
struct v2f |
|
{ |
|
float4 pos : SV_POSITION; |
|
half4 color : COLOR; |
|
float4 uv_uv2 : TEXCOORD0; //uv + particle data |
|
float4 ringData : TEXCOORD1; //procedural ring data |
|
float4 uvRing_uvCartesian : TEXCOORD2; |
|
#if !defined(GLOBAL_DISABLE_SOFT_PARTICLES) && ((defined(SOFTPARTICLES_ON) || defined(CFXR_URP) || defined(SOFT_PARTICLES_ORTHOGRAPHIC)) && defined(_FADING_ON)) |
|
float4 projPos : TEXCOORD3; |
|
#endif |
|
UNITY_FOG_COORDS(4) //note: does nothing if fog is not enabled |
|
#if _CFXR_DISSOLVE |
|
float4 custom1 : TEXCOORD5; |
|
#endif |
|
UNITY_VERTEX_INPUT_INSTANCE_ID |
|
UNITY_VERTEX_OUTPUT_STEREO |
|
}; |
|
|
|
// vertex to fragment (shadow caster) |
|
struct v2f_shadowCaster |
|
{ |
|
V2F_SHADOW_CASTER_NOPOS |
|
half4 color : COLOR; |
|
float4 uv_uv2 : TEXCOORD1; //uv + particle data |
|
float4 ringData : TEXCOORD2; //procedural ring data |
|
float4 uvRing_uvCartesian : TEXCOORD3; |
|
#if _CFXR_DISSOLVE |
|
float4 custom1 : TEXCOORD4; |
|
#endif |
|
}; |
|
|
|
// -------------------------------- |
|
|
|
#include "CFXR.cginc" |
|
|
|
// -------------------------------- |
|
// Vertex |
|
#if PASS_SHADOW_CASTER |
|
void vertex_program (appdata v, out v2f_shadowCaster o, out float4 opos : SV_POSITION) |
|
#else |
|
v2f vertex_program (appdata v) |
|
#endif |
|
{ |
|
#if !PASS_SHADOW_CASTER |
|
v2f o; |
|
// o.pos = UnityObjectToClipPos(v.vertex); |
|
#endif |
|
|
|
UNITY_SETUP_INSTANCE_ID(v); |
|
UNITY_TRANSFER_INSTANCE_ID(v, o); |
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); |
|
|
|
//-------------------------------- |
|
// procedural ring |
|
|
|
float ringWidth = v.texcoord2.x; |
|
float ringSmooth = v.texcoord2.y; |
|
float ringRotation = v.texcoord2.z; |
|
float particleSize = v.texcoord2.w; |
|
|
|
// avoid artifacts when vertex are pushed too much |
|
ringWidth = min(particleSize, ringWidth); |
|
|
|
// constants calculated per vertex |
|
o.ringData.x = pow(1 - ringWidth / particleSize, 2); |
|
o.ringData.y = 1 - _RingTopOffset; |
|
o.ringData.z = ringSmooth / particleSize; // smoothing depends on particle size |
|
o.ringData.w = ringRotation; |
|
|
|
// regular ring UVs |
|
float2 uv = v.texcoord.xy + float2(ringRotation, 0); |
|
o.uvRing_uvCartesian.xy = 1 - TRANSFORM_TEX(uv, _MainTex); |
|
|
|
|
|
#if _CFXR_WORLD_SPACE_RING |
|
// to clip space with width offset |
|
v.vertex.xyz = v.vertex.xyz - v.normal.xyz * v.texcoord.y * ringWidth; |
|
#if !PASS_SHADOW_CASTER |
|
o.pos = UnityObjectToClipPos(v.vertex); |
|
#endif |
|
#else |
|
// to clip space with width offset |
|
float4 m = mul(UNITY_MATRIX_V, v.vertex); |
|
m.xy += -v.texcoord.zw * v.texcoord.y * ringWidth; |
|
#if !PASS_SHADOW_CASTER |
|
o.pos = mul(UNITY_MATRIX_P, m); |
|
#endif |
|
#endif |
|
|
|
//------------------------------------------ |
|
/* |
|
//v.vertex.xy += -v.texcoord.zw * v.texcoord.y * ringWidth; |
|
v.vertex.xy += v.texcoord.zw * v.texcoord.y * 0.5; |
|
#if !PASS_SHADOW_CASTER |
|
o.pos = UnityObjectToClipPos(v.vertex); |
|
#endif |
|
*/ |
|
//------------------------------------------ |
|
|
|
// calculate cartesian UVs to accurately calculate ring in fragment shader |
|
o.uvRing_uvCartesian.zw = v.texcoord.zw - v.texcoord.zw * v.texcoord.y * ringWidth / particleSize; |
|
|
|
//-------------------------------- |
|
|
|
o.color = v.color; |
|
o.uv_uv2 = v.texcoord; |
|
|
|
//-------------------------------- |
|
|
|
#if _CFXR_DISSOLVE |
|
o.custom1 = v.texcoord1; |
|
#endif |
|
|
|
#if PASS_SHADOW_CASTER |
|
vert(v, o, opos); |
|
#else |
|
return vert(v, o); |
|
#endif |
|
} |
|
|
|
// -------------------------------- |
|
// Fragment |
|
|
|
#if PASS_SHADOW_CASTER |
|
float4 fragment_program (v2f_shadowCaster i, UNITY_VPOS_TYPE vpos : VPOS) : SV_Target |
|
#else |
|
half4 fragment_program (v2f i) : SV_Target |
|
#endif |
|
{ |
|
UNITY_SETUP_INSTANCE_ID(i); |
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); |
|
|
|
// ================================================================ |
|
// Color & Alpha |
|
|
|
//-------------------------------- |
|
// procedural ring |
|
|
|
float b = i.ringData.x; // bottom |
|
float t = i.ringData.y; // top |
|
float smooth = i.ringData.z; // smoothing |
|
float gradient = dot(i.uvRing_uvCartesian.zw, i.uvRing_uvCartesian.zw); |
|
float ring = saturate( smoothstep(b, b + smooth, gradient) - smoothstep(t - smooth, t, gradient) ); |
|
|
|
#if _CFXR_RADIAL_UV |
|
// approximate polar coordinates |
|
float2 radialUv = float2 |
|
( |
|
(atan2(i.uvRing_uvCartesian.z, i.uvRing_uvCartesian.w) / UNITY_PI) * 0.5 + 0.5 + 0.23 - i.ringData.w, |
|
(gradient * (1.0 / (t - b)) - (b / (t - b))) * 0.9 - 0.92 + 1 |
|
); |
|
radialUv.xy = radialUv.xy * _MainTex_ST.xy + _MainTex_ST.zw; |
|
float dx = ddx(i.uvRing_uvCartesian.x); |
|
//float dy = ddx(i.uvRing_uvCartesian.x); |
|
#define TEX2D_MAIN_TEXCOORD(sampler) tex2Dgrad(sampler, radialUv, dx, dx) |
|
#else |
|
#define TEX2D_MAIN_TEXCOORD(sampler) tex2D(sampler, i.uvRing_uvCartesian.xy) |
|
#endif |
|
|
|
#if _CFXR_SINGLE_CHANNEL |
|
half4 mainTex = half4(1, 1, 1, TEX2D_MAIN_TEXCOORD(_MainTex).r); |
|
#else |
|
half4 mainTex = TEX2D_MAIN_TEXCOORD(_MainTex); |
|
#endif |
|
|
|
mainTex *= ring; |
|
|
|
//-------------------------------- |
|
|
|
half3 particleColor = mainTex.rgb * i.color.rgb; |
|
half particleAlpha = mainTex.a * i.color.a; |
|
|
|
#if _CFXR_HDR_BOOST |
|
#ifdef UNITY_COLORSPACE_GAMMA |
|
_HdrMultiply = LinearToGammaSpaceApprox(_HdrMultiply); |
|
#endif |
|
particleColor.rgb *= _HdrMultiply * GLOBAL_HDR_MULTIPLIER; |
|
#endif |
|
|
|
// ================================================================ |
|
// Dissolve |
|
|
|
#if _CFXR_DISSOLVE |
|
half dissolveTex = TEX2D_MAIN_TEXCOORD(_DissolveTex).r; |
|
dissolveTex = _InvertDissolveTex <= 0 ? 1 - dissolveTex : dissolveTex; |
|
half dissolveTime = i.custom1.x; |
|
#else |
|
half dissolveTex = 0; |
|
half dissolveTime = 0; |
|
#endif |
|
|
|
// ================================================================ |
|
// |
|
|
|
#if PASS_SHADOW_CASTER |
|
return frag(i, vpos, particleColor, particleAlpha, dissolveTex, dissolveTime); |
|
#else |
|
return frag(i, particleColor, particleAlpha, dissolveTex, dissolveTime); |
|
#endif |
|
} |
|
|
|
|
|
ENDCG |
|
|
|
//==================================================================================================================================== |
|
// Universal Rendering Pipeline |
|
|
|
SubShader |
|
{ |
|
Pass |
|
{ |
|
Name "BASE" |
|
Tags { "LightMode"="UniversalForward" } |
|
|
|
CGPROGRAM |
|
|
|
#pragma vertex vertex_program |
|
#pragma fragment fragment_program |
|
|
|
#pragma target 2.0 |
|
|
|
#pragma multi_compile_particles |
|
#pragma multi_compile_fog |
|
|
|
#pragma multi_compile CFXR_URP |
|
|
|
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL |
|
#pragma shader_feature_local _ _CFXR_RADIAL_UV |
|
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING |
|
#pragma shader_feature_local _ _CFXR_DISSOLVE |
|
#pragma shader_feature_local _ _CFXR_HDR_BOOST |
|
|
|
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage |
|
#pragma shader_feature_local _ _FADING_ON |
|
#pragma shader_feature_local _ _ALPHATEST_ON |
|
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE |
|
|
|
|
|
ENDCG |
|
} |
|
|
|
// Same as above with 'Universal2D' instead and DISABLE_SOFT_PARTICLES keyword |
|
Pass |
|
{ |
|
Name "BASE" |
|
Tags { "LightMode"="Universal2D" } |
|
|
|
CGPROGRAM |
|
|
|
#pragma vertex vertex_program |
|
#pragma fragment fragment_program |
|
|
|
#pragma target 2.0 |
|
|
|
#pragma multi_compile_particles |
|
#pragma multi_compile_fog |
|
|
|
#pragma multi_compile CFXR_URP |
|
#pragma multi_compile DISABLE_SOFT_PARTICLES |
|
|
|
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL |
|
#pragma shader_feature_local _ _CFXR_RADIAL_UV |
|
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING |
|
#pragma shader_feature_local _ _CFXR_DISSOLVE |
|
#pragma shader_feature_local _ _CFXR_HDR_BOOST |
|
|
|
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage |
|
#pragma shader_feature_local _ _FADING_ON |
|
#pragma shader_feature_local _ _ALPHATEST_ON |
|
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE |
|
|
|
|
|
ENDCG |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
Pass |
|
{ |
|
Name "ShadowCaster" |
|
Tags { "LightMode" = "ShadowCaster" } |
|
|
|
BlendOp Add |
|
Blend One Zero |
|
ZWrite On |
|
Cull Off |
|
|
|
CGPROGRAM |
|
|
|
#pragma multi_compile PASS_SHADOW_CASTER |
|
|
|
#pragma vertex vertex_program |
|
#pragma fragment fragment_program |
|
|
|
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL |
|
#pragma shader_feature_local _ _CFXR_RADIAL_UV |
|
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING |
|
#pragma shader_feature_local _ _CFXR_DISSOLVE |
|
|
|
#pragma shader_feature_local _ _ALPHATEST_ON |
|
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE |
|
|
|
#pragma multi_compile_shadowcaster |
|
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE |
|
|
|
#if _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE |
|
#pragma target 3.0 //needed for VPOS |
|
#endif |
|
|
|
ENDCG |
|
} |
|
} |
|
|
|
//==================================================================================================================================== |
|
// Built-in Rendering Pipeline |
|
|
|
SubShader |
|
{ |
|
Pass |
|
{ |
|
Name "BASE" |
|
Tags { "LightMode"="ForwardBase" } |
|
|
|
CGPROGRAM |
|
|
|
#pragma vertex vertex_program |
|
#pragma fragment fragment_program |
|
|
|
#pragma target 2.0 |
|
|
|
#pragma multi_compile_particles |
|
#pragma multi_compile_fog |
|
|
|
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL |
|
#pragma shader_feature_local _ _CFXR_RADIAL_UV |
|
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING |
|
#pragma shader_feature_local _ _CFXR_DISSOLVE |
|
#pragma shader_feature_local _ _CFXR_HDR_BOOST |
|
|
|
// Using the same keywords as Unity's Standard Particle shader to minimize project-wide keyword usage |
|
#pragma shader_feature_local _ _FADING_ON |
|
#pragma shader_feature_local _ _ALPHATEST_ON |
|
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE |
|
|
|
|
|
ENDCG |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
Pass |
|
{ |
|
Name "ShadowCaster" |
|
Tags { "LightMode" = "ShadowCaster" } |
|
|
|
BlendOp Add |
|
Blend One Zero |
|
ZWrite On |
|
Cull Off |
|
|
|
CGPROGRAM |
|
|
|
#pragma multi_compile PASS_SHADOW_CASTER |
|
|
|
#pragma vertex vertex_program |
|
#pragma fragment fragment_program |
|
|
|
#pragma shader_feature_local _ _CFXR_SINGLE_CHANNEL |
|
#pragma shader_feature_local _ _CFXR_RADIAL_UV |
|
#pragma shader_feature_local _ _CFXR_WORLD_SPACE_RING |
|
#pragma shader_feature_local _ _CFXR_DISSOLVE |
|
|
|
#pragma shader_feature_local _ _ALPHATEST_ON |
|
#pragma shader_feature_local _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON _CFXR_ADDITIVE |
|
|
|
#pragma multi_compile_shadowcaster |
|
#pragma shader_feature_local _ _CFXR_DITHERED_SHADOWS_ON _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE |
|
|
|
#if _CFXR_DITHERED_SHADOWS_ON || _CFXR_DITHERED_SHADOWS_CUSTOMTEXTURE |
|
#pragma target 3.0 //needed for VPOS |
|
#endif |
|
|
|
ENDCG |
|
} |
|
} |
|
} |
|
|
|
CustomEditor "CartoonFX.MaterialInspector" |
|
} |
|
|
|
|