Gemma 4 31B
by Googlereasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 46.5 s
- Cost
- $0.0012
- Output tokens
- 3,257
- Spent thinking
- 0 tokens
- Speed
- 71 tok/s
- Console errors
- 0
- First token after
- 663 ms
- First visible text after
- 663 ms
- Prompt tokens
- 610
- Code size
- 10.2 KB
- Finish reason
- stop
- Served by
- CoreWeave
- Model id
google/gemma-4-31b-it- Reasoning sent
model default- Max output
- 16,384 tokens
- Generated
- Nov 13, 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 · 278 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Low Poly Campfire Night</title>
<style>
body { margin: 0; overflow: hidden; background-color: #050508; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
canvas { display: block; }
#ui {
position: absolute;
top: 20px;
left: 20px;
color: #ddd;
pointer-events: none;
text-shadow: 1px 1px 2px black;
}
.hint {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255,255,255,0.6);
font-size: 14px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="ui">
<h1 style="margin:0; font-size: 24px;">Midnight Clearing</h1>
<p style="margin:5px 0;">Low-Poly Ambient Scene</p>
</div>
<div class="hint">Drag to rotate • Scroll to zoom</div>
<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>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// --- Setup ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x020205);
scene.fog = new THREE.FogExp2(0x020205, 0.07);
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(8, 5, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.maxPolarAngle = Math.PI / 2.1; // Stop camera from going underground
controls.minDistance = 4;
controls.maxDistance = 25;
// --- Lighting ---
const ambientLight = new THREE.AmbientLight(0x101020, 0.5);
scene.add(ambientLight);
const moonLight = new THREE.DirectionalLight(0x445577, 0.3);
moonLight.position.set(10, 20, 10);
scene.add(moonLight);
// Fire Light
const fireLight = new THREE.PointLight(0xff6600, 4, 15);
fireLight.position.set(0, 0.5, 0);
fireLight.castShadow = true;
fireLight.shadow.mapSize.width = 512;
fireLight.shadow.mapSize.height = 512;
scene.add(fireLight);
// --- Environment ---
// Ground
const groundGeo = new THREE.PlaneGeometry(50, 50);
const groundMat = new THREE.MeshStandardMaterial({ color: 0x1a2a1a, roughness: 0.8 });
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Low Poly Trees
function createTree(x, z) {
const group = new THREE.Group();
// Trunk
const trunkGeo = new THREE.CylinderGeometry(0.2, 0.3, 1.5, 6);
const trunkMat = new THREE.MeshStandardMaterial({ color: 0x3d2817 });
const trunk = new THREE.Mesh(trunkGeo, trunkMat);
trunk.position.y = 0.75;
trunk.castShadow = true;
trunk.receiveShadow = true;
group.add(trunk);
// Leaves (Conical)
const leavesMat = new THREE.MeshStandardMaterial({ color: 0x1a3a1a, flatShading: true });
for(let i=0; i<3; i++) {
const leavesGeo = new THREE.ConeGeometry(1.2 - i*0.3, 1.5, 6);
const leaves = new THREE.Mesh(leavesGeo, leavesMat);
leaves.position.y = 1.5 + i * 0.8;
leaves.castShadow = true;
leaves.receiveShadow = true;
group.add(leaves);
}
group.position.set(x, 0, z);
scene.add(group);
}
// Distribute trees randomly, avoiding the center
for(let i=0; i<40; i++) {
const angle = Math.random() * Math.PI * 2;
const dist = 6 + Math.random() * 15;
createTree(Math.cos(angle) * dist, Math.sin(angle) * dist);
}
// Rocks and Logs
function createRock(x, z) {
const geo = new THREE.DodecahedronGeometry(0.3 + Math.random() * 0.4, 0);
const mat = new THREE.MeshStandardMaterial({ color: 0x555555 });
const rock = new THREE.Mesh(geo, mat);
rock.position.set(x, 0.2, z);
rock.rotation.set(Math.random(), Math.random(), Math.random());
rock.castShadow = true;
rock.receiveShadow = true;
scene.add(rock);
}
function createLog(x, z) {
const geo = new THREE.CylinderGeometry(0.15, 0.15, 1.2, 6);
const mat = new THREE.MeshStandardMaterial({ color: 0x4b3621 });
const log = new THREE.Mesh(geo, mat);
log.position.set(x, 0.15, z);
log.rotation.set(Math.random() * 0.5, Math.random() * Math.PI, Math.random() * 0.5);
log.castShadow = true;
log.receiveShadow = true;
scene.add(log);
}
// Scatter debris around the fire
for(let i=0; i<8; i++) {
const angle = Math.random() * Math.PI * 2;
const dist = 1.5 + Math.random() * 2;
createRock(Math.cos(angle)*dist, Math.sin(angle)*dist);
createLog(Math.cos(angle+1)*dist, Math.sin(angle+1)*dist);
}
// --- Campfire ---
// Firewood logs in the center
const woodGroup = new THREE.Group();
for(let i=0; i<4; i++) {
const log = new THREE.Mesh(
new THREE.CylinderGeometry(0.1, 0.1, 0.8, 6),
new THREE.MeshStandardMaterial({ color: 0x4b3621 })
);
log.rotation.set(0, 0, (i * Math.PI/2) + 0.5);
log.position.y = 0.1;
log.castShadow = true;
woodGroup.add(log);
}
scene.add(woodGroup);
// Animated Flame
const flameGeo = new THREE.ConeGeometry(0.3, 0.8, 6);
const flameMat = new THREE.MeshStandardMaterial({
color: 0xff4400,
emissive: 0xff2200,
emissiveIntensity: 2
});
const flame = new THREE.Mesh(flameGeo, flameMat);
flame.position.y = 0.4;
scene.add(flame);
// Sparks Particle System
const sparkCount = 20;
const sparksGeo = new THREE.BufferGeometry();
const sparksPos = new Float32Array(sparkCount * 3);
const sparksVel = [];
for(let i=0; i<sparkCount; i++) {
sparksPos[i*3] = 0;
sparksPos[i*3+1] = 0.5;
sparksPos[i*3+2] = 0;
sparksVel.push(new THREE.Vector3(
(Math.random() - 0.5) * 0.02,
0.05 + Math.random() * 0.05,
(Math.random() - 0.5) * 0.02
));
}
sparksGeo.setAttribute('position', new THREE.BufferAttribute(sparksPos, 3));
const sparksMat = new THREE.PointsMaterial({ color: 0xffaa00, size: 0.05 });
const sparks = new THREE.Points(sparksGeo, sparksMat);
scene.add(sparks);
// --- Sky/Stars ---
const starGeo = new THREE.BufferGeometry();
const starPos = new Float32Array(1000 * 3);
for(let i=0; i<1000 * 3; i++) {
starPos[i] = (Math.random() - 0.5) * 100;
}
starGeo.setAttribute('position', new THREE.BufferAttribute(starPos, 3));
const starMat = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const starField = new THREE.Points(starGeo, starMat);
scene.add(starField);
const moonGeo = new THREE.SphereGeometry(0.5, 8, 8);
const moonMat = new THREE.MeshStandardMaterial({ color: 0xeeeeee, emissive: 0xaaaaaa });
const moon = new THREE.Mesh(moonGeo, moonMat);
moon.position.set(20, 20, -20);
scene.add(moon);
// --- Animation loop ---
let time = 0;
function animate() {
time += 0.05;
requestAnimationFrame(animate);
// Flicker fire light
fireLight.intensity = 3 + Math.sin(time * 4) * 1 + Math.random() * 0.5;
// Animate flame size/tilt
flame.scale.set(
1 + Math.sin(time * 5) * 0.1,
1 + Math.cos(time * 6) * 0.2,
1 + Math.sin(time * 5) * 0.1
);
flame.rotation.z = Math.sin(time * 3) * 0.1;
// Animate sparks
const positions = sparks.geometry.attributes.position.array;
for(let i=0; i<sparkCount; i++) {
positions[i*3] += sparksVel[i].x;
positions[i*3+1] += sparksVel[i].y;
positions[i*3+2] += sparksVel[i].z;
// Reset spark if it goes too high or falls
if(positions[i*3+1] > 3 || Math.random() > 0.98) {
positions[i*3] = 0;
positions[i*3+1] = 0.5;
positions[i*3+2] = 0;
sparksVel[i].set(
(Math.random() - 0.5) * 0.02,
0.05 + Math.random() * 0.05,
(Math.random() - 0.5) * 0.02
);
}
}
sparks.geometry.attributes.position.needsUpdate = true;
controls.update();
renderer.render(scene, camera);
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate();
</script>
</body>
</html>