112 lines
6.9 KiB
C#
112 lines
6.9 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
||
// WLCharacterBacklightSettings.cs — 캐릭터 역광(림·라이트 랩·피부 투과) + 번짐(Bloom) 값 (C45 · 코드 상수 금지)
|
||
//
|
||
// 2026-09-17 PD 「캐릭터가 조금 더 돋보이게」 + 팁(차가운 역광 · SSS · Bloom).
|
||
// enabled_ = 0 → 아무 것도 덧붙이지 않는다(캐릭터 재질 배열 원래대로) · bloomEnabled = 0 → 카메라/볼륨 0 변경.
|
||
// 🔴 Debug.LogError / Debug.LogException 을 쓰지 않는다(813z 규칙).
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
using UnityEngine;
|
||
|
||
namespace WL.Look.Character
|
||
{
|
||
public class WLCharacterBacklightSettings : ScriptableObject
|
||
{
|
||
[Header("스위치")]
|
||
[Tooltip("0 = 역광 패스 전체 off(재질 배열 원래대로).")]
|
||
public int enabled_ = 1;
|
||
[Tooltip("1 이면 적용 내역을 로그로 남긴다.")]
|
||
public int verboseLog = 0;
|
||
|
||
[Header("대상")]
|
||
[Tooltip("이 셰이더 이름의 재질을 가진 렌더러에만 덧붙인다(얼굴 Unlit/Transparent · 파티클 제외). 비우면 파티클 외 전부.")]
|
||
public string shaderNameFilter = "Shader Graphs/Toon";
|
||
[Tooltip("재질 이름에 이 글자가 들어 있으면 피부로 보고 피부 투과(SSS)를 켠 재질을 물린다.")]
|
||
public string[] skinMaterialHints = { "Skin" };
|
||
|
||
[Header("① 역광 림 — 메인 조명(따뜻함)과 반대인 차가운 색")]
|
||
[ColorUsage(false, true)] public Color rimColor = new Color(0.28f, 0.62f, 1f, 1f);
|
||
[Tooltip("림 밝기 배수(1 초과 = HDR · Bloom 이 집어낸다).")]
|
||
public float rimStrength = 1.45f;
|
||
[Header("①-b 화면 공간 깊이 림(기본) — 실루엣 바깥쪽에만 · 화면 픽셀 굵기 일정")]
|
||
[Tooltip("1 = 깊이 림 사용(URP 에셋의 Depth Texture 가 꺼져 있으면 자동으로 프레넬만 쓴다). 실측: 프레넬만 쓰면 머리카락 안쪽 가닥마다 줄이 생긴다.")]
|
||
public int rimUseDepth = 1;
|
||
[Tooltip("띠 굵기 = 화면 짧은 변 × 이 값(0.0045 → 1080 기준 ≈ 5 px).")]
|
||
[Range(0f, 0.02f)] public float rimWidth = 0.0045f;
|
||
[Tooltip("역광 쪽 이웃 픽셀이 이만큼(m) 더 멀면 실루엣으로 본다(작으면 머리카락 가닥에도 생긴다).")]
|
||
public float rimDepthThreshold = 0.12f;
|
||
[Tooltip("깊이 림에 섞는 프레넬 림의 양 — 가까울 때(두께감).")]
|
||
[Range(0f, 1f)] public float rimFresnelNear = 0.6f;
|
||
[Tooltip("깊이 림에 섞는 프레넬 림의 양 — 멀 때(0 = 깊이 림만 · 가닥 줄 없음).")]
|
||
[Range(0f, 1f)] public float rimFresnelFar = 0f;
|
||
|
||
[Header("①-a 프레넬 림(보조 · 깊이 텍스처가 없을 때는 이것만)")]
|
||
[Tooltip("가까울 때(rimNearDistance 이하)의 띠 굵기 — 클수록 가는 띠(0.4 = 굵게 · 0.7 = 가늘게).")]
|
||
[Range(0f, 1f)] public float rimThreshold = 0.52f;
|
||
[Tooltip("멀 때(rimFarDistance 이상)의 띠 굵기 — 작게 줘서 굵게. 게임 카메라(섬 12 m · 던전 11 m)에서 캐릭터가 ~70 px 라 가는 띠는 1 px 로 사라진다(실측).")]
|
||
[Range(0f, 1f)] public float rimThresholdFar = 0.36f;
|
||
[Tooltip("이 거리(m) 이하 = 가까움.")]
|
||
public float rimNearDistance = 3f;
|
||
[Tooltip("이 거리(m) 이상 = 멂.")]
|
||
public float rimFarDistance = 12f;
|
||
[Tooltip("띠 가장자리 부드러움(작을수록 셀 느낌).")]
|
||
[Range(0.001f, 0.5f)] public float rimSoftness = 0.05f;
|
||
[Tooltip("0 = 둘레 전부 · 1 = 가상 역광 쪽 윤곽만.")]
|
||
[Range(0f, 1f)] public float rimDirectional = 0.85f;
|
||
[Tooltip("림이 바탕을 덮는 정도(1 = 림 색 그대로 · 0 = 순수 가산). 실측: 순수 가산은 노란 머리·살색 위에서 흰 테가 돼 차가운 색이 안 보였다.")]
|
||
[Range(0f, 1f)] public float rimOpacity = 0.85f;
|
||
|
||
[Header("가상 역광 위치(카메라 기준) — 캐릭터 뒤 + 위 + 옆")]
|
||
[Tooltip("위쪽 성분(클수록 머리·어깨 윗선에 맺힌다).")]
|
||
public float backlightUp = 0.7f;
|
||
[Tooltip("옆 성분(+ = 화면 오른쪽 · − = 왼쪽). 메인 조명이 왼쪽 앞에서 오므로 오른쪽 뒤가 자연스럽다.")]
|
||
public float backlightSide = 0.8f;
|
||
|
||
[Header("② 라이트 랩 — 빛이 안쪽으로 스며드는 옅은 번짐")]
|
||
[ColorUsage(false, true)] public Color wrapColor = new Color(0.75f, 0.85f, 1f, 1f);
|
||
public float wrapStrength = 0.12f;
|
||
public float wrapPower = 1.6f;
|
||
|
||
[Header("③ 피부 투과(SSS 흉내) — 피부 재질에만")]
|
||
[ColorUsage(false, true)] public Color sssColor = new Color(1f, 0.32f, 0.22f, 1f);
|
||
public float sssStrength = 1.5f;
|
||
public float sssPower = 1.7f;
|
||
|
||
[Header("④ 번짐(Bloom) — 역광이 화사하게 번지게(전체 화면 패스 · 모바일 비용 있음)")]
|
||
[Tooltip("0 = 카메라·볼륨을 건드리지 않는다.")]
|
||
public int bloomEnabled = 1;
|
||
[Tooltip("이 씬이 떠 있을 때만 켠다(전투 맵의 기존 후처리는 그대로).")]
|
||
public string[] bloomScenes = { "Level01" };
|
||
[Tooltip("이 밝기 이상만 번진다(HDR 1 초과 = 림·반짝임만).")]
|
||
public float bloomThreshold = 1.05f;
|
||
public float bloomIntensity = 0.55f;
|
||
[Range(0f, 1f)] public float bloomScatter = 0.55f;
|
||
[Tooltip("1 = 카메라 HDR 을 켠다(림만 골라 번지게 · 끄면 흰 거품·밝은 모래도 같이 번진다).")]
|
||
public int bloomHdr = 1;
|
||
[Tooltip("1 = 1/4 해상도에서 시작(모바일 권장).")]
|
||
public int bloomQuarter = 1;
|
||
[Tooltip("블러 단계 수(작을수록 쌈).")]
|
||
public int bloomMaxIterations = 4;
|
||
|
||
// ───────────────────────────────────────── 싱글턴(Resources)
|
||
public const string ResourcePath = "WL/WLCharacterBacklightSettings";
|
||
static WLCharacterBacklightSettings s_inst;
|
||
static bool s_tried;
|
||
|
||
public static WLCharacterBacklightSettings Instance
|
||
{
|
||
get
|
||
{
|
||
if (s_inst == null && !s_tried)
|
||
{
|
||
s_tried = true;
|
||
s_inst = Resources.Load<WLCharacterBacklightSettings>(ResourcePath);
|
||
}
|
||
return s_inst;
|
||
}
|
||
}
|
||
|
||
public static void Invalidate() { s_inst = null; s_tried = false; }
|
||
}
|
||
}
|