mozgi ← Все промпты
Claude Opus 5.5

Чёрный hero-экран «Design World» в одном HTML: вращающийся 3D-брусок из стекла преломляет огромный заголовок с хроматической дисперсией

Промпт

Создай один автономный файл index.html (встроенные CSS + JS, без локальных ресурсов, без этапа сборки), содержащий ОДНУ полноэкранную hero-секцию: чёрный hero-блок лендинга «Design World» с вращаемым 3D-стеклянным параллелепипедом в центре, который преломляет огромный фоновый заголовок с хроматической дисперсией. В точности воспроизведи спецификацию ниже.

==================================================
1. ВНЕШНИЕ РЕСУРСЫ (используй эти точные URL)
==================================================
- Шрифт: Google Fonts Poppins, начертания 300/400/500/600/700/800
<link rel="preconnect" href="https://fonts.googleapis.com/">
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
- Three.js r169 через importmap:
"three": "https://cdn.jsdelivr.net/npm/three@0.169.0/build/three.module.js"
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.169.0/examples/jsm/"
Импорты: GLTFLoader (loaders/GLTFLoader.js), mergeVertices + mergeGeometries (utils/BufferGeometryUtils.js), RoundedBoxGeometry (geometries/RoundedBoxGeometry.js).
- 3D-модель (скруглённый куб GLB, с поддержкой CORS, загружать напрямую, НЕ скачивать и НЕ заменять):
const MODEL_URL = 'https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260929_212926_92423081-b0e4-4f5a-b650-14af6c05c058.glb';
Если загрузить её не удалось, использовать new RoundedBoxGeometry(1, 1, 1, 8, 0.12).

Заголовок страницы <title>: "Design World — Explore New Ideas".

==================================================
2. СТРУКТУРА СТРАНИЦЫ (HTML)
==================================================
<section class="hero" id="hero">
<canvas id="scene" aria-label="Rotatable glass cube. Drag to rotate."></canvas>
<div class="ui">
<h1 class="sr-only">Explore New Ideas</h1>
<header class="nav">
<a href="#" class="logo"><i class="logo-mark"></i><b>Design</b><span>World</span></a>
<ul class="nav-links"><li><a>Home</a></li><li><a>Portfolio</a></li><li><a>Contact Us</a></li></ul>
</header>
<div class="arrows">
<button class="arrow" id="prev">[left-arrow SVG]</button>
<button class="arrow" id="next">[right-arrow SVG]</button>
</div>
<nav class="dots"><button class="dot"></button><button class="dot active"></button><button class="dot"></button></nav>
<p class="tagline">Let's Build the<br>Future of <strong>Design.</strong></p>
<div class="cta-row">
<a href="#" class="cta">Explore Now</a>
<span class="cta-line"></span>
<span class="count" aria-hidden="true">07</span>
</div>
<div class="loader" id="loader">Loading model</div>
</div>
</section>

SVG-стрелки: viewBox 0 0 24 24, fill none, stroke currentColor, stroke-width 2.6, круглые окончания и соединения линий.
path для prev: "M19 12H5M11 6l-6 6 6 6" path для next: "M5 12h14M13 6l6 6-6 6"

ВАЖНО: большой заголовок «Explore / New / Ideas» — это НЕ HTML-текст. Он рисуется на 2D canvas внутри WebGL, чтобы стеклянный куб мог его преломлять (см. раздел 4). В HTML для доступности присутствует только визуально скрытый <h1>.

==================================================
3. CSS (точные значения)
==================================================
:root { --bg:#000; --fg:#fff; --pad-x: clamp(20px, 6.95vw, 120px) }
html, body { height:100%; background:#000; color:#fff; font-family:'Poppins',sans-serif; -webkit-font-smoothing:antialiased }

.hero { position:relative; width:100%; height:100vh; height:100svh; min-height:520px; overflow:hidden; background:#000 }
#scene { position:absolute; inset:0; width:100%; height:100%; display:block; cursor:grab; touch-action:none }
#scene.dragging { cursor:grabbing }
.ui { position:absolute; inset:0; pointer-events:none; z-index:2 } /* перетаскивание проходит к canvas */
.ui a, .ui button { pointer-events:auto }
.sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap }

НАВИГАЦИЯ
.nav { position:absolute; top:clamp(24px,4.7vh,40px); left:var(--pad-x); right:var(--pad-x); display:flex; align-items:center; justify-content:space-between }
.logo { display:flex; align-items:center; gap:8px; color:#fff; text-decoration:none; font-size:15px; letter-spacing:-0.01em }
.logo-mark { width:20px; height:40px; background:#fff; border-radius:0 20px 20px 0 } /* белая полукруглая «D» */
.logo b { font-weight:700 } .logo span { font-weight:400 }
.nav-links { display:flex; gap:clamp(20px,4.1vw,60px); list-style:none }
.nav-links a { color:#fff; text-decoration:none; font-size:15px; font-weight:500; position:relative }
.nav-links a::after { content:''; position:absolute; left:0; right:0; bottom:-4px; height:1px; background:currentColor; transform:scaleX(0); transform-origin:right; transition:transform .35s ease }
.nav-links a:hover::after { transform:scaleX(1); transform-origin:left }

СТРЕЛКИ (в правом верхнем углу, слева от колонки с точками)
.arrows { position:absolute; top:18.9%; left:76.7%; display:flex; gap:32px; transform:translate(-19px,-50%) }
.arrow { width:38px; height:38px; border-radius:50%; border:2.5px solid #fff; background:transparent; color:#fff; display:grid; place-items:center; cursor:pointer; transition:background .25s, color .25s }
.arrow svg { width:18px; height:18px }
.arrow:hover { background:#fff; color:#000 }

ТОЧКИ ПАГИНАЦИИ (вертикально, у правого края)
.dots { position:absolute; right:calc(var(--pad-x) - 7px); top:49.4%; transform:translateY(-50%); display:flex; flex-direction:column; gap:33px }
.dot { width:14px; height:14px; border-radius:50%; border:2px solid #fff; background:#fff; cursor:pointer; transition:background .25s }
.dot.active { background:transparent } /* активная = пустое кольцо, по умолчанию активна средняя */

СЛОГАН (внизу слева)
.tagline { position:absolute; left:var(--pad-x); bottom:clamp(40px,7.5vh,70px); font-size:clamp(24px,2.65vw,44px); line-height:1.2; font-weight:300; letter-spacing:-0.01em }
.tagline strong { font-weight:700; display:block }

СТРОКА CTA (кнопка → горизонтальная линия → огромный контурный «07», выходящий за правый край)
.cta-row { position:absolute; left:45.6%; right:-1vw; top:88.7%; transform:translateY(-50%); display:flex; align-items:center }
.cta { flex:none; padding:0 15px; height:48px; display:inline-flex; align-items:center; border:1.5px solid rgba(255,255,255,.85); border-radius:6px; background:rgba(0,0,0,.15); color:#fff; font-size:14px; font-weight:400; text-decoration:none; cursor:pointer; transition:background .25s, color .25s }
.cta:hover { background:#fff; color:#000 }
.cta-line { flex:1; height:1.5px; background:rgba(255,255,255,.8); min-width:40px }
.count { flex:none; font-size:clamp(140px,19.8vw,360px); font-weight:400; line-height:1; letter-spacing:-0.02em; color:transparent; -webkit-text-stroke:1.5px rgba(255,255,255,.9); transform:translateY(6%); user-select:none }

ИНДИКАТОР ЗАГРУЗКИ
.loader { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); font-size:12px; letter-spacing:.2em; text-transform:uppercase; opacity:.6; transition:opacity .6s }
.loader.done { opacity:0 }

АДАПТИВНОСТЬ
@media (max-width:900px), (max-aspect-ratio:1/1) {
.arrows { left:auto; right:var(--pad-x); top:15%; transform:translateY(-50%); gap:14px }
.tagline { bottom:clamp(150px,20vh,220px) }
.cta-row { left:var(--pad-x); right:-3vw; top:auto; bottom:24px; transform:none }
.count { font-size:clamp(120px,22vw,200px) }
}
@media (max-width:640px) {
.nav-links { gap:16px }
.nav-links a, .logo { font-size:13px }
.dots { gap:20px; right:16px }
.dot { width:10px; height:10px }
.cta-row { right:-8vw }
.count { font-size:120px }
}
@media (max-width:420px) { .nav-links li:nth-child(2) { display:none } } /* скрыть «Portfolio» */
Горизонтальная прокрутка страницы не должна появляться ни при какой ширине.

==================================================
4. СЦЕНА WEBGL (Three.js)
==================================================
Рендерер: WebGLRenderer({ canvas:#scene, antialias:true, alpha:false }), clearColor #000, outputColorSpace SRGBColorSpace, pixelRatio = min(devicePixelRatio, 2).
Камера: PerspectiveCamera(fov 30, aspect W/H, 0.1, 100) в позиции (0,0,10), направлена на начало координат.

4a. Фоновый заголовок (рисуется на автономном 2D canvas → CanvasTexture)
- Размер canvas = viewport × DPR, заливка #000.
- mobile = (W < 768) || (W/H < 1).
- fontSize fs = min(H*0.21, W*(mobile ? 0.21 : 0.118)); font = `800 ${fs}px Poppins`.
Если самая широкая строка шире W*(mobile ? 0.9 : 0.5), уменьшить fs так, чтобы она уместилась.
- Строки: "Explore", "New", "Ideas". Заливка #e9e9e9, textAlign center, baseline alphabetic.
- Центр по x = W*(mobile ? 0.5 : 0.505); центр по y = H*(mobile ? 0.45 : 0.468).
Межстрочный интервал = fs*1.07; высота прописных ≈ fs*0.7. Для строки i (0..2) базовая линия y = cy + cap/2 + (i-1)*gap.
- Текстура: colorSpace SRGB, LinearFilter, без mipmaps. Перерисовывать при изменении размера окна и при событии document.fonts 'loadingdone'.
- Отобразить её с помощью полноэкранного квадрата (PlaneGeometry(2,2), ShaderMaterial, vertex outputs position.xy directly, fragment = texture2D(uTex, vUv) followed by #include <colorspace_fragment> ON ITS OWN LINE; depthTest/depthWrite false; frustumCulled false) в отдельной bgScene.
- Дождаться загрузки шрифтов перед первой отрисовкой: Promise.race([Promise.all([document.fonts.load('800 100px Poppins'), document.fonts.ready]), 2500ms timeout]) затем выполнить layout() + запустить цикл.

4b. Загрузка модели
- GLTFLoader.load(MODEL_URL). Обойти gltf.scene; для каждого mesh: клонировать geometry, удалить атрибуты 'uv','color','tangent', выполнить mergeVertices(g, 1e-4), computeVertexNormals(), applyMatrix4(mesh.matrixWorld). Объединить все части с помощью mergeGeometries.
- Отцентрировать геометрию по её bounding box и равномерно масштабировать так, чтобы её наибольший размер = 1.
- Граф сцены: scene → pivot (положение на экране + масштаб) → spinner (вращение) → cube mesh. После загрузки добавить классу #loader "done".

4c. Размещение куба (в layout(), при загрузке и при изменении размера окна)
- visH = 2*tan(fov/2)*10; visW = visH*aspect.
- Центр в долях экрана: sx = mobile ? 0.5 : 0.517, sy = mobile ? 0.45 : 0.488.
pivot.position = ((sx-0.5)*visW, (0.5-sy)*visH, 0).
Длина ребра на экране в пикселях = min(H*0.44, W*(mobile ? 0.45 : 0.29)); pivot.scale = (px/H)*visH.
Начальное вращение spinner: Euler(-0.42, 0.62, 0.18).

4d. Стеклянный материал — пользовательский ShaderMaterial, преломление в экранном пространстве с 6-полосной хроматической дисперсией, отрисовываемое в два прохода (сначала задние грани, затем передние).
Вершинный шейдер:
varying vec3 vNormal; varying vec3 vEye;
worldPos = modelMatrix*position; mvPos = viewMatrix*worldPos; gl_Position = projectionMatrix*mvPos;
vNormal = normalize(normalMatrix*normal); vEye = normalize(https://mvpos.xyz/);
Фрагментный шейдер:
uv = gl_FragCoord.xy / uResolution (размер drawing-buffer).
n = normalize(vNormal); if (uBackside > 0.5) n = -n; // НЕ использовать gl_FrontFacing, three.js меняет порядок обхода для BackSide
eye = normalize(vEye).
ЦИКЛ = 16 итераций; slide = i/LOOP * 0.045.
Для каждой полосы вычислить refract(eye, n, 1.0/ior) с iorR/Y/G/C/B/P и выбрать сэмпл uTexture по адресу
uv + refr.xy * (uRefractPower + slide*k) * uChromatic, где k = 1 (R), 1 (Y), 2 (G), 2.5 (C), 3 (B), 1 (P):
r = tex(R).x*0.5
y = (tex(Y).x*2 + tex(Y).y*2 - tex(Y).z)/6
g = tex(G).y*0.5
c = (tex(C).y*2 + tex(C).z*2 - tex(C).x)/6
b = tex(B).z*0.5
p = (tex(P).z*2 + tex(P).x*2 - tex(P).y)/6
R = r + (2p + 2y - c)/3; G = g + (2y + 2c - p)/3; B = b + (2c + 2p - y)/3
color += vec3(R,G,B)
color /= LOOP; настройка насыщенности: mix(luma(color), color, uSaturation) с весами luma (0.2125, 0.7154, 0.0721).
Блик (Blinn-Phong, вектор света = normalize(-light), направление взгляда = -eye):
spec = specular(uLight, uShininess, uDiffuseness) + 0.6 * specular(vec3(1,1,-1), uShininess*0.6, uDiffuseness*0.5)
spec(x) = pow(max(dot(n,halfVec),0), shininess) + max(0,dot(n,lightVec))*diffuseness
color += spec * (backside ? 0.35 : 1.0)
Fresnel: f = pow(1.0 + dot(eye, n), uFresnelPower); color = mix(color, vec3(1), f * (backside ? 0.25 : 0.55)).
color += vec3(0.004, 0.005, 0.007). gl_FragColor = vec4(color,1); затем #include <colorspace_fragment> на отдельной строке.
Значения uniform:
uIorR 1.15, uIorY 1.16, uIorG 1.18, uIorC 1.22, uIorB 1.22, uIorP 1.22,
uRefractPower 0.30 (front) / 0.22 (back), uChromatic 0.5, uSaturation 1.08,
uShininess 90, uDiffuseness 0.02, uFresnelPower 5.0, uLight (-1, 1, 1),
uBackside 0 (fr
Открыть в каталоге
Права на промпт принадлежат автору @viktoroddy. За коммерческое использование — продвижение нейросетей, агрегаторов, Telegram-ботов — отвечаете вы: mozgi.io ответственности не несёт. Подробнее →
Модель
Claude Opus 5.5
Формат
3/2
Автор
@viktoroddy
Оригинал
x.com ↗

Похожие промпты

Все промпты для Claude Opus 5.5

Скопировано