Models 44

GPT-6 Luna

by OpenAIReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
36.4 s
Cost
$0.0021
Output tokens
4,021
Spent thinking
0 tokens
Speed
139.5 tok/s
Console errors
0
First token after
7.6 s
First visible text after
7.6 s
Prompt tokens
423
Code size
12.4 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-6-luna
Reasoning sent
{"effort":"none"}
Max output
64,000 tokens
Generated
Nov 10, 2026

What it was asked

The prompt
“a 3D aquarium with Three.js where the fish swim away when I move the mouse near them (Load Three.js only through this import map: <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>)”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 222 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Blue Room — Aquarium</title>
<script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>
<style>
  *{box-sizing:border-box}
  html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#04131d;color:#e9f8f5;font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}
  #scene{position:fixed;inset:0}
  canvas{display:block;width:100%;height:100%;outline:none}
  .shade{position:fixed;inset:0;pointer-events:none;background:linear-gradient(90deg,rgba(2,14,22,.78) 0%,rgba(2,14,22,.42) 34%,transparent 70%),linear-gradient(0deg,rgba(1,12,18,.44),transparent 30%,rgba(2,14,22,.18))}
  .topbar{position:fixed;inset:0 0 auto;display:flex;align-items:center;justify-content:space-between;padding:28px 42px;pointer-events:none}
  .brand{display:flex;align-items:center;gap:12px;font-size:12px;font-weight:700;letter-spacing:.2em;text-transform:uppercase}
  .brand-mark{height:30px;width:30px;border:1px solid rgba(145,230,215,.55);border-radius:50%;display:grid;place-items:center;color:#8ce4d5;font-size:14px}
  .status{display:flex;align-items:center;gap:9px;color:rgba(226,245,241,.65);font-size:10px;letter-spacing:.16em;text-transform:uppercase}
  .dot{width:6px;height:6px;background:#80dbc7;border-radius:50%;box-shadow:0 0 12px #80dbc7}
  .copy{position:fixed;left:9.5%;top:50%;transform:translateY(-43%);width:min(390px,40vw);pointer-events:none}
  .eyebrow{display:flex;align-items:center;gap:11px;color:#8ce2d1;font-size:10px;letter-spacing:.25em;text-transform:uppercase;font-weight:700}
  .eyebrow:before{content:"";display:block;width:28px;height:1px;background:#8ce2d1}
  h1{font-family:Georgia,"Times New Roman",serif;font-size:clamp(43px,6.3vw,82px);line-height:.98;font-weight:400;letter-spacing:-.045em;margin:22px 0 20px}
  h1 em{font-weight:400;color:#8edbca}
  .description{max-width:305px;color:rgba(224,242,239,.64);font-size:14px;line-height:1.75;margin:0}
  .hint{display:flex;align-items:center;gap:12px;margin-top:35px;color:rgba(224,242,239,.72);font-size:11px;letter-spacing:.09em;text-transform:uppercase}
  .mouse-icon{width:19px;height:27px;border:1px solid rgba(161,224,212,.7);border-radius:12px;position:relative}
  .mouse-icon:before{content:"";position:absolute;top:5px;left:8px;width:2px;height:5px;border-radius:2px;background:#8ce2d1}
  .bottom{position:fixed;left:42px;right:42px;bottom:24px;display:flex;align-items:center;justify-content:space-between;color:rgba(218,239,234,.45);font-size:9px;letter-spacing:.18em;text-transform:uppercase;pointer-events:none}
  .bottom span:last-child{display:flex;align-items:center;gap:9px}
  .bottom span:last-child:before{content:"";width:28px;height:1px;background:rgba(218,239,234,.4)}
  @media(max-width:700px){
    .topbar{padding:19px 20px}.status{font-size:8px}
    .copy{left:8%;top:44%;width:80%;transform:translateY(-25%)}
    h1{font-size:clamp(48px,13vw,72px);margin:16px 0}
    .description{font-size:13px;max-width:285px}
    .hint{margin-top:24px}
    .bottom{left:20px;right:20px;bottom:17px;font-size:8px}
    .shade{background:linear-gradient(90deg,rgba(2,14,22,.72),rgba(2,14,22,.25) 70%),linear-gradient(0deg,rgba(1,12,18,.48),transparent 48%)}
  }
  @media(max-height:570px) and (min-width:701px){.copy{top:53%}h1{font-size:56px;margin:15px 0}.hint{margin-top:20px}}
</style>
</head>
<body>
<div id="scene"></div>
<div class="shade"></div>
<header class="topbar">
  <div class="brand"><div class="brand-mark">≈</div><span>Blue Room</span></div>
  <div class="status"><i class="dot"></i> Living collection&nbsp; / &nbsp;01</div>
</header>
<main class="copy">
  <div class="eyebrow">A quiet little world</div>
  <h1>Drift<br>into the <em>blue.</em></h1>
  <p class="description">A small moment of calm, just beneath the surface. Follow the light and see what swims by.</p>
  <div class="hint"><span class="mouse-icon"></span><span>Move your cursor to explore</span></div>
</main>
<footer class="bottom"><span>Ocean study no. 01</span><span>Move gently</span></footer>
<script type="module">
import * as THREE from 'three';

const host=document.getElementById('scene');
const scene=new THREE.Scene();
scene.background=new THREE.Color(0x082432);
scene.fog=new THREE.FogExp2(0x082432,.035);
const camera=new THREE.PerspectiveCamera(48,innerWidth/innerHeight,.1,100);
camera.position.set(0,0,13);
const renderer=new THREE.WebGLRenderer({antialias:true,alpha:false});
renderer.setPixelRatio(Math.min(devicePixelRatio,2));
renderer.setSize(innerWidth,innerHeight);
renderer.outputColorSpace=THREE.SRGBColorSpace;
renderer.toneMapping=THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure=1.08;
host.appendChild(renderer.domElement);

scene.add(new THREE.AmbientLight(0x8cc7c5,1.05));
const key=new THREE.PointLight(0x9ce9d8,50,30);key.position.set(-4,5,5);scene.add(key);
const blueLight=new THREE.PointLight(0x246c9a,32,30);blueLight.position.set(5,-3,3);scene.add(blueLight);

const tank=new THREE.Group();scene.add(tank);
const glassMat=new THREE.MeshPhysicalMaterial({color:0x286479,transparent:true,opacity:.075,roughness:.12,metalness:.18,side:THREE.DoubleSide,depthWrite:false});
const back=new THREE.Mesh(new THREE.PlaneGeometry(21,13),new THREE.MeshBasicMaterial({color:0x0a3140}));
back.position.z=-4.2;tank.add(back);
// A fine, luminous frame makes the aquarium read as a glass volume.
const frameMat=new THREE.LineBasicMaterial({color:0x85d4c6,transparent:true,opacity:.27});
const frameGeo=new THREE.EdgesGeometry(new THREE.BoxGeometry(20.8,12.5,8.2));
const frame=new THREE.LineSegments(frameGeo,frameMat);frame.position.set(0,0,-.1);tank.add(frame);

const glass=new THREE.Mesh(new THREE.BoxGeometry(20.8,12.5,8.2),glassMat);glass.position.set(0,0,-.1);tank.add(glass);

// Soft shafts of light in the water.
for(let i=0;i<5;i++){
  const ray=new THREE.Mesh(new THREE.PlaneGeometry(.24,10),new THREE.MeshBasicMaterial({color:0x9de7d8,transparent:true,opacity:.045,side:THREE.DoubleSide,depthWrite:false}));
  ray.position.set(-6+i*3.2,1.2,-3.9);ray.rotation.z=-.13+(i%3)*.08;tank.add(ray);
}

// Gravel and gently swaying plants.
const gravelMat=new THREE.MeshStandardMaterial({color:0x425e54,roughness:1});
for(let i=0;i<90;i++){
  const r=.035+Math.random()*.095;
  const pebble=new THREE.Mesh(new THREE.SphereGeometry(r,7,5),gravelMat);
  pebble.position.set(-9.8+Math.random()*19.6,-5.65+Math.random()*.18,-3.4+Math.random()*1.3);
  pebble.scale.y=.55; tank.add(pebble);
}
const plants=[];
for(let i=0;i<12;i++){
  const x=-9.2+i*1.65+(Math.random()-.5)*.55;
  const h=.8+Math.random()*2.2;
  const points=[new THREE.Vector3(x,-5.65,-2.9),new THREE.Vector3(x+(Math.random()-.5)*.4,-5.65+h*.5,-2.9),new THREE.Vector3(x+(Math.random()-.5)*.8,-5.65+h,-2.9)];
  const curve=new THREE.CatmullRomCurve3(points);
  const mesh=new THREE.Mesh(new THREE.TubeGeometry(curve,16,.035+Math.random()*.025,5,false),new THREE.MeshStandardMaterial({color:[0x327e70,0x4d9a78,0x27675f][i%3],roughness:.75}));
  tank.add(mesh);plants.push({mesh,x,h,phase:Math.random()*6});
}

// Fish geometry: tapered body, fins, tail, and bright eyes, grouped around a swimming pivot.
const fishGroup=new THREE.Group();scene.add(fishGroup);
const fishList=[];
const palettes=[
  {body:0xf2aa69,fin:0xd97e52,detail:0xffe1a6},
  {body:0x6fd2c3,fin:0x318e91,detail:0xd6fff0},
  {body:0xe5d58b,fin:0xb29e58,detail:0xfff5c5},
  {body:0xd17d82,fin:0x914f69,detail:0xffd8c4},
  {body:0x86aee1,fin:0x526fa8,detail:0xe2f4ff}
];
const sphereGeo=new THREE.SphereGeometry(1,20,14);
function createFish(index){
  const p=palettes[index%palettes.length];
  const root=new THREE.Group();
  const bodyMat=new THREE.MeshStandardMaterial({color:p.body,roughness:.36,metalness:.08});
  const finMat=new THREE.MeshStandardMaterial({color:p.fin,roughness:.42,side:THREE.DoubleSide});
  const body=new THREE.Mesh(sphereGeo,bodyMat);
  body.scale.set(.67,.32,.25);root.add(body);
  const tail=new THREE.Mesh(new THREE.BufferGeometry(),finMat);
  const tailShape=new THREE.Shape();
  tailShape.moveTo(0,0);tailShape.lineTo(-.48,.38);tailShape.lineTo(-.39,0);tailShape.lineTo(-.48,-.38);tailShape.closePath();
  const tailMesh=new THREE.Mesh(new THREE.ShapeGeometry(tailShape),finMat);
  tailMesh.position.x=-.58;tailMesh.position.z=-.02;root.add(tailMesh);
  const dorsalShape=new THREE.Shape();dorsalShape.moveTo(-.12,.2);dorsalShape.lineTo(.05,.52);dorsalShape.lineTo(.34,.22);dorsalShape.closePath();
  const dorsal=new THREE.Mesh(new THREE.ShapeGeometry(dorsalShape),finMat);dorsal.position.z=0;root.add(dorsal);
  const lowerShape=new THREE.Shape();lowerShape.moveTo(-.12,-.2);lowerShape.lineTo(.08,-.42);lowerShape.lineTo(.3,-.22);lowerShape.closePath();
  const lower=new THREE.Mesh(new THREE.ShapeGeometry(lowerShape),finMat);root.add(lower);
  const eyeMat=new THREE.MeshStandardMaterial({color:0x09222b,roughness:.2});
  const eye=new THREE.Mesh(new THREE.SphereGeometry(.052,10,8),eyeMat);eye.position.set(.46,.07,.213);root.add(eye);
  const glint=new THREE.Mesh(new THREE.SphereGeometry(.016,8,6),new THREE.MeshBasicMaterial({color:0xffffff}));glint.position.set(.472,.089,.254);root.add(glint);
  const stripeMat=new THREE.MeshBasicMaterial({color:p.detail,transparent:true,opacity:.55});
  const stripe=new THREE.Mesh(new THREE.SphereGeometry(1,12,10),stripeMat);stripe.scale.set(.045,.25,.258);stripe.position.set(.02,0,0);root.add(stripe);
  fishGroup.add(root);
  const z=-1.35+Math.random()*2.3;
  const y=-1.8+Math.random()*4.0;
  fishList.push({root,tailMesh,index,x:(Math.random()-.5)*13,y,z,baseY:y,phase:Math.random()*6.28,speed:.55+Math.random()*.42, flee:0, fleeX:0,fleeY:0,side:Math.random()>.5?1:-1});
}
for(let i=0;i<11;i++)createFish(i);

const bubbles=[];
const bubbleMat=new THREE.MeshBasicMaterial({color:0xb9eee6,transparent:true,opacity:.22,wireframe:true});
for(let i=0;i<34;i++){
  const radius=.025+Math.random()*.045;
  const mesh=new THREE.Mesh(new THREE.SphereGeometry(radius,7,6),bubbleMat);
  mesh.position.set(-9.5+Math.random()*19,-5.7+Math.random()*10,-2.8+Math.random()*2);
  scene.add(mesh);bubbles.push({mesh,speed:.3+Math.random()*.55,phase:Math.random()*6});
}

const pointer=new THREE.Vector2(9,9);
const raycaster=new THREE.Raycaster();
const interactionPlane=new THREE.Plane(new THREE.Vector3(0,0,1),0);
const pointerWorld=new THREE.Vector3();
let hasPointer=false;
function movePointer(event){
  const rect=renderer.domElement.getBoundingClientRect();
  pointer.x=(event.clientX-rect.left)/rect.width*2-1;
  pointer.y=-((event.clientY-rect.top)/rect.height*2-1);
  raycaster.setFromCamera(pointer,camera);
  if(raycaster.ray.intersectPlane(interactionPlane,pointerWorld))hasPointer=true;
}
renderer.domElement.addEventListener('pointermove',movePointer);
renderer.domElement.addEventListener('pointerleave',()=>{hasPointer=false});

const clock=new THREE.Clock();
function animate(){
  requestAnimationFrame(animate);
  const t=clock.getElapsedTime();
  for(const f of fishList){
    const fish=f.root;
    const homeX=f.x+Math.sin(t*f.speed+f.phase)*2.15*f.side;
    const homeY=f.baseY+Math.sin(t*1.3+f.phase)*.42;
    if(hasPointer){
      const dx=fish.position.x-pointerWorld.x,dy=fish.position.y-pointerWorld.y;
      const dist=Math.sqrt(dx*dx+dy*dy);
      if(dist<2.05){
        f.flee=Math.max(f.flee,1);
        const inv=1/Math.max(dist,.15);
        f.fleeX=dx*inv;f.fleeY=dy*inv;
      }
    }
    f.flee=Math.max(0,f.flee-.023);
    const fleeEase=f.flee*f.flee;
    fish.position.x=THREE.MathUtils.damp(fish.position.x,homeX+f.fleeX*fleeEase*2.7,2.8,1/60);
    fish.position.y=THREE.MathUtils.damp(fish.position.y,homeY+f.fleeY*fleeEase*1.65,2.8,1/60);
    fish.position.z=f.z+Math.sin(t*.8+f.phase)*.25;
    fish.rotation.z=Math.sin(t*1.5+f.phase)*.055+f.fleeY*fleeEase*.16;
    fish.rotation.y=f.side===1?0:Math.PI;
    f.tailMesh.rotation.y=Math.sin(t*12+f.phase)*.45;
  }
  plants.forEach(p=>{p.mesh.rotation.z=Math.sin(t*.8+p.phase)*.035});
  bubbles.forEach(b=>{
    b.mesh.position.y+=b.speed/60;
    b.mesh.position.x+=Math.sin(t+b.phase)*.0018;
    if(b.mesh.position.y>6.2){b.mesh.position.y=-5.8;b.mesh.position.x=-9.5+Math.random()*19}
  });
  renderer.render(scene,camera);
}
animate();

function resize(){
  camera.aspect=innerWidth/innerHeight;
  camera.position.x=innerWidth<700?0:0;
  camera.fov=innerWidth<700?56:48;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth,innerHeight);
}
addEventListener('resize',resize);
</script>
</body>
</html>