Merge branch 'wl/gameplay/WL-816j2-water-fix'
This commit is contained in:
commit
0087a6cab5
|
|
@ -0,0 +1,4 @@
|
|||
띠 텍스처 = Assets/WL/Look/Farm/Textures/WL_ShoreFoam.png (512×128 · U 반복 / V 고정 · mip on)
|
||||
띠 머티리얼 = Assets/WL/Look/Farm/Materials/Farm_ShoreFoam.mat · shader Universal Render Pipeline/Unlit · queue 3050
|
||||
물 E = Assets/WL/Look/Farm/Materials/Farm_Water_WL_E.mat · Size 166.67(무늬 1칸 1 m) · LightColor RGBA(0.420, 0.720, 0.845, 1.000) · FoamShadowColor 흰색 · FoamColor = 물색(깊이 거품 off) · FoamDistance 2.2 · FoamEdge 4
|
||||
SO waterTo = Farm_Water_WL_E · shoreFoamMaterial = Farm_ShoreFoam · 폭 1.6 m · 격자 0.5 m
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
=== WL-816j2 ③ 띠 진단 ===
|
||||
띠 머티리얼 = WL_ShoreFoam(runtime) shader=Universal Render Pipeline/Unlit renderQueue=3050 _Surface=1 _ZWrite=0 _SrcBlend=5 _DstBlend=10 _BaseMap=WL_ShoreFoam keyword_TRANSPARENT=True
|
||||
물 머티리얼 renderQueue = 3000
|
||||
띠 메시 bounds = Center: (3.90, -0.98, 3.90), Extents: (9.50, 0.00, 9.50) · 렌더러 enabled=True bounds=Center: (3.90, -0.98, 3.90), Extents: (9.50, 0.00, 9.50)
|
||||
|
||||
1) 지금 그대로 밝은픽셀 1.67% → Screenshots_WL/WL816j2/g_diag_asis.png
|
||||
2) renderQueue 3100 강제 밝은픽셀 1.64% → Screenshots_WL/WL816j2/g_diag_q3100.png
|
||||
3) 물 끄고 띠만 밝은픽셀 0.09% → Screenshots_WL/WL816j2/g_diag_bandonly.png
|
||||
4) 띠 메시 위치(빨강) 밝은픽셀 0.05% → Screenshots_WL/WL816j2/g_diag_red.png
|
||||
PD 구도에서도 밝은픽셀 0.09% → Screenshots_WL/WL816j2/g_diag_red_pd.png
|
||||
5) 큐 3100 · PD 구도 밝은픽셀 0.35% → Screenshots_WL/WL816j2/g_diag_q3100_pd.png
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// WL-816j2 — ③ 띠가 왜 안 보이나 (실측) · 물보다 뒤에 그려지는지 · 알파가 살아 있는지
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using WL.Look.Farm;
|
||||
|
||||
public static class WL816j2_Diag
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2D");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2D");
|
||||
go.AddComponent<WL816j2_DiagRunner>();
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_DiagRunner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Diag.D;
|
||||
const int PW = 1280, PH = 720;
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
string Shot(Camera cam, string path)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(PW, PH, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, PW, PH), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
var px = t.GetPixels32();
|
||||
int white = 0;
|
||||
for (int i = 0; i < px.Length; i += 3) if (px[i].r > 205 && px[i].g > 200 && px[i].b > 200) white++;
|
||||
Object.DestroyImmediate(t);
|
||||
return "밝은픽셀 " + (300f * white / px.Length).ToString("F2") + "% → " + path;
|
||||
}
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 ③ 띠 진단 ===");
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
var foam = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
|
||||
if (foam == null || water == null || live == null) { L("🔴 없음"); Done(); yield break; }
|
||||
var mr = foam.GetComponent<MeshRenderer>();
|
||||
var mf = foam.GetComponent<MeshFilter>();
|
||||
var m = mr.sharedMaterial;
|
||||
L("띠 머티리얼 = " + m.name + " shader=" + m.shader.name + " renderQueue=" + m.renderQueue
|
||||
+ " _Surface=" + m.GetFloat("_Surface") + " _ZWrite=" + m.GetFloat("_ZWrite")
|
||||
+ " _SrcBlend=" + m.GetFloat("_SrcBlend") + " _DstBlend=" + m.GetFloat("_DstBlend")
|
||||
+ " _BaseMap=" + (m.GetTexture("_BaseMap") ? m.GetTexture("_BaseMap").name : "없음")
|
||||
+ " keyword_TRANSPARENT=" + m.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT"));
|
||||
L("물 머티리얼 renderQueue = " + water.sharedMaterial.renderQueue);
|
||||
L("띠 메시 bounds = " + mf.sharedMesh.bounds + " · 렌더러 enabled=" + mr.enabled + " bounds=" + mr.bounds);
|
||||
|
||||
// 카메라를 물가로 가까이 — 띠가 잘 보이는 확대
|
||||
var cgo = new GameObject("~WL816j2DCam"); cgo.hideFlags = HideFlags.DontSave;
|
||||
var cam = cgo.AddComponent<Camera>();
|
||||
cam.fieldOfView = 34f; cam.nearClipPlane = 0.1f; cam.farClipPlane = 2000f;
|
||||
cam.clearFlags = CameraClearFlags.Skybox; cam.cullingMask = ~0; cam.depth = -100f;
|
||||
cgo.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
|
||||
var b = mr.bounds;
|
||||
cgo.transform.position = new Vector3(b.center.x, 3.2f, b.min.z - 9f);
|
||||
cgo.transform.LookAt(new Vector3(b.center.x, -1f, b.min.z + 2f));
|
||||
|
||||
L("");
|
||||
L("1) 지금 그대로 " + Shot(cam, D + "g_diag_asis.png"));
|
||||
|
||||
// ① 큐를 강제로 물 뒤로
|
||||
var q = new Material(m); q.renderQueue = 3100;
|
||||
mr.sharedMaterial = q; yield return null; yield return null;
|
||||
L("2) renderQueue 3100 강제 " + Shot(cam, D + "g_diag_q3100.png"));
|
||||
|
||||
// ② 물을 끄고 띠만
|
||||
water.enabled = false; yield return null; yield return null;
|
||||
L("3) 물 끄고 띠만 " + Shot(cam, D + "g_diag_bandonly.png"));
|
||||
water.enabled = true; yield return null;
|
||||
|
||||
// ③ 알파 무시하고 불투명 빨강 — 띠 메시가 어디에 있는지
|
||||
var dbg = new Material(Shader.Find("Universal Render Pipeline/Unlit"));
|
||||
dbg.SetColor("_BaseColor", new Color(1f, 0f, 0f, 1f));
|
||||
dbg.renderQueue = 3100;
|
||||
mr.sharedMaterial = dbg; yield return null; yield return null;
|
||||
L("4) 띠 메시 위치(빨강) " + Shot(cam, D + "g_diag_red.png"));
|
||||
L(" PD 구도에서도 " + Shot(live, D + "g_diag_red_pd.png"));
|
||||
|
||||
mr.sharedMaterial = q; yield return null;
|
||||
L("5) 큐 3100 · PD 구도 " + Shot(live, D + "g_diag_q3100_pd.png"));
|
||||
|
||||
Object.DestroyImmediate(cgo);
|
||||
Done();
|
||||
}
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_DIAG.txt", sb.ToString());
|
||||
Debug.Log("[816j2 diag]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
=== WL-816j2 ⑧ 최종 (PD 구도 1280×720) ===
|
||||
Load_Map(900) = 🔴 로그인 없이는 못 탄다 → LoadSceneAsync(Level01, Additive)
|
||||
물 = Farm_Water_WL_E · 둘레 띠 = 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
|
||||
1) [전] main(물 D · 띠 없음 = PD 가 본 화면) 바다평균 #5C96C2 · 거품 10.19% #EDD9E6(R−B 7) → Screenshots_WL/WL816j2/z2_before_pd.png
|
||||
[후] 816j2(물 E · 둘레 띠) 바다평균 #5794C1 · 거품 1.16% #F4F3FC(R−B -8) → Screenshots_WL/WL816j2/z2_after_pd.png
|
||||
세로(게임 기준 1080×1920) 바다평균 #5694C1 · 거품 3.32% #F6F5FC(R−B -6) → Screenshots_WL/WL816j2/z2_after_portrait.png
|
||||
|
||||
2) 사방(위에서) 바다평균 #5894C1 · 거품 0.43% #F6F5FC(R−B -6) → Screenshots_WL/WL816j2/z2_top.png
|
||||
물가 확대 [전] 바다평균 #A2B3CE · 거품 38.36% #FBDFE4(R−B 23) → Screenshots_WL/WL816j2/z2_zoom_before.png
|
||||
물가 확대 [후] 바다평균 #5F93BD · 거품 2.08% #F0DFF1(R−B -1) → Screenshots_WL/WL816j2/z2_zoom_after.png
|
||||
|
||||
3) 걷기 (0.00, 0.00, 0.00) → (4.24, 0.01, 4.24) · 이동 6.00 m · grounded=True
|
||||
확장 1칸 잠금 → 타일 3 · 띠 삼각형 1268 · 정점 766 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
바다평균 #5794C1 · 거품 0.33% #F6F7FB(R−B -5) → Screenshots_WL/WL816j2/z2_top_locked.png
|
||||
다시 열기 → 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1 · 띠 재생성 2회
|
||||
바다평균 #5794C1 · 거품 0.80% #F7F5FD(R−B -6) → Screenshots_WL/WL816j2/z2_top_unlocked.png
|
||||
|
||||
4) 성능 (PD 구도 1280×720 · 60프레임 · 교대 2회)
|
||||
0회차 전(물 D · 띠 없음) = 0.882 ms
|
||||
0회차 후(물 E · 띠 on) = 0.872 ms
|
||||
0회차 후(물 E · 띠 off) = 0.926 ms
|
||||
1회차 전(물 D · 띠 없음) = 0.944 ms
|
||||
1회차 후(물 E · 띠 on) = 0.916 ms
|
||||
1회차 후(물 E · 띠 off) = 0.851 ms
|
||||
띠 = 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
|
||||
5) 되돌리기
|
||||
shoreFoamEnabled 0 + waterTo=D → 816j 그대로 바다평균 #6098C3 · 거품 10.26% #EEDBE7(R−B 7) → Screenshots_WL/WL816j2/z2_rollback_816j.png
|
||||
waterMode 0 → FI 원본 물 바다평균 #5DB6FD · 거품 1.66% #FAF9FC(R−B -2) → Screenshots_WL/WL816j2/z2_rollback_fi.png
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
// WL-816j2 — ⑧ 최종 확인: PD 구도 전/후 · 사방 띠 · 확장 · 걷기 · 성능 · 되돌리기
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.SceneManagement;
|
||||
using WL.Look.Farm;
|
||||
using FIIsland = CryingSnow.FarmingIsland.Island;
|
||||
|
||||
public static class WL816j2_Final
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public const int PW = 1280, PH = 720;
|
||||
public static void Open()
|
||||
{
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(
|
||||
"Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single);
|
||||
}
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2F");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2F");
|
||||
go.AddComponent<WL816j2_FinalRunner>();
|
||||
}
|
||||
public static string Shot(Camera cam, string path, int w, int h)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var rt = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(w, h, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, w, h), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
var px = t.GetPixels32();
|
||||
long r = 0, g = 0, b = 0; int n = 0; long fr = 0, fg = 0, fb = 0; int fn = 0, tot = 0;
|
||||
for (int y = 20; y < Mathf.Min(320, h); y += 2)
|
||||
for (int x = 20; x < Mathf.Min(340, w); x += 2) { var c = px[y * w + x]; r += c.r; g += c.g; b += c.b; n++; }
|
||||
int y1 = (int)(h * 0.55f);
|
||||
for (int y = 0; y < y1; y++)
|
||||
for (int x = 0; x < w; x += 2) { var c = px[y * w + x]; tot++; if (c.r > 200 && c.g > 195 && c.b > 195) { fr += c.r; fg += c.g; fb += c.b; fn++; } }
|
||||
Object.DestroyImmediate(t);
|
||||
string foam = fn == 0 ? "거품 0%" : "거품 " + (100f * fn / tot).ToString("F2") + "% #"
|
||||
+ ((int)(fr / fn)).ToString("X2") + ((int)(fg / fn)).ToString("X2") + ((int)(fb / fn)).ToString("X2")
|
||||
+ "(R−B " + ((int)(fr / fn) - (int)(fb / fn)) + ")";
|
||||
return "바다평균 #" + ((int)(r / n)).ToString("X2") + ((int)(g / n)).ToString("X2") + ((int)(b / n)).ToString("X2")
|
||||
+ " · " + foam + " → " + path;
|
||||
}
|
||||
public static float Ms(Camera cam, int frames)
|
||||
{
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; cam.targetTexture = rt;
|
||||
for (int i = 0; i < 10; i++) cam.Render();
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
for (int i = 0; i < frames; i++) cam.Render();
|
||||
sw.Stop();
|
||||
cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
return (float)sw.Elapsed.TotalMilliseconds / frames;
|
||||
}
|
||||
public static void Strip(string[] paths, string outPath)
|
||||
{
|
||||
var ts = new Texture2D[paths.Length]; int w = 0, h = 0;
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
{
|
||||
if (!System.IO.File.Exists(paths[i])) return;
|
||||
ts[i] = new Texture2D(2, 2, TextureFormat.RGB24, false);
|
||||
ts[i].LoadImage(System.IO.File.ReadAllBytes(paths[i]));
|
||||
w = Mathf.Max(w, ts[i].width); h += ts[i].height;
|
||||
}
|
||||
var o = new Texture2D(w, h, TextureFormat.RGB24, false);
|
||||
var f = new Color32[w * h];
|
||||
for (int i = 0; i < f.Length; i++) f[i] = new Color32(24, 24, 28, 255);
|
||||
o.SetPixels32(f);
|
||||
int y = h;
|
||||
for (int i = 0; i < ts.Length; i++) { y -= ts[i].height; o.SetPixels32(0, y, ts[i].width, ts[i].height, ts[i].GetPixels32()); }
|
||||
o.Apply();
|
||||
System.IO.File.WriteAllBytes(outPath, o.EncodeToPNG());
|
||||
Object.DestroyImmediate(o);
|
||||
for (int i = 0; i < ts.Length; i++) Object.DestroyImmediate(ts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_FinalRunner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Final.D;
|
||||
const string MatDir = "Assets/WL/Look/Farm/Materials/";
|
||||
const int PW = WL816j2_Final.PW, PH = WL816j2_Final.PH;
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 ⑧ 최종 (PD 구도 1280×720) ===");
|
||||
bool viaGame = false;
|
||||
try { if (InGameInfo.Ins != null) { InGameInfo.Ins.Load_Map(900); viaGame = true; } } catch { }
|
||||
L("Load_Map(900) = " + (viaGame ? "성공" : "🔴 로그인 없이는 못 탄다 → LoadSceneAsync(Level01, Additive)"));
|
||||
if (!viaGame)
|
||||
{
|
||||
var op = SceneManager.LoadSceneAsync("Level01", LoadSceneMode.Additive);
|
||||
while (op != null && !op.isDone) yield return null;
|
||||
}
|
||||
for (int i = 0; i < 8; i++) yield return new WaitForSeconds(1f);
|
||||
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
var foam = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
|
||||
if (water == null || live == null || foam == null) { L("🔴 없음"); Done(); yield break; }
|
||||
var mr = foam.GetComponent<MeshRenderer>();
|
||||
var E = water.sharedMaterial;
|
||||
var Dm = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_Water_WL_D.mat");
|
||||
var FI = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_SimpleWater_Demo.mat");
|
||||
L("물 = " + E.name + " · 둘레 띠 = " + WLShoreFoam.LastLog);
|
||||
|
||||
// 1) 전/후
|
||||
mr.enabled = false; water.sharedMaterial = Dm; yield return null; yield return new WaitForSeconds(0.4f);
|
||||
L("");
|
||||
L("1) [전] main(물 D · 띠 없음 = PD 가 본 화면) " + WL816j2_Final.Shot(live, D + "z2_before_pd.png", PW, PH));
|
||||
mr.enabled = true; water.sharedMaterial = E; yield return null; yield return new WaitForSeconds(0.4f);
|
||||
L(" [후] 816j2(물 E · 둘레 띠) " + WL816j2_Final.Shot(live, D + "z2_after_pd.png", PW, PH));
|
||||
WL816j2_Final.Strip(new[] { D + "z2_before_pd.png", D + "z2_after_pd.png" }, D + "z2_pd_before_after.png");
|
||||
L(" 세로(게임 기준 1080×1920) " + WL816j2_Final.Shot(live, D + "z2_after_portrait.png", 1080, 1920));
|
||||
|
||||
// 2) 사방 + 물가 확대
|
||||
var tgo = new GameObject("~WL816j2FT"); tgo.hideFlags = HideFlags.DontSave;
|
||||
var tc = tgo.AddComponent<Camera>();
|
||||
tc.fieldOfView = 55f; tc.nearClipPlane = 0.1f; tc.farClipPlane = 2000f;
|
||||
tc.clearFlags = CameraClearFlags.Skybox; tc.cullingMask = ~0; tc.depth = -100f;
|
||||
tgo.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
|
||||
tgo.transform.position = new Vector3(0f, 42f, -12f); tgo.transform.LookAt(Vector3.zero);
|
||||
L("");
|
||||
L("2) 사방(위에서) " + WL816j2_Final.Shot(tc, D + "z2_top.png", PW, PH));
|
||||
|
||||
var b = mr.bounds;
|
||||
var zgo = new GameObject("~WL816j2FZ"); zgo.hideFlags = HideFlags.DontSave;
|
||||
var zc = zgo.AddComponent<Camera>();
|
||||
zc.fieldOfView = 34f; zc.nearClipPlane = 0.1f; zc.farClipPlane = 2000f;
|
||||
zc.clearFlags = CameraClearFlags.Skybox; zc.cullingMask = ~0; zc.depth = -100f;
|
||||
zgo.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
|
||||
zgo.transform.position = new Vector3(b.center.x, 3.2f, b.min.z - 9f);
|
||||
zgo.transform.LookAt(new Vector3(b.center.x, -1f, b.min.z + 2f));
|
||||
mr.enabled = false; water.sharedMaterial = Dm; yield return null; yield return null;
|
||||
L(" 물가 확대 [전] " + WL816j2_Final.Shot(zc, D + "z2_zoom_before.png", PW, PH));
|
||||
mr.enabled = true; water.sharedMaterial = E; yield return null; yield return null;
|
||||
L(" 물가 확대 [후] " + WL816j2_Final.Shot(zc, D + "z2_zoom_after.png", PW, PH));
|
||||
WL816j2_Final.Strip(new[] { D + "z2_zoom_before.png", D + "z2_zoom_after.png" }, D + "z2_zoom_pair.png");
|
||||
|
||||
// 3) 걷기 + 확장
|
||||
var cc = Object.FindFirstObjectByType<CharacterController>(FindObjectsInactive.Exclude);
|
||||
if (cc != null)
|
||||
{
|
||||
var p0 = cc.transform.position; var dir = new Vector3(1f, 0f, 1f).normalized; float moved = 0f;
|
||||
for (int i = 0; i < 120 && moved < 6f; i++) { cc.Move(dir * 0.05f + Vector3.down * 0.05f); moved += 0.05f; yield return null; }
|
||||
L("");
|
||||
L("3) 걷기 " + p0.ToString("F2") + " → " + cc.transform.position.ToString("F2") + " · 이동 "
|
||||
+ Vector3.Distance(new Vector3(p0.x, 0, p0.z), new Vector3(cc.transform.position.x, 0, cc.transform.position.z)).ToString("F2")
|
||||
+ " m · grounded=" + cc.isGrounded);
|
||||
}
|
||||
var islands = Object.FindObjectsByType<FIIsland>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
||||
FIIsland target = null;
|
||||
foreach (var isl in islands) if (isl != null && isl.IsUnlocked && isl.gameObject.activeInHierarchy) target = isl;
|
||||
if (target != null)
|
||||
{
|
||||
target.gameObject.SetActive(false); yield return new WaitForSeconds(2.5f);
|
||||
L(" 확장 1칸 잠금 → " + WLShoreFoam.LastLog);
|
||||
L(" " + WL816j2_Final.Shot(tc, D + "z2_top_locked.png", PW, PH));
|
||||
target.gameObject.SetActive(true); yield return new WaitForSeconds(3.5f);
|
||||
L(" 다시 열기 → " + WLShoreFoam.LastLog + " · 띠 재생성 " + WL.Look.Farm.WLIslandLook.ShoreFoamRebuilds + "회");
|
||||
L(" " + WL816j2_Final.Shot(tc, D + "z2_top_unlocked.png", PW, PH));
|
||||
WL816j2_Final.Strip(new[] { D + "z2_top.png", D + "z2_top_locked.png", D + "z2_top_unlocked.png" }, D + "z2_expand_steps.png");
|
||||
}
|
||||
|
||||
// 4) 성능
|
||||
L("");
|
||||
L("4) 성능 (PD 구도 1280×720 · 60프레임 · 교대 2회)");
|
||||
for (int round = 0; round < 2; round++)
|
||||
{
|
||||
mr.enabled = false; water.sharedMaterial = Dm; yield return null; yield return null;
|
||||
L(" " + round + "회차 전(물 D · 띠 없음) = " + WL816j2_Final.Ms(live, 60).ToString("F3") + " ms");
|
||||
mr.enabled = true; water.sharedMaterial = E; yield return null; yield return null;
|
||||
L(" " + round + "회차 후(물 E · 띠 on) = " + WL816j2_Final.Ms(live, 60).ToString("F3") + " ms");
|
||||
mr.enabled = false; yield return null; yield return null;
|
||||
L(" " + round + "회차 후(물 E · 띠 off) = " + WL816j2_Final.Ms(live, 60).ToString("F3") + " ms");
|
||||
mr.enabled = true;
|
||||
}
|
||||
L(" 띠 = " + WLShoreFoam.LastLog);
|
||||
|
||||
// 5) 되돌리기
|
||||
L("");
|
||||
L("5) 되돌리기");
|
||||
mr.enabled = false; water.sharedMaterial = Dm; yield return null; yield return new WaitForSeconds(0.3f);
|
||||
L(" shoreFoamEnabled 0 + waterTo=D → 816j 그대로 " + WL816j2_Final.Shot(live, D + "z2_rollback_816j.png", PW, PH));
|
||||
water.sharedMaterial = FI; yield return null; yield return new WaitForSeconds(0.3f);
|
||||
L(" waterMode 0 → FI 원본 물 " + WL816j2_Final.Shot(live, D + "z2_rollback_fi.png", PW, PH));
|
||||
water.sharedMaterial = E; mr.enabled = true; yield return null;
|
||||
|
||||
Object.DestroyImmediate(tgo); Object.DestroyImmediate(zgo);
|
||||
Done();
|
||||
}
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_FINAL.txt", sb.ToString());
|
||||
Debug.Log("[816j2 final]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
=== WL-816j2 ⑥ 격자선 세기 스윕 (바다 평균색은 유지해야 한다) ===
|
||||
816h 채택색 WaterColor RGBA(0.360, 0.690, 0.820, 1.000) DarkColor RGBA(0.170, 0.420, 0.570, 1.000)
|
||||
0 기준 E · 바다 평균 #5A96C3 → Screenshots_WL/WL816j2/m_sweep0.png
|
||||
1 Shadow=0.30 회색 · 바다 평균 #5A96C2 → Screenshots_WL/WL816j2/m_sweep1.png
|
||||
2 Shadow=흰색 · 바다 평균 #5896C3 → Screenshots_WL/WL816j2/m_sweep2.png
|
||||
3 Dark→Water 50% · 바다 평균 #5A96C3 → Screenshots_WL/WL816j2/m_sweep3.png
|
||||
4 Dark→Water 75% · 바다 평균 #5B97C3 → Screenshots_WL/WL816j2/m_sweep4.png
|
||||
5 Dark→Water 75% + Light=Water + Shadow=흰색 · 바다 평균 #5695C2 → Screenshots_WL/WL816j2/m_sweep5.png
|
||||
6 Dark→Water 90% + Light=Water + Shadow=흰색 · 바다 평균 #5695C2 → Screenshots_WL/WL816j2/m_sweep6.png
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
=== WL-816j2 ⑦ FoamColor 후보 + 무늬 잘게 ===
|
||||
0 Light 부드럽게(2.5 m) · 바다 평균 #5795C2 → Screenshots_WL/WL816j2/n_s2_0.png
|
||||
1 + FoamColor = 물색 · 바다 평균 #5695C2 → Screenshots_WL/WL816j2/n_s2_1.png
|
||||
2 + FoamColor = 물색 · 1.5 m · 바다 평균 #5895C2 → Screenshots_WL/WL816j2/n_s2_2.png
|
||||
3 + FoamColor = 물색 · 1.0 m · 바다 평균 #5896C2 → Screenshots_WL/WL816j2/n_s2_3.png
|
||||
4 FoamColor 흰색 · 1.0 m · 바다 평균 #5895C2 → Screenshots_WL/WL816j2/n_s2_4.png
|
||||
5 + FoamColor = 물색 · 0.6 m · 바다 평균 #5996C3 → Screenshots_WL/WL816j2/n_s2_5.png
|
||||
6 FoamColor=물색 · Shadow=흰색 · Light=물색 · 1.0 m (선 최소) · 바다 평균 #5695C2 → Screenshots_WL/WL816j2/n_s2_6.png
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// WL-816j2 — ⑥ 격자선 세기를 실제로 낮추는 값 찾기 (PD 구도 · 6단 스윕 · 평균 바다색은 유지)
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
public static class WL816j2_Sweep
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2S");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2S");
|
||||
go.AddComponent<WL816j2_SweepRunner>();
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_SweepRunner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Sweep.D;
|
||||
const int PW = 1280, PH = 720;
|
||||
const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
|
||||
const string C_FoamShadow = "Color_2323d69962e04c499c5d5f0925432b55";
|
||||
const string C_Water = "Color_9af4ad59934f40d1ae6565e6ab22c45e";
|
||||
const string C_Dark = "Color_ca031ae309ff42bdb95f777248fb961d";
|
||||
const string R_DeepDistance = "Vector1_566e288f42864b8e9432d81fbdb83f38";
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
string Shot(Camera cam, string path)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(PW, PH, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, PW, PH), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
var px = t.GetPixels32();
|
||||
long r = 0, g = 0, b = 0; int n = 0;
|
||||
for (int y = 20; y < 320; y += 2)
|
||||
for (int x = 20; x < 340; x += 2) { var c = px[y * PW + x]; r += c.r; g += c.g; b += c.b; n++; }
|
||||
Object.DestroyImmediate(t);
|
||||
return "바다 평균 #" + ((int)(r / n)).ToString("X2") + ((int)(g / n)).ToString("X2") + ((int)(b / n)).ToString("X2") + " → " + path;
|
||||
}
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 ⑥ 격자선 세기 스윕 (바다 평균색은 유지해야 한다) ===");
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
if (water == null || live == null) { L("🔴 없음"); Done(); yield break; }
|
||||
var E = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>("Assets/WL/Look/Farm/Materials/Farm_Water_WL_E.mat");
|
||||
Color W = E.GetColor(C_Water), Dk = E.GetColor(C_Dark);
|
||||
L("816h 채택색 WaterColor " + W + " DarkColor " + Dk);
|
||||
|
||||
var names = new string[]
|
||||
{
|
||||
"0 기준 E",
|
||||
"1 Shadow=0.30 회색",
|
||||
"2 Shadow=흰색",
|
||||
"3 Dark→Water 50%",
|
||||
"4 Dark→Water 75%",
|
||||
"5 Dark→Water 75% + Light=Water + Shadow=흰색",
|
||||
"6 Dark→Water 90% + Light=Water + Shadow=흰색",
|
||||
};
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
var m = new Material(E);
|
||||
if (i == 1) m.SetColor(C_FoamShadow, new Color(0.30f, 0.30f, 0.30f, 1f));
|
||||
if (i == 2) m.SetColor(C_FoamShadow, Color.white);
|
||||
if (i == 3) m.SetColor(C_Dark, Color.Lerp(Dk, W, 0.50f));
|
||||
if (i == 4) m.SetColor(C_Dark, Color.Lerp(Dk, W, 0.75f));
|
||||
if (i == 5) { m.SetColor(C_Dark, Color.Lerp(Dk, W, 0.75f)); m.SetColor(C_Light, W); m.SetColor(C_FoamShadow, Color.white); }
|
||||
if (i == 6) { m.SetColor(C_Dark, Color.Lerp(Dk, W, 0.90f)); m.SetColor(C_Light, W); m.SetColor(C_FoamShadow, Color.white); }
|
||||
water.sharedMaterial = m; yield return null; yield return new WaitForSeconds(0.25f);
|
||||
L(names[i] + " · " + Shot(live, D + "m_sweep" + i + ".png"));
|
||||
}
|
||||
Done();
|
||||
}
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_SWEEP.txt", sb.ToString());
|
||||
Debug.Log("[816j2 sweep]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// WL-816j2 — ⑦ 격자선을 「금 간 유리」가 아니게: FoamColor 후보 + 무늬를 더 잘게 (PD 구도)
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
public static class WL816j2_Sweep2
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2S2");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2S2");
|
||||
go.AddComponent<WL816j2_Sweep2Runner>();
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_Sweep2Runner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Sweep2.D;
|
||||
const int PW = 1280, PH = 720;
|
||||
const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
|
||||
const string C_Water = "Color_9af4ad59934f40d1ae6565e6ab22c45e";
|
||||
const string C_Foam = "Color_e1f155248d144786a62fc1585ca21e9a";
|
||||
const string C_FoamShadow = "Color_2323d69962e04c499c5d5f0925432b55";
|
||||
const string R_Size = "Vector1_07238257334b4a149e675e2451801030";
|
||||
const string R_Strength = "Vector1_99cc56b5c6fd474082f07f00a6df94f9";
|
||||
const string R_Speed = "Vector1_8e22a98f75c94b218c49e6c4805e799d";
|
||||
const string R_NoiseSpeed = "Vector1_ad7e0fcd37f44d68b68de6f06bb43b96";
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
string Shot(Camera cam, string path)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(PW, PH, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, PW, PH), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
var px = t.GetPixels32();
|
||||
long r = 0, g = 0, b = 0; int n = 0;
|
||||
for (int y = 20; y < 320; y += 2)
|
||||
for (int x = 20; x < 340; x += 2) { var c = px[y * PW + x]; r += c.r; g += c.g; b += c.b; n++; }
|
||||
Object.DestroyImmediate(t);
|
||||
return "바다 평균 #" + ((int)(r / n)).ToString("X2") + ((int)(g / n)).ToString("X2") + ((int)(b / n)).ToString("X2") + " → " + path;
|
||||
}
|
||||
static void Cell(Material m, float cellM)
|
||||
{
|
||||
float size = 1000f / (cellM * 6f);
|
||||
m.SetFloat(R_Size, size);
|
||||
m.SetFloat(R_Strength, 0.3085f / size);
|
||||
m.SetFloat(R_Speed, 0.8f * size / 1000f);
|
||||
m.SetFloat(R_NoiseSpeed, 0.8f * size / 1000f);
|
||||
}
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 ⑦ FoamColor 후보 + 무늬 잘게 ===");
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
if (water == null || live == null) { L("🔴 없음"); Done(); yield break; }
|
||||
var E = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>("Assets/WL/Look/Farm/Materials/Farm_Water_WL_E.mat");
|
||||
Color W = E.GetColor(C_Water);
|
||||
var soft = new Color(0.42f, 0.72f, 0.845f, 1f);
|
||||
|
||||
var names = new[]
|
||||
{
|
||||
"0 Light 부드럽게(2.5 m)",
|
||||
"1 + FoamColor = 물색",
|
||||
"2 + FoamColor = 물색 · 1.5 m",
|
||||
"3 + FoamColor = 물색 · 1.0 m",
|
||||
"4 FoamColor 흰색 · 1.0 m",
|
||||
"5 + FoamColor = 물색 · 0.6 m",
|
||||
"6 FoamColor=물색 · Shadow=흰색 · Light=물색 · 1.0 m (선 최소)",
|
||||
};
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
var m = new Material(E);
|
||||
m.SetColor(C_Light, soft);
|
||||
if (i >= 1 && i != 4) m.SetColor(C_Foam, W);
|
||||
if (i == 2) Cell(m, 1.5f);
|
||||
if (i == 3 || i == 4) Cell(m, 1.0f);
|
||||
if (i == 5) Cell(m, 0.6f);
|
||||
if (i == 6) { Cell(m, 1.0f); m.SetColor(C_Foam, W); m.SetColor(C_FoamShadow, Color.white); m.SetColor(C_Light, W); }
|
||||
water.sharedMaterial = m; yield return null; yield return new WaitForSeconds(0.25f);
|
||||
L(names[i] + " · " + Shot(live, D + "n_s2_" + i + ".png"));
|
||||
}
|
||||
Done();
|
||||
}
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_SWEEP2.txt", sb.ToString());
|
||||
Debug.Log("[816j2 sweep2]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
=== WL-816j2 ④ 마지막 조율 (PD 구도 1280×720) ===
|
||||
|
||||
1) 무늬 선 3단 — LightColor + FoamShadowColor(무늬의 어두운 쪽). 목표 = 데모(σ 0.0024)에 가깝게
|
||||
Light RGBA(0.450, 0.740, 0.860, 1.000) Shadow RGBA(0.780, 0.860, 0.920, 1.000) σ=0.0552 · 거품 1.16% #F9F5F9(R−B 0) → Screenshots_WL/WL816j2/h_soft1.png
|
||||
Light RGBA(0.420, 0.720, 0.845, 1.000) Shadow RGBA(0.930, 0.960, 0.980, 1.000) σ=0.0515 · 거품 1.14% #F9F5F9(R−B 0) → Screenshots_WL/WL816j2/h_soft2.png
|
||||
Light RGBA(0.385, 0.705, 0.830, 1.000) Shadow RGBA(1.000, 1.000, 1.000, 1.000) σ=0.0488 · 거품 1.20% #F9F4F8(R−B 1) → Screenshots_WL/WL816j2/h_soft3.png
|
||||
|
||||
2) 띠 폭 3단 + 폭별 비용 (60프레임 × 2회)
|
||||
[띠 off] σ=0.0525 · 거품 1.13% #FCF2F3(R−B 9) → Screenshots_WL/WL816j2/i_w0_off.png · 0.858 ms
|
||||
[폭 0.9 m · 삼각형 744] σ=0.0517 · 거품 1.16% #FCF1F3(R−B 9) → Screenshots_WL/WL816j2/i_w1.png · 0.840 / 0.867 ms
|
||||
[폭 1.6 m · 삼각형 1280] σ=0.0508 · 거품 1.22% #FBF4F7(R−B 4) → Screenshots_WL/WL816j2/i_w2.png · 0.878 / 0.882 ms
|
||||
[폭 2.6 m · 삼각형 1864] σ=0.0502 · 거품 2.34% #F3EFFB(R−B -8) → Screenshots_WL/WL816j2/i_w3.png · 0.888 / 0.848 ms
|
||||
|
||||
3) 최종 전/후 (PD 구도)
|
||||
[전] main(물 D · 띠 없음) σ=0.0820 · 거품 10.16% #ECDAE7(R−B 5) → Screenshots_WL/WL816j2/z_before_pd.png
|
||||
[후] 816j2(물 E · 띠 on) σ=0.0473 · 거품 1.14% #FBF3F6(R−B 5) → Screenshots_WL/WL816j2/z_after_pd.png
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
// WL-816j2 — ④ PD 구도에서 마지막 조율: 무늬 선을 데모만큼 은은하게 · 띠 폭/비용 · 최종 전후
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using WL.Look.Farm;
|
||||
|
||||
public static class WL816j2_Tune
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public const int PW = 1280, PH = 720;
|
||||
public const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
|
||||
public const string C_FoamShadow = "Color_2323d69962e04c499c5d5f0925432b55";
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2T");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2T");
|
||||
go.AddComponent<WL816j2_TuneRunner>();
|
||||
}
|
||||
public static string Shot(Camera cam, string path)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(PW, PH, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, PW, PH), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
var px = t.GetPixels32();
|
||||
double sum = 0, sum2 = 0; int n = 0;
|
||||
for (int y = 20; y < 320; y += 2)
|
||||
for (int x = 20; x < 340; x += 2)
|
||||
{ var c = px[y * PW + x]; float l = (0.299f * c.r + 0.587f * c.g + 0.114f * c.b) / 255f; sum += l; sum2 += l * l; n++; }
|
||||
double mean = sum / n, sd = System.Math.Sqrt(System.Math.Max(0, sum2 / n - mean * mean));
|
||||
long fr = 0, fg = 0, fb = 0; int fn = 0, tot = 0;
|
||||
int y1 = (int)(PH * 0.55f);
|
||||
for (int y = 0; y < y1; y++)
|
||||
for (int x = 0; x < PW; x += 2)
|
||||
{ var c = px[y * PW + x]; tot++; if (c.r > 200 && c.g > 195 && c.b > 195) { fr += c.r; fg += c.g; fb += c.b; fn++; } }
|
||||
Object.DestroyImmediate(t);
|
||||
string foam = fn == 0 ? "거품 0%" : "거품 " + (100f * fn / tot).ToString("F2") + "% #"
|
||||
+ ((int)(fr / fn)).ToString("X2") + ((int)(fg / fn)).ToString("X2") + ((int)(fb / fn)).ToString("X2")
|
||||
+ "(R−B " + ((int)(fr / fn) - (int)(fb / fn)) + ")";
|
||||
return "σ=" + sd.ToString("F4") + " · " + foam + " → " + path;
|
||||
}
|
||||
public static float Ms(Camera cam, int frames)
|
||||
{
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; cam.targetTexture = rt;
|
||||
for (int i = 0; i < 10; i++) cam.Render();
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
for (int i = 0; i < frames; i++) cam.Render();
|
||||
sw.Stop();
|
||||
cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
return (float)sw.Elapsed.TotalMilliseconds / frames;
|
||||
}
|
||||
public static void Strip(string[] paths, string outPath)
|
||||
{
|
||||
var ts = new Texture2D[paths.Length]; int w = 0, h = 0;
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
{
|
||||
if (!System.IO.File.Exists(paths[i])) return;
|
||||
ts[i] = new Texture2D(2, 2, TextureFormat.RGB24, false);
|
||||
ts[i].LoadImage(System.IO.File.ReadAllBytes(paths[i]));
|
||||
w = Mathf.Max(w, ts[i].width); h += ts[i].height;
|
||||
}
|
||||
var o = new Texture2D(w, h, TextureFormat.RGB24, false);
|
||||
var f = new Color32[w * h];
|
||||
for (int i = 0; i < f.Length; i++) f[i] = new Color32(24, 24, 28, 255);
|
||||
o.SetPixels32(f);
|
||||
int y = h;
|
||||
for (int i = 0; i < ts.Length; i++) { y -= ts[i].height; o.SetPixels32(0, y, ts[i].width, ts[i].height, ts[i].GetPixels32()); }
|
||||
o.Apply();
|
||||
System.IO.File.WriteAllBytes(outPath, o.EncodeToPNG());
|
||||
Object.DestroyImmediate(o);
|
||||
for (int i = 0; i < ts.Length; i++) Object.DestroyImmediate(ts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_TuneRunner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Tune.D;
|
||||
const string MatDir = "Assets/WL/Look/Farm/Materials/";
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 ④ 마지막 조율 (PD 구도 1280×720) ===");
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
var foam = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
|
||||
if (water == null || live == null || foam == null) { L("🔴 없음"); Done(); yield break; }
|
||||
var E = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_Water_WL_E.mat");
|
||||
var mr = foam.GetComponent<MeshRenderer>();
|
||||
|
||||
// ── 1) 무늬 선을 데모만큼 은은하게 (기준 데모 σ=0.0024 · 지금 D σ=0.0823) ──
|
||||
L("");
|
||||
L("1) 무늬 선 3단 — LightColor + FoamShadowColor(무늬의 어두운 쪽). 목표 = 데모(σ 0.0024)에 가깝게");
|
||||
var lc = new[] { new Color(0.45f, 0.74f, 0.86f), new Color(0.42f, 0.72f, 0.845f), new Color(0.385f, 0.705f, 0.83f) };
|
||||
var fs = new[] { new Color(0.78f, 0.86f, 0.92f), new Color(0.93f, 0.96f, 0.98f), new Color(1f, 1f, 1f) };
|
||||
var ps = new string[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var m = new Material(E);
|
||||
m.SetColor(WL816j2_Tune.C_Light, lc[i]);
|
||||
m.SetColor(WL816j2_Tune.C_FoamShadow, fs[i]);
|
||||
water.sharedMaterial = m; yield return null; yield return new WaitForSeconds(0.2f);
|
||||
ps[i] = D + "h_soft" + (i + 1) + ".png";
|
||||
L(" Light " + lc[i] + " Shadow " + fs[i] + " " + WL816j2_Tune.Shot(live, ps[i]));
|
||||
}
|
||||
WL816j2_Tune.Strip(ps, D + "h_soft_steps.png");
|
||||
|
||||
// 채택 후보 = 가운데
|
||||
var adopt = new Material(E);
|
||||
adopt.SetColor(WL816j2_Tune.C_Light, lc[1]);
|
||||
adopt.SetColor(WL816j2_Tune.C_FoamShadow, fs[1]);
|
||||
water.sharedMaterial = adopt; yield return null;
|
||||
|
||||
// ── 2) 띠 폭 3단 (고친 텍스처로 다시) + 폭별 비용 ────────────
|
||||
L("");
|
||||
L("2) 띠 폭 3단 + 폭별 비용 (60프레임 × 2회)");
|
||||
var ws = new string[4]; float[] wid = { 0.9f, 1.6f, 2.6f };
|
||||
mr.enabled = false; yield return null; yield return null;
|
||||
ws[0] = D + "i_w0_off.png";
|
||||
L(" [띠 off] " + WL816j2_Tune.Shot(live, ws[0]) + " · " + WL816j2_Tune.Ms(live, 60).ToString("F3") + " ms");
|
||||
mr.enabled = true;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
foam.widthOverride = wid[i]; foam.Rebuild();
|
||||
yield return null; yield return new WaitForSeconds(0.2f);
|
||||
ws[i + 1] = D + "i_w" + (i + 1) + ".png";
|
||||
float a = WL816j2_Tune.Ms(live, 60), b = WL816j2_Tune.Ms(live, 60);
|
||||
L(" [폭 " + wid[i] + " m · 삼각형 " + WLShoreFoam.Tris + "] " + WL816j2_Tune.Shot(live, ws[i + 1])
|
||||
+ " · " + a.ToString("F3") + " / " + b.ToString("F3") + " ms");
|
||||
}
|
||||
WL816j2_Tune.Strip(ws, D + "i_band_steps.png");
|
||||
foam.widthOverride = 0f; foam.Rebuild(); yield return null;
|
||||
|
||||
// ── 3) 최종 전/후 (PD 구도) ─────────────────────────────────
|
||||
var Dm = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_Water_WL_D.mat");
|
||||
L("");
|
||||
L("3) 최종 전/후 (PD 구도)");
|
||||
mr.enabled = false; water.sharedMaterial = Dm; yield return null; yield return new WaitForSeconds(0.3f);
|
||||
L(" [전] main(물 D · 띠 없음) " + WL816j2_Tune.Shot(live, D + "z_before_pd.png"));
|
||||
mr.enabled = true; water.sharedMaterial = adopt; yield return null; yield return new WaitForSeconds(0.3f);
|
||||
L(" [후] 816j2(물 E · 띠 on) " + WL816j2_Tune.Shot(live, D + "z_after_pd.png"));
|
||||
WL816j2_Tune.Strip(new[] { D + "z_before_pd.png", D + "z_after_pd.png" }, D + "z_pd_before_after.png");
|
||||
|
||||
Done();
|
||||
}
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_TUNE.txt", sb.ToString());
|
||||
Debug.Log("[816j2 tune]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
=== WL-816j2 — PD 구도(FOV 60 · 45° · 22 m · 1280×720)에서 다시 맞춘다 ===
|
||||
카메라 MainCamera pos=(0.00, 15.56, -15.56) 각=(45, 0, 0) fov=60 · 거리 22.0 m
|
||||
물 = Farm_Water_WL_E · 둘레 띠 = 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
|
||||
1) 지금(main · 물 D · 띠 없음) 바다 무늬대비 σ=0.0823 · 거품 10.20% 색 #EDDAE7 (R−B 6) → Screenshots_WL/WL816j2/a_now_pd.png
|
||||
|
||||
2) 무늬 흰 선 3단 — LightColor (물색 0.36/0.69/0.82 에 가까울수록 은은)
|
||||
RGBA(0.800, 0.900, 0.960, 1.000) 바다 무늬대비 σ=0.0787 · 거품 6.47% 색 #E1D4E8 (R−B -7) → Screenshots_WL/WL816j2/b_line1.png
|
||||
RGBA(0.600, 0.820, 0.910, 1.000) 바다 무늬대비 σ=0.0644 · 거품 1.09% 색 #FCF2F3 (R−B 9) → Screenshots_WL/WL816j2/b_line2.png
|
||||
RGBA(0.450, 0.740, 0.860, 1.000) 바다 무늬대비 σ=0.0506 · 거품 1.12% 색 #FCF1F3 (R−B 9) → Screenshots_WL/WL816j2/b_line3.png
|
||||
[기준] 데모 물(FI SimpleWater) 바다 무늬대비 σ=0.0024 · 거품 1.13% 색 #FAF8FC (R−B -2) → Screenshots_WL/WL816j2/b_line0_demo.png
|
||||
|
||||
3) 둘레 띠 폭 3단 (PD 구도)
|
||||
폭 0.9 m · 타일 4 · 띠 삼각형 744 · 정점 496 · 폭 0.90 m · 격자 0.50 m · 드로우콜 +1
|
||||
바다 무늬대비 σ=0.0637 · 거품 1.10% 색 #FCF2F3 (R−B 9) → Screenshots_WL/WL816j2/c_band1.png
|
||||
폭 1.6 m · 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
바다 무늬대비 σ=0.0641 · 거품 1.23% 색 #FBF5FA (R−B 1) → Screenshots_WL/WL816j2/c_band2.png
|
||||
폭 2.6 m · 타일 4 · 띠 삼각형 1864 · 정점 1072 · 폭 2.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
바다 무늬대비 σ=0.0646 · 거품 2.51% 색 #F4F1FC (R−B -8) → Screenshots_WL/WL816j2/c_band3.png
|
||||
|
||||
4) 거품 색 — PD 캡처가 분홍빛이었다. 화면에서 재서 중립 흰색으로 맞춘다(R−B 가 0 에 가까울수록 중립)
|
||||
_BaseColor RGBA(1.000, 1.000, 1.000, 0.920) 바다 무늬대비 σ=0.0671 · 거품 2.58% 색 #F6F4FD (R−B -7) → Screenshots_WL/WL816j2/d_tint1.png
|
||||
_BaseColor RGBA(0.930, 0.970, 1.000, 0.920) 바다 무늬대비 σ=0.0689 · 거품 2.42% 색 #F3F2FD (R−B -10) → Screenshots_WL/WL816j2/d_tint2.png
|
||||
_BaseColor RGBA(0.860, 0.950, 1.000, 0.900) 바다 무늬대비 σ=0.0698 · 거품 2.17% 색 #E9F0FD (R−B -20) → Screenshots_WL/WL816j2/d_tint3.png
|
||||
|
||||
4-b) 물가 확대 — 띠 off 바다 무늬대비 σ=0.0565 · 거품 2.51% 색 #FEE1E5 (R−B 25) → Screenshots_WL/WL816j2/f_zoom_off.png
|
||||
물가 확대 — 띠 on 바다 무늬대비 σ=0.0619 · 거품 6.24% 색 #F8F6FD (R−B -5) → Screenshots_WL/WL816j2/f_zoom_on.png
|
||||
|
||||
5) 사방 확인(위에서) + 섬 확장
|
||||
위에서 바다 무늬대비 σ=0.0648 · 거품 0.87% 색 #F6F4FC (R−B -6) → Screenshots_WL/WL816j2/e_top_allsides.png
|
||||
1칸 잠금 → 타일 3 · 띠 삼각형 1268 · 정점 766 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
바다 무늬대비 σ=0.0648 · 거품 0.34% 색 #FAF9FB (R−B -1) → Screenshots_WL/WL816j2/e_top_locked.png
|
||||
다시 열기 → 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1 · 띠 재생성 2회
|
||||
바다 무늬대비 σ=0.0647 · 거품 0.80% 색 #F7F5FD (R−B -6) → Screenshots_WL/WL816j2/e_top_unlocked.png
|
||||
|
||||
6) 성능 (PD 구도 1280×720 · 60프레임 오프스크린 · 순서 교대 2회)
|
||||
0회차 띠 off = 0.817 ms/frame
|
||||
0회차 띠 on = 0.896 ms/frame
|
||||
1회차 띠 off = 0.846 ms/frame
|
||||
1회차 띠 on = 0.942 ms/frame
|
||||
띠 = 렌더러 1 · 머티리얼 1 · 드로우콜 +1 · 타일 4 · 띠 삼각형 1280 · 정점 772 · 폭 1.60 m · 격자 0.50 m · 드로우콜 +1
|
||||
화면 통계(에디터) drawCalls=6720 batches=6720 tris=1646610
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
// WL-816j2 — ② 🔴 판정은 **PD 카메라 구도**(MainCamera · FOV 60 · 45° · 22 m · 1280×720)에서.
|
||||
// 무늬 선 3단 · 띠 폭 3단 · 거품 색 중립화 · 사방 확인 · 성능(드로우콜·ms/frame) 전/후.
|
||||
// 🔴 Play 중 에셋 수정 0 — 물은 런타임 Material 복사본, 띠는 컴포넌트의 런타임 오버라이드.
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.SceneManagement;
|
||||
using WL.Look.Farm;
|
||||
using FIIsland = CryingSnow.FarmingIsland.Island;
|
||||
|
||||
public static class WL816j2_Verify
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public const int PW = 1280, PH = 720; // 🔴 PD 화면과 같은 해상도·화각
|
||||
public const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
|
||||
public const string C_Foam = "Color_e1f155248d144786a62fc1585ca21e9a";
|
||||
public const string R_FoamDistance = "Vector1_101dc4546b684d40bc2ff2fc59ab43d5";
|
||||
public const string R_FoamEdge = "Vector1_34f757bec6b8422b9aef3b9d97117a6e";
|
||||
|
||||
public static void Open()
|
||||
{
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(
|
||||
"Assets/Scenes/InGame.unity", UnityEditor.SceneManagement.OpenSceneMode.Single);
|
||||
}
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2V");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2V");
|
||||
go.AddComponent<WL816j2_VerifyRunner>();
|
||||
}
|
||||
|
||||
public static Texture2D Grab(Camera cam, int w, int h)
|
||||
{
|
||||
var rt = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(w, h, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, w, h), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
return t;
|
||||
}
|
||||
/// <summary>PD 구도로 찍고 ⓐ 물 무늬 선 대비 ⓑ 거품(밝은 픽셀) 평균색·비율을 잰다.</summary>
|
||||
public static string Shot(Camera cam, string path)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var t = Grab(cam, PW, PH);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
var px = t.GetPixels32();
|
||||
// ⓐ 무늬 선 대비 — 🔴 **바다만 있는 왼쪽 아래 구역**(섬·UI 가 절대 안 들어온다)에서만 잰다
|
||||
double sum = 0, sum2 = 0; int n = 0;
|
||||
for (int y = 20; y < 320; y += 2)
|
||||
for (int x = 20; x < 340; x += 2)
|
||||
{
|
||||
var c = px[y * PW + x];
|
||||
float lum = (0.299f * c.r + 0.587f * c.g + 0.114f * c.b) / 255f;
|
||||
sum += lum; sum2 += lum * lum; n++;
|
||||
}
|
||||
double mean = n > 0 ? sum / n : 0, sd = n > 0 ? System.Math.Sqrt(System.Math.Max(0, sum2 / n - mean * mean)) : 0;
|
||||
// ⓑ 거품(밝은 픽셀) — 화면 아래 55 %(UI 회피)에서 비율과 색
|
||||
long fr = 0, fg = 0, fb = 0; int fn = 0, tot = 0;
|
||||
int y1 = (int)(PH * 0.55f);
|
||||
for (int y = 0; y < y1; y++)
|
||||
for (int x = 0; x < PW; x += 2)
|
||||
{
|
||||
var c = px[y * PW + x]; tot++;
|
||||
if (c.r > 200 && c.g > 195 && c.b > 195) { fr += c.r; fg += c.g; fb += c.b; fn++; }
|
||||
}
|
||||
Object.DestroyImmediate(t);
|
||||
string foam = fn == 0 ? "거품 0%" :
|
||||
"거품 " + (100f * fn / tot).ToString("F2") + "% 색 #"
|
||||
+ ((int)(fr / fn)).ToString("X2") + ((int)(fg / fn)).ToString("X2") + ((int)(fb / fn)).ToString("X2")
|
||||
+ " (R−B " + ((int)(fr / fn) - (int)(fb / fn)) + ")";
|
||||
return "바다 무늬대비 σ=" + sd.ToString("F4") + " · " + foam + " → " + path;
|
||||
}
|
||||
public static float Ms(Camera cam, int frames)
|
||||
{
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; cam.targetTexture = rt;
|
||||
for (int i = 0; i < 10; i++) cam.Render();
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
for (int i = 0; i < frames; i++) cam.Render();
|
||||
sw.Stop();
|
||||
cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
return (float)sw.Elapsed.TotalMilliseconds / frames;
|
||||
}
|
||||
public static void Strip(string[] paths, string outPath)
|
||||
{
|
||||
var ts = new Texture2D[paths.Length]; int w = 0, h = 0;
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
{
|
||||
if (!System.IO.File.Exists(paths[i])) return;
|
||||
ts[i] = new Texture2D(2, 2, TextureFormat.RGB24, false);
|
||||
ts[i].LoadImage(System.IO.File.ReadAllBytes(paths[i]));
|
||||
w = Mathf.Max(w, ts[i].width); h += ts[i].height;
|
||||
}
|
||||
var o = new Texture2D(w, h, TextureFormat.RGB24, false);
|
||||
var f = new Color32[w * h];
|
||||
for (int i = 0; i < f.Length; i++) f[i] = new Color32(24, 24, 28, 255);
|
||||
o.SetPixels32(f);
|
||||
int y = h;
|
||||
for (int i = 0; i < ts.Length; i++) { y -= ts[i].height; o.SetPixels32(0, y, ts[i].width, ts[i].height, ts[i].GetPixels32()); }
|
||||
o.Apply();
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outPath));
|
||||
System.IO.File.WriteAllBytes(outPath, o.EncodeToPNG());
|
||||
Object.DestroyImmediate(o);
|
||||
for (int i = 0; i < ts.Length; i++) Object.DestroyImmediate(ts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_VerifyRunner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Verify.D;
|
||||
const string MatDir = "Assets/WL/Look/Farm/Materials/";
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 — PD 구도(FOV 60 · 45° · 22 m · 1280×720)에서 다시 맞춘다 ===");
|
||||
var op = SceneManager.LoadSceneAsync("Level01", LoadSceneMode.Additive);
|
||||
while (op != null && !op.isDone) yield return null;
|
||||
for (int i = 0; i < 8; i++) yield return new WaitForSeconds(1f);
|
||||
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
var foam = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
|
||||
if (water == null || live == null) { L("🔴 물/카메라 없음"); Done(); yield break; }
|
||||
L("카메라 " + live.name + " pos=" + live.transform.position.ToString("F2") + " 각=" + live.transform.eulerAngles.ToString("F0")
|
||||
+ " fov=" + live.fieldOfView + " · 거리 " + live.transform.position.magnitude.ToString("F1") + " m");
|
||||
L("물 = " + water.sharedMaterial.name + " · 둘레 띠 = " + (foam == null ? "🔴 없음" : WLShoreFoam.LastLog));
|
||||
var E = water.sharedMaterial;
|
||||
var Dm = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_Water_WL_D.mat");
|
||||
|
||||
// ── 1) 지금(main 상태 = 물 D · 띠 없음) ─────────────────────
|
||||
if (foam != null) foam.GetComponent<MeshRenderer>().enabled = false;
|
||||
water.sharedMaterial = Dm; yield return null; yield return new WaitForSeconds(0.3f);
|
||||
L("");
|
||||
L("1) 지금(main · 물 D · 띠 없음) " + WL816j2_Verify.Shot(live, D + "a_now_pd.png"));
|
||||
|
||||
// ── 2) 무늬 선 3단 (띠 없이 · 물만) ──────────────────────────
|
||||
L("");
|
||||
L("2) 무늬 흰 선 3단 — LightColor (물색 0.36/0.69/0.82 에 가까울수록 은은)");
|
||||
var lc = new[] { new Color(0.80f, 0.90f, 0.96f), new Color(0.60f, 0.82f, 0.91f), new Color(0.45f, 0.74f, 0.86f) };
|
||||
var ls = new string[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var m = new Material(E); m.SetColor(WL816j2_Verify.C_Light, lc[i]);
|
||||
water.sharedMaterial = m; yield return null; yield return new WaitForSeconds(0.2f);
|
||||
ls[i] = D + "b_line" + (i + 1) + ".png";
|
||||
L(" " + lc[i] + " " + WL816j2_Verify.Shot(live, ls[i]));
|
||||
}
|
||||
WL816j2_Verify.Strip(ls, D + "b_line_steps.png");
|
||||
|
||||
// 데모(FI 원본) 물의 선 대비 = 기준
|
||||
var FI = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>(MatDir + "Farm_SimpleWater_Demo.mat");
|
||||
water.sharedMaterial = FI; yield return null; yield return new WaitForSeconds(0.2f);
|
||||
L(" [기준] 데모 물(FI SimpleWater) " + WL816j2_Verify.Shot(live, D + "b_line0_demo.png"));
|
||||
|
||||
// ── 3) 띠 폭 3단 (물 = E · 선 중간값) ───────────────────────
|
||||
var pick = new Material(E); pick.SetColor(WL816j2_Verify.C_Light, lc[1]);
|
||||
water.sharedMaterial = pick; yield return null;
|
||||
L("");
|
||||
L("3) 둘레 띠 폭 3단 (PD 구도)");
|
||||
if (foam != null)
|
||||
{
|
||||
foam.GetComponent<MeshRenderer>().enabled = true;
|
||||
var ws = new string[3]; float[] wid = { 0.9f, 1.6f, 2.6f };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
foam.widthOverride = wid[i]; foam.Rebuild();
|
||||
yield return null; yield return new WaitForSeconds(0.2f);
|
||||
ws[i] = D + "c_band" + (i + 1) + ".png";
|
||||
L(" 폭 " + wid[i] + " m · " + WLShoreFoam.LastLog);
|
||||
L(" " + WL816j2_Verify.Shot(live, ws[i]));
|
||||
}
|
||||
WL816j2_Verify.Strip(ws, D + "c_band_steps.png");
|
||||
foam.widthOverride = 0f; foam.Rebuild(); yield return null;
|
||||
}
|
||||
else L(" 🔴 띠 컴포넌트가 없다");
|
||||
|
||||
// ── 4) 거품 색 중립화 — 화면에서 R−B 를 0 에 가깝게 ─────────
|
||||
L("");
|
||||
L("4) 거품 색 — PD 캡처가 분홍빛이었다. 화면에서 재서 중립 흰색으로 맞춘다(R−B 가 0 에 가까울수록 중립)");
|
||||
if (foam != null)
|
||||
{
|
||||
var mr = foam.GetComponent<MeshRenderer>();
|
||||
var tints = new[] { new Color(1f,1f,1f,0.92f), new Color(0.93f,0.97f,1f,0.92f), new Color(0.86f,0.95f,1f,0.90f) };
|
||||
var cs = new string[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var mi = new Material(foam.cfg.shoreFoamMaterial); mi.SetColor("_BaseColor", tints[i]);
|
||||
mr.sharedMaterial = mi; yield return null; yield return new WaitForSeconds(0.2f);
|
||||
cs[i] = D + "d_tint" + (i + 1) + ".png";
|
||||
L(" _BaseColor " + tints[i] + " " + WL816j2_Verify.Shot(live, cs[i]));
|
||||
}
|
||||
WL816j2_Verify.Strip(cs, D + "d_tint_steps.png");
|
||||
}
|
||||
|
||||
// ── 5) 사방 확인 + 확장 ─────────────────────────────────────
|
||||
// ── 4-b) 물가 확대 (띠가 어떻게 보이는지) ───────────────────
|
||||
if (foam != null)
|
||||
{
|
||||
var mr2 = foam.GetComponent<MeshRenderer>();
|
||||
mr2.sharedMaterial = foam.cfg.shoreFoamMaterial;
|
||||
var b = mr2.bounds;
|
||||
var zgo = new GameObject("~WL816j2Zoom"); zgo.hideFlags = HideFlags.DontSave;
|
||||
var zc = zgo.AddComponent<Camera>();
|
||||
zc.fieldOfView = 34f; zc.nearClipPlane = 0.1f; zc.farClipPlane = 2000f;
|
||||
zc.clearFlags = CameraClearFlags.Skybox; zc.cullingMask = ~0; zc.depth = -100f;
|
||||
zgo.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
|
||||
zgo.transform.position = new Vector3(b.center.x, 3.2f, b.min.z - 9f);
|
||||
zgo.transform.LookAt(new Vector3(b.center.x, -1f, b.min.z + 2f));
|
||||
mr2.enabled = false; yield return null; yield return null;
|
||||
L("");
|
||||
L("4-b) 물가 확대 — 띠 off " + WL816j2_Verify.Shot(zc, D + "f_zoom_off.png"));
|
||||
mr2.enabled = true; yield return null; yield return null;
|
||||
L(" 물가 확대 — 띠 on " + WL816j2_Verify.Shot(zc, D + "f_zoom_on.png"));
|
||||
WL816j2_Verify.Strip(new[] { D + "f_zoom_off.png", D + "f_zoom_on.png" }, D + "f_zoom_pair.png");
|
||||
Object.DestroyImmediate(zgo);
|
||||
}
|
||||
|
||||
L("");
|
||||
L("5) 사방 확인(위에서) + 섬 확장");
|
||||
var top = new GameObject("~WL816j2Top"); top.hideFlags = HideFlags.DontSave;
|
||||
var tc = top.AddComponent<Camera>();
|
||||
tc.fieldOfView = 55f; tc.nearClipPlane = 0.1f; tc.farClipPlane = 2000f;
|
||||
tc.clearFlags = CameraClearFlags.Skybox; tc.cullingMask = ~0; tc.depth = -100f;
|
||||
top.AddComponent<UniversalAdditionalCameraData>().renderPostProcessing = true;
|
||||
top.transform.position = new Vector3(0f, 42f, -12f); top.transform.LookAt(Vector3.zero);
|
||||
L(" 위에서 " + WL816j2_Verify.Shot(tc, D + "e_top_allsides.png"));
|
||||
|
||||
var islands = Object.FindObjectsByType<FIIsland>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
||||
FIIsland target = null;
|
||||
foreach (var isl in islands) if (isl != null && isl.IsUnlocked && isl.gameObject.activeInHierarchy) target = isl;
|
||||
if (target != null)
|
||||
{
|
||||
target.gameObject.SetActive(false); yield return new WaitForSeconds(2.5f);
|
||||
L(" 1칸 잠금 → " + WLShoreFoam.LastLog);
|
||||
L(" " + WL816j2_Verify.Shot(tc, D + "e_top_locked.png"));
|
||||
target.gameObject.SetActive(true); yield return new WaitForSeconds(3.5f);
|
||||
L(" 다시 열기 → " + WLShoreFoam.LastLog + " · 띠 재생성 " + WL.Look.Farm.WLIslandLook.ShoreFoamRebuilds + "회");
|
||||
L(" " + WL816j2_Verify.Shot(tc, D + "e_top_unlocked.png"));
|
||||
}
|
||||
WL816j2_Verify.Strip(new[] { D + "e_top_allsides.png", D + "e_top_locked.png", D + "e_top_unlocked.png" }, D + "e_expand_steps.png");
|
||||
|
||||
// ── 6) 성능 — 띠 on/off 교대 2회 ────────────────────────────
|
||||
L("");
|
||||
L("6) 성능 (PD 구도 1280×720 · 60프레임 오프스크린 · 순서 교대 2회)");
|
||||
var fr = foam != null ? foam.GetComponent<MeshRenderer>() : null;
|
||||
for (int round = 0; round < 2; round++)
|
||||
{
|
||||
if (fr != null) { fr.enabled = false; yield return null; yield return null; }
|
||||
L(" " + round + "회차 띠 off = " + WL816j2_Verify.Ms(live, 60).ToString("F3") + " ms/frame");
|
||||
if (fr != null) { fr.enabled = true; yield return null; yield return null; }
|
||||
L(" " + round + "회차 띠 on = " + WL816j2_Verify.Ms(live, 60).ToString("F3") + " ms/frame");
|
||||
}
|
||||
L(" 띠 = 렌더러 1 · 머티리얼 1 · 드로우콜 +1 · " + WLShoreFoam.LastLog);
|
||||
L(" 화면 통계(에디터) drawCalls=" + UnityEditor.UnityStats.drawCalls + " batches=" + UnityEditor.UnityStats.batches
|
||||
+ " tris=" + UnityEditor.UnityStats.triangles);
|
||||
|
||||
Object.DestroyImmediate(top);
|
||||
Done();
|
||||
}
|
||||
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_VERIFY.txt", sb.ToString());
|
||||
Debug.Log("[816j2 verify]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
=== WL-816j2 ⑤ 격자선의 정체 (색으로 찍기) ===
|
||||
1) Light=초록 Shadow=파랑 Foam=빨강 Water=흰 Dark=검 밝은점 #FEE3E6 어두운점 #1515F8 → Screenshots_WL/WL816j2/k_which_paint.png
|
||||
2) 기준(E 그대로) 밝은점 #B6C4E3 어두운점 #5091BF → Screenshots_WL/WL816j2/k_off0.png
|
||||
3) FoamEdge 100(가장자리 거품 완전 off) 밝은점 #B6C3E3 어두운점 #5091BF → Screenshots_WL/WL816j2/k_off1.png
|
||||
4) LightColor = WaterColor 밝은점 #97B9DA 어두운점 #5091BF → Screenshots_WL/WL816j2/k_off2.png
|
||||
5) FoamShadowColor = 흰색 밝은점 #B6C3E3 어두운점 #5091BF → Screenshots_WL/WL816j2/k_off3.png
|
||||
6) 셋 다 밝은점 #97B9DA 어두운점 #5091BF → Screenshots_WL/WL816j2/k_off4.png
|
||||
7) 셋 다 + Height 0(버텍스 파도 off) 밝은점 #97B9DA 어두운점 #5091BF → Screenshots_WL/WL816j2/k_off5.png
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
// WL-816j2 — ⑤ 바다의 흰 격자선을 만드는 속성이 무엇인지 **색으로 찍어서** 가려낸다
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
public static class WL816j2_Which
|
||||
{
|
||||
public const string D = "Screenshots_WL/WL816j2/";
|
||||
public static void Start()
|
||||
{
|
||||
var go = GameObject.Find("~WL816j2W");
|
||||
if (go != null) Object.DestroyImmediate(go);
|
||||
go = new GameObject("~WL816j2W");
|
||||
go.AddComponent<WL816j2_WhichRunner>();
|
||||
}
|
||||
}
|
||||
|
||||
public class WL816j2_WhichRunner : MonoBehaviour
|
||||
{
|
||||
static StringBuilder sb;
|
||||
static void L(string s) { sb.AppendLine(s); }
|
||||
const string D = WL816j2_Which.D;
|
||||
const int PW = 1280, PH = 720;
|
||||
const string C_Light = "Color_1ec6cccf8ead489ebb917674f7e8b3b1";
|
||||
const string C_FoamShadow = "Color_2323d69962e04c499c5d5f0925432b55";
|
||||
const string C_Water = "Color_9af4ad59934f40d1ae6565e6ab22c45e";
|
||||
const string C_Dark = "Color_ca031ae309ff42bdb95f777248fb961d";
|
||||
const string C_Foam = "Color_e1f155248d144786a62fc1585ca21e9a";
|
||||
const string R_FoamEdge = "Vector1_34f757bec6b8422b9aef3b9d97117a6e";
|
||||
const string R_FoamDistance = "Vector1_101dc4546b684d40bc2ff2fc59ab43d5";
|
||||
const string R_DeepDistance = "Vector1_566e288f42864b8e9432d81fbdb83f38";
|
||||
const string R_Height = "Vector1_d813b569a4d541d1b2ac4ea9bc66a3b9";
|
||||
|
||||
void Start() { StartCoroutine(Co()); }
|
||||
|
||||
string Shot(Camera cam, string path)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
var rt = new RenderTexture(PW, PH, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
|
||||
rt.antiAliasing = 1; rt.Create();
|
||||
var pT = cam.targetTexture; var pA = RenderTexture.active;
|
||||
cam.targetTexture = rt; cam.Render(); RenderTexture.active = rt;
|
||||
var t = new Texture2D(PW, PH, TextureFormat.RGB24, false);
|
||||
t.ReadPixels(new Rect(0, 0, PW, PH), 0, 0); t.Apply();
|
||||
RenderTexture.active = pA; cam.targetTexture = pT; rt.Release(); Object.DestroyImmediate(rt);
|
||||
System.IO.File.WriteAllBytes(path, t.EncodeToPNG());
|
||||
// 바다만 있는 구역에서 가장 밝은/어두운 픽셀의 색
|
||||
var px = t.GetPixels32();
|
||||
int bi = 0, di = 0; float bl = -1, dl = 2;
|
||||
for (int y = 20; y < 320; y += 2)
|
||||
for (int x = 20; x < 340; x += 2)
|
||||
{
|
||||
int k = y * PW + x; var c = px[k];
|
||||
float l = (0.299f * c.r + 0.587f * c.g + 0.114f * c.b) / 255f;
|
||||
if (l > bl) { bl = l; bi = k; }
|
||||
if (l < dl) { dl = l; di = k; }
|
||||
}
|
||||
var b2 = px[bi]; var d2 = px[di];
|
||||
Object.DestroyImmediate(t);
|
||||
return "밝은점 #" + b2.r.ToString("X2") + b2.g.ToString("X2") + b2.b.ToString("X2")
|
||||
+ " 어두운점 #" + d2.r.ToString("X2") + d2.g.ToString("X2") + d2.b.ToString("X2") + " → " + path;
|
||||
}
|
||||
|
||||
IEnumerator Co()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
L("=== WL-816j2 ⑤ 격자선의 정체 (색으로 찍기) ===");
|
||||
Renderer water = null;
|
||||
foreach (var r in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
if (r != null && r.gameObject.scene.name == "Level01" && r.name == "Water") water = r;
|
||||
Camera live = null;
|
||||
foreach (var c in Object.FindObjectsByType<Camera>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
if (!c.gameObject.activeInHierarchy || !c.enabled || c.targetTexture != null) continue;
|
||||
if (c.name.StartsWith("~WL816")) continue;
|
||||
if (live == null || c.depth > live.depth) live = c;
|
||||
}
|
||||
if (water == null || live == null) { L("🔴 없음"); Done(); yield break; }
|
||||
var E = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>("Assets/WL/Look/Farm/Materials/Farm_Water_WL_E.mat");
|
||||
|
||||
// ① 색 찍기 — LightColor=초록 · FoamShadowColor=파랑 · FoamColor=빨강 · Water=흰 · Dark=검
|
||||
var m = new Material(E);
|
||||
m.SetColor(C_Water, Color.white); m.SetColor(C_Dark, Color.black);
|
||||
m.SetColor(C_Light, Color.green); m.SetColor(C_FoamShadow, Color.blue); m.SetColor(C_Foam, Color.red);
|
||||
water.sharedMaterial = m; yield return null; yield return new WaitForSeconds(0.3f);
|
||||
L("1) Light=초록 Shadow=파랑 Foam=빨강 Water=흰 Dark=검 " + Shot(live, D + "k_which_paint.png"));
|
||||
|
||||
// ② 하나씩 끄기
|
||||
var tests = new (string, System.Action<Material>)[]
|
||||
{
|
||||
("기준(E 그대로)", mm => { }),
|
||||
("FoamEdge 100(가장자리 거품 완전 off)", mm => mm.SetFloat(R_FoamEdge, 100f)),
|
||||
("LightColor = WaterColor", mm => mm.SetColor(C_Light, mm.GetColor(C_Water))),
|
||||
("FoamShadowColor = 흰색", mm => mm.SetColor(C_FoamShadow, Color.white)),
|
||||
("셋 다", mm => { mm.SetFloat(R_FoamEdge, 100f); mm.SetColor(C_Light, mm.GetColor(C_Water)); mm.SetColor(C_FoamShadow, Color.white); }),
|
||||
("셋 다 + Height 0(버텍스 파도 off)", mm => { mm.SetFloat(R_FoamEdge, 100f); mm.SetColor(C_Light, mm.GetColor(C_Water)); mm.SetColor(C_FoamShadow, Color.white); mm.SetFloat(R_Height, 0f); }),
|
||||
};
|
||||
for (int i = 0; i < tests.Length; i++)
|
||||
{
|
||||
var mm = new Material(E); tests[i].Item2(mm);
|
||||
water.sharedMaterial = mm; yield return null; yield return new WaitForSeconds(0.25f);
|
||||
L((i + 2) + ") " + tests[i].Item1 + " " + Shot(live, D + "k_off" + i + ".png"));
|
||||
}
|
||||
Done();
|
||||
}
|
||||
void Done()
|
||||
{
|
||||
System.IO.File.WriteAllText("AgentScripts/WL816j2_WHICH.txt", sb.ToString());
|
||||
Debug.Log("[816j2 which]\n" + sb);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Farm_ShoreFoam
|
||||
m_Shader: {fileID: 4800000, guid: 650dd9526735d5b46b79224bc6e94025, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords:
|
||||
- _SURFACE_TYPE_TRANSPARENT
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 1
|
||||
m_CustomRenderQueue: 3050
|
||||
stringTagMap:
|
||||
RenderType: Transparent
|
||||
disabledShaderPasses:
|
||||
- MOTIONVECTORS
|
||||
- DepthOnly
|
||||
- SHADOWCASTER
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 2800000, guid: 7501e662a59f9e94f975c263139cfc57, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 7501e662a59f9e94f975c263139cfc57, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AddPrecomputedVelocity: 0
|
||||
- _AlphaClip: 0
|
||||
- _AlphaToMask: 0
|
||||
- _Blend: 0
|
||||
- _BlendOp: 0
|
||||
- _Cull: 0
|
||||
- _Cutoff: 0.5
|
||||
- _DstBlend: 10
|
||||
- _DstBlendAlpha: 10
|
||||
- _QueueOffset: 50
|
||||
- _SampleGI: 0
|
||||
- _SrcBlend: 5
|
||||
- _SrcBlendAlpha: 1
|
||||
- _Surface: 1
|
||||
- _XRMotionVectorsPass: 1
|
||||
- _ZWrite: 0
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 1, b: 1, a: 0.92}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 0.92}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &4198336840671140510
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
|
||||
version: 10
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d24a4c5ce16646c409631c112b57f2cf
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Farm_Water_WL_E
|
||||
m_Shader: {fileID: -6465566751694194690, guid: 85b142f88e4bec1488c6b275a0e5dc57,
|
||||
type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses:
|
||||
- MOTIONVECTORS
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- Texture2D_086cedcb1d864765840f9996e4b0002d:
|
||||
m_Texture: {fileID: 2800000, guid: 945a5174b1a6da34ea1028ed2feeb1e9, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- Texture2D_1d2b8f4484d74423a27218f18b962ade:
|
||||
m_Texture: {fileID: 2800000, guid: d48aae5302069a94f9410b8d6b76fed1, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- Texture2D_4094dc7f19e94579ac3bbc9c811f51a4:
|
||||
m_Texture: {fileID: 2800000, guid: 62100fbe73f198245b71c0a6eeeb94f6, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- Texture2D_685ca00e8e7c4cb2b45a9e11981bb64a:
|
||||
m_Texture: {fileID: 2800000, guid: 5088aa2234cf5b24cad13def77f7da5f, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- Vector1_07238257334b4a149e675e2451801030: 166.66667
|
||||
- Vector1_101dc4546b684d40bc2ff2fc59ab43d5: 2.2
|
||||
- Vector1_11671d7a4cdb4d059a6c69e39f3f7b3f: 1333.3334
|
||||
- Vector1_21ae4fce4585460386edec89c9895501: 0
|
||||
- Vector1_2b4963cef1de4859983ffcbae94c6f60: 0
|
||||
- Vector1_3089b6a325a44c1686907af4ee3b0776: 0.6666667
|
||||
- Vector1_34f757bec6b8422b9aef3b9d97117a6e: 4
|
||||
- Vector1_566e288f42864b8e9432d81fbdb83f38: 7
|
||||
- Vector1_68f0c21b684f4b7c9ebef8789113b107: 2
|
||||
- Vector1_7090c8ca8ea84e2d85858ae4beb5be38: 1
|
||||
- Vector1_85ea9246e72a44ed9e0482861767c826: 0.03
|
||||
- Vector1_8e22a98f75c94b218c49e6c4805e799d: 0.13333334
|
||||
- Vector1_99cc56b5c6fd474082f07f00a6df94f9: 0.0018509999
|
||||
- Vector1_ad7e0fcd37f44d68b68de6f06bb43b96: 0.13333334
|
||||
- Vector1_c6f2603b30534ec8b0039379573789e3: 1
|
||||
- Vector1_d813b569a4d541d1b2ac4ea9bc66a3b9: 0.09
|
||||
- Vector1_dd1e17693dc14b10b91828bdfd5adaa8: 0
|
||||
- Vector1_ff7a2780aaa94ddd86e156c4707e39a2: 0.4
|
||||
- _QueueControl: 0
|
||||
- _QueueOffset: 0
|
||||
- _XRMotionVectorsPass: 1
|
||||
m_Colors:
|
||||
- Color_1ec6cccf8ead489ebb917674f7e8b3b1: {r: 0.42, g: 0.72, b: 0.845, a: 1}
|
||||
- Color_2323d69962e04c499c5d5f0925432b55: {r: 1, g: 1, b: 1, a: 1}
|
||||
- Color_9af4ad59934f40d1ae6565e6ab22c45e: {r: 0.36, g: 0.69, b: 0.82, a: 1}
|
||||
- Color_ca031ae309ff42bdb95f777248fb961d: {r: 0.17, g: 0.42, b: 0.57, a: 1}
|
||||
- Color_e1f155248d144786a62fc1585ca21e9a: {r: 0.35999998, g: 0.69, b: 0.82, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &7840779067325084833
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
|
||||
version: 10
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7432692635bf09d4eb5271f2b366839e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -64,7 +64,16 @@ MonoBehaviour:
|
|||
skyReleaseDelaySeconds: 1.5
|
||||
waterMode: 1
|
||||
waterFrom: {fileID: 2100000, guid: ce0f8fd131f36964dbc918b8c63f838b, type: 2}
|
||||
waterTo: {fileID: 2100000, guid: 064fa97251666874e9da5473b09d43bd, type: 2}
|
||||
waterTo: {fileID: 2100000, guid: 7432692635bf09d4eb5271f2b366839e, type: 2}
|
||||
shoreFoamEnabled: 1
|
||||
shoreFoamMaterial: {fileID: 2100000, guid: d24a4c5ce16646c409631c112b57f2cf, type: 2}
|
||||
shoreFoamWidth: 1.6
|
||||
shoreFoamInner: 0.5
|
||||
shoreFoamCell: 0.5
|
||||
shoreFoamY: 0.02
|
||||
shoreFoamFallbackY: -1
|
||||
shoreFoamTileLength: 6
|
||||
shoreFoamScroll: 0.06
|
||||
grassEnabled: 1
|
||||
scatter:
|
||||
- enabled_: 1
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,181 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7501e662a59f9e94f975c263139cfc57
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -134333910614944054
|
||||
second: WL_ShoreFoam_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 1
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: iOS
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: WL_ShoreFoam_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 512
|
||||
height: 128
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: ac6d1802500c22ef0800000000000000
|
||||
internalID: -134333910614944054
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -132,13 +132,15 @@ namespace WL.Look.Farm
|
|||
if (cfg.soilToneEnabled != 0) ToneSoil(cfg, scene);
|
||||
|
||||
if (cfg.grassEnabled != 0) SpawnGrass(cfg, scene);
|
||||
if (cfg.shoreFoamEnabled != 0) SpawnShoreFoam(cfg, scene);
|
||||
|
||||
HookIslands(cfg, scene);
|
||||
|
||||
cfg.Log("섬 룩 적용 — 렌더러 " + SwappedRenderers + " · 슬롯 " + SwappedSlots
|
||||
+ " · 조명 " + (cfg.applyLighting != 0 ? "데모" : "원본")
|
||||
+ " · ReferenceLook " + (ReferenceLookApplied ? "on" : "off")
|
||||
+ " · 풀 " + WLIslandGrass.LastLog);
|
||||
+ " · 풀 " + WLIslandGrass.LastLog
|
||||
+ " · 둘레거품 " + WLShoreFoam.LastLog);
|
||||
|
||||
// 늦게 생기는 오브젝트(상인·작물·아이템)까지 다시 훑는다
|
||||
if (cfg.rescanAtSeconds != null)
|
||||
|
|
@ -221,11 +223,37 @@ namespace WL.Look.Farm
|
|||
|
||||
static void RequestGrassRebuild(WLIslandLookSettings cfg)
|
||||
{
|
||||
if (cfg.grassEnabled == 0) return;
|
||||
var g = Object.FindFirstObjectByType<WLIslandGrass>(FindObjectsInactive.Include);
|
||||
if (g == null) return;
|
||||
g.Rebuild();
|
||||
GrassRebuilds++;
|
||||
if (cfg.grassEnabled != 0)
|
||||
{
|
||||
var g = Object.FindFirstObjectByType<WLIslandGrass>(FindObjectsInactive.Include);
|
||||
if (g != null) { g.Rebuild(); GrassRebuilds++; }
|
||||
}
|
||||
// 🔴 816j2 — 섬이 확장되면 **둘레 거품 띠도 같은 훅으로** 다시 만든다(새 가장자리 자동).
|
||||
if (cfg.shoreFoamEnabled != 0)
|
||||
{
|
||||
var f = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
|
||||
if (f != null) { f.cfg = cfg; f.Rebuild(); ShoreFoamRebuilds++; }
|
||||
}
|
||||
}
|
||||
|
||||
public static int ShoreFoamRebuilds;
|
||||
public static bool ShoreFoamSpawned;
|
||||
|
||||
/// <summary>섬 둘레 거품 띠 — 풀과 같은 자리에서 만들고 같은 훅으로 다시 만든다(816j2).</summary>
|
||||
public static void SpawnShoreFoam(WLIslandLookSettings cfg, Scene scene)
|
||||
{
|
||||
var f = Object.FindFirstObjectByType<WLShoreFoam>(FindObjectsInactive.Include);
|
||||
if (f == null)
|
||||
{
|
||||
var go = new GameObject(WLShoreFoam.ObjectName);
|
||||
SceneManager.MoveGameObjectToScene(go, scene);
|
||||
go.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||
f = go.AddComponent<WLShoreFoam>();
|
||||
f.cfg = cfg;
|
||||
f.Rebuild(); // OnEnable 이 cfg 전에 돌 수 있다
|
||||
}
|
||||
else { f.cfg = cfg; f.Rebuild(); }
|
||||
ShoreFoamSpawned = true;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -197,6 +197,35 @@ namespace WL.Look.Farm
|
|||
[Tooltip("WL 워터 복사본(`Assets/WL/Materials/WL_Water_Ocean.mat` 기준). 비우면 교체하지 않는다.")]
|
||||
public Material waterTo;
|
||||
|
||||
// ───────────────────────────────── §816j2 섬 둘레 거품 띠
|
||||
[Header("§816j2 — 섬 둘레 흰 거품 띠 (PD 「둘레에 띠를 둘러줘」)")]
|
||||
[Tooltip("0 = 띠 없음(816j 상태로 100 % 복귀) · 1 = 섬 둘레를 따라 메시 띠 1장(드로우콜 +1).")]
|
||||
public int shoreFoamEnabled = 1;
|
||||
|
||||
[Tooltip("띠에 쓰는 머티리얼(URP Unlit · 반투명). 비우면 띠를 만들지 않는다.")]
|
||||
public Material shoreFoamMaterial;
|
||||
|
||||
[Tooltip("띠가 물 쪽으로 뻗는 폭(m). 캐릭터 키 1.19 m · 섬 타일 8 m 기준.")]
|
||||
public float shoreFoamWidth = 1.6f;
|
||||
|
||||
[Tooltip("섬 안쪽으로 겹쳐 들어가는 길이(m) — 물가에 틈이 생기지 않게. 섬 벽이 가려 준다.")]
|
||||
public float shoreFoamInner = 0.5f;
|
||||
|
||||
[Tooltip("띠 메시의 격자 간격(m). 크면 싸고 거칠다. 비용이 문제면 이것부터 키운다.")]
|
||||
public float shoreFoamCell = 0.5f;
|
||||
|
||||
[Tooltip("물 표면보다 얼마나 위에 깔 것인가(m). 너무 작으면 z-fighting.")]
|
||||
public float shoreFoamY = 0.02f;
|
||||
|
||||
[Tooltip("씬에서 `Water` 를 못 찾았을 때 쓸 물 높이(m).")]
|
||||
public float shoreFoamFallbackY = -1f;
|
||||
|
||||
[Tooltip("거품 무늬가 해안을 따라 반복되는 길이(m).")]
|
||||
public float shoreFoamTileLength = 6f;
|
||||
|
||||
[Tooltip("거품이 흐르는 속도(1 = 초당 무늬 1칸). 0 이면 정지.")]
|
||||
public float shoreFoamScroll = 0.06f;
|
||||
|
||||
// ───────────────────────────────── §1 풀밭
|
||||
[Header("§1 — 섬 타일 위 풀밭 (데모와 같은 인스턴싱)")]
|
||||
[Tooltip("0 이면 풀을 깔지 않는다.")]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,269 @@
|
|||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// WLShoreFoam.cs — 섬 **둘레**를 따라 흰 거품 띠를 두른다 (WL-816j2 · #816)
|
||||
//
|
||||
// 왜 필요한가 (816j 실측)
|
||||
// 셰이더의 깊이 기반 Foam 은 **카메라가 보는 쪽 가장자리에만** 거품이 생긴다
|
||||
// (섬이 수직 벽 덩어리라 시선이 물을 뚫고 잠긴 벽에 닿는 쪽만 「얕은 물」로 읽힌다).
|
||||
// PD 가 「둘레에 띠를 둘러줘」로 결정 → 섬 윗면 footprint 의 **바깥 테두리**를 따라
|
||||
// 메시 띠를 하나 만들어 물 위에 깐다. 사방 전부에 생기고, 카메라 방향과 무관하다.
|
||||
//
|
||||
// 비용
|
||||
// 메시 1장 · 머티리얼 1개 · **드로우콜 +1**. 섬 타일 4칸 기준 삼각형 1천 대.
|
||||
// 비싸면 `shoreFoamCell`(격자 간격)을 키우거나 `shoreFoamWidth`(폭)를 줄인다.
|
||||
//
|
||||
// 섬 확장
|
||||
// `WLIslandLook.RequestIslandRebuild` 가 풀과 함께 이 띠도 다시 만든다
|
||||
// (816e 확장 훅 = `FIIsland.OnActivated` + 잠금 해제 수 폴링) → 새 가장자리 자동.
|
||||
//
|
||||
// 🔴 FI 코드 0줄 · 씬 파일 0줄 · 원본 셰이더 0줄. 런타임에 메시만 만든다.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using FIIsland = CryingSnow.FarmingIsland.Island;
|
||||
|
||||
namespace WL.Look.Farm
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class WLShoreFoam : MonoBehaviour
|
||||
{
|
||||
public const string ObjectName = "~WL_ShoreFoam";
|
||||
|
||||
public static int Rebuilds, Verts, Tris, Tiles;
|
||||
public static string LastLog = "";
|
||||
|
||||
public WLIslandLookSettings cfg;
|
||||
|
||||
// 검증용 런타임 오버라이드 — 0/음수면 설정값을 쓴다. 🔴 에셋을 고치지 않고 3단 비교를 하기 위한 것.
|
||||
[System.NonSerialized] public float widthOverride = 0f;
|
||||
[System.NonSerialized] public float innerOverride = -1f;
|
||||
[System.NonSerialized] public float cellOverride = 0f;
|
||||
|
||||
MeshFilter _mf;
|
||||
MeshRenderer _mr;
|
||||
Mesh _mesh;
|
||||
float _scroll;
|
||||
|
||||
void OnEnable() { Ensure(); Rebuild(); }
|
||||
void OnDisable() { if (_mr != null) _mr.enabled = false; }
|
||||
|
||||
void Ensure()
|
||||
{
|
||||
if (_mf == null) _mf = GetComponent<MeshFilter>();
|
||||
if (_mf == null) _mf = gameObject.AddComponent<MeshFilter>();
|
||||
if (_mr == null) _mr = GetComponent<MeshRenderer>();
|
||||
if (_mr == null) _mr = gameObject.AddComponent<MeshRenderer>();
|
||||
_mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
||||
_mr.receiveShadows = false;
|
||||
_mr.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
|
||||
_mr.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
|
||||
_mr.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
|
||||
if (_mesh == null)
|
||||
{
|
||||
_mesh = new Mesh { name = "WL_ShoreFoamMesh" };
|
||||
_mesh.MarkDynamic();
|
||||
_mesh.hideFlags = HideFlags.DontSave;
|
||||
}
|
||||
_mf.sharedMesh = _mesh;
|
||||
}
|
||||
|
||||
/// <summary>거품이 해안을 따라 천천히 흐른다. 🔴 에셋이 아니라 **런타임 복사본**의 오프셋만 만진다.</summary>
|
||||
void Update()
|
||||
{
|
||||
if (cfg == null || _mr == null || _inst == null) return;
|
||||
float sp = cfg.shoreFoamScroll;
|
||||
if (sp == 0f) return;
|
||||
_scroll += Time.deltaTime * sp;
|
||||
if (_scroll > 1f) _scroll -= 1f;
|
||||
_inst.SetTextureOffset(IdBase, new Vector2(_scroll, _scroll * 0.37f));
|
||||
}
|
||||
Material _inst;
|
||||
static readonly int IdBase = Shader.PropertyToID("_BaseMap");
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
public void Rebuild()
|
||||
{
|
||||
Ensure();
|
||||
if (cfg == null) cfg = WLIslandLookSettings.Instance;
|
||||
if (cfg == null || cfg.enabled_ == 0 || cfg.shoreFoamEnabled == 0)
|
||||
{ _mr.enabled = false; LastLog = "꺼짐"; return; }
|
||||
|
||||
if (cfg.shoreFoamMaterial == null) { _mr.enabled = false; LastLog = "🔴 머티리얼 없음"; return; }
|
||||
if (_inst == null || _inst.shader != cfg.shoreFoamMaterial.shader)
|
||||
{
|
||||
if (_inst != null) Destroy(_inst);
|
||||
_inst = new Material(cfg.shoreFoamMaterial) { name = "WL_ShoreFoam(runtime)", hideFlags = HideFlags.DontSave };
|
||||
}
|
||||
_mr.sharedMaterial = _inst;
|
||||
|
||||
var tiles = CollectTiles();
|
||||
Tiles = tiles.Count;
|
||||
if (tiles.Count == 0) { _mesh.Clear(); _mr.enabled = false; LastLog = "타일 0"; return; }
|
||||
|
||||
float cell = Mathf.Max(0.15f, cellOverride > 0f ? cellOverride : cfg.shoreFoamCell);
|
||||
float w = Mathf.Max(0.1f, widthOverride > 0f ? widthOverride : cfg.shoreFoamWidth);
|
||||
float inner = Mathf.Max(0f, innerOverride >= 0f ? innerOverride : cfg.shoreFoamInner);
|
||||
float pad = w + inner + cell * 2f;
|
||||
|
||||
// 섬 전체를 덮는 격자
|
||||
float minX = float.MaxValue, minZ = float.MaxValue, maxX = float.MinValue, maxZ = float.MinValue;
|
||||
for (int i = 0; i < tiles.Count; i++)
|
||||
{
|
||||
var t = tiles[i]; float h = t.half;
|
||||
minX = Mathf.Min(minX, t.center.x - h); maxX = Mathf.Max(maxX, t.center.x + h);
|
||||
minZ = Mathf.Min(minZ, t.center.z - h); maxZ = Mathf.Max(maxZ, t.center.z + h);
|
||||
}
|
||||
minX -= pad; minZ -= pad; maxX += pad; maxZ += pad;
|
||||
int nx = Mathf.Clamp(Mathf.CeilToInt((maxX - minX) / cell) + 1, 2, 1024);
|
||||
int nz = Mathf.Clamp(Mathf.CeilToInt((maxZ - minZ) / cell) + 1, 2, 1024);
|
||||
|
||||
// ① 안/밖
|
||||
var inside = new bool[nx * nz];
|
||||
for (int j = 0; j < nz; j++)
|
||||
{
|
||||
float z = minZ + j * cell;
|
||||
for (int i = 0; i < nx; i++)
|
||||
{
|
||||
float x = minX + i * cell;
|
||||
inside[j * nx + i] = OnAnyTile(tiles, x, z);
|
||||
}
|
||||
}
|
||||
|
||||
// ② 부호 있는 거리(챔퍼 2패스) — 밖은 +, 안은 −
|
||||
var d = Chamfer(inside, nx, nz, cell, false); // 밖 → 가장 가까운 안까지
|
||||
var e = Chamfer(inside, nx, nz, cell, true); // 안 → 가장 가까운 밖까지
|
||||
var sd = new float[nx * nz];
|
||||
for (int k = 0; k < sd.Length; k++) sd[k] = inside[k] ? -e[k] : d[k];
|
||||
|
||||
// ③ 띠 구간([-inner, w])에 걸치는 칸만 삼각형으로
|
||||
float y = WaterY(tiles) + cfg.shoreFoamY;
|
||||
float tileLen = Mathf.Max(0.5f, cfg.shoreFoamTileLength);
|
||||
var vmap = new int[nx * nz];
|
||||
for (int k = 0; k < vmap.Length; k++) vmap[k] = -1;
|
||||
var verts = new List<Vector3>(4096);
|
||||
var uvs = new List<Vector2>(4096);
|
||||
var tris = new List<int>(8192);
|
||||
|
||||
for (int j = 0; j < nz - 1; j++)
|
||||
for (int i = 0; i < nx - 1; i++)
|
||||
{
|
||||
int a = j * nx + i, b = a + 1, c = a + nx, dd = c + 1;
|
||||
float lo = Mathf.Min(Mathf.Min(sd[a], sd[b]), Mathf.Min(sd[c], sd[dd]));
|
||||
float hi = Mathf.Max(Mathf.Max(sd[a], sd[b]), Mathf.Max(sd[c], sd[dd]));
|
||||
if (lo > w || hi < -inner) continue;
|
||||
int va = V(a), vb = V(b), vc = V(c), vd = V(dd);
|
||||
tris.Add(va); tris.Add(vc); tris.Add(vb);
|
||||
tris.Add(vb); tris.Add(vc); tris.Add(vd);
|
||||
}
|
||||
|
||||
int V(int k)
|
||||
{
|
||||
if (vmap[k] >= 0) return vmap[k];
|
||||
int i = k % nx, j = k / nx;
|
||||
float x = minX + i * cell, z = minZ + j * cell;
|
||||
verts.Add(new Vector3(x, y, z));
|
||||
float v = Mathf.Clamp01((sd[k] + inner) / (w + inner));
|
||||
uvs.Add(new Vector2((x * 0.7071f + z * 0.7071f) / tileLen, v));
|
||||
vmap[k] = verts.Count - 1;
|
||||
return vmap[k];
|
||||
}
|
||||
|
||||
_mesh.Clear();
|
||||
if (verts.Count == 0 || tris.Count == 0) { _mr.enabled = false; LastLog = "띠 0"; return; }
|
||||
_mesh.indexFormat = verts.Count > 65000
|
||||
? UnityEngine.Rendering.IndexFormat.UInt32 : UnityEngine.Rendering.IndexFormat.UInt16;
|
||||
_mesh.SetVertices(verts);
|
||||
_mesh.SetUVs(0, uvs);
|
||||
_mesh.SetTriangles(tris, 0);
|
||||
_mesh.RecalculateBounds();
|
||||
_mr.enabled = true;
|
||||
|
||||
Rebuilds++; Verts = verts.Count; Tris = tris.Count / 3;
|
||||
LastLog = "타일 " + Tiles + " · 띠 삼각형 " + Tris + " · 정점 " + Verts
|
||||
+ " · 폭 " + w.ToString("F2") + " m · 격자 " + cell.ToString("F2") + " m · 드로우콜 +1";
|
||||
cfg.Log("둘레 거품 띠 — " + LastLog);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
struct TileRef { public Transform tf; public Vector3 center; public WLTileMask mask; public float half; }
|
||||
|
||||
readonly List<TileRef> _tiles = new List<TileRef>(96);
|
||||
|
||||
List<TileRef> CollectTiles()
|
||||
{
|
||||
_tiles.Clear();
|
||||
var islands = Object.FindObjectsByType<FIIsland>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < islands.Length; i++)
|
||||
{
|
||||
var isl = islands[i];
|
||||
if (isl == null || !isl.IsUnlocked) continue;
|
||||
if (!isl.gameObject.activeInHierarchy) continue;
|
||||
if (isl.transform.localScale.x < 0.99f) continue; // 확장 애니메이션 중
|
||||
var mf = isl.GetComponent<MeshFilter>();
|
||||
if (mf == null || mf.sharedMesh == null) continue;
|
||||
var mask = cfg.FindTileMask(mf.sharedMesh.name);
|
||||
if (mask == null) continue;
|
||||
_tiles.Add(new TileRef { tf = isl.transform, center = isl.transform.position, mask = mask, half = mask.half });
|
||||
}
|
||||
return _tiles;
|
||||
}
|
||||
|
||||
static bool OnAnyTile(List<TileRef> tiles, float wx, float wz)
|
||||
{
|
||||
for (int i = 0; i < tiles.Count; i++)
|
||||
{
|
||||
var t = tiles[i];
|
||||
var l = t.tf.InverseTransformPoint(new Vector3(wx, t.center.y, wz));
|
||||
if (t.mask.At(l.x, l.z)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>물 평면의 높이 — 섬 씬의 `Water` 를 찾고 없으면 설정값.</summary>
|
||||
float WaterY(List<TileRef> tiles)
|
||||
{
|
||||
var scene = tiles.Count > 0 ? tiles[0].tf.gameObject.scene : gameObject.scene;
|
||||
var roots = scene.GetRootGameObjects();
|
||||
for (int i = 0; i < roots.Length; i++)
|
||||
{
|
||||
var t = roots[i].transform.Find("Water");
|
||||
if (t != null) return t.position.y;
|
||||
if (roots[i].name == "Water") return roots[i].transform.position.y;
|
||||
}
|
||||
return cfg.shoreFoamFallbackY;
|
||||
}
|
||||
|
||||
/// <summary>챔퍼 거리 변환 — seed 가 true 인 칸에서의 거리(m).</summary>
|
||||
static float[] Chamfer(bool[] inside, int nx, int nz, float cell, bool seedOutside)
|
||||
{
|
||||
const float BIG = 1e9f;
|
||||
var d = new float[nx * nz];
|
||||
for (int k = 0; k < d.Length; k++)
|
||||
{
|
||||
bool seed = seedOutside ? !inside[k] : inside[k];
|
||||
d[k] = seed ? 0f : BIG;
|
||||
}
|
||||
float a = cell, b = cell * 1.41421356f;
|
||||
for (int j = 0; j < nz; j++)
|
||||
for (int i = 0; i < nx; i++)
|
||||
{
|
||||
int k = j * nx + i; float m = d[k];
|
||||
if (i > 0) m = Mathf.Min(m, d[k - 1] + a);
|
||||
if (j > 0) m = Mathf.Min(m, d[k - nx] + a);
|
||||
if (i > 0 && j > 0) m = Mathf.Min(m, d[k - nx - 1] + b);
|
||||
if (i < nx - 1 && j > 0) m = Mathf.Min(m, d[k - nx + 1] + b);
|
||||
d[k] = m;
|
||||
}
|
||||
for (int j = nz - 1; j >= 0; j--)
|
||||
for (int i = nx - 1; i >= 0; i--)
|
||||
{
|
||||
int k = j * nx + i; float m = d[k];
|
||||
if (i < nx - 1) m = Mathf.Min(m, d[k + 1] + a);
|
||||
if (j < nz - 1) m = Mathf.Min(m, d[k + nx] + a);
|
||||
if (i < nx - 1 && j < nz - 1) m = Mathf.Min(m, d[k + nx + 1] + b);
|
||||
if (i > 0 && j < nz - 1) m = Mathf.Min(m, d[k + nx - 1] + b);
|
||||
d[k] = m;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb10258ab89aad24c991df4bff681ba4
|
||||
Loading…
Reference in New Issue