فهرست مستندات

تنظیم حال‌وهوا و نور zoneهای پارک#

این یک دفترچهٔ عملی برای درجه‌بندیٔ مجدد دو zone منتشرشدهٔ پارک است — شکوفه‌زار مرجانی (coral-bloom) و ایوان ابر (cloud-terrace) — با روش آزمون‌وخطا: کدام دستگیره در کدام فایل است، بصری چه می‌کند و برای کدام حس به کدام سمت باید بردش. فرض بر این است که تکنیک‌های سه‌بعدی zoneهای پارک را برای معماری رندرینگ خوانده‌اید؛ اینجا فقط مقادیر جهت هنری را دست می‌زنیم، هرگز ساختار را نه. هر مقداری که در ادامه نقل می‌شود مقدار فعلی منتشرشده است تا بتوانید ویرایش‌تان را با یک مبنای مشخص مقایسه کنید.

پنل تنظیم حال‌وهوا (فقط توسعه)#

سریع‌ترین راه پیداکردن مقادیر اصلاً ویرایش فایل نیست. پارک یک پنل تنظیم حال‌وهوای مخصوص توسعه دارد و همان چرخهٔ ترجیحی کاوش است:

  1. سرور توسعه را بالا بیاورید (pnpm --filter park dev) و zoneای را که درجه‌بندی می‌کنید باز کنید.
  2. کلید M را بزنید. یک پنل DOM با اسلایدرها و انتخاب‌گرهای رنگ برای مه، نور خورشید و نیمکره، پالت آسمان، قرص خورشید، ابرها (پوشش، مقیاس، سرعت، روشنایی) و post (bloom و exposure) متعلق به zone فعال باز می‌شود.
  3. بکشید و فریم را ببینید — هر تغییر یک نوشتن uniform زنده یا یک به‌روزرسانی ارزان prop است، هرگز بازسازی pipeline یا گراف shader نه. پیش‌نویس در localStorage بین reloadها می‌ماند.
  4. وقتی حال‌وهوا درست خوانده شد، «کپی JSON» را بزنید. خروجی برای پختن در فایل‌ها شکل گرفته است:
{
  "zone": "coral-bloom",
  "skyModel": { "fogFar": 300, "palette": { "zenithColor": "#1b5fd7" } },
  "registryPost": { "bloom": { "strength": 0.55 }, "exposure": 1.12 }
}
  1. مقادیر را در فایل‌های authored بپزید — دستی یا با یک دستیار هوش مصنوعی: skyModel در *-sky-model.ts مربوط به zone و registryPost در ورودی art.post همان zone در src/zones/registry.ts.
  2. نزدیک‌ترین تست‌ها را اجرا کنید و مثل همیشه روی هر دو backend درجه‌بندی کنید.

پنل با import.meta.env.DEV گیره شده، پس Vite آن را کاملاً از build محصول حذف می‌کند. مقادیر ساختاری build-time می‌مانند و قابل‌تنظیم نیستند: octaves/detail ابر، اندازه و بسط نقشهٔ سایه، و اندازهٔ زاویه‌ای قرص خورشید (discInnerCos/discOuterCos). نقشهٔ دستگیره‌های زیر همچنان مرجع این است که هر مقدار سرانجام کجا زندگی می‌کند — و برای دستگیره‌هایی که پنل عمداً در معرض نمی‌گذارد.

کار روزمره با پنل#

  • هر کنترل از روی مقدار authored زون شروع می‌شود و نشان «· پیش‌فرض» دارد؛ با دست‌کاری، نشان پاک می‌شود، پس diff فعلی همیشه دیده می‌شود.
  • «بازنشانی» همهٔ overrideها را به حال‌وهوای authored برمی‌گرداند و پیش‌نویس localStorage را هم همراهش پاک می‌کند.
  • جعبهٔ import («وارد کردن JSON» + «اعمال») یک خروجی الصاق‌شده را برمی‌گرداند — همان اعتبارسنجی ویرایش محلی اجرا می‌شود، پس ورودی نامعتبر با پیام رد می‌شود.
  • پیش‌نویس سراسری است نه per-zone: یک zone را تنظیم کنید، JSON را کپی کنید، بازنشانی کنید، بعد سراغ zone بعدی بروید. فیلد zone خروجی پاکت‌ها را از هم جدا نگه می‌دارد.
  • برای درجه‌بندی با هنرمندی که checkout ندارد، سرور توسعه را روی شبکهٔ محلی بالا بیاورید و لینک بدهید — پنل روی هر صفحهٔ سروشدهٔ dev کار می‌کند.

انتقال پنل به یک محیط دیگر#

پنل امروز عمداً محلیِ پارک است — generic کردنش پیش از وجود مصرف‌کنندهٔ دوم همان اشتباه تک‌مصرف‌کننده‌ای را تکرار می‌کند که ADR-0060 بازنشسته‌اش کرد. درزها از قبل تمیزند، پس وقتی وقتش برسد انتقال ارزان است:

  • بدون تغییر قابل استفادهٔ مجدد: مکانیک store، نگهبان کلید M، پوستهٔ پنل، و چرخهٔ export/import.
  • مخصوص هر محیط: تایپ override و کاتالوگ خودش، یک مدل merge/serialize روی تایپ sky-spec خودش، و نگاشت handle زنده برای کامپوننت آسمان خودش.
  • پیش‌نیاز: محیط باید از قبل art direction را به صورت داده (فایل‌های model) نگه دارد و از طریق prop و نوشتن uniform زنده مصرف کند — همان الگویی که این سند شرح می‌دهد. نورهای هاردکد در JSX اول به همان ریفکتور نیاز دارند.
  • وقتی محیط دوم واقعاً پنل را به کار گرفت، هستهٔ generic به جای کپی‌شدن به یک ماژول مشترک منتقل می‌شود.

چرخهٔ تکرار#

  1. سرور توسعه را با pnpm --filter park dev بالا بیاورید. Vite روی پورت 4800 سرو می‌کند (با AL_AMR_DEV_PARK_PORT قابل تغییر است).
  2. zoneای را که درجه‌بندی می‌کنید باز کنید: /zones/coral-bloom یا /zones/cloud-terrace (مسیر / قلب باغ است).
  3. هر مقدار زیر را ویرایش و ذخیره کنید — همهٔ تغییرات hot-reload می‌شوند؛ نه build، نه restart، نه پاک‌کردن کش.
  4. بدانید کدام سطح کیفیت را قضاوت می‌کنید. نشست با standard شروع می‌شود و بعد از فریم‌های کند پایدار (دو پنجرهٔ متوالی با p95 بالای ۲۴ میلی‌ثانیه) به‌صورت خودکار به compatible تنزل می‌کند و هرگز برنمی‌گردد. compatible اکتاوها و جزئیات ابر، پاس bloom و سایه‌های پوشش گیاهی را حذف می‌کند — تصویری ذاتاً تخت‌تر. enhanced هرگز خودکار انتخاب نمی‌شود. اگر وسط نشست فریم ناگهان بی‌روح‌تر شد، احتمالاً سطح جابه‌جا شده، نه ویرایش شما.
  5. backend دوم را عمداً ببینید: renderer اول WebGPU را ترجیح می‌دهد و به WebGL2 برمی‌گردد؛ با افزودن ?al-amr-rendering=force-webgl2 به URL، مسیر WebGL2 را اجباری کنید. روی هر دو درجه‌بندی کنید.
  6. قبل از آزمایش پشتیبان بگیرید. سورس‌های cloud-terrace ممکن است در worktree شما commit نشده باشند، پس git checkout -- آن‌ها را برنمی‌گرداند — اول فایل را کپی کنید (cp cloud-terrace-sky-model.ts /tmp/backup/) یا مبنایتان را commit کنید.

سه لایهٔ حال‌وهوا#

حال‌وهوا از سه لایه می‌آید، به ترتیب اهرم‌بری:

  1. مدل آسمان zonecoral-bloom-sky-model.ts یا cloud-terrace-sky-model.ts. این تقریباً ۹۰٪ حال‌وهواست: پالت آسمان، مه، نور خورشید و نیمکره، بودجهٔ ابر. همیشه از اینجا شروع کنید.
  2. overrideهای post در zone — ورودی art.post در environments/park/src/zones/registry.ts. فقط دو دستگیره وجود دارد: bloom.strength (در بازهٔ [0, 8] گیره می‌شود) و exposure (در بازهٔ [0.1, 8] گیره می‌شود و به‌صورت جهش uniform زنده روی renderer.toneMappingExposure نوشته می‌شود — هرگز بازسازی pipeline نه). روشنایی و درخشش سراسری، نه چیز دیگر.
  3. رنگ‌های مواد در کامپوننت‌های .tsx — سبزهای چمن‌زار، رنگ بدنهٔ آب، tintهای پوشش گیاهی. چاشنی نهایی بعد از آنکه نور درست شد.

قاعدهٔ سرانگشتی: اول نور را درست کنید، بعد مواد را. صحنه‌ای که زیر نور غلط بد به نظر می‌رسد، زیر نور درست به شکل متفاوتی بد به نظر خواهد رسید.

پارامترهای پالت آسمان#

هر دو zone همان ساختار ParkSkySpec را از environments/park/src/scenes/sky/park-sky-model.ts resolve می‌کنند. پالت، گرادیان گنبد و ابرها را رنگ می‌کند؛ هیچ سطحی را نور نمی‌کند.

پارامترشکوفه‌زار مرجانیایوان ابراثر بصری
zenithColor#1b5fd7#4aa8e8آسمان درست بالای سر. برای روز آبی‌تر و صاف‌تر عمیق‌تر کنید؛ برای بهشت high-key به سمت فیروزه‌ای روشن کنید.
midColor#6fb2f0#8ecbf4رنگ میانی آسمان بین سماوی و افق. همراه zenithColor حرکتش دهید وگرنه گرادیان باند می‌شود.
horizonColor#dff0ff#f4fbffافق سمت خورشید که با جملهٔ خورشید گرم می‌شود. برای مه سفیدتر، برای هوای شفاف اشباع‌تر کنید.
horizonAwayColor#cfe4f8#e6f3fcافق روبه‌روی خورشید. کمی سردتر/تیره‌تر از horizonColor نگهش دارید وگرنه آسمان جهتش را از دست می‌دهد.
hazeColor#e4f1fd#eef7fdهالهٔ زیرافق — و رنگ مه خطی (دام‌ها را ببینید).
sunDiscColor#fffef8#ffffffرنگ قرص خورشید. برای ساعت طلایی گرمتر، برای ظهر سفیدتر کنید.
sunHaloColor#fff3d4#fff6e2هالهٔ تنگ دور قرص. مهم‌ترین سرنخ «خورشید گرم».
cloudLitColor#ffffff#ffffffوجه‌های آفتابی ابر.
cloudShadeColor#b6c6dd#c2d2e4سایهٔ ابر. تیره‌تر = ابر دراماتیک‌تر؛ روشن‌تر = بهشت پنبه‌ای.

برای آسمان آبی‌تر و صاف‌تر: zenithColor و midColor را عمیق‌تر کنید، دو رنگ افق را کمی به آبی بکشید و cloudShadeColor را روشن‌تر کنید. برای آسمان نرم‌تر و رؤیایی‌تر: همه‌چیز را به سمت سفید ببرید، از افق شروع کنید.

پارامترهای بصری خورشید#

این‌ها خورشید را داخل گنبد شکل می‌دهند. discInnerCos/discOuterCos اندازهٔ زاویه‌ای قرص را تعیین می‌کنند (کسینوس نیم‌زاویهٔ هسته و لبه — مقدار منتشرشده 0.99972/0.99912 یعنی حدود ۱٫۳۵/۲٫۴ درجه، در هر دو zone یکسان؛ هر چه به ۱ نزدیک‌تر، قرص کوچک‌تر). قرص و هاله به attachment امیسیو می‌رسند، پس آن‌ها همان چیزی هستند که پاس انتخابی bloom واقعاً می‌بیند.

پارامترشکوفه‌زار مرجانیایوان ابراثر بصری
discIntensity4.23.8روشنایی HDR قرص؛ قوی‌ترین تغذیهٔ bloom. برای خورشید آرام‌تر کمتر، برای جرقه بیشتر کنید.
haloIntensity2.11.6هالهٔ طلایی تنگ (هم HDR؛ نرم bloom می‌گیرد).
glowIntensity0.550.6درخشش گرم پهن، فقط پاس زیبایی (زیر آستانهٔ bloom).
washIntensity0.20.22رنگ‌مایهٔ گرم بسیار پهن روی آسمانی سمت خورشید.

نور، مه و سایهٔ resolveشده#

این فیلدهای خروجی resolve*Sky رگ نور واقعی را می‌رانند — تنها عددهایی که روشنایی سطوح را عوض می‌کنند.

پارامترشکوفه‌زار مرجانیایوان ابراثر بصری
sunColor#fff2dc#fff6e8رنگ نور جهت‌دار. گرم‌تر = عصر دیرتر.
sunIntensity11.5قدرت نور جهت‌دار: آفتاب مستقیم، هایلایت‌ها و کنتراست سایه. دستگیرهٔ مدل‌سازی فرم.
hemisphereSkyColor#93c4f2#93c4f2نور محیطی از بالا. آبی‌تر = سایه‌های سردتر.
hemisphereGroundColor#c0a075#c0a075بازتاب محیطی از پایین. لحن خاک گرم‌تر/تیره‌تر، زیر سطوح را گرم می‌کند.
hemisphereIntensity23قدرت نور پرکنندهٔ محیطی: چقدر همه‌چیز از هر زاویه خوانا است.
skyBrightness1.421.55ضریب HDR فقط روی گرادیان گنبد — هیچ چیز را نور نمی‌کند، اما تعیین می‌کند خود آسمان از میان ACES چقدر درخشان خوانده شود.
fogNear / fogFar96 / 260110 / 300کجا مه چشم‌انداز شروع و کجا تمام می‌شود، بر حسب متر. fogFar کوتاه‌تر = جهان صمیمی‌تر و مه‌آلودتر.
shadowExtent92104نیم‌بسط سایهٔ ارتوگرافیک؛ باید کل دیسک zone را بپوشاند (با تست پین شده).
shadowMapSize1024 (در enhanced برابر 2048)مانند همرزولوشن سایه؛ برای کار حال‌وهوا دست نزنید.

بودجهٔ ابر#

شیء clouds در هر مدل آسمان دو بار ظاهر می‌شود — یک بار برای شاخهٔ compatible و یک بار برای بقیه — پس هر دو را ویرایش کنید وگرنه سطح‌ها ناسازگار می‌شوند. مقادیر فعلی داخل هر zone بین شاخه‌ها یکسان است.

پارامترشکوفه‌زار مرجانیایوان ابراثر بصری
octaves5 (در enhanced برابر 6، در compatible برابر 3)مانند همجزئیات FBM؛ دستگیرهٔ هزینهٔ واقعی fragment است، نه دستگیرهٔ حال‌وهوا.
detailtrue (در compatible برابر false)مانند همروشن/خاموش‌بودن لایهٔ جزئیات billow.
coverage0.50.62چقدر آسمان ابری است. واضح‌ترین صفحه‌کلید «هوا».
scale0.50.5اندازهٔ عارضه‌های ابر. کمتر = توده‌های بزرگ‌تر و نرم‌تر.
speed0.0080.008سرعت رانش روی ساعت TSL.
brightness1.81.9ضریب HDR روی رنگ آفتابی ابر؛ در مقادیر بالا bloom را تغذیه می‌کند.

نسبت، خودِ حال‌وهواست#

روشنایی سطح تقریباً برابر است با رنگ ماده × (خورشید جهت‌دار + محیطی نیمکره). هیچ‌کدام از این دو عدد به‌تنهایی معنا ندارند — نسبت بینشان معنا دارد:

  • حس تابستان سوزان: sunIntensity بالا، hemisphereIntensity پایین — سایه‌های عمیق، مدل‌سازی قوی، روشنایی خیره‌کننده روی وجه‌های آفتابی.
  • حس نرم و روشن: sunIntensity پایین‌تر، hemisphereIntensity بالا — سایه‌های کم‌عمق، همه‌چیز خوانا، با بهای کمی تخت‌شدن.

ایوان ابر دقیقاً از طریق همین نسبت نرم‌تر و روشن‌تر از شکوفه‌زار مرجانی منتشر شده (خورشید ۱٫۵ / نیمکره ۳ در برابر خورشید ۱ / نیمکره ۲ — نور پرکنندهٔ ایوان کاملاً غالب است). مواد پوشش گیاهی گراف‌های MeshStandardNodeMaterial بدون جملهٔ امیسیو هستند، پس یک گل روی زمین که روبه‌خورشید دیده می‌شود تقریباً فقط با نور پرکنندهٔ نیمکره روشن می‌شود: اگر گل‌ها از بعضی زاویه‌ها مثل کاغذرنگی تیره خوانده می‌شوند، محیطی را بالا ببرید، نه خورشید را.

دستور: باغ آفتابی‌تر که خوانا می‌ماند#

یک قبل/بعد مشخص روی شکوفه‌زار مرجانی — مدل‌سازی و جرقهٔ خورشید بیشتر بدون ازدست‌دادن چمن‌زار روشن و خوانا. در coral-bloom-sky-model.ts:

sunColor: "#fff2dc",
sunIntensity: 1,
sunColor: "#fff2dc",
sunIntensity: 1.7,
hemisphereSkyColor: "#93c4f2",
hemisphereGroundColor: "#c0a075",
hemisphereIntensity: 2,
hemisphereSkyColor: "#93c4f2",
hemisphereGroundColor: "#c0a075",
hemisphereIntensity: 1.7,

و در environments/park/src/zones/registry.ts:

art: Object.freeze({
  resolveSky: resolveCoralBloomSky,
  post: Object.freeze({ bloom: Object.freeze({ strength: 0.62 }) }),
}),
art: Object.freeze({
  resolveSky: resolveCoralBloomSky,
  post: Object.freeze({ bloom: Object.freeze({ strength: 0.55 }), exposure: 1.12 }),
}),

دلیل: بالابردن خورشید از ۱ به ۱٫۷ فرم سایه و جرقهٔ سقف‌ها را برمی‌گرداند؛ نیمکره از ۲ به ۱٫۷ پایین می‌آید تا نور پرکننده، مدل‌سازی‌ای را که خورشید تازه افزوده تخت نکند؛ exposure برابر ۱٫۱۲ کل فریم را به روشنایی ادراکی قبلی برمی‌گرداند؛ و bloom شل می‌شود تا برق‌های خورشید قوی‌تر هاله نگیرند. در این دو zone بازهٔ شیرین sunIntensity تقریباً بین ۱٫۲ تا ۱٫۸ است — پایین‌تر از آن سایه‌ها شست می‌شوند و بالاتر از آن خورشید مشترک اواخر ظهر با پالت‌های تازهٔ روز می‌جنگد. برای ایوان ابر همین حرکت از مبنای ۱٫۵ کار می‌کند، اما نیمکره را غالب نگه دارید (همین است که ایوان را بهشت می‌خواند).

اهرم‌های خوانایی گل#

وقتی نور درست شد، کنتراست گیاهان زمینی در سطح ماده تنظیم می‌شود، همه داخل environments/park/src/scenes/coral-bloom/:

  • رنگ‌مایهٔ گلبرگ زمینCoralBloomTerrain.tsx. لکهٔ صورتی زیر باغ با گل‌ها رقابت می‌کند. برای کنتراست کمش کنید:
const blushed = mix(crest, petalBlush, blushMask.mul(0.32));
const blushed = mix(crest, petalBlush, blushMask.mul(0.15));
  • روشنایی per نمونهٔ گل‌هاCoralBloomFlora.tsx (در FlowerInstances). کف 0.85 تعیین می‌کند تیره‌ترین گل چقدر روشن است؛ بالا ببریدش تا همهٔ سرها بلند شوند (سیستم گلبرگ‌های لانه با 0.85 + 0.3 * petal.tint هم همین‌طور پاسخ می‌دهد):
mesh.setColorAt(index, color.copy(hue).multiplyScalar(0.85 + 0.3 * flower.tint));
mesh.setColorAt(index, color.copy(hue).multiplyScalar(1.0 + 0.3 * flower.tint));
  • اشباع پالت گلبرگCORAL_PETAL_PALETTE در coral-bloom-model.ts هم گل‌ها را تغذیه می‌کند هم گلبرگ‌های لانه را؛ برای پاستلی کم‌اشباع کنید، برای جشن پراشباع.
  • چگالی و اندازهٔ سر — تعداد گل‌ها per سطح و headScale: 0.75 + random() * 0.6 در coral-bloom-model.ts. سرهای بزرگ‌تر از دور بهتر خوانده می‌شوند؛ تعداد، بودجه‌های رندر را جابه‌جا می‌کند، پس مقیاس را ترجیح دهید.

پروتکل آزمایش#

به این ترتیب کار کنید؛ هر قدم یک چرخهٔ ذخیره-ونگاه است:

  1. از مبنای دست‌نخورده اسکرین‌شات بگیرید (نمای spawn به‌علاوهٔ یک نمای روبه‌خورشید) تا «بهتر» صادق بماند.
  2. اول sunIntensity را حرکت دهید — مدل‌سازی‌ای را تعریف می‌کند که بقیه به آن واکنش نشان می‌دهند.
  3. hemisphereIntensity را برای عمق سایه و خوانایی گل‌ها تنظیم کنید.
  4. exposure را در رجیستری برای روشنایی سراسری اضافه یا تنظیم کنید.
  5. fogFar (و همراهش fogNear) را برای عمق و صمیمیت تنظیم کنید.
  6. رنگ‌ها را آخر از همه ریزتنظیم کنید: پالت، رنگ‌های نیمکره، tint مواد.
  7. روی هر دو backend راستی‌آزمایی کنید (با و بدون ?al-amr-rendering=force-webgl2) و یادتان باشد compatible چه چیزهایی را حذف می‌کند: bloom، جزئیات ابر، سایه‌های پوشش گیاهی. اگر روی compatible منتشر می‌کنید، روی compatible درجه‌بندی کنید.

دام‌ها و نامتغیرها#

  • fogColor باید همیشه با hazeColor پالت برابر باشد — مه همان هالهٔ زیرافق گنبد است و هر ناهماهنگی لبهٔ جهان را با آسمان درز می‌کند. پالت را ویرایش کنید، نه خط مه را.
  • clouds.coverage (و خواهربرادرهایش) در هر مدل آسمان دو بار ظاهر می‌شود — شاخهٔ compatible و بقیه. هر دو را عوض کنید وگرنه سطح‌ها هوای متفاوت نشان می‌دهند.
  • fogNear < fogFar را حفظ کنید و shadowExtent را برابر یا بالاتر از شعاع zone نگه دارید: ثابت‌های guardrail به نام *_SHADOW_COVERS_* با تست‌های آسمان پین شده‌اند و مجموعهٔ تست را قرمز می‌کنند.
  • تغییر رنگ و نور هیچ تست و هیچ بودجهٔ رندری را نمی‌شکند. افزودن مش، نمونه یا attribute نمونه می‌شکند — بودجه‌ها per zone per مسیر اندازه می‌شوند، پس در سمت تنظیم مقادیر بمانید مگر آنکه قصد بودجه‌بندی مجدد دارید.
  • octaves و coverage ابر هزینهٔ واقعی fragment را per سطح عوض می‌کنند. کارایی را روی سطحی قضاوت کنید که منتشر می‌کنید، نه روی enhanced.
  • overrideهای post جهش uniform هستند، پس جابه‌جاکردنشان ارزان است — اما per تعویض zone اعمال می‌شوند و مقدار خارج از بازه بی‌صدا گیره می‌شود (bloom.strength به [0, 8] و exposure به [0.1, 8]). اگر یک ویرایش افراطی «هیچ کاری نکرد»، احتمالاً روی گیره نشسته‌اید.

برای معماری پشت همهٔ این دستگیره‌ها — گنبد، pipeline پس‌پردازش، سیاست سطح‌ها — تکنیک‌های سه‌بعدی zoneهای پارک را ببینید.