Models 44

GLM 5.3

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
39.0 s
Cost
$0.0073
Output tokens
3,652
Spent thinking
17 tokens
Speed
95.8 tok/s
Console errors
0
First token after
903 ms
First visible text after
1.1 s
Prompt tokens
559
Code size
10.8 KB
Finish reason
stop
Served by
Decart
Model id
z-ai/glm-5.3
Reasoning sent
{"effort":"low"}
Max output
943,718 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
Build a low-poly 3D scene of a campfire in a forest clearing at night, with Three.js in a single HTML file. Load Three.js only through this import map (do not use any other URL or version): <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> Requirements: - A ground with a few low-poly rocks and logs around a campfire in the center. - At least 30 low-poly trees placed randomly around the clearing (not on the fire). - The campfire has animated flames and a warm point light that flickers and casts shadows. - Sparks rising from the fire as a simple particle system. - A dark night sky with stars and a moon, plus fog that fades the distant trees. - OrbitControls to look around, with limits so the camera stays above the ground. - The renderer fills the window and handles resizing correctly.
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 · 301 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Night Campfire — Low Poly Forest</title>
<style>
  html, body { margin:0; padding:0; overflow:hidden; height:100%; background:#06090f; }
  #info {
    position:fixed; bottom:14px; left:14px; color:#e8d9b8;
    font:13px/1.5 system-ui, sans-serif; letter-spacing:.4px;
    background:rgba(10,12,18,.55); padding:8px 14px; border-radius:8px;
    border:1px solid rgba(232,180,90,.25); pointer-events:none; user-select:none;
  }
  #info b { color:#ffb347; font-weight:600; }
</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="info">🌙 <b>Drag</b> to orbit · <b>Scroll</b> to zoom · Camera stays above ground</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

// ---------- Renderer / scene / camera ----------
const renderer = new THREE.WebGLRenderer({ antialias:true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.1;
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x070b16);
scene.fog = new THREE.Fog(0x070b16, 18, 55);

const camera = new THREE.PerspectiveCamera(55, innerWidth/innerHeight, 0.1, 200);
camera.position.set(9, 5.5, 11);

const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1.2, 0);
controls.enableDamping = true;
controls.dampingFactor = 0.06;
controls.minDistance = 4;
controls.maxDistance = 30;
controls.maxPolarAngle = Math.PI * 0.49;   // stay above ground
controls.minPolarAngle = 0.15;

// ---------- Lights ----------
const moon = new THREE.DirectionalLight(0x7d8fc4, 0.35);
moon.position.set(-20, 25, -14);
moon.castShadow = true;
moon.shadow.mapSize.set(2048, 2048);
moon.shadow.camera.left = -30; moon.shadow.camera.right = 30;
moon.shadow.camera.top = 30; moon.shadow.camera.bottom = -30;
moon.shadow.camera.far = 80;
scene.add(moon);

scene.add(new THREE.HemisphereLight(0x22305c, 0x0a0d12, 0.45));

const fireLight = new THREE.PointLight(0xff8b3d, 3.2, 30, 1.8);
fireLight.position.set(0, 1.6, 0);
fireLight.castShadow = true;
fireLight.shadow.mapSize.set(1024, 1024);
fireLight.shadow.camera.near = 0.3;
fireLight.shadow.camera.far = 30;
fireLight.shadow.bias = -0.004;
scene.add(fireLight);
const fireGlow = new THREE.PointLight(0xffb066, 1.0, 8, 2);
fireGlow.position.set(0, 1.0, 0);
scene.add(fireGlow);

// ---------- Ground ----------
const groundGeo = new THREE.CircleGeometry(60, 24);
const groundMat = new THREE.MeshStandardMaterial({ color:0x1c3320, roughness:1, flatShading:true });
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI/2;
ground.receiveShadow = true;
scene.add(ground);

// Low-poly ground bumps
const bumpMat = new THREE.MeshStandardMaterial({ color:0x23402a, roughness:1, flatShading:true });
for (let i=0;i<24;i++){
  const r = 6 + Math.random()*26, a = Math.random()*Math.PI*2;
  const g = new THREE.Mesh(new THREE.ConeGeometry(0.8+Math.random()*1.5, 0.3+Math.random()*0.5, 5), bumpMat);
  g.position.set(Math.cos(a)*r, 0.05, Math.sin(a)*r);
  g.rotation.y = Math.random()*Math.PI;
  g.receiveShadow = true; g.castShadow = true;
  scene.add(g);
}

// ---------- Helpers ----------
const flatMat = (c) => new THREE.MeshStandardMaterial({ color:c, roughness:.9, flatShading:true });
const rand = (a,b) => a + Math.random()*(b-a);

// ---------- Rocks ----------
const rockMat = flatMat(0x6b7078);
for (let i=0;i<9;i++){
  const a = i/9*Math.PI*2 + rand(-.3,.3), r = rand(1.6, 3.2);
  const geo = new THREE.DodecahedronGeometry(rand(.25,.6), 0);
  const rock = new THREE.Mesh(geo, rockMat);
  rock.position.set(Math.cos(a)*r, rand(.05,.15), Math.sin(a)*r);
  rock.rotation.set(rand(0,3), rand(0,3), rand(0,3));
  rock.scale.y = rand(.5,.8);
  rock.castShadow = rock.receiveShadow = true;
  scene.add(rock);
}

// ---------- Campfire logs ----------
const logMat = flatMat(0x4a3220);
const logMatDark = flatMat(0x2b1d12);
for (let i=0;i<5;i++){
  const a = i/5*Math.PI*2;
  const len = 1.4;
  const log = new THREE.Mesh(new THREE.CylinderGeometry(.11,.13,len,6), i<3?logMat:logMatDark);
  log.position.set(Math.cos(a)*.28, .45, Math.sin(a)*.28);
  log.rotation.set(Math.PI/2 - .55*Math.cos(a), a, .55*Math.sin(a));
  log.castShadow = log.receiveShadow = true;
  scene.add(log);
}
// stone ring
for (let i=0;i<8;i++){
  const a = i/8*Math.PI*2;
  const s = new THREE.Mesh(new THREE.DodecahedronGeometry(rand(.16,.24),0), flatMat(0x585d66));
  s.position.set(Math.cos(a)*1.15, .12, Math.sin(a)*1.15);
  s.rotation.set(rand(0,3),rand(0,3),rand(0,3));
  s.castShadow = s.receiveShadow = true;
  scene.add(s);
}
// glowing embers core
const emberMat = new THREE.MeshBasicMaterial({ color:0xff5a1f });
const embers = new THREE.Mesh(new THREE.IcosahedronGeometry(.35,0), emberMat);
embers.position.y = .3;
scene.add(embers);

// ---------- Flames (animated low-poly cones) ----------
const flames = [];
const flameColors = [0xffdf6b, 0xffa63d, 0xff7a1a, 0xff4d00];
for (let i=0;i<7;i++){
  const h = rand(.5, 1.1);
  const f = new THREE.Mesh(
    new THREE.ConeGeometry(rand(.12,.25), h, 5),
    new THREE.MeshBasicMaterial({ color: flameColors[i%4], transparent:true, opacity:.85, blending:THREE.AdditiveBlending, depthWrite:false })
  );
  f.position.set(rand(-.15,.15), .35 + h/2, rand(-.15,.15));
  f.userData = { h, ph: Math.random()*Math.PI*2, sp: rand(4,8) };
  scene.add(f);
  flames.push(f);
}

// ---------- Sparks (particles) ----------
const SPARKS = 180;
const sparkGeo = new THREE.BufferGeometry();
const pos = new Float32Array(SPARKS*3);
const life = new Float32Array(SPARKS);
const vel = [];
for (let i=0;i<SPARKS;i++){
  pos[i*3]   = rand(-.2,.2);
  pos[i*3+1] = rand(.4, 2.5);
  pos[i*3+2] = rand(-.2,.2);
  life[i] = Math.random();
  vel.push(new THREE.Vector3(rand(-.25,.25), rand(.8,1.8), rand(-.25,.25)));
}
sparkGeo.setAttribute('position', new THREE.BufferAttribute(pos,3));
const sparkMat = new THREE.PointsMaterial({ color:0xffc266, size:.09, transparent:true, opacity:.95, blending:THREE.AdditiveBlending, depthWrite:false, sizeAttenuation:true });
const sparks = new THREE.Points(sparkGeo, sparkMat);
scene.add(sparks);

// ---------- Trees (>=30, low-poly, away from fire) ----------
const trunkMat = flatMat(0x3d2a18);
const leafMats = [flatMat(0x14361e), flatMat(0x0f2e2a), flatMat(0x1a4020)];
const trees = [];
let placed = 0, guard = 0;
while (placed < 42 && guard++ < 500){
  const a = Math.random()*Math.PI*2;
  const r = 4.5 + Math.random()*30;
  const x = Math.cos(a)*r, z = Math.sin(a)*r;
  // avoid overlaps
  let ok = true;
  for (const t of trees){
    const dx = t.position.x - x, dz = t.position.z - z;
    if (dx*dx + dz*dz < 4.5) { ok = false; break; }
  }
  if (!ok) continue;
  const g = new THREE.Group();
  const th = rand(1.0, 1.6);
  const trunk = new THREE.Mesh(new THREE.CylinderGeometry(.14,.2,th,5), trunkMat);
  trunk.position.y = th/2;
  trunk.castShadow = true;
  g.add(trunk);
  const lm = leafMats[placed % 3];
  const tiers = 2 + (Math.random()<.5 ? 1 : 0);
  let y = th*0.85, rad = rand(1.1, 1.6), ch = rand(.9,1.3);
  for (let t=0;t<tiers;t++){
    const cone = new THREE.Mesh(new THREE.ConeGeometry(rad, ch, 6), lm);
    cone.position.y = y + ch/2;
    cone.castShadow = cone.receiveShadow = true;
    g.add(cone);
    y += ch*0.55; rad *= .72; ch *= .85;
  }
  const scale = rand(.8, 1.5);
  g.scale.setScalar(scale);
  g.position.set(x, 0, z);
  g.rotation.y = Math.random()*Math.PI*2;
  scene.add(g);
  trees.push(g);
  placed++;
}

// ---------- Sky: stars + moon ----------
function makeStars(count, radiusMin, radiusMax, size, color){
  const g = new THREE.BufferGeometry();
  const p = new Float32Array(count*3);
  for (let i=0;i<count;i++){
    const th = Math.random()*Math.PI*2;
    const ph = Math.acos(rand(-0.05, 0.95)); // mostly above horizon
    const r = rand(radiusMin, radiusMax);
    p[i*3]   = r*Math.sin(ph)*Math.cos(th);
    p[i*3+1] = r*Math.cos(ph);
    p[i*3+2] = r*Math.sin(ph)*Math.sin(th);
  }
  g.setAttribute('position', new THREE.BufferAttribute(p,3));
  return new THREE.Points(g, new THREE.PointsMaterial({ color, size, sizeAttenuation:false, transparent:true, opacity:.95, depthWrite:false, fog:false }));
}
scene.add(makeStars(600, 70, 95, 1.4, 0xffffff));
scene.add(makeStars(150, 70, 95, 2.4, 0xcfe0ff));

// moon (sphere + glow)
const moonGroup = new THREE.Group();
const moonBall = new THREE.Mesh(new THREE.IcosahedronGeometry(3.2, 1),
  new THREE.MeshBasicMaterial({ color:0xf5f2e0, fog:false }));
moonGroup.add(moonBall);
const moonHalo = new THREE.Mesh(new THREE.IcosahedronGeometry(4.6, 1),
  new THREE.MeshBasicMaterial({ color:0x9fb4e8, transparent:true, opacity:.18, blending:THREE.AdditiveBlending, depthWrite:false, fog:false }));
moonGroup.add(moonHalo);
moonGroup.position.set(-34, 38, -26);
moonGroup.lookAt(0,0,0);
scene.add(moonGroup);

// ---------- Animation ----------
const clock = new THREE.Clock();
const sparkPosAttr = sparkGeo.getAttribute('position');

function tick(){
  requestAnimationFrame(tick);
  const t = clock.getElapsedTime();
  const dt = Math.min(clock.getDelta(), 0.05) || 0.016;

  // flicker light
  const flick = 1 + Math.sin(t*11)*0.12 + Math.sin(t*23+1.7)*0.08 + Math.sin(t*5.3)*0.06;
  fireLight.intensity = 3.2 * flick;
  fireGlow.intensity = 1.0 * flick;
  fireLight.position.set(Math.sin(t*7)*0.08, 1.6 + Math.sin(t*13)*0.05, Math.cos(t*9)*0.08);
  emberMat.color.setHSL(0.045, 1, 0.35 + 0.15*flick);

  // flames
  for (const f of flames){
    const u = f.userData;
    const pulse = 0.75 + 0.25*Math.sin(t*u.sp + u.ph);
    f.scale.set(pulse, 1 + Math.sin(t*u.sp*1.3 + u.ph)*0.25, pulse);
    f.rotation.y = t*rand ? f.rotation.y + 0.02 : 0;
    f.rotation.y = t*1.5 + u.ph;
    f.position.y = 0.35 + u.h/2*f.scale.y + Math.sin(t*u.sp+u.ph)*0.05;
    f.material.opacity = 0.55 + 0.35*pulse;
  }

  // sparks
  for (let i=0;i<SPARKS;i++){
    life[i] -= dt*0.55;
    if (life[i] <= 0){
      life[i] = 1;
      pos[i*3] = rand(-.15,.15);
      pos[i*3+1] = 0.45;
      pos[i*3+2] = rand(-.15,.15);
      vel[i].set(rand(-.25,.25), rand(.9,2.0), rand(-.25,.25));
    }
    vel[i].x += Math.sin(t*3 + i)*0.02;
    pos[i*3]   += vel[i].x*dt;
    pos[i*3+1] += vel[i].y*dt*1.4;
    pos[i*3+2] += vel[i].z*dt;
  }
  sparkPosAttr.needsUpdate = true;

  controls.update();
  renderer.render(scene, camera);
}
tick();

// ---------- Resize ----------
addEventListener('resize', () => {
  camera.aspect = innerWidth/innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>
Reasoning trace (17 tokens)
Write a single HTML file with Three.js scene. Careful with performance and correctness.