Project_WL/AgentScripts/WL816j2_Build.cs

158 lines
8.6 KiB
C#
Raw Permalink Normal View History

// WL-816j2 — ① 띠 텍스처·머티리얼·물 머티리얼 E 를 만든다 (에디트 모드)
// 🔴 원본 셰이더/FI/씬 0줄. 전부 새 에셋(`Assets/WL/Look/Farm/**`)이다.
using System.Text;
using UnityEngine;
using UnityEditor;
public static class WL816j2_Build
{
const string MatDir = "Assets/WL/Look/Farm/Materials/";
const string TexDir = "Assets/WL/Look/Farm/Textures/";
const string TexPath = TexDir + "WL_ShoreFoam.png";
const string FoamMat = MatDir + "Farm_ShoreFoam.mat";
const string R_FoamScale = "Vector1_11671d7a4cdb4d059a6c69e39f3f7b3f";
const string R_FoamSpeed = "Vector1_3089b6a325a44c1686907af4ee3b0776";
const string R_FoamDistance = "Vector1_101dc4546b684d40bc2ff2fc59ab43d5";
const string R_FoamEdge = "Vector1_34f757bec6b8422b9aef3b9d97117a6e";
const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
const string C_Foam = "Color_e1f155248d144786a62fc1585ca21e9a";
const string C_FoamShadow = "Color_2323d69962e04c499c5d5f0925432b55";
public static void Run()
{
var sb = new StringBuilder();
// ── ① 거품 띠 텍스처 (가로 = 해안을 따라 · 세로 v0 = 물가, v1 = 바깥) ──
System.IO.Directory.CreateDirectory(TexDir);
const int W = 512, H = 128;
var tex = new Texture2D(W, H, TextureFormat.RGBA32, false);
var px = new Color32[W * H];
for (int y = 0; y < H; y++)
{
float v = y / (float)(H - 1);
float t = 1f - v; // 물가에서 1, 바깥에서 0
for (int x = 0; x < W; x++)
{
float n = Fbm(x, y, W); // 0~1 · 가로로 이어진다
// 🔴 Mathf.SmoothStep(a,b,t) 는 「a~b 사이 보간」이지 GLSL smoothstep 이 아니다(816j2 에서 이걸로 한 번 틀렸다).
float k = Mathf.Clamp01((t - 0.18f) / 0.30f + (n - 0.5f) * 1.0f);
float a = k * k * (3f - 2f * k); // 물가 = 1 · 바깥으로 가며 거품이 부서진다
px[y * W + x] = new Color32(255, 255, 255, (byte)Mathf.RoundToInt(Mathf.Clamp01(a) * 255f));
}
}
tex.SetPixels32(px); tex.Apply();
System.IO.File.WriteAllBytes(TexPath, tex.EncodeToPNG());
Object.DestroyImmediate(tex);
AssetDatabase.ImportAsset(TexPath, ImportAssetOptions.ForceUpdate);
var imp = AssetImporter.GetAtPath(TexPath) as TextureImporter;
if (imp != null)
{
imp.textureType = TextureImporterType.Default;
imp.alphaIsTransparency = true;
imp.alphaSource = TextureImporterAlphaSource.FromInput;
imp.wrapModeU = TextureWrapMode.Repeat;
imp.wrapModeV = TextureWrapMode.Clamp;
imp.filterMode = FilterMode.Bilinear;
imp.mipmapEnabled = true;
imp.maxTextureSize = 512;
imp.SaveAndReimport();
}
sb.AppendLine("띠 텍스처 = " + TexPath + " (" + W + "×" + H + " · U 반복 / V 고정 · mip on)");
// ── ② 띠 머티리얼 (URP Unlit · 반투명 · ZWrite off · 물보다 뒤에) ──
var sh = Shader.Find("Universal Render Pipeline/Unlit");
if (sh == null) { Debug.LogError("[816j2] URP Unlit 셰이더 없음"); return; }
var fm = AssetDatabase.LoadAssetAtPath<Material>(FoamMat);
if (fm == null) { fm = new Material(sh); AssetDatabase.CreateAsset(fm, FoamMat); }
fm.shader = sh;
fm.SetTexture("_BaseMap", AssetDatabase.LoadAssetAtPath<Texture2D>(TexPath));
fm.SetColor("_BaseColor", new Color(1f, 1f, 1f, 0.92f));
fm.SetFloat("_Surface", 1f); // Transparent
fm.SetFloat("_Blend", 0f); // Alpha
fm.SetFloat("_AlphaClip", 0f);
fm.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
fm.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
fm.SetFloat("_ZWrite", 0f);
fm.SetFloat("_Cull", (float)UnityEngine.Rendering.CullMode.Off);
fm.SetFloat("_QueueOffset", 50f); // 물(3000)보다 뒤
fm.SetFloat("_QueueControl", 0f); // 0 = 사용자 지정(URP 가 자동으로 되돌리지 못하게)
fm.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
fm.DisableKeyword("_ALPHATEST_ON");
fm.DisableKeyword("_ALPHAPREMULTIPLY_ON");
fm.renderQueue = 3050; // 물(3000)보다 뒤에 그린다
EditorUtility.SetDirty(fm);
sb.AppendLine("띠 머티리얼 = " + FoamMat + " · shader " + fm.shader.name + " · queue " + fm.renderQueue);
// ── ③ 물 머티리얼 E = D 복사본 + 무늬 선 약화 + 깊이 거품 낮춤 ──
string dst = MatDir + "Farm_Water_WL_E.mat";
if (AssetDatabase.LoadAssetAtPath<Material>(dst) == null)
{ AssetDatabase.CopyAsset(MatDir + "Farm_Water_WL_D.mat", dst); AssetDatabase.ImportAsset(dst); }
var e = AssetDatabase.LoadAssetAtPath<Material>(dst);
// ⓐ 무늬를 1칸 2.5 m → **1.0 m** 로 더 잘게(「금 간 유리」 → 잔물결) · 흐름 0.8 m/s 유지
const float cellM = 1.0f;
float size = 1000f / (cellM * 6f);
e.SetFloat("Vector1_07238257334b4a149e675e2451801030", size); // Size
e.SetFloat("Vector1_99cc56b5c6fd474082f07f00a6df94f9", 0.3085f / size); // Strength
e.SetFloat("Vector1_8e22a98f75c94b218c49e6c4805e799d", 0.8f * size / 1000f); // Speed
e.SetFloat("Vector1_ad7e0fcd37f44d68b68de6f06bb43b96", 0.8f * size / 1000f); // NoiseSpeed
// ⓑ 선 세기 — 밝은 쪽(LightColor)은 물색 가까이, 어두운 쪽(FoamShadowColor)은 흰색으로 없앤다
e.SetColor(C_Light, new Color(0.42f, 0.72f, 0.845f, 1f));
e.SetColor(C_FoamShadow, Color.white);
// ⓒ 깊이 기반 거품은 **끈다** — 둘레 띠가 대신한다(둘 다 켜면 분홍 얼룩이 된다)
e.SetColor(C_Foam, e.GetColor("Color_9af4ad59934f40d1ae6565e6ab22c45e")); // = WaterColor
e.SetFloat(R_FoamDistance, 2.2f);
e.SetFloat(R_FoamEdge, 4f);
EditorUtility.SetDirty(e);
sb.AppendLine("물 E = " + dst + " · Size " + size.ToString("F2") + "(무늬 1칸 " + cellM + " m)"
+ " · LightColor " + e.GetColor(C_Light) + " · FoamShadowColor 흰색"
+ " · FoamColor = 물색(깊이 거품 off) · FoamDistance " + e.GetFloat(R_FoamDistance) + " · FoamEdge " + e.GetFloat(R_FoamEdge));
// ── ④ SO ──
var cfg = AssetDatabase.LoadAssetAtPath<WL.Look.Farm.WLIslandLookSettings>(
"Assets/WL/Look/Farm/Resources/WL/WLIslandLookSettings.asset");
var so = new SerializedObject(cfg);
so.FindProperty("waterTo").objectReferenceValue = e;
so.FindProperty("shoreFoamMaterial").objectReferenceValue = fm;
so.FindProperty("shoreFoamEnabled").intValue = 1;
so.ApplyModifiedPropertiesWithoutUndo();
EditorUtility.SetDirty(cfg);
AssetDatabase.SaveAssets();
sb.AppendLine("SO waterTo = " + cfg.waterTo.name + " · shoreFoamMaterial = " + cfg.shoreFoamMaterial.name
+ " · 폭 " + cfg.shoreFoamWidth + " m · 격자 " + cfg.shoreFoamCell + " m");
System.IO.File.WriteAllText("AgentScripts/WL816j2_BUILD.txt", sb.ToString());
Debug.Log("[816j2 build]\n" + sb);
}
// 가로로 이어지는(타일링) 값 노이즈 fbm
static float Fbm(int x, int y, int W)
{
float s = 0f, amp = 0.5f; int period = 32;
for (int o = 0; o < 3; o++)
{
s += amp * Value(x, y, W, period);
amp *= 0.5f; period *= 2;
}
return Mathf.Clamp01(s + 0.25f);
}
static float Value(int x, int y, int W, int period)
{
float fx = x / (float)period, fy = y / (float)period;
int x0 = Mathf.FloorToInt(fx), y0 = Mathf.FloorToInt(fy);
float tx = fx - x0, ty = fy - y0;
tx = tx * tx * (3f - 2f * tx); ty = ty * ty * (3f - 2f * ty);
int wrap = Mathf.Max(1, W / period);
float a = H2(Mod(x0, wrap), y0), b = H2(Mod(x0 + 1, wrap), y0);
float c = H2(Mod(x0, wrap), y0 + 1), d = H2(Mod(x0 + 1, wrap), y0 + 1);
return Mathf.Lerp(Mathf.Lerp(a, b, tx), Mathf.Lerp(c, d, tx), ty);
}
static int Mod(int a, int m) { int r = a % m; return r < 0 ? r + m : r; }
static float H2(int x, int y)
{
uint h = (uint)(x * 374761393 + y * 668265263 + 1442695040);
h = (h ^ (h >> 13)) * 1274126177u;
return ((h ^ (h >> 16)) & 0xFFFFFF) / (float)0xFFFFFF;
}
}