Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Создан URP HLSL шейдер CartoonFire.shader с процедурным FBM-шумом искажения и 3-ступенчатой постеризацией цветов (красный/оранжевый/желтый). - Создан редакторский скрипт ApplyCartoonFireShader.cs для быстрого переключения материала. - Материал Fire_Material.mat обновлен и переведен на новый мультяшный шейдер с настроенными параметрами.
173 lines
5.5 KiB
GLSL
173 lines
5.5 KiB
GLSL
Shader "Custom/CartoonFire"
|
|
{
|
|
Properties
|
|
{
|
|
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
|
_Color ("Main Color (Multiplier)", Color) = (1,1,1,1)
|
|
|
|
[HDR] _ColorOuter ("Outer Color (Red)", Color) = (1.5, 0.2, 0.1, 1)
|
|
[HDR] _ColorMid ("Mid Color (Orange)", Color) = (1.8, 0.55, 0.0, 1)
|
|
[HDR] _ColorInner ("Inner Color (Yellow)", Color) = (2.2, 0.95, 0.15, 1)
|
|
|
|
_Speed ("Scroll Speed (XY)", Vector) = (0.0, -1.8, 0.0, 0.0)
|
|
_DistortStrength ("Distort Strength", Range(0, 0.5)) = 0.08
|
|
|
|
_ThresholdOuter ("Threshold Outer", Range(0, 1)) = 0.15
|
|
_ThresholdMid ("Threshold Mid", Range(0, 1)) = 0.38
|
|
_ThresholdInner ("Threshold Inner", Range(0, 1)) = 0.58
|
|
|
|
_NoiseScale ("Noise Scale", Range(1, 50)) = 15.0
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags
|
|
{
|
|
"Queue" = "Transparent"
|
|
"IgnoreProjector" = "True"
|
|
"RenderType" = "Transparent"
|
|
"PreviewType" = "Plane"
|
|
"CanUseSpriteAtlas" = "True"
|
|
"RenderPipeline" = "UniversalPipeline"
|
|
}
|
|
|
|
Cull Off
|
|
Lighting Off
|
|
ZWrite Off
|
|
Blend SrcAlpha OneMinusSrcAlpha
|
|
|
|
Pass
|
|
{
|
|
Name "SpriteUnlit"
|
|
HLSLPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float4 color : COLOR;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float4 color : COLOR;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
TEXTURE2D(_MainTex);
|
|
SAMPLER(sampler_MainTex);
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float4 _MainTex_ST;
|
|
float4 _Color;
|
|
float4 _ColorOuter;
|
|
float4 _ColorMid;
|
|
float4 _ColorInner;
|
|
float4 _Speed;
|
|
float _DistortStrength;
|
|
float _ThresholdOuter;
|
|
float _ThresholdMid;
|
|
float _ThresholdInner;
|
|
float _NoiseScale;
|
|
CBUFFER_END
|
|
|
|
// Procedural noise functions
|
|
float hash(float2 p)
|
|
{
|
|
p = frac(p * float2(123.34, 456.21));
|
|
p += dot(p, p + 45.32);
|
|
return frac(p.x * p.y);
|
|
}
|
|
|
|
float noise(float2 p)
|
|
{
|
|
float2 i = floor(p);
|
|
float2 f = frac(p);
|
|
float2 u = f * f * (3.0 - 2.0 * f);
|
|
|
|
return lerp(lerp(hash(i + float2(0.0,0.0)), hash(i + float2(1.0,0.0)), u.x),
|
|
lerp(hash(i + float2(0.0,1.0)), hash(i + float2(1.0,1.0)), u.x), u.y);
|
|
}
|
|
|
|
float fbm(float2 p)
|
|
{
|
|
float v = 0.0;
|
|
float a = 0.5;
|
|
float2 shift = float2(100.0, 100.0);
|
|
float2x2 rot = float2x2(0.8, 0.6, -0.6, 0.8);
|
|
for (int i = 0; i < 4; ++i) {
|
|
v += a * noise(p);
|
|
p = mul(rot, p) * 2.0 + shift;
|
|
a *= 0.5;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
Varyings vert(Attributes input)
|
|
{
|
|
Varyings output;
|
|
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
|
|
output.uv = input.uv;
|
|
output.color = input.color;
|
|
return output;
|
|
}
|
|
|
|
float4 frag(Varyings input) : SV_Target
|
|
{
|
|
// Calculate moving noise coordinates
|
|
float2 noiseUV = input.uv * _NoiseScale + _Speed.xy * _Time.y;
|
|
float n = fbm(noiseUV);
|
|
|
|
// Distort the UV coordinates
|
|
float2 distortedUV = input.uv + float2(n - 0.5, n - 0.5) * _DistortStrength;
|
|
|
|
// Sample the main sprite texture
|
|
float4 mainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, distortedUV);
|
|
|
|
// Base value is derived from texture transparency and color
|
|
float value = mainTex.a;
|
|
|
|
// Fade out at the top of the sprite (vertical gradient)
|
|
value *= saturate(1.15 - input.uv.y);
|
|
|
|
// Combine with noise value
|
|
value = saturate(value * 0.3 + value * n * 0.7);
|
|
|
|
// Toon stepping (thresholds)
|
|
float stepOuter = step(_ThresholdOuter, value);
|
|
float stepMid = step(_ThresholdMid, value);
|
|
float stepInner = step(_ThresholdInner, value);
|
|
|
|
// Select color based on steps
|
|
float4 fireColor = float4(0, 0, 0, 0);
|
|
|
|
if (stepInner > 0.5)
|
|
{
|
|
fireColor = _ColorInner;
|
|
}
|
|
else if (stepMid > 0.5)
|
|
{
|
|
fireColor = _ColorMid;
|
|
}
|
|
else if (stepOuter > 0.5)
|
|
{
|
|
fireColor = _ColorOuter;
|
|
}
|
|
|
|
// Final alpha is gated by the outer step
|
|
fireColor.a *= stepOuter;
|
|
|
|
// Modulate by sprite / particle vertex color
|
|
fireColor *= input.color * _Color;
|
|
|
|
return fireColor;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
}
|