Models 44

GLM 5.3 Flash

by Z.aiReasoningClean
Open in new window

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

How it went

Total time
25.7 s
Cost
$0.0024
Output tokens
4,704
Spent thinking
475 tokens
Speed
188.6 tok/s
Console errors
0
First token after
790 ms
First visible text after
4.7 s
Prompt tokens
424
Code size
12.3 KB
Finish reason
stop
Served by
Venice
Model id
z-ai/glm-5.3-flash
Reasoning sent
{"effort":"high"}
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 · 351 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Aquarium</title>
<style>
  html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #04202e; }
  #app { position: fixed; inset: 0; }
  canvas { display: block; }
  .ui {
    position: fixed; pointer-events: none; color: #dff6ff;
    font-family: "Segoe UI", system-ui, sans-serif;
    text-shadow: 0 2px 8px rgba(0,20,35,.7);
    z-index: 10;
  }
  #title { top: 20px; left: 24px; }
  #title h1 { margin: 0; font-size: 22px; letter-spacing: 4px; font-weight: 600; text-transform: uppercase; }
  #title p { margin: 4px 0 0; font-size: 13px; opacity: .75; letter-spacing: 1px; }
  #hint {
    bottom: 22px; left: 0; right: 0; text-align: center;
    font-size: 14px; letter-spacing: 2px; opacity: .8;
    animation: pulse 2.4s ease-in-out infinite;
  }
  @keyframes pulse { 0%,100% { opacity: .85; } 50% { opacity: .35; } }
  #vignette {
    position: fixed; inset: 0; pointer-events: none; z-index: 5;
    background: radial-gradient(ellipse at center, rgba(0,0,0,0) 55%, rgba(0,15,28,.55) 100%);
  }
</style>
<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>
</head>
<body>
<div id="app"></div>
<div id="vignette"></div>
<div class="ui" id="title">
  <h1>Coral Bay Aquarium</h1>
  <p>Move your mouse near the fish — they will scatter</p>
</div>
<div class="ui" id="hint">Move the mouse to start</div>

<script type="module">
import * as THREE from 'three';

const app = document.getElementById('app');
const hint = document.getElementById('hint');

/* ---------- Renderer / Scene / Camera ---------- */
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(window.innerWidth, window.innerHeight);
app.appendChild(renderer.domElement);

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a3a52);
scene.fog = new THREE.FogExp2(0x0a3a52, 0.028);

const camera = new THREE.PerspectiveCamera(58, window.innerWidth / window.innerHeight, 0.1, 120);
camera.position.set(0, 2.2, 16);

/* ---------- Lights ---------- */
scene.add(new THREE.HemisphereLight(0x9fd8ff, 0x0a2a3a, 1.1));
const sun = new THREE.DirectionalLight(0xcfefff, 1.6);
sun.position.set(6, 18, 6);
scene.add(sun);
const glow = new THREE.PointLight(0x66d9ff, 40, 40);
glow.position.set(0, 6, 4);
scene.add(glow);

/* ---------- Sand floor ---------- */
{
  const g = new THREE.PlaneGeometry(70, 70, 64, 64);
  const pos = g.attributes.position;
  for (let i = 0; i < pos.count; i++) {
    const x = pos.getX(i), y = pos.getY(i);
    pos.setZ(i, (Math.sin(x * 0.6) + Math.cos(y * 0.5)) * 0.22 + Math.random() * 0.1);
  }
  g.computeVertexNormals();
  const floor = new THREE.Mesh(g, new THREE.MeshStandardMaterial({ color: 0x3a6b70, roughness: 1, metalness: 0 }));
  floor.rotation.x = -Math.PI / 2;
  floor.position.y = -4;
  scene.add(floor);
}

/* ---------- Rocks ---------- */
const rockMat = new THREE.MeshStandardMaterial({ color: 0x35545e, roughness: 0.95, flatShading: true });
for (let i = 0; i < 14; i++) {
  const g = new THREE.IcosahedronGeometry(0.6 + Math.random() * 1.4, 1);
  const p = g.attributes.position;
  for (let j = 0; j < p.count; j++) {
    p.setXYZ(j, p.getX(j) * (0.75 + Math.random() * 0.5), p.getY(j) * (0.6 + Math.random() * 0.4), p.getZ(j) * (0.75 + Math.random() * 0.5));
  }
  g.computeVertexNormals();
  const rock = new THREE.Mesh(g, rockMat);
  const a = Math.random() * Math.PI * 2, r = 7 + Math.random() * 14;
  rock.position.set(Math.cos(a) * r, -4 + Math.random() * 0.8, Math.sin(a) * r * 0.7 - 2);
  rock.rotation.set(Math.random(), Math.random(), Math.random());
  scene.add(rock);
}

/* ---------- Seaweed ---------- */
const weeds = [];
const weedMat = new THREE.MeshStandardMaterial({ color: 0x2e8b57, roughness: 0.8, side: THREE.DoubleSide });
for (let i = 0; i < 26; i++) {
  const h = 2 + Math.random() * 3.5;
  const g = new THREE.PlaneGeometry(0.45, h, 1, 6);
  g.translate(0, h / 2, 0);
  const w = new THREE.Mesh(g, weedMat.clone());
  w.material.color.offsetHSL(0, 0, (Math.random() - 0.5) * 0.15);
  const a = Math.random() * Math.PI * 2, r = 6 + Math.random() * 15;
  w.position.set(Math.cos(a) * r, -4, Math.sin(a) * r * 0.7 - 2);
  w.rotation.y = Math.random() * Math.PI;
  scene.add(w);
  weeds.push({ mesh: w, phase: Math.random() * 10, baseX: w.position.x });
}

/* ---------- Bubbles ---------- */
const bubbleGroup = new THREE.Group();
scene.add(bubbleGroup);
const bubbleMat = new THREE.MeshStandardMaterial({ color: 0xbfeaff, transparent: true, opacity: 0.35, roughness: 0.1, metalness: 0.2 });
const bubbles = [];
const bubbleGeo = new THREE.SphereGeometry(1, 10, 10);
for (let i = 0; i < 60; i++) {
  const s = 0.03 + Math.random() * 0.09;
  const b = new THREE.Mesh(bubbleGeo, bubbleMat);
  b.scale.setScalar(s);
  b.position.set((Math.random() - 0.5) * 26, -4 + Math.random() * 14, (Math.random() - 0.5) * 14 - 2);
  bubbles.push({ mesh: b, speed: 0.6 + Math.random() * 1.2, wob: Math.random() * 10 });
  bubbleGroup.add(b);
}

/* ---------- Fish factory ---------- */
const palette = [0xff9a3c, 0xffd23f, 0xff5d73, 0x4fd6ff, 0x9b5dff, 0x3cffa0, 0xffffff, 0xff8fc7];
function makeFish() {
  const group = new THREE.Group();
  const scale = 0.55 + Math.random() * 0.8;
  const color = new THREE.Color(palette[Math.floor(Math.random() * palette.length)]);
  color.offsetHSL(0, 0, (Math.random() - 0.5) * 0.1);
  const mat = new THREE.MeshStandardMaterial({ color, roughness: 0.45, metalness: 0.25 });
  const finMat = new THREE.MeshStandardMaterial({ color: color.clone().offsetHSL(0, 0, -0.12), roughness: 0.6, transparent: true, opacity: 0.9 });

  // body
  const body = new THREE.Mesh(new THREE.SphereGeometry(0.42, 16, 12), mat);
  body.scale.set(1.7, 0.75, 0.6);
  group.add(body);

  // tail (pivots to wag)
  const tailPivot = new THREE.Group();
  tailPivot.position.x = -0.75;
  const tail = new THREE.Mesh(new THREE.ConeGeometry(0.36, 0.7, 8), finMat);
  tail.rotation.z = Math.PI / 2;
  tail.position.x = -0.3;
  tail.scale.set(1, 1, 0.25);
  tailPivot.add(tail);
  group.add(tailPivot);

  // dorsal fin
  const dorsal = new THREE.Mesh(new THREE.ConeGeometry(0.22, 0.42, 6), finMat);
  dorsal.position.set(-0.05, 0.42, 0);
  dorsal.scale.z = 0.25;
  group.add(dorsal);

  // side fins
  for (const s of [-1, 1]) {
    const fin = new THREE.Mesh(new THREE.ConeGeometry(0.14, 0.34, 6), finMat);
    fin.position.set(0.05, -0.12, s * 0.28);
    fin.rotation.x = s * 1.1;
    fin.rotation.z = -0.8;
    fin.scale.z = 0.25;
    group.add(fin);
  }

  // eyes
  const eyeMat = new THREE.MeshStandardMaterial({ color: 0x101418, roughness: 0.2 });
  const eyeGeo = new THREE.SphereGeometry(0.08, 10, 10);
  for (const s of [-1, 1]) {
    const eye = new THREE.Mesh(eyeGeo, eyeMat);
    eye.position.set(0.55, 0.12, s * 0.19);
    group.add(eye);
  }

  group.scale.setScalar(scale);
  return { group, tailPivot };
}

/* ---------- Fish behavior ---------- */
const BOUNDS = { x: 14, yMin: -3.2, yMax: 7.5, z: -3 };
const FISH_COUNT = 26;
const fishes = [];

for (let i = 0; i < FISH_COUNT; i++) {
  const { group, tailPivot } = makeFish();
  const pos = new THREE.Vector3((Math.random() - 0.5) * 20, -2 + Math.random() * 8, (Math.random() - 0.5) * 8 - 2);
  group.position.copy(pos);
  scene.add(group);
  fishes.push({
    group, tailPivot, pos,
    vel: new THREE.Vector3((Math.random() - 0.5), (Math.random() - 0.5) * 0.4, (Math.random() - 0.5)).multiplyScalar(1.2),
    wander: new THREE.Vector3(),
    phase: Math.random() * 100,
    scale: group.scale.x,
    panic: 0
  });
}

/* ---------- Mouse handling ---------- */
const mouseNDC = new THREE.Vector2(0, 0);
let mouseActive = false;
const raycaster = new THREE.Raycaster();

function updateMouse(cx, cy) {
  mouseNDC.set((cx / window.innerWidth) * 2 - 1, -(cy / window.innerHeight) * 2 + 1);
  if (!mouseActive) {
    mouseActive = true;
    hint.style.display = 'none';
  }
}
window.addEventListener('mousemove', e => updateMouse(e.clientX, e.clientY));
window.addEventListener('touchmove', e => {
  if (e.touches[0]) updateMouse(e.touches[0].clientX, e.touches[0].clientY);
}, { passive: true });

/* ---------- Camera parallax target ---------- */
const camTarget = new THREE.Vector3(0, 0, 0);

/* ---------- Simulation ---------- */
const _toFish = new THREE.Vector3();
const _closest = new THREE.Vector3();
const _steer = new THREE.Vector3();
const _fleeDir = new THREE.Vector3();
const clock = new THREE.Clock();

function simulate(dt, t) {
  raycaster.setFromCamera(mouseNDC, camera);
  const ro = raycaster.ray.origin;
  const rd = raycaster.ray.direction;

  for (const f of fishes) {
    // closest point on mouse ray to this fish
    _toFish.subVectors(f.pos, ro);
    const along = Math.max(0, _toFish.dot(rd));
    _closest.copy(rd).multiplyScalar(along).add(ro);
    const distToRay = f.pos.distanceTo(_closest);

    // wander
    f.wander.x += (Math.random() - 0.5) * 2.4 * dt;
    f.wander.y += (Math.random() - 0.5) * 1.6 * dt;
    f.wander.z += (Math.random() - 0.5) * 2.0 * dt;
    f.wander.multiplyScalar(0.96);

    _steer.copy(f.wander);

    // soft walls
    const m = 3;
    if (f.pos.x > BOUNDS.x) _steer.x -= (f.pos.x - BOUNDS.x) * 0.9;
    if (f.pos.x < -BOUNDS.x) _steer.x -= (f.pos.x + BOUNDS.x) * 0.9;
    if (f.pos.y > BOUNDS.yMax) _steer.y -= (f.pos.y - BOUNDS.yMax) * 0.9;
    if (f.pos.y < BOUNDS.yMin) _steer.y -= (f.pos.y - BOUNDS.yMin) * 0.9;
    if (f.pos.z > BOUNDS.z + 9) _steer.z -= (f.pos.z - (BOUNDS.z + 9)) * 0.9;
    if (f.pos.z < BOUNDS.z - 4) _steer.z -= (f.pos.z - (BOUNDS.z - 4)) * 0.9;

    // flee from cursor
    let speed = 1.6 * f.scale;
    if (mouseActive && distToRay < 4.5) {
      const urgency = 1 - distToRay / 4.5;
      _fleeDir.subVectors(f.pos, _closest).normalize();
      _steer.addScaledVector(_fleeDir, urgency * 26);
      speed += urgency * 9 * f.scale;
      f.panic = Math.min(1, f.panic + urgency * 4 * dt);
    }
    f.panic = Math.max(0, f.panic - 1.2 * dt);

    // schooling cohesion (gentle)
    for (let j = 0; j < fishes.length; j += 3) {
      const o = fishes[j];
      if (o === f) continue;
      const d = f.pos.distanceTo(o.pos);
      if (d < 2.2 && d > 0.001) {
        _steer.addScaledVector(_toFish.copy(o.pos).sub(f.pos).normalize(), -0.6 / d);
      }
    }

    f.vel.addScaledVector(_steer, dt);
    // clamp speed
    const sp = f.vel.length();
    const maxSp = speed;
    if (sp > maxSp) f.vel.multiplyScalar(maxSp / sp);
    if (sp < maxSp * 0.4) f.vel.multiplyScalar(1 + dt * 0.8);

    f.pos.addScaledVector(f.vel, dt);
    f.group.position.copy(f.pos);

    // orientation — face velocity, slight roll when panicking
    if (f.vel.lengthSq() > 0.0001) {
      const look = _toFish.copy(f.pos).add(f.vel);
      f.group.lookAt(look);
      f.group.rotation.z += f.panic * Math.sin(t * 14 + f.phase) * 0.25;
    }

    // tail wag — faster when panicked
    const wagSp = 6 + f.panic * 14;
    f.tailPivot.rotation.y = Math.sin(t * wagSp + f.phase) * (0.45 + f.panic * 0.3);
  }
}

function animate(t, dt) {
  for (const w of weeds) {
    w.mesh.rotation.z = Math.sin(t * 0.8 + w.phase) * 0.12;
    w.mesh.rotation.x = Math.cos(t * 0.6 + w.phase) * 0.07;
  }
  for (const b of bubbles) {
    b.mesh.position.y += b.speed * dt;
    b.mesh.position.x += Math.sin(t * 2 + b.wob) * 0.15 * dt;
    if (b.mesh.position.y > 9) {
      b.mesh.position.y = -4;
      b.mesh.position.x = (Math.random() - 0.5) * 26;
      b.mesh.position.z = (Math.random() - 0.5) * 14 - 2;
    }
  }
  glow.intensity = 36 + Math.sin(t * 1.3) * 8;
}

function tick() {
  const dt = Math.min(clock.getDelta(), 0.05);
  const t = clock.elapsedTime;
  simulate(dt, t);
  animate(t, dt);

  // camera drift + slight mouse parallax
  camTarget.x = mouseNDC.x * 2.2;
  camTarget.y = 2.2 + mouseNDC.y * 1.2;
  camera.position.x += (camTarget.x - camera.position.x) * 0.03;
  camera.position.y += (camTarget.y - camera.position.y) * 0.03;
  camera.lookAt(0, 1, -2);

  renderer.render(scene, camera);
  requestAnimationFrame(tick);
}

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

tick();
</script>
</body>
</html>
Reasoning trace (475 tokens)
Create a 3D aquarium with Three.js. Fish swim, flee from mouse cursor. Use import map. Fish built from geometry (body cone + tail), boids-like motion with flee behavior from mouse projected into 3D. Add bubbles, caustics-ish background, seaweed, sand floor, light rays maybe. Self-running without keyboard needed (mouse-based). Should look good at first paint.

Plan:
- Scene: fog underwater blue, sand floor, rocks, seaweed (animated), bubbles rising, fish.
- Fish: simple low-poly fish made from scaled sphere/cone, tail wiggle via bone-less animation (rotate tail mesh).
- Movement: each fish has velocity, wander target, avoid walls, flee from mouse ray point. Mouse -> unproject to a point at some depth; compute distance, if close, steer away with stronger force and speed boost.
- Also add caustic light via moving spotlight? Keep simple.
- Title overlay, instructions.
- Handle resize.

Write code carefully. Fish class:

body: sphere scaled (elongated), tail: cone rotated, fins. Colors varied. Eye spheres.

Update: steering = wander + bounds avoidance + flee. Flee point: raycast mouse onto plane z = 0? Better: compute point along camera ray at closest distance to fish — for each fish, project fish position onto mouse ray; if distance from fish to ray < fleeRadius, steer away. That's accurate and feels good.

Speed: base 1.2, boost when fleeing.

Orientation: fish look along velocity; banking slight.

Bubbles: points or small spheres rising.

Seaweed: cylinders/planes with vertex animation via sine in onBeforeRender or simple rotation sway.

Rocks: icosahedron deformed.

Sand: big plane with slight noise displacement.

Lights: hemisphere + directional + point light.

Post: none.

Let me write it. Keep code robust, no errors.

Tail wiggle: tail.rotation.y = sin(t*speed + phase)*0.4; body slight rotation.

Also make fish flee near cursor: use raycaster from camera through mouse NDC; closest point on ray to fish pos.

Camera slight parallax with mouse too.

Overlay: title top-left, hint bottom. Fade hint after a while? Keep visible.

Write the HTML.