GLM 5.3
by Z.aiReasoningClean
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.