تصور کنید بخواهید ۱۷ هزار درخت سهبعدی را در یک تب مرورگر رندر کنید، بدون اینکه لپتاپ کاربر داغ کند یا بازی دچار تپق شود. این همان چالشی است که در پروژه بازی TAKEN حل شده تا تجربهای روان با نرخ ۶۰ فریم بر ثانیه خلق شود. این اثر توسط یک توسعهدهنده منتشر شده است؛ یک بازی ترسناک با کیفیت بصری بالا (High-Fidelity) با محوریت ربوده شدن توسط یوفوها (UFO abduction) که نیاز به هیچگونه نصبی ندارد و کاملاً در مرورگر اجرا میشود.
طبق گزارش منتشر شده در ۳۰ ژوئن ۲۰۲۶، این پروژه به عنوان یک مطالعه موردی فنی برای بررسی مرزهای توانایی three.js و WebGL2 عمل میکند. در این مسیر، توسعهدهنده بهجای استخدام یک تیم مهندسی کامل، از یک گردشکار عاملمحور (Agentic) استفاده کرد تا جایگزینی برای یک تیم مهندسی شود. همانطور که در تحلیلهای قبلی ما دربارهی رقابت Claude و سایر مدلهای زبانی در کدنویسی اشاره کردیم، این پروژه فراتر از تولید اسکریپتهای ساده است. این سطح از پیچیدگی در معماری نرمافزار، مشابه آن چیزی است که در تستهای استرس واقعی برای سنجش توانمندی عاملهای هوش مصنوعی در کدنویسی مورد بررسی قرار گرفت. در این سیستم، یک «زیربنای کانتکست» (Context Substrate) — شامل سیستمی از قوانین و وضعیتهای مشترک — پیادهسازی شده است که به انسان اجازه میدهد در نقش مدیر هنری عمل کند، در حالی که عاملهای هوش مصنوعی کارهای سخت بهینهسازی گرافیکی و لولهکشی داراییها (Asset Plumbing) را بر عهده میگیرند.
چالش اصلی در TAKEN، مبارزه با محدودیتهای تک-رشتهای (Single Main Thread) مرورگر و تفاوتهای سختافزاری کاربران بود. برای دستیابی به نرخ ثابت ۶۰ فریم بر ثانیه، بازی از چندین ترفند پیچیده رندرینگ استفاده میکند.
توهم هندسی و مدیریت درختان
برای مدیریت جنگل، بازی از یک سیستم سفارشی «سطح جزئیات» (LOD) استفاده میکند. در بالاترین تنظیمات، جهان بازی شامل کمی کمتر از ۱۷,۰۰۰ درخت است. از آنجایی که هر درخت کاج مناسب از چند هزار مثلث تشکیل شده، رندر کردن همهی آنها باعث تولید دهها میلیون مثلث در هر فریم میشد؛ حجمی که برای اکثر پردازندههای گرافیکی در مورد اشیایی که بازیکن حتی از صدها متری بهسختی میبیند، بسیار زیاد است.
به نقل از توسعهدهنده، برای حل این مشکل از «ایمپاسترها» (Imposters) استفاده شده است؛ یعنی درختان دوردست بهجای مدل سهبعدی، با صفحات دوبعدی مسطح که شامل عکسهای رندر شده از پروفیل درخت هستند، جایگزین میشوند. در فاصلههای دور، چشم انسان نمیتواند تفاوتی بین مدل واقعی و کارتی که همیشه رو به دوربین میچرخد تشخیص دهد. توسعهدهنده اشاره میکند که این یک ترفند استاندارد در صنعت است و بازی Ghosts of Tsushima را به عنوان نمونهای که این تکنیک را بینقص اجرا کرده، ذکر میکند.
برای جلوگیری از پدیده «پرش» (Popping) یا تغییر ناگهانی مدل در هنگام جابجایی، موتور بازی از یک باند همپوشانی بین ۱۱۵ تا ۱۴۰ متر استفاده میکند. در این محدوده، هم مدل سهبعدی و هم بیلبورد دوبعدی بهطور همزمان رندر میشوند و بیلبورد از طریق Dither-fading (محو شدن نقطهای) ظاهر میشود تا مدل سهبعدی حذف گردد. این انتقال برای بازیکن کاملاً نامرئی است.

منطق گیاه شناختی و بهینهسازی
همه اشیاء از قوانین LOD یکسانی پیروی نمیکنند. سیستم بر اساس اندازه و حرکت بهینهسازی میکند:
- پذیرش بر اساس ارتفاع: هر چیزی بلندتر از ۵.۵ متر بهصورت خودکار به عنوان درخت شناسایی شده و به بیلبورد تبدیل میشود.
- پذیرش دستی: داراییهای کوچکتر مانند سرخسها، قارچها، شبدرها و گلها دارای فواصل دستی هستند. برای مثال، یک قارچ در فاصله ۴۰ متری از دید خارج میشود و نیازی نیست تا ۱۴۰ متر به صورت بیلبورد باقی بماند.
- بازبینی دورهای (Throttled Repacking): محاسبه مجدد اینکه کدام درختان نزدیک یا دور هستند در هر فریم بسیار هزینهبر است. سیستم از رویکرد Round-robin استفاده میکند که در آن در هر فریم تنها دو گونه گیاهی بازبینی میشوند و این کار تنها در صورتی رخ میدهد که بازیکن از آخرین بازبینی بیش از ۱۰ متر حرکت کرده باشد. اگر بازیکن ثابت بماند، سیستم هیچ کاری نمیکند و با حرکت کاربر، بهآرامی چند هزار نمونه (Instance) را در پشت سر او بازآرایی میکند.
- تغییر وضعیت پویا: وقتی صاعقه درختی را میسوزاند، آن درخت خاص از استخر نمونهها (Instance Pool) خارج میشود. درخت بین ۲۶ تا ۴۰ ثانیه میسوزد و سپس با یک مدل سوخته جایگزین میشود. برای جلوگیری از نشت حافظه در جلسات طولانی بازی، سقف سخت ۶۴ درختی برای درختان سوخته تعیین شده است.
حل مشکل «تپق در شیدرهای گرافیکی»
یکی از بحرانیترین باگهای کشف شده، تپق زدن نرخ فریم (Frame-rate stutter) هنگام تغییر هر منبع نوری بود. علامت این باگ یک «توقف سخت» برای یک تک فریم بود؛ نه یک فریم کند، بلکه یک لرزش (Hitch) که هنگام شلیک تفنگ، روشن شدن پرتو یوفو یا برداشتن یک باتری رخ میداد. دو ساعت زمان برد تا فهمیده شود سیستمهای کاملاً غیرمرتبط در حال تحریک یک نقطه حساس در موتور بازی هستند.
در three.js، متریالهایی که به نور واکنش میدهند، تعداد نورها را در زمان کامپایل در شیدر میپزند (Bake میکنند). حلقه نورپردازی بهطور دقیق برای تعداد نورهای موجود در صحنه باز شده است (Unrolled). اگر شما نوری را اضافه، حذف یا پرچم .visible آن را تغییر دهید، تعداد نورها تغییر میکند. این امر باعث میشود هر متریال نورپردازی شده در صحنه — از هر تکه چمن و درخت گرفته تا بدنه یوفو — مجبور شود شیدر خود را در میانه فریم دوباره کامپایل کند.
توسعهدهنده برای حل این موضوع، تمام نورهای مورد نیاز بازی را در زمان لود (قبل از کامپایل اولیه شیدرها) ایجاد کرد. بهجای تغییر پرچم .visible — که در ظاهر عملی رایگان به نظر میرسد اما در واقع اثر معکوس دارد — بازی شدت نور (intensity) را از ۰ تا ۱۰ تغییر میدهد. این کار باعث میشود تعداد نورها ثابت بماند و recompilationهای میانی حذف شوند.
برای مثال، نور شلیک دهانه تفنگ (Muzzle Flash) به این صورت مقداردهی شده است: this.muzzle = new THREE.PointLight(0xfff0c0, 0, 24, 2);. برای «روشن کردن» آن، کد صرفاً مقدار this.muzzle.intensity = 10; را تنظیم میکند.
این رویکرد چنان سختگیرانه است که سفینه رباینده حیوانات بهجای دو نور، دقیقاً از یک نور در قسمت شکم استفاده میکند؛ زیرا نور دوم باعث میشد به محض پایین آمدن بشقاب یوفو، یک بازکامپایل جهانی (Global Recompilation) رخ دهد. برای پنهان کردن بیشتر این هزینهها، بازی تابع compileAsync را روی کل صحنه در پشت صفحه لودینگ فراخوانی میکند تا اطمینان حاصل شود تمام شیدرها قبل از دیدن اولین فریم توسط بازیکن تولید شدهاند. نادیده گرفتن این مرحله باعث «تپق کامپایل» میشد، هر بار که بازیکن برای اولین بار رو به یک هندسه جدید میچرخید.

مهندسی اتمسفر و آسمان
اتمسفر بازی برای ایجاد حس «ترس از آسمان روستاهای آمریکا» طراحی شده تا حال و هوایی شبیه به فیلمهای Nope یا Signs داشته باشد. هدف، ثبت حس حضور موجودی عظیم و ساکت بر فراز یک دشت باز در هنگام غروب بود. اولین تصمیم کلیدی، استفاده از AgX Tone Mapping بهجای منحنی استاندارد ACES Filmic بود. AgX شانه (Shoulder) بلندتر و نرمتری دارد و قسمت «پنجه» (Toe) را سختتر میکوبد، که تضمین میکند آسمانهای روشن به سفیدی تخت تبدیل نشوند و سایهها بدون اینکه گلآلود شوند، بهطرز ناخوشایندی تاریک بمانند.
چرخه شب و روز یک دور کامل ۲۴ ساعته را در ۵۴۰ ثانیه (۹ دقیقه) اجرا میکند. بازی در اواخر بعدازظهر شروع میشود تا بازیکنان «ساعت طلایی» را در حال لغزش به سمت تاریکی تجربه کنند. فازهای ماه در هر بار اجرای بازی تصادفی است و در طول روزهای بازی پیش میرود؛ ماه کامل یک محرک گیمپلی است که گله گرگها را بیرون میکشد.

در حالی که نسخه نهایی از مدل تحلیلی Preetham برای گرادینت و خورشید باورپذیر استفاده میکند، یک نسخه آزمایشی موازی در یک ساندباکس ایزوله با «اتمسفر ریمارچ شده» (Raymarched Atmosphere) سفارشی در حال ساخت است. این سیستم فیزیک واقعی را شبیهسازی میکند:
- پراکندگی ریلیجه (Rayleigh Scattering): مدیریت تنهای آبی آسمان.
- پراکندگی می (Mie Scattering): ایجاد مه و هالهای که دور خورشید جمع میشود.
- جذب اوزون (Ozone Absorption): شبیهسازی لایهای نازک در ارتفاع ۲۵ کیلومتری که نور آبی را در مسیرهای مایل طولانی جذب میکند و باعث قرمز شدن افق در هنگام غروب میشود.
این مدل سفارشی، ۲۴ گام را در اتمسفر برای هر پیکسل طی میکند و ۶ گام دیگر را به سمت خورشید برای محاسبه سهم نور میرود. این روش سنگینتر از Preetham است و در آزمایشگاه در حال تنظیم است تا پیش از انتقال به بازی، ثابت شود که واقعاً «بهتر» است، نه فقط «متفاوت».
مقیاسپذیری و داراییهای گرافیکی
برای پشتیبانی از طیف گسترده سختافزارها، از لپتاپهای بسیار ضعیف (Potato Laptops) تا RTX 4090، بازی از ۵ سطح کیفیت استفاده میکند که در واقع ساختارهای متفاوتی از بیلد بازی هستند:
- سطح Low: رندر در ۴۲٪ رزولوشن و سپس Upscale میشود. بدون سایه، بدون Bloom و بدون پرتوهای نوری حجمی (God-rays). زمین یک مش درشت با ۱۲۸ قطعه (Segment) و تنها ۳,۰۰۰ تکه چمن است.
- سطح Ultra: رزولوشن بومی (Native) با ۱۵۰,۰۰۰ نمونه چمن و یک Raymarch فضای صفحه با ۴۸ نمونه برای پرتوهای نوری حجمی.
- سطح Ridiculous: فوقنمونهبرداری ۲ برابر (Supersampling) — یعنی میانگینگیری از چهار پیکسل برای هر پیکسل نمایش داده شده — با زمین ۵۱۲ قطعهای و ۳۲۰,۰۰۰ نمونه چمن.

سیستم رزولوشن پویا (Dynamic Resolution) وظیفه مدیریت لحظهای را بر عهده دارد. موتور بازی بودجه ۶۰ فریم بر ثانیه را مانیتور میکند؛ اگر فریمها کاهش یابد، بهآرامی مقیاس رندر را به سمت کفِ آن سطح کیفیت پایین میآورد و با بازگشت فضای خالی (Headroom)، دوباره آن را بالا میبرد. این باعث میشود بازیکن بهجای تپق زدن فریم، برای یک ثانیه تصویری کمی نرمتر را ببیند. علاوه بر این، موتور بازی برچسبهای زمانی فریمهای مرورگر را نمونهبرداری میکند تا خود را روی یک مقسومعلیه تمیز از نرخ نوسازی نمایشگر قفل کند (مثلاً ۶۰ فریم ثابت روی نمایشگر ۱۲۰ هرتز) تا از لرزش (Jitter) جلوگیری شود.
پردازش داراییها (Assets) زمانبرترین بخش خط لوله بود. توسعهدهنده با استفاده از gltf-transform، meshoptimizer و sharp، رئوس (Vertices) تکراری را حذف کرد، درزها را جوش داد و تمام تکسچرها را به فرمت WebP فشرده کرد. اسکنهای عکس با پلیگان بالا یا سادهسازی شدند یا اگر درزهای UV آنها مانع از تخریب لبهها (Edge Collapsing) میشد، حذف شدند؛ زیرا یک دارایی سنگین و حریص میتواند سرعت دانلود را برای همه کاربران تخریب کند.

دو نکته فنی در مورد داراییها (Asset Gotchas) یک شب کامل از توسعهدهنده گرفت: اول، مشکلات چرخش در خروجیهای Sketchfab یا FBX که باعث میشد گرهها (Nodes) چرخیده باشند و اگر رئوس بهصورت دستی روی اصلاح خودکار لودر چرخانده شوند، منجر به «جنگلی از کاجها که روی پهلویشان خوابیدهاند» شود. دوم، شفافیت گیاهان از طریق alpha-test (برشهای سخت) بهجای alpha-blend مدیریت شد تا از مرتبسازی هزاران برگ روی یکدیگر و لرزش آنها شبیه به یک تلویزیون خراب جلوگیری شود.
لودینگ همچنین جایی است که Instancing سیمکشی میشود. اکثر مدلها در هنگام لود در یک متریال واحد ادغام میشوند تا تمام گونهها بتوانند به عنوان یک Mesh نمونهبرداری شده (Instanced Mesh) رسم شوند. درختانی که به متریالهای جداگانه برای تنه و تاج نیاز دارند، از یک لودر گروهبندی شده استفاده میکنند. این لولهکشی به موتور اجازه میدهد ۱۶,۰۰۰ درخت را در چند Draw Call رسم کند، بهجای اینکه ۱۶,۰۰۰ درخواست مجزا ارسال کند.
گردشکار عاملمحور با Claude Code
این پروژه توسط یک انسان و چندین عامل هوش مصنوعی با استفاده از Claude Code و Codex ساخته شده است. استفاده از این ابزارها برای خلق محیطهای پیچیده، یادآور آزمونهایی برای شناسایی ماشین در محیط سهبعدی است که مرز بین خلاقیت انسانی و دقت ماشینی را به چالش میکشد. برای جلوگیری از تخریب بیلد توسط عاملها، توسعهدهنده فایلهای CLAUDE.md و .context را در ریشه مخزن (Repo root) پیاده کرد. این فایلها به عنوان یک قرارداد الزامآور عمل میکنند و دستورات بیلد (مانند tsc && vite build برای جلوگیری از خطاهای تایپی خاموش) و قوانین معماری را مشخص میکنند.
برای مدیریت همکاریهای چند-عاملی، توسعهدهنده ابزاری به نام Traffic Control (در دسترس در گیتهاب در andrefigueira/traffic-control) طراحی کرد؛ یک Worker مبتنی بر زبان Go که با Claude ادغام میشود تا از بازنویسی تغییرات توسط عاملهای مختلف در یک Working Tree جلوگیری کند. قانون این است که عاملها فقط فایلهای خاصی را که توسط مسیر صریح تغییر کردهاند Stage میکنند و هرگز از git add -A بهصورت کلی استفاده نمیکنند.
این ساختار اجازه داد تا عاملها کارهای تکراری — مانند متصل کردن هر شیء سهبعدی و پخش سنگها به یک اسلایدر تراکم در پنل ادمین برای دیباگ — را بر عهده بگیرند، در حالی که انسان روی کارگردانی هنری، موسیقی و سلیقه تمرکز کند. این قوانین «حامل بار» (Load-bearing) هستند و تضمین میکنند هر ویژگی جدیدی که توسط یک عامل ساخته شود، بهطور خودکار سیستم LOD و ابزارهای دیباگ را به ارث ببرد، بدون اینکه نیاز به بررسی دستی روزها بعد باشد.

صدا و محیط
طراحی فضای صوتی بهگونهای بود که نیمی از تجربه بازی را فراهم کند. توسعهدهنده از پیشینه خود در تولید موسیقی و مهندسی صدا برای خلق لایههای محیطی استفاده کرد، از جمله:
- صدای جیرجیرکها و غوربغه در شب.
- صدای خزیدن مارها و برخورد با برگها.
- بادی که در ارتفاعات شدیدتر میشود، به همراه رعد و برق.
- یک دیجی رادیویی طنزآمیز به سبک Rick and Morty با تبلیغات موضوعی شبیه به تلویزیونهای بینبعدی.
موسیقی با ترکیبی از Claude برای بررسی عمیق تماتیک (با ارجاع به Red Dead Redemption 2، Nope و Signs به عنوان نمونههایی برای ژانر، سرعت و سازبندی) و Suno برای تولید نهایی بر اساس آن دستورات صریح، تولید شد.
آینده بازیهای وب
هیچکدام از این ترفندها بهتنهایی عجیب یا ناشناخته نیستند، اما محدودیتهای مرورگر باعث شد مهندسی پروژه بسیار بهینه و lean باشد. چون هیچ نصب ۴۰ گیگابایتی، هیچ لانچری و راهی برای پنهان کردن یک فریم بد پشت صفحه لودینگ وجود ندارد، هر میانبری بهوضوح دیده میشود.
در حالی که TAKEN برای انتشار در Steam از طریق یک Wrapper الکترون (Electron) آماده میشود، تمرکز همچنان روی تجربه «اول-وب» (Web-first) است. هدف، خلق یک بازی ترسناک است که تنها یک کلیک با بازیکن فاصله دارد — جایی که بازیکن قبل از اینکه تصمیم بگیرد وارد بازی شود، در میدان جنگ ایستاده است. شما میتوانید نسخه پیش-آلفای فعلی را در www.taken-game.com بررسی کنید تا این تکنیکهای بهینهسازی را در عمل ببینید.
گام بعدی شما
- اگر توسعهدهنده هستید، ابزار Traffic Control را برای مدیریت همکاری چندین مدل AI در یک مخزن کد بررسی کنید.
- برای مشاهده عملی تکنیکهای بهینهسازی WebGL2، نسخه پیش-آلفای بازی را در www.taken-game.com تجربه کنید.
- ساختار فایلهای
.contextرا برای هدایت دقیقتر عاملهای کدنویس در پروژههای خود پیادهسازی کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو