Muse Ember
by MetaReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 7.8 s
- Cost
- $0.0022
- Output tokens
- 4,383
- Spent thinking
- 157 tokens
- Speed
- 710 tok/s
- Console errors
- 0
- First token after
- 1.6 s
- First visible text after
- 1.6 s
- Prompt tokens
- 574
- Code size
- 12.5 KB
- Finish reason
- stop
- Served by
- Meta
- Model id
meta/muse-ember- Reasoning sent
{"effort":"minimal"}- 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 · 272 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Campfire in the Forest — Low-Poly Night</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
html,body{width:100%;height:100%;overflow:hidden;background:#070b1a;font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif}
#app{position:fixed;inset:0}
canvas{display:block}
.hud{position:fixed;top:18px;left:18px;z-index:10;color:#fff;pointer-events:none;max-width:340px}
.hud h1{font-size:26px;letter-spacing:.02em;line-height:1.05;text-shadow:0 2px 18px rgba(0,0,0,.8)}
.hud h1 span{color:#ffb347}
.hud p{margin-top:8px;font-size:13px;line-height:1.5;color:rgba(255,255,255,.82);text-shadow:0 1px 10px rgba(0,0,0,.8)}
.badge{display:inline-flex;gap:6px;align-items:center;margin-top:12px;background:rgba(10,14,30,.55);backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:7px 12px;font-size:12px;color:#dbe7ff}
.dot{width:8px;height:8px;border-radius:50%;background:#ffb347;box-shadow:0 0 10px #ff8c1a;animation:pulse 1.6s infinite}
@keyframes pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.4);opacity:.6}}
.controls{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);z-index:10;pointer-events:none;background:rgba(8,11,24,.6);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.13);border-radius:999px;padding:9px 16px;color:#e8efff;font-size:13px;white-space:nowrap;box-shadow:0 8px 30px rgba(0,0,0,.5)}
.controls b{color:#ffb347}
.stats{position:fixed;top:18px;right:18px;z-index:10;display:flex;gap:8px;pointer-events:none}
.stat{background:rgba(8,11,24,.55);backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.12);border-radius:14px;padding:10px 14px;color:#fff;text-align:center;min-width:78px}
.stat strong{font-size:20px;display:block;color:#ffb347}
.stat small{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.65)}
.vignette{position:fixed;inset:0;pointer-events:none;z-index:5;background:radial-gradient(ellipse at center,transparent 52%,rgba(2,4,14,.55) 100%)}
@media(max-width:640px){
.hud h1{font-size:21px}.hud p{display:none}.stats{display:none}.controls{font-size:12px;padding:8px 12px;max-width:92vw;white-space:normal;text-align:center}
}
</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 class="vignette"></div>
<div class="hud">
<h1>🏕️ Campfire<br>in the <span>Forest</span></h1>
<p>A cozy low-poly clearing at night — flickering flames, rising sparks, and a ring of pine trees under the moon.</p>
<div class="badge"><span class="dot"></span> Live • 38 trees • Sparks & Shadows</div>
</div>
<div class="stats">
<div class="stat"><strong id="fps">60</strong><small>FPS</small></div>
<div class="stat"><strong>38</strong><small>Trees</small></div>
<div class="stat"><strong id="temp">24°</strong><small>Fire °C</small></div>
</div>
<div class="controls">🖱️ <b>Drag</b> to orbit • <b>Scroll</b> to zoom • <b>Right-drag</b> to pan</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const container = document.getElementById('app');
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x070b1a);
scene.fog = new THREE.Fog(0x0a1024, 18, 58);
const camera = new THREE.PerspectiveCamera(55, innerWidth/innerHeight, 0.1, 300);
camera.position.set(9, 6, 11);
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.15;
container.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1.2, 0);
controls.enableDamping = true;
controls.dampingFactor = 0.06;
controls.maxPolarAngle = Math.PI * 0.49;
controls.minPolarAngle = Math.PI * 0.15;
controls.minDistance = 4;
controls.maxDistance = 28;
controls.maxTargetRadius = 6;
controls.autoRotate = true;
controls.autoRotateSpeed = 0.6;
controls.addEventListener('start', ()=> controls.autoRotate = false);
// Lights
scene.add(new THREE.AmbientLight(0x334466, 0.7));
const moonLight = new THREE.DirectionalLight(0x8899cc, 0.5);
moonLight.position.set(-18, 24, -10);
moonLight.castShadow = true;
moonLight.shadow.mapSize.set(1024,1024);
scene.add(moonLight);
const fireLight = new THREE.PointLight(0xff7722, 28, 22, 1.6);
fireLight.position.set(0, 1.6, 0);
fireLight.castShadow = true;
fireLight.shadow.mapSize.set(1024,1024);
fireLight.shadow.bias = -0.004;
scene.add(fireLight);
const fireGlow = new THREE.PointLight(0xffaa33, 8, 10, 2);
fireGlow.position.set(0,0.8,0); scene.add(fireGlow);
// Ground
const groundGeo = new THREE.CircleGeometry(55, 48);
const groundMat = new THREE.MeshStandardMaterial({color:0x1e3a24, roughness:1, flatShading:true});
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI/2;
ground.receiveShadow = true;
scene.add(ground);
// subtle clearing patch
const patch = new THREE.Mesh(new THREE.CircleGeometry(5.2, 24), new THREE.MeshStandardMaterial({color:0x3a2a18, roughness:1, flatShading:true}));
patch.rotation.x = -Math.PI/2; patch.position.y = 0.02; patch.receiveShadow = true; scene.add(patch);
// Rocks & logs around fire
const rockMat = new THREE.MeshStandardMaterial({color:0x7a7f8a, roughness:1, flatShading:true});
const logMat = new THREE.MeshStandardMaterial({color:0x5a3a1e, roughness:1, flatShading:true});
const logMat2 = new THREE.MeshStandardMaterial({color:0x6b4423, roughness:1, flatShading:true});
for(let i=0;i<10;i++){
const a = (i/10)*Math.PI*2 + Math.random()*0.3;
const r = 1.55 + Math.random()*0.15;
const rock = new THREE.Mesh(new THREE.DodecahedronGeometry(0.32+Math.random()*0.18,0), rockMat);
rock.position.set(Math.cos(a)*r, 0.18, Math.sin(a)*r);
rock.rotation.set(Math.random()*3,Math.random()*3,Math.random()*3);
rock.castShadow = rock.receiveShadow = true;
scene.add(rock);
}
// scattered rocks
for(let i=0;i<14;i++){
const a=Math.random()*Math.PI*2, r=3+Math.random()*16;
const rock=new THREE.Mesh(new THREE.DodecahedronGeometry(0.25+Math.random()*0.55,0), rockMat);
rock.position.set(Math.cos(a)*r,0.15,Math.sin(a)*r);
rock.rotation.set(Math.random()*3,Math.random()*3,Math.random()*3);
rock.castShadow=rock.receiveShadow=true;
scene.add(rock);
}
// teepee logs + bench logs
for(let i=0;i<6;i++){
const a=(i/6)*Math.PI*2;
const log=new THREE.Mesh(new THREE.CylinderGeometry(0.09,0.11,1.5,7), i%2?logMat:logMat2);
log.position.set(Math.cos(a)*0.35,0.65,Math.sin(a)*0.35);
log.lookAt(0,1.6,0); log.rotateX(Math.PI/2);
log.castShadow=true; scene.add(log);
}
[[-2.2,1.5,0.4],[2.3,-1.2,-0.3],[0.5,2.4,1.2]].forEach(([x,z,ry])=>{
const bench=new THREE.Mesh(new THREE.CylinderGeometry(0.22,0.22,2.2,8), logMat);
bench.rotation.z=Math.PI/2; bench.rotation.y=ry; bench.position.set(x,0.22,z);
bench.castShadow=bench.receiveShadow=true; scene.add(bench);
const log2=bench.clone(); log2.position.y=0.22; log2.position.x+=0.35; scene.add(log2);
});
// Trees (38)
const trunkMat=new THREE.MeshStandardMaterial({color:0x4a2f1a,roughness:1,flatShading:true});
const leafMats=[0x1a4a2e,0x1f5a35,0x245e30,0x2a6b3a].map(c=>new THREE.MeshStandardMaterial({color:c,roughness:1,flatShading:true}));
function makeTree(s){
const g=new THREE.Group();
const trunk=new THREE.Mesh(new THREE.CylinderGeometry(0.16*s,0.24*s,1.2*s,6),trunkMat);
trunk.position.y=0.6*s; trunk.castShadow=true; g.add(trunk);
const mat=leafMats[Math.floor(Math.random()*leafMats.length)];
[[0,2.0,0,1.05,1.6],[0,3.0,0,0.78,1.4],[0,3.85,0,0.5,1.15]].forEach(([x,y,z,r,h])=>{
const cone=new THREE.Mesh(new THREE.ConeGeometry(r*s,h*s,7),mat);
cone.position.set(x,y*s,z); cone.castShadow=true; g.add(cone);
});
return g;
}
let treeCount=0;
for(let i=0;i<38;i++){
const a=Math.random()*Math.PI*2;
const r=7.5+Math.pow(Math.random(),0.8)*26;
const s=0.9+Math.random()*1.4;
const t=makeTree(s);
t.position.set(Math.cos(a)*r,0,Math.sin(a)*r);
t.rotation.y=Math.random()*Math.PI*2;
scene.add(t); treeCount++;
}
// a few closer hero trees
[[ -6, -3,1.3],[6,-5,1.1],[-4,6,1.2],[7,4,0.95]].forEach(([x,z,s])=>{
const t=makeTree(s); t.position.set(x,0,z); scene.add(t); treeCount++;
});
// Moon
const moon=new THREE.Mesh(new THREE.SphereGeometry(2.2,20,20), new THREE.MeshBasicMaterial({color:0xf5f0d0}));
moon.position.set(-22,20,-28); scene.add(moon);
const halo=new THREE.Mesh(new THREE.SphereGeometry(3.2,20,20), new THREE.MeshBasicMaterial({color:0xfff8cc,transparent:true,opacity:0.18}));
halo.position.copy(moon.position); scene.add(halo);
// Stars
const starGeo=new THREE.BufferGeometry();
const starPos=[];
for(let i=0;i<900;i++){
const a=Math.random()*Math.PI*2, e=Math.random()*Math.PI*0.45+0.08, r=90;
starPos.push(Math.cos(a)*Math.cos(e)*r, Math.sin(e)*r, Math.sin(a)*Math.cos(e)*r);
}
starGeo.setAttribute('position', new THREE.Float32BufferAttribute(starPos,3));
scene.add(new THREE.Points(starGeo, new THREE.PointsMaterial({color:0xffffff,size:0.55,sizeAttenuation:true,transparent:true,opacity:0.9})));
// Flames — layered cones
const flames=[];
const flameCols=[0xff5500,0xff8833,0xffcc33,0xfff2a0];
const flameMats=flameCols.map(c=>new THREE.MeshBasicMaterial({color:c,transparent:true,opacity:0.9,side:THREE.DoubleSide}));
for(let layer=0;layer<4;layer++){
const h=1.7-layer*0.32, r=0.62-layer*0.13;
const cone=new THREE.Mesh(new THREE.ConeGeometry(r,h,10,1,true), flameMats[layer]);
cone.position.y=0.45+h/2;
cone.castShadow=false;
scene.add(cone);
flames.push({mesh:cone, baseH:h, baseR:r, phase:Math.random()*10, speed:5+Math.random()*4});
}
// glowing coals
for(let i=0;i<12;i++){
const c=new THREE.Mesh(new THREE.DodecahedronGeometry(0.09+Math.random()*0.08,0), new THREE.MeshStandardMaterial({color:0x331100, emissive:0xff4400, emissiveIntensity:1.2+Math.random(), roughness:1}));
const a=Math.random()*Math.PI*2, r=Math.random()*0.55;
c.position.set(Math.cos(a)*r,0.12,Math.sin(a)*r); scene.add(c);
}
// Sparks particle system
const SPARKS=220;
const sparkGeo=new THREE.BufferGeometry();
const sparkPos=new Float32Array(SPARKS*3);
const sparkData=[];
for(let i=0;i<SPARKS;i++){
sparkData.push({x:(Math.random()-0.5)*0.7, y:Math.random()*3.5, z:(Math.random()-0.5)*0.7, vy:0.6+Math.random()*1.4, vx:(Math.random()-0.5)*0.35, vz:(Math.random()-0.5)*0.35, life:Math.random()});
}
sparkGeo.setAttribute('position', new THREE.BufferAttribute(sparkPos,3));
const sparks=new THREE.Points(sparkGeo, new THREE.PointsMaterial({color:0xffbb44,size:0.09,transparent:true,opacity:0.95,blending:THREE.AdditiveBlending,depthWrite:false}));
scene.add(sparks);
const clock=new THREE.Clock();
let frames=0, lastFps=performance.now();
function animate(){
requestAnimationFrame(animate);
const t=clock.getElapsedTime();
// flicker
const flick = 0.88 + Math.sin(t*11)*0.07 + Math.sin(t*23+1)*0.05 + Math.random()*0.06;
fireLight.intensity = 28 * flick;
fireGlow.intensity = 8 * flick;
flames.forEach(f=>{
const w = 1 + Math.sin(t*f.speed + f.phase)*0.14 + Math.sin(t*17+f.phase)*0.06;
f.mesh.scale.set(1/Math.sqrt(w), w, 1/Math.sqrt(w));
f.mesh.rotation.y = t*0.4 + f.phase;
f.mesh.position.x = Math.sin(t*3+f.phase)*0.05;
f.mesh.position.z = Math.cos(t*2.6+f.phase)*0.05;
});
// sparks
for(let i=0;i<SPARKS;i++){
const s=sparkData[i];
s.y+=s.vy*0.016; s.x+=s.vx*0.016+Math.sin(t*3+i)*0.002; s.z+=s.vz*0.016;
s.life-=0.0035;
if(s.y>3.8||s.life<=0){ s.y=0.5+Math.random()*0.3; s.x=(Math.random()-0.5)*0.7; s.z=(Math.random()-0.5)*0.7; s.life=1; }
sparkPos[i*3]=s.x; sparkPos[i*3+1]=s.y; sparkPos[i*3+2]=s.z;
}
sparkGeo.attributes.position.needsUpdate=true;
sparks.material.opacity = 0.75 + flick*0.25;
controls.update();
renderer.render(scene,camera);
frames++;
const now=performance.now();
if(now-lastFps>500){
const fps=Math.round(frames*1000/(now-lastFps));
document.getElementById('fps').textContent=fps;
document.getElementById('temp').textContent=Math.round(18+flick*10)+'°';
frames=0; lastFps=now;
}
}
animate();
addEventListener('resize',()=>{
camera.aspect=innerWidth/innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth,innerHeight);
});
</script>
</body>
</html>