sharp.go
← Назад

· Sharp.go Team

Всередині рушія: як sharp.go рендерить 361 камінь на 60fps

П’ять років тому дошка для Го на 60 кадрах за секунду з повноцінною 3D-інспекцією була мрією рендерера. Сьогодні це його денна задача. Цей пост — той розбір із коментарями, якого нам не вистачало на початку: архітектурні рішення, глухі кути та дрібні деталі, що змінили все.

Проблема

01

Чому це складно

Три обмеження, що сформували 3D-рушій, який ми випускаємо сьогодні.

Гра в Го — це дерево, а не лінія. У будь-який момент гравець може розгалузитися у тисячі альтернативних продовжень, і кожне має свою розстановку каменів на сітці 19×19. Ми хотіли все три водночас: інтерактивну 3D-камеру, затримку аналізу менше 100 мс і партію, що не розвалюється після 200-го ходу.

Кожне з цих обмежень вирішуване окремо. Проблема в тому, що всі вони зачіпають одну й ту саму гарячу стежку — мить, коли камінь торкається дошки — і кожному потрібен різний час.

Кодування ходів

02

21-байтний дротовий формат

Компактний, детерміністичний, відтворюваний між версіями.

Кожен хід у sharp.go — це 21-байтне корисне навантаження. Ми перепробували JSON, CBOR і protobuf, перш ніж зупинитися на самописному бінарному форматі. Формат настільки компактний, що 400 ходів реальної гри займають 8,4 КБ — приблизно стільки, скільки стиснутий JPEG самої дошки.

  • 01.

    Байт 0 — Колір

    0x00 для чорних, 0x01 для білих. Один байт. Без узгоджень.

  • 02.

    Байти 1–2 — Координата

    Два байти у little-endian: рядок (0–18) і стовпець (0–18). 361 допустима позиція на сітці 19×19.

  • 03.

    Байти 3–6 — Номер ходу

    32-бітний індекс ходу без знаку. Послідовний у межах партії, детерміністичний між відтвореннями.

  • 04.

    Байти 7–10 — Мітка реального часу

    мілісекунди від початку гри. Використовується для перемотки відтворення.

  • 05.

    Байти 11–14 — Геш позиції

    32-бітний геш Zobrist. Дозволяє виявляти дубльовані позиції та суперко без повного сканування дошки.

  • 06.

    Байти 15–20 — Зарезервовано для сигналів рушія

    Захоплені камені, маркер ко, прапорець пасу. Зарезервовано для прямої сумісності.

Розділ

"

Ми не збиралися винаходити бінарний формат. Ми хотіли зробити аналіз миттєвим, і кількість байтів виявилася найпростішим обмеженням, яке варто послабити останнім.

"

Naomi S. / Провідний інженер рушія
Рука ставить чорний камінь на дошку 19×19 посеред гри, з групами каменів у формуванні біля верхнього правого та нижнього країв.

Хід 217 — чорні грають розширення знизу. Один байт кольору, два байти координати, вісімнадцять байтів контексту.

Конвеєр рендерингу

03

Три проходи, одне полотно

Порядок важливіший за вартість.

Рендерер — це суворий трипрохідний конвеєр. Ми не сортуємо, не змішуємо й не відбиваємо між проходами — кожен прохід пише у власну текстуру, а наступний її читає.

Tabs

Кожен камінь — це одиничний інстансний куб з PBR-матеріалом. Ми рендеримо всі 361 позицію у позаекранну текстуру глибини дошки. Порожні позиції пропускаються повністю; зайняті отримують індивідуальну трансформацію.
Частота кадрів у сталому режимі 60fps
Пропускна здатність декодування формату ходів 1.1GB/s
Байтів на хід у дротовому форматі 21B

Дизайн-рішення

04

Чому ми випускаємо 3D першим

Логіка нашого першого продукту, а не вирок 2D.

Comparison

Порівняння рушіїв

Feature sharp.go 2D-клієнти Мобільні застосунки
3D-інспекція дошки
Відгук ШІ швидше 100 мс
Відкритий формат партій
Спільний розбір
Посилання для поширення у два кліки
Режим лише в браузері
  • Інстансний рендеринг по всій дошці

    361 інстанс, один виклик малювання. Все інше було повільнішим.

  • Кешовані відображення, а не реалтайм

    Перемальовування при повороті камери більше 5°. Гравці не помічають.

  • Бінарний формат ходів на диску

    Компактний, детерміністичний — партії 2026 року завантажуються й у 2027.

  • Глибокі посилання як URL першого класу

    Кожна позиція має стабільний URL. Поділитися дошкою — це копіпаст, а не скріншот.

Часті запитання

Часті запитання

01 Чому рушій використовує Zobrist-гешування для позицій?

Геші Zobrist оновлюються за O(1) на кожен хід (xor змінених бітів) і дозволяють виявляти суперко та дубльовані позиції за одне 32-бітне порівняння. Повне сканування дошки на кожному ході нормально працює на 19×19, але не масштабується на 25×25, які ми плануємо підтримувати.

02 Чи можна відтворити партію з URL на іншому пристрої?

Так. Кожна партія має стабільний URL з послідовністю ходів, закодованою в шляху. Відкрийте URL на будь-якому пристрої в будь-якому браузері — і відтворення почнеться з тієї самої позиції.

03 Чи грає ШІ на тому самому рівні офлайн?

Так. Локальний ШІ працює повністю офлайн і за замовчуванням відкалібрований на рівень початківця. У меню можна підняти рівень сильніше — жодного мережевого запиту не потрібно.

04 Чому бінарний формат ходів не описано в публічній специфікації?

Стабільність. Формат — частина нашої обіцянки сумісності відтворень. Ми опублікуємо стабільну специфікацію v1, коли вийде рушій 1.0. До того моменту формат може змінюватися між мінорними версіями.

Що далі

05

Дорожня карта, а не обіцянки

Над чим ми працюємо зараз, у порядку очікуваної вартості.

Наступні шість місяців — про переносимість відтворень. Кожна зіграна вами партія має пережити клієнт, на якому була зіграна.

Спробувати рушій

Зіграти на справжній 3D-дошці

Без встановлення. Відкрийте гру у браузері, зіграйте проти відкаліброваного ШІ, поділіться позицією одним кліком.

"

Найкращий інтерфейс для Го — той, що зникає. Ви дивитеся на дошку, а не на застосунок.

"

Команда sharp.go / Гонконг, травень 2026
enginerenderingperformance