gpt-oss-120b
by OpenAIReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 10.9 s
- Cost
- $0.0007
- Output tokens
- 2,836
- Spent thinking
- 570 tokens
- Speed
- 270.4 tok/s
- Console errors
- 0
- First token after
- 444 ms
- First visible text after
- 2.2 s
- Prompt tokens
- 619
- Code size
- 7.7 KB
- Finish reason
- stop
- Served by
- Crusoe
- Model id
openai/gpt-oss-120b- Reasoning sent
{"effort":"medium"}- Max output
- 64,000 tokens
- Generated
- Nov 11, 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 · 244 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Low‑Poly Campfire Scene</title>
<style>
body{margin:0;overflow:hidden;background:#000;}
#overlay{
position:absolute;top:0;left:0;width:100%;height:100%;
display:flex;align-items:center;justify-content:center;
color:#fff;font-family:sans-serif;font-size:1.2rem;
pointer-events:none;
}
</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="overlay">Click or press any key to start</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// ----- Basic Setup -----
const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x0d0b1a, 0.022);
const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 200);
camera.position.set(0, 8, 15);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(devicePixelRatio);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// ----- Controls -----
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.minDistance = 5;
controls.maxDistance = 40;
controls.minPolarAngle = Math.PI / 6; // prevent looking below ground
controls.maxPolarAngle = Math.PI / 2.2; // limit high angle
controls.target.set(0, 1, 0);
// ----- Ground -----
const groundGeo = new THREE.PlaneGeometry(200, 200);
const groundMat = new THREE.MeshStandardMaterial({ color: 0x1b1b1e, roughness: 1, metalness: 0 });
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI/2;
ground.receiveShadow = true;
scene.add(ground);
// ----- Low‑Poly Rocks -----
function addRock(x, z) {
const geo = new THREE.DodecahedronGeometry(0.5 + Math.random()*0.5, 0);
const mat = new THREE.MeshStandardMaterial({ color: 0x555555, flatShading:true });
const rock = new THREE.Mesh(geo, mat);
rock.position.set(x, 0.25, z);
rock.castShadow = true;
rock.receiveShadow = true;
scene.add(rock);
}
for (let i = 0; i < 12; i++) {
const angle = Math.random()*Math.PI*2;
const radius = 3 + Math.random()*4;
addRock(Math.cos(angle)*radius, Math.sin(angle)*radius);
}
// ----- Logs -----
function createLog() {
const geo = new THREE.CylinderGeometry(0.12,0.12,2,6);
const mat = new THREE.MeshStandardMaterial({ color: 0x8b5a2b, flatShading:true });
const log = new THREE.Mesh(geo, mat);
log.castShadow = true;
log.receiveShadow = true;
return log;
}
const log1 = createLog();
log1.rotation.z = Math.PI/4;
log1.position.set(0.3,0.6,0);
scene.add(log1);
const log2 = createLog();
log2.rotation.z = -Math.PI/4;
log2.position.set(-0.3,0.6,0);
scene.add(log2);
const log3 = createLog();
log3.rotation.z = 0;
log3.position.set(0,0.6,0.3);
scene.add(log3);
const log4 = createLog();
log4.rotation.z = Math.PI;
log4.position.set(0,0.6,-0.3);
scene.add(log4);
// ----- Campfire Flames -----
const flameGeo = new THREE.SphereGeometry(0.4, 5,5);
const flameMat = new THREE.MeshBasicMaterial({ color: 0xffa500, transparent:true, opacity:0.8, depthWrite:false });
const flame = new THREE.Mesh(flameGeo, flameMat);
flame.position.set(0,0.9,0);
scene.add(flame);
// ----- Light -----
const fireLight = new THREE.PointLight(0xffaa33, 2, 12, 2);
fireLight.position.set(0,1.2,0);
fireLight.castShadow = true;
fireLight.shadow.mapSize.width = 256;
fireLight.shadow.mapSize.height = 256;
scene.add(fireLight);
// ----- Sparks Particle System -----
const maxSparks = 100;
const sparkPos = new Float32Array(maxSparks*3);
const sparkVel = new Float32Array(maxSparks*3);
const sparkLife = new Float32Array(maxSparks);
const sparkGeo = new THREE.BufferGeometry();
sparkGeo.setAttribute('position', new THREE.BufferAttribute(sparkPos,3));
const sparkMat = new THREE.PointsMaterial({ color:0xffaa33, size:0.07, transparent:true, opacity:0.9 });
const sparks = new THREE.Points(sparkGeo, sparkMat);
scene.add(sparks);
function spawnSpark(i) {
sparkPos[i*3] = (Math.random()-0.5)*0.3;
sparkPos[i*3+1] = 0.7;
sparkPos[i*3+2] = (Math.random()-0.5)*0.3;
const speed = 0.02 + Math.random()*0.02;
sparkVel[i*3] = (Math.random()-0.5)*speed;
sparkVel[i*3+1] = 0.03 + Math.random()*0.03;
sparkVel[i*3+2] = (Math.random()-0.5)*speed;
sparkLife[i] = 1.0;
}
for(let i=0;i<maxSparks;i++) spawnSpark(i);
// ----- Trees -----
function addTree(x,z) {
const trunkGeo = new THREE.CylinderGeometry(0.12,0.12,1,6);
const trunkMat = new THREE.MeshStandardMaterial({color:0x4b332e, flatShading:true});
const trunk = new THREE.Mesh(trunkGeo, trunkMat);
trunk.position.set(x,0.5,z);
trunk.castShadow = true;
trunk.receiveShadow = true;
scene.add(trunk);
const foliageGeo = new THREE.ConeGeometry(0.8,2,5);
const foliageMat = new THREE.MeshStandardMaterial({color:0x2a5d29, flatShading:true});
const foliage = new THREE.Mesh(foliageGeo, foliageMat);
foliage.position.set(x,1.8,z);
foliage.castShadow = true;
foliage.receiveShadow = true;
scene.add(foliage);
}
function randPos(radius) {
const a = Math.random()*Math.PI*2;
const r = radius*Math.sqrt(Math.random());
return [Math.cos(a)*r, Math.sin(a)*r];
}
for(let i=0; i<30; i++) {
const [x,z] = randPos(20);
// keep a clear area (radius ~5) around fire
if (Math.hypot(x,z) < 5) { i--; continue; }
addTree(x,z);
}
// ----- Night Sky -----
function addStars() {
const starGeo = new THREE.BufferGeometry();
const starCount = 400;
const positions = new Float32Array(starCount*3);
for(let i=0;i<starCount;i++) {
const theta = Math.random()*2*Math.PI;
const phi = Math.acos(2*Math.random()-1);
const r = 80;
positions[i*3] = r*Math.sin(phi)*Math.cos(theta);
positions[i*3+1] = r*Math.cos(phi)+20; // raise a bit
positions[i*3+2] = r*Math.sin(phi)*Math.sin(theta);
}
starGeo.setAttribute('position', new THREE.BufferAttribute(positions,3));
const starMat = new THREE.PointsMaterial({color:0xffffff, size:0.5});
const stars = new THREE.Points(starGeo, starMat);
scene.add(stars);
}
addStars();
const moonGeo = new THREE.SphereGeometry(2,16,16);
const moonMat = new THREE.MeshStandardMaterial({color:0xe0e0e0, emissive:0xaaaaaa, emissiveIntensity:0.2, flatShading:true});
const moon = new THREE.Mesh(moonGeo, moonMat);
moon.position.set(-30,25,-20);
scene.add(moon);
// ----- Animation -----
let clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const dt = clock.getDelta();
// flame flicker
const scale = 0.9 + Math.random()*0.2;
flame.scale.set(scale,scale,scale);
fireLight.intensity = 1.8 + Math.random()*0.4;
fireLight.distance = 10 + Math.random()*2;
// sparks update
for(let i=0;i<maxSparks;i++) {
if (sparkLife[i] > 0) {
sparkPos[i*3] += sparkVel[i*3];
sparkPos[i*3+1] += sparkVel[i*3+1];
sparkPos[i*3+2] += sparkVel[i*3+2];
sparkVel[i*3+1] += 0.001; // slight upward acceleration
sparkLife[i] -= dt;
if (sparkLife[i] <= 0) spawnSpark(i);
}
}
sparkGeo.attributes.position.needsUpdate = true;
controls.update();
renderer.render(scene,camera);
}
animate();
// ----- Resize -----
window.addEventListener('resize',()=>{
camera.aspect = innerWidth/innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth,innerHeight);
});
// ----- Interaction hint removal -----
function startDemo(){
document.getElementById('overlay').style.display='none';
window.removeEventListener('keydown',startDemo);
window.removeEventListener('click',startDemo);
}
window.addEventListener('keydown',startDemo);
window.addEventListener('click',startDemo);
</script>
</body>
</html>Reasoning trace (570 tokens)
We need to output a single HTML file with import map loading three and addons via CDNs. Then use ES modules. We'll need to include importmap script, then a module script that imports from 'three', 'three/addons/controls/OrbitControls.js', possibly also 'three/addons/objects/PointsMaterial' etc. We'll construct scene, camera, renderer. We must create low-poly objects: for simplicity use BoxGeometry for logs, Icosahedron for rocks, Cone for trees? Could use simple geometries to mimic low-poly style. For trees: cylinder trunk and cone foliage, but low poly can be simple cone geometries repeated. Campfire: logs arranged in a circle; flames: use a simple particle system with sprites or use a torus with custom shader? Simpler: create a small sphere with emissive orange material and animate scale/size/spread to simulate flicker; also use point light with intensity flicker. Sparks: use Points with random positions moving upward and fading. Stars: create a large sphere with star texture? Could generate points in sphere. Moon: a sphere with emissive material placed. Fog: use scene.fog. OrbitControls: restrict minPolarAngle and maxPolarAngle to stay above ground (e.g., 0 to Math.PI/2.5). Make renderer fill window, with shadow map enabled. All assets must be procedural; no external textures allowed unless can load from CDN? Not allowed unless via importmap only. So use basic materials with colors. We need to ensure it's visible on first paint: show scene immediately. Need to write code within a <script type="module"> after import map. Add event listener for resize. Implement animate loop: update flame: tween light intensity and sphere scale. Update sparks positions; remove those that go high. Initialize particle system: create array of positions for sparks and lifetimes; use BufferGeometry with dynamic positions. Will need to compute random positions for trees while avoiding central area. Let's write code. Potential issues: three version 0.170.0. Use import from 'three', 'three/addons/controls/OrbitControls.js'. We'll need to enable shadows on renderer, light, and objects. Let's code. Check for low-poly: set material flatShading true. Now produce final answer: one code block with html.