Streamingle_URP/Assets/Scripts/NiloToonPlanarReflectionBridge.cs

203 lines
7.4 KiB
C#

using UnityEngine;
using PlanarReflections5;
/// <summary>
/// NiloToon Environment 셰이더와 PIDI Planar Reflections 5를 연동하는 브리지 스크립트
/// </summary>
[System.Serializable]
public class NiloToonReflectionSettings
{
[Header("Reflection Control")]
[Range(0f, 1f)]
public float reflectionIntensity = 1.0f;
[ColorUsage(false)]
public Color reflectionTintColor = Color.white;
[Range(0.1f, 5f)]
public float fresnelPower = 1.5f;
[Range(0f, 0.1f)]
public float distortionStrength = 0.02f;
[Range(0f, 10f)]
public float depthFade = 1.0f;
[Range(0f, 2f)]
public float blurRadius = 0.5f;
[Header("Advanced")]
public bool enableReflection = true;
public bool useDepthFade = false;
public LayerMask reflectionLayers = -1;
}
[RequireComponent(typeof(PlanarReflectionRenderer))]
public class NiloToonPlanarReflectionBridge : MonoBehaviour
{
[Header("NiloToon Integration Settings")]
public NiloToonReflectionSettings reflectionSettings = new NiloToonReflectionSettings();
[Header("Shader Keywords")]
[SerializeField] private bool enableReflectionDepthFade = false;
private PlanarReflectionRenderer planarRenderer;
private Camera[] monitoredCameras;
// 셰이더 프로퍼티 IDs (성능 최적화)
private static readonly int EnablePlanarReflectionID = Shader.PropertyToID("_EnablePlanarReflection");
private static readonly int ReflectionIntensityID = Shader.PropertyToID("_ReflectionIntensity");
private static readonly int ReflectionTintColorID = Shader.PropertyToID("_ReflectionTintColor");
private static readonly int ReflectionFresnelID = Shader.PropertyToID("_ReflectionFresnel");
private static readonly int ReflectionDistortionID = Shader.PropertyToID("_ReflectionDistortion");
private static readonly int ReflectionDepthFadeID = Shader.PropertyToID("_ReflectionDepthFade");
private static readonly int ReflectionBlurRadiusID = Shader.PropertyToID("_ReflectionBlurRadius");
private void Awake()
{
planarRenderer = GetComponent<PlanarReflectionRenderer>();
if (planarRenderer == null)
{
Debug.LogError("NiloToonPlanarReflectionBridge requires PlanarReflectionRenderer component!");
enabled = false;
return;
}
}
private void Start()
{
// 초기 설정 적용
UpdateShaderProperties();
UpdateShaderKeywords();
}
private void Update()
{
// 실시간으로 셰이더 프로퍼티 업데이트
UpdateShaderProperties();
// 카메라 변경 감지 및 업데이트
if (monitoredCameras == null || monitoredCameras.Length != Camera.allCamerasCount)
{
UpdateCameraReferences();
}
}
private void UpdateShaderProperties()
{
// Global 셰이더 프로퍼티 업데이트
Shader.SetGlobalFloat(EnablePlanarReflectionID, reflectionSettings.enableReflection ? 1.0f : 0.0f);
Shader.SetGlobalFloat(ReflectionIntensityID, reflectionSettings.reflectionIntensity);
Shader.SetGlobalVector(ReflectionTintColorID, new Vector4(
reflectionSettings.reflectionTintColor.r,
reflectionSettings.reflectionTintColor.g,
reflectionSettings.reflectionTintColor.b,
reflectionSettings.reflectionTintColor.a));
Shader.SetGlobalFloat(ReflectionFresnelID, reflectionSettings.fresnelPower);
Shader.SetGlobalFloat(ReflectionDistortionID, reflectionSettings.distortionStrength);
Shader.SetGlobalFloat(ReflectionDepthFadeID, reflectionSettings.depthFade);
Shader.SetGlobalFloat(ReflectionBlurRadiusID, reflectionSettings.blurRadius);
}
private void UpdateShaderKeywords()
{
// 셰이더 키워드 업데이트
if (enableReflectionDepthFade && reflectionSettings.useDepthFade)
{
Shader.EnableKeyword("_REFLECTION_DEPTH_FADE");
}
else
{
Shader.DisableKeyword("_REFLECTION_DEPTH_FADE");
}
}
private void UpdateCameraReferences()
{
monitoredCameras = new Camera[Camera.allCamerasCount];
Camera.GetAllCameras(monitoredCameras);
// Planar Reflection 설정을 카메라별로 동기화
if (planarRenderer != null && planarRenderer.Settings != null)
{
planarRenderer.Settings.reflectLayers = reflectionSettings.reflectionLayers;
planarRenderer.Settings.renderDepth = reflectionSettings.useDepthFade;
}
}
/// <summary>
/// 특정 재질에 반사 설정을 적용합니다.
/// </summary>
/// <param name="material">적용할 재질</param>
public void ApplyToMaterial(Material material)
{
if (material == null) return;
material.SetFloat(EnablePlanarReflectionID, reflectionSettings.enableReflection ? 1.0f : 0.0f);
material.SetFloat(ReflectionIntensityID, reflectionSettings.reflectionIntensity);
material.SetVector(ReflectionTintColorID, new Vector4(
reflectionSettings.reflectionTintColor.r,
reflectionSettings.reflectionTintColor.g,
reflectionSettings.reflectionTintColor.b,
reflectionSettings.reflectionTintColor.a));
material.SetFloat(ReflectionFresnelID, reflectionSettings.fresnelPower);
material.SetFloat(ReflectionDistortionID, reflectionSettings.distortionStrength);
material.SetFloat(ReflectionDepthFadeID, reflectionSettings.depthFade);
material.SetFloat(ReflectionBlurRadiusID, reflectionSettings.blurRadius);
// 키워드 설정
if (enableReflectionDepthFade && reflectionSettings.useDepthFade)
{
material.EnableKeyword("_REFLECTION_DEPTH_FADE");
}
else
{
material.DisableKeyword("_REFLECTION_DEPTH_FADE");
}
}
/// <summary>
/// 씬의 모든 NiloToon Environment 재질에 설정을 적용합니다.
/// </summary>
public void ApplyToAllNiloToonMaterials()
{
Renderer[] renderers = FindObjectsOfType<Renderer>();
foreach (Renderer renderer in renderers)
{
foreach (Material mat in renderer.materials)
{
// NiloToon Environment 셰이더인지 확인 (이름으로 판별)
if (mat.shader.name.Contains("NiloToon") && mat.shader.name.Contains("Environment"))
{
ApplyToMaterial(mat);
}
}
}
}
private void OnValidate()
{
// Inspector에서 값이 변경될 때 실시간 업데이트
if (Application.isPlaying)
{
UpdateShaderProperties();
UpdateShaderKeywords();
}
}
#if UNITY_EDITOR
[UnityEditor.MenuItem("Tools/NiloToon/Create Planar Reflection Bridge")]
private static void CreateBridge()
{
GameObject bridge = new GameObject("NiloToon Planar Reflection Bridge");
bridge.AddComponent<PlanarReflectionRenderer>();
bridge.AddComponent<NiloToonPlanarReflectionBridge>();
UnityEditor.Selection.activeGameObject = bridge;
UnityEditor.EditorGUIUtility.PingObject(bridge);
Debug.Log("NiloToon Planar Reflection Bridge가 생성되었습니다!");
}
#endif
}