Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/Language/NoiseOverlayRenderer.cs
T
2026-02-09 14:02:41 +08:00

253 lines
8.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using Shapes;
namespace AibisDream.MiniGame.Language
{
/// <summary>
/// 复古噪点叠加渲染器 - 在指定区域上方绘制复古显示器效果
/// 使用 Shapes 库绘制,与粒子系统使用相同的渲染方式
/// </summary>
[ExecuteAlways]
public class NoiseOverlayRenderer : ImmediateModeShapeDrawer
{
[Header("区域设置")]
[Tooltip("效果覆盖的世界空间区域中心")]
public Vector3 areaCenter = Vector3.zero;
[Tooltip("效果覆盖的区域大小")]
public Vector2 areaSize = new Vector2(10f, 10f);
[Header("噪点效果")]
[Tooltip("启用噪点效果")]
public bool enableNoise = true;
[Range(0f, 1f)]
[Tooltip("噪点强度")]
public float noiseIntensity = 0.15f;
[Range(1, 100)]
[Tooltip("噪点密度(点数)")]
public int noiseDensity = 50;
[Tooltip("噪点颜色")]
public Color noiseColor = new Color(1f, 1f, 1f, 0.3f);
[Range(0.001f, 0.05f)]
[Tooltip("噪点大小")]
public float noiseSize = 0.02f;
[Header("扫描线效果")]
[Tooltip("启用扫描线")]
public bool enableScanlines = true;
[Range(0f, 1f)]
[Tooltip("扫描线强度")]
public float scanlineIntensity = 0.1f;
[Range(10, 200)]
[Tooltip("扫描线数量")]
public int scanlineCount = 60;
[Tooltip("扫描线颜色")]
public Color scanlineColor = new Color(0f, 0f, 0f, 0.15f);
[Range(0.001f, 0.02f)]
[Tooltip("扫描线厚度")]
public float scanlineThickness = 0.005f;
[Header("闪烁效果")]
[Tooltip("启用闪烁")]
public bool enableFlicker = true;
[Range(0f, 0.5f)]
[Tooltip("闪烁强度")]
public float flickerIntensity = 0.05f;
[Range(1f, 30f)]
[Tooltip("闪烁频率")]
public float flickerFrequency = 10f;
[Header("边框暗角")]
[Tooltip("启用边框暗角")]
public bool enableVignette = true;
[Range(0f, 1f)]
[Tooltip("暗角强度")]
public float vignetteIntensity = 0.3f;
[Tooltip("暗角颜色")]
public Color vignetteColor = new Color(0f, 0f, 0f, 0.5f);
[Header("颜色失真")]
[Tooltip("启用色差")]
public bool enableChromaticAberration = false;
[Range(0f, 0.05f)]
[Tooltip("色差偏移量")]
public float chromaticOffset = 0.01f;
// 内部状态
private float noiseTimer = 0f;
private float flickerValue = 1f;
private System.Random noiseRandom;
private void OnEnable()
{
noiseRandom = new System.Random(42);
}
private void Update()
{
// 更新噪点动画
noiseTimer += Time.deltaTime * 20f;
if (noiseTimer > 1000f) noiseTimer = 0f;
// 更新闪烁
if (enableFlicker)
{
flickerValue = 1f - flickerIntensity * Mathf.PerlinNoise(Time.time * flickerFrequency, 0f);
}
else
{
flickerValue = 1f;
}
// 重新生成噪点种子
noiseRandom = new System.Random((int)(Time.time * 60f) % 10000);
}
public override void DrawShapes(Camera cam)
{
if (!enabled) return;
using (Draw.Command(cam))
{
Draw.BlendMode = ShapesBlendMode.Transparent;
Draw.ZTest = UnityEngine.Rendering.CompareFunction.Always;
// 绘制暗角
if (enableVignette)
{
DrawVignette();
}
// 绘制扫描线
if (enableScanlines)
{
DrawScanlines();
}
// 绘制噪点
if (enableNoise)
{
DrawNoise();
}
}
}
private void DrawNoise()
{
float halfWidth = areaSize.x / 2f;
float halfHeight = areaSize.y / 2f;
// 根据闪烁调整噪点数量
int actualDensity = Mathf.RoundToInt(noiseDensity * noiseIntensity * flickerValue);
for (int i = 0; i < actualDensity; i++)
{
// 使用随机数生成器获取位置
float x = areaCenter.x + (float)(noiseRandom.NextDouble() * 2 - 1) * halfWidth;
float y = areaCenter.y + (float)(noiseRandom.NextDouble() * 2 - 1) * halfHeight;
float z = areaCenter.z;
// 随机亮度
float brightness = (float)noiseRandom.NextDouble();
Color pointColor = noiseColor;
pointColor.a = noiseColor.a * brightness * flickerValue;
// 随机大小
float size = noiseSize * (0.5f + (float)noiseRandom.NextDouble());
Draw.Disc(new Vector3(x, y, z), size, pointColor);
}
}
private void DrawScanlines()
{
float halfWidth = areaSize.x / 2f;
float halfHeight = areaSize.y / 2f;
// 计算扫描线间距
float spacing = areaSize.y / scanlineCount;
Draw.LineGeometry = LineGeometry.Flat2D;
Draw.Thickness = scanlineThickness;
Color lineColor = scanlineColor;
lineColor.a = scanlineColor.a * scanlineIntensity * flickerValue;
for (int i = 0; i < scanlineCount; i++)
{
float y = areaCenter.y - halfHeight + spacing * i + spacing * 0.5f;
// 添加轻微的闪烁变化
float lineAlpha = lineColor.a * (0.8f + 0.2f * Mathf.Sin(y * 10f + Time.time * 5f));
Color finalColor = lineColor;
finalColor.a = lineAlpha;
Vector3 start = new Vector3(areaCenter.x - halfWidth, y, areaCenter.z);
Vector3 end = new Vector3(areaCenter.x + halfWidth, y, areaCenter.z);
Draw.Line(start, end, finalColor);
}
}
private void DrawVignette()
{
float halfWidth = areaSize.x / 2f;
float halfHeight = areaSize.y / 2f;
// 绘制四个角落的暗角渐变(使用多个半透明矩形模拟)
int steps = 8;
for (int i = 0; i < steps; i++)
{
float t = (float)i / steps;
float alpha = vignetteColor.a * vignetteIntensity * (1f - t) * flickerValue;
Color cornerColor = vignetteColor;
cornerColor.a = alpha * 0.3f;
float cornerSize = Mathf.Lerp(areaSize.x * 0.3f, 0.1f, t);
float offset = cornerSize * 0.5f;
// 四个角落
Vector3[] corners = new Vector3[]
{
new Vector3(areaCenter.x - halfWidth + offset, areaCenter.y + halfHeight - offset, areaCenter.z),
new Vector3(areaCenter.x + halfWidth - offset, areaCenter.y + halfHeight - offset, areaCenter.z),
new Vector3(areaCenter.x - halfWidth + offset, areaCenter.y - halfHeight + offset, areaCenter.z),
new Vector3(areaCenter.x + halfWidth - offset, areaCenter.y - halfHeight + offset, areaCenter.z)
};
foreach (var corner in corners)
{
Draw.Disc(corner, cornerSize, cornerColor);
}
}
}
/// <summary>
/// 设置覆盖区域(可以从 LanguageParticleManager 获取 Canvas 区域)
/// </summary>
public void SetArea(Vector3 center, Vector2 size)
{
areaCenter = center;
areaSize = size;
}
/// <summary>
/// 设置效果强度(0-1
/// </summary>
public void SetIntensity(float intensity)
{
intensity = Mathf.Clamp01(intensity);
noiseIntensity = intensity * 0.15f;
scanlineIntensity = intensity * 0.1f;
flickerIntensity = intensity * 0.05f;
vignetteIntensity = intensity * 0.3f;
}
private void OnDrawGizmosSelected()
{
// 在编辑器中显示效果区域
Gizmos.color = new Color(0f, 1f, 0f, 0.3f);
Gizmos.DrawWireCube(areaCenter, new Vector3(areaSize.x, areaSize.y, 0.01f));
}
}
}