Модели пишут на JavaScript модуль для three.js, который превращает JSON-описание в 3D-сцену: иерархию объектов с поворотами и масштабом, примитивы, выдавленные контуры, тысячи экземпляров, свет и камеру. Каждую сцену сравнивают с эталоном по мировым матрицам, габаритам, цветам и попаданиям лучей из камеры.
29 октября 2026. 7 прогонов, 5 моделей.
Одна и та же сцена, отрендеренная WebGL в Chrome без окна одним и тем же рендерером. Отличаются только сами сцены, которые построил код модели. Переключатель «Отличия от эталона» подсвечивает красным пиксели, которые не совпали.
Покрутить сцену в 3D







Пять моделей прошли всё.Opus 5.5 агентом, Qwen3.8-Max, Kimi K3.1 Pro, GPT-6.1 Sol и DeepSeek Flash прошли 164 сцены из 164: совпали матрицы, габариты, цвета в линейном пространстве, матрицы экземпляров и все 63 луча из камеры. Ловушки three.js вроде lookAt, который у объекта и у камеры смотрит в разные стороны, никого не поймали.
Фраза в задании выключила размышление у Opus через API.«Ответь ТОЛЬКО кодом» адаптивный Opus 5.5 понимает как «не размышляй», даже при effort: max, и пишет код с 5-й секунды. Проверка шлюза показала, что effort передаётся правильно. С формулировкой «сначала продумай» Opus думал 6 тысяч токенов и прошёл 161 сцену вместо 158. В следующих тестах формулировка заменена.
Скорость кода здесь не различает модели.Все решения строят 50 000 экземпляров и тысячи объектов с lookAt за сотые доли секунды. Места среди безошибочных определяются суммарным временем замеров, а эта разница на уровне погрешности.
Время ответа различается почти в 70 раз.Opus через API ответил за 30 секунд, Opus-агент за 2 минуты 40 секунд, DeepSeek Flash за 3,5 минуты, GPT за 5 минут, Kimi за 12 минут, Qwen за 34 минуты. Колонка «Токенов/с» в таблице показывает, кто медленно пишет, а кто много думает.
| Место | Модель | Тесты | Ловушки | Случайные | Ошибки | Скорость | Время | Рассуждение | Всего токенов | Токенов/с | Строк кода | С правкой |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 🥇 1 | Qwen3.8-Max | 164 (100.0%) | 38/38 | 120/120 | 6/6 | 3/3 | 34 мин 12 с | 81.5K | 85.2K | 42 | 446 | — |
| 🥈 2 | Kimi K3.1 Pro | 164 (100.0%) | 38/38 | 120/120 | 6/6 | 3/3 | 11 мин 56 с | 17K | 19.2K | 27 | 341 | — |
| 🥉 3 | Claude Opus 5.5 (агент) | 164 (100.0%) | 38/38 | 120/120 | 6/6 | 3/3 | 2 мин 40 с | 8.5K* | 13K | 81* | 277 | — |
| 4 | Claude Opus 5.5 (агент, effort max) | 164 (100.0%) | 38/38 | 120/120 | 6/6 | 3/3 | 12 мин 05 с | 80.8K* | 83.7K | 115* | 325 | — |
| 5 | GPT-6.1 Sol | 164 (100.0%) | 38/38 | 120/120 | 6/6 | 3/3 | 5 мин 11 с | скрыто | 13.4K | 43 | 415 | — |
| 6 | DeepSeek Flash (V4.1) | 164 (100.0%) | 38/38 | 120/120 | 6/6 | 3/3 | 3 мин 33 с | 38.8K | 41.4K | 194 | 336 | — |
| 7 | Claude Opus 5.5 (effort max) | 158 (96.3%) | 38/38 | 117/120 | 3/6 | 3/3 | 30 с | 0 | 4.2K | 140 | 284 | — |
В колонке «С правкой» указан результат того же кода после исправления одной-двух строк, он нужен только для понимания. Звёздочка означает оценку. «Токенов/с» показывает, как быстро модель пишет: все токены ответа, включая рассуждение, делённые на полное время ответа.
От отправки задания до последнего символа ответа. Зависит и от загрузки серверов провайдера.
qwen3.8-maxkimi-k3.1-proclaude-opus-5-5claude-opus-5-5effort: max не рассуждал вовсе и прошёл 158 сцен, так что разница в шесть сцен целиком объясняется размышлением. Протокол соблюдён: одно чтение задания и одна запись решения.gpt-6.1-soldeepseek-flashclaude-opus-5-5lookAt подряд, поэтому потомок поворачивается по устаревшему положению родителя, у которого тоже есть lookAt. Ещё три промаха на проверке ввода: не ловятся неверный цвет, цвет из четырёх цифр и неверный порядок поворота у узла без rotation. Отдельная проверка показала, что размышление отключает последняя фраза задания «Ответь ТОЛЬКО кодом»: с фразой «сначала продумай» тот же Opus думал 6 тысяч токенов и прошёл 161 сцену.Нужно написать ES-модуль с функцией buildScene(THREE, spec), которая возвращает { scene, camera }. Описание задаёт дерево узлов с позицией, поворотом в градусах и порядком Эйлера, масштабом (в том числе отрицательным) и lookAt, примитивы box, sphere, cylinder, torus, plane, выдавленные контуры с отверстиями, InstancedMesh, три вида света и перспективную или ортографическую камеру. Цвета задаются в sRGB.
Напиши на JavaScript модуль для three.js r186, который строит 3D-сцену по описанию в JSON. Модуль экспортирует одну функцию и ничего не импортирует: объект `THREE` (то, что экспортирует пакет `three`) передаётся аргументом.
## Интерфейс
```js
export function buildScene(THREE, spec) {
// ...
return { scene, camera };
}
```
`scene` это `THREE.Scene`, `camera` это `THREE.PerspectiveCamera` или `THREE.OrthographicCamera`. Камеру в сцену добавлять не нужно. Перед возвратом у сцены и камеры должны быть актуальны мировые матрицы, а у камеры матрица проекции.
## Описание сцены
```js
{
"background": "#101820", // цвет фона: scene.background = new THREE.Color(...); по умолчанию "#000000"
"camera": { ... }, // камера, см. ниже
"nodes": [ { ... }, { ... } ] // узлы верхнего уровня, у каждого могут быть "children"
}
```
## Узлы
Каждый узел становится объектом three.js с `name` из описания и добавляется к родителю (узлы верхнего уровня к сцене) в порядке описания. Общие поля всех узлов:
- `name`: уникальное имя, записывается в `object.name`.
- `type`: тип узла, см. ниже.
- `position`: `[x, y, z]`, по умолчанию `[0, 0, 0]`.
- `rotation`: углы `[x, y, z]` **в градусах**, по умолчанию нули. `rotationOrder`: порядок поворотов Эйлера, одна из строк `"XYZ"`, `"XZY"`, `"YXZ"`, `"YZX"`, `"ZXY"`, `"ZYX"`, по умолчанию `"XYZ"`.
- `scale`: число (одинаковый масштаб по всем осям) или `[x, y, z]`, по умолчанию 1. Значения могут быть отрицательными.
- `lookAt`: точка `[x, y, z]` в мировых координатах. Если она задана, узел поворачивается методом `Object3D.lookAt` к этой точке, а `rotation` не используется. Все `lookAt` применяются после того, как построено всё дерево, в порядке описания (родитель раньше потомков), и каждый учитывает текущие мировые преобразования родителей.
- `visible`: `false` делает объект невидимым, по умолчанию видимый.
- `children`: дочерние узлы.
Типы узлов:
- `group`: `THREE.Group`.
- Примитивы, каждый становится `THREE.Mesh` со своей геометрией three.js:
- `box`: `size: [w, h, d]` → `BoxGeometry(w, h, d)`;
- `sphere`: `radius`, `widthSegments` (по умолчанию 32), `heightSegments` (по умолчанию 16) → `SphereGeometry`;
- `cylinder`: `radiusTop`, `radiusBottom`, `height`, `radialSegments` (по умолчанию 32) → `CylinderGeometry`;
- `torus`: `radius`, `tube`, `radialSegments` (по умолчанию 16), `tubularSegments` (по умолчанию 48) → `TorusGeometry`;
- `plane`: `size: [w, h]` → `PlaneGeometry(w, h)`;
- `extrude`: `points` (контур `[[x, y], ...]` в плоскости XY, не меньше трёх точек), `holes` (необязательный список отверстий, каждое тоже список точек), `depth` → `ExtrudeGeometry` с `bevelEnabled: false` и `steps: 1`.
- `instances`: `THREE.InstancedMesh`. Поле `geometry` описывает геометрию одного экземпляра так же, как примитив (`{"type": "box", "size": [...]}`, допустимы типы `box`, `sphere`, `cylinder`, `torus`, `plane`), `items` это список экземпляров, у каждого необязательные `position`, `rotation` (градусы, порядок всегда `"XYZ"`) и `scale` (число или тройка). Число экземпляров равно длине `items`, может быть нулём. Матрица экземпляра собирается из его позиции, поворота и масштаба.
- Источники света:
- `ambient`: `THREE.AmbientLight(color, intensity)`;
- `directional`: `THREE.DirectionalLight(color, intensity)`, поле `target: [x, y, z]` (по умолчанию начало координат) задаёт позицию `light.target`, а сам `target` добавляется в сцену;
- `point`: `THREE.PointLight(color, intensity, distance, decay)`, по умолчанию `distance` 0 и `decay` 2.
У света `color` по умолчанию `"#ffffff"`, `intensity` по умолчанию 1.
## Материал
У примитивов и `instances` материал `THREE.MeshStandardMaterial`:
- `color`: цвет из описания, по умолчанию `"#ffffff"`;
- `opacity`: из поля `opacity`, по умолчанию 1; `transparent: true`, если `opacity < 1`;
- `side`: `THREE.DoubleSide`, если у узла `doubleSided: true`, иначе `THREE.FrontSide`.
## Цвета
Цвет задаётся строкой `#rgb` или `#rrggbb` в пространстве sRGB, как в CSS, и превращается в `THREE.Color` стандартным способом three.js. Любая другая строка считается ошибкой.
## Камера
- `"type": "perspective"` (по умолчанию): `fov` (по умолчанию 50), `aspect` (по умолчанию 1), `near` (0.1), `far` (1000).
- `"type": "orthographic"`: `left`, `right`, `top`, `bottom`, `near` (0.1), `far` (1000).
- Общие поля: `position` (по умолчанию `[0, 0, 10]`), `lookAt` (по умолчанию `[0, 0, 0]`), необязательный `up: [x, y, z]`, который задаётся до `lookAt`.
## Ошибки
Неизвестный тип узла или геометрии экземпляров, неверная строка цвета, `extrude` меньше чем из трёх точек и неизвестный `rotationOrder` должны выбрасывать исключение.
## Производительность
Сцена из 3000 объектов с `lookAt`, цепочка из 1500 вложенных групп с `lookAt` у каждого объекта и `instances` из 50 000 экземпляров должны строиться не дольше 2 секунд каждая.
## Формат ответа
Ответь ТОЛЬКО кодом модуля в одном блоке ```javascript.
YXZ и ZYX, глубокая иерархия с масштабом, отрицательный масштаб, lookAt, который у обычного объекта направляет к цели ось +Z, а у камеры ось −Z, lookAt внутри повёрнутого родителя и у родителя с потомком, цвет #ff8800, который three.js хранит в линейном пространстве, короткие записи цвета, контур с отверстием, пустой список экземпляров, цель направленного света, ортографическая камера и камера с осью up.lookAt, прозрачность, невидимые объекты, свет и камеры.lookAt, цепочка из 1500 вложенных групп с lookAt и 50 000 экземпляров. На каждый даётся 2 секунды, эталон укладывается в 0,11 секунды.enable_thinking, у GPT reasoning_effort: high, Opus через API получал thinking: adaptive и effort: max через нативный /messages партнёрского шлюза, Kimi и DeepSeek работали в режиме по умолчанию.effort: low думал 700 токенов, с max 19 тысяч. Значит, effort доходит до модели, и дело не в коннекторе.effort: max добавлен 29.10.2026, после основного прогона, по тому же протоколу: одно чтение задания и одна запись решения, без запуска кода. Его запустили, чтобы сравнить с Opus через API на том же effort: max: через партнёрский шлюз модель рассуждает заметно меньше.| Модель | Разработчик | ID | Доступ | Лимит ответа |
|---|---|---|---|---|
| Claude Opus 5.5 (агент) | Anthropic | claude-opus-5-5 | субагент Claude Code, чистый контекст, без запуска кода | — |
| Claude Opus 5.5 (агент, effort max) | Anthropic | claude-opus-5-5 | субагент Claude Code, effort: max, чистый контекст, без запуска кода | — |
| Kimi K3.1 Pro | Moonshot AI | kimi-k3.1-pro | API api.moonshot.ai (через VPN роутера) | 128K |
| Qwen3.8-Max | Alibaba | qwen3.8-max | API token-plan.maas.qwencloudapi.com | 131.1K |
| GPT-6.1 Sol | OpenAI | gpt-6.1-sol | партнёрский шлюз, reasoning_effort: high | 128K |
| DeepSeek Flash (V4.1) | DeepSeek | deepseek-flash | API api.deepseek.com | 384K |
| Claude Opus 5.5 (effort max) | Anthropic | claude-opus-5-5 | партнёрский шлюз, нативный /messages, thinking: adaptive, effort: max | 128K |