qwen3.7-plus Code
Model-specific source generated from the shared prompt shown on the gallery page. The prompt itself is intentionally not duplicated here.

JavaScript
src/main.js
1import './styles.css';2import * as THREE from 'three';3 4const app = document.getElementById('app');5 6const scene = new THREE.Scene();7 8const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);9camera.position.set(0, 8, 20);10camera.lookAt(0, 0, 0);11 12const renderer = new THREE.WebGLRenderer({ antialias: true });13renderer.setSize(window.innerWidth, window.innerHeight);14renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));15renderer.setClearColor(0x0a1628);16app.appendChild(renderer.domElement);17 18function createSkyGradient() {19 const canvas = document.createElement('canvas');20 canvas.width = 2;21 canvas.height = 512;22 const ctx = canvas.getContext('2d');23 const gradient = ctx.createLinearGradient(0, 0, 0, 512);24 gradient.addColorStop(0, '#0a0e1a');25 gradient.addColorStop(0.3, '#0f1e3d');26 gradient.addColorStop(0.5, '#1a3a5c');27 gradient.addColorStop(0.7, '#2a5a7a');28 gradient.addColorStop(1.0, '#3a7a9a');29 ctx.fillStyle = gradient;30 ctx.fillRect(0, 0, 2, 512);31 const texture = new THREE.CanvasTexture(canvas);32 texture.magFilter = THREE.LinearFilter;33 return texture;34}35 36const skyTexture = createSkyGradient();37scene.background = skyTexture;38 39const ambientLight = new THREE.AmbientLight(0x3a5a7a, 0.6);40scene.add(ambientLight);41 42const dirLight = new THREE.DirectionalLight(0xffeedd, 1.2);43dirLight.position.set(5, 10, 5);44scene.add(dirLight);45 46const oceanVertexShader = /* glsl */ `47 uniform float uTime;48 uniform float uWaveHeight;49 uniform float uWaveSpeed;50 51 varying vec3 vWorldPosition;52 varying vec3 vNormal;53 varying float vElevation;54 55 vec3 gerstnerWave(vec2 dir, float steepness, float wavelength, vec2 pos, float speed) {56 float k = 2.0 * 3.14159265 / wavelength;57 float c = sqrt(9.8 / k);58 vec2 d = normalize(dir);59 float f = k * (dot(d, pos) - c * speed * uTime);60 float a = steepness / k;61 62 return vec3(63 d.x * (a * cos(f)),64 a * sin(f),65 d.y * (a * cos(f))66 );67 }68 69 void main() {70 vec3 pos = position;71 float speed = uWaveSpeed;72 float height = uWaveHeight;73 74 vec3 wave1 = gerstnerWave(vec2(1.0, 0.3), 0.25 * height, 10.0, pos.xz, speed);75 vec3 wave2 = gerstnerWave(vec2(0.5, 1.0), 0.2 * height, 7.0, pos.xz, speed * 1.1);76 vec3 wave3 = gerstnerWave(vec2(-0.3, 0.7), 0.15 * height, 5.0, pos.xz, speed * 0.9);77 vec3 wave4 = gerstnerWave(vec2(0.8, -0.5), 0.1 * height, 3.5, pos.xz, speed * 1.3);78 vec3 wave5 = gerstnerWave(vec2(-0.6, -0.3), 0.08 * height, 2.5, pos.xz, speed * 1.5);79 80 vec3 displacement = wave1 + wave2 + wave3 + wave4 + wave5;81 pos += displacement;82 83 vElevation = displacement.y;84 vWorldPosition = (modelMatrix * vec4(pos, 1.0)).xyz;85 86 float eps = 0.01;87 vec3 posT = position + vec3(eps, 0.0, 0.0);88 vec3 posB = position + vec3(0.0, 0.0, eps);89 90 vec3 dT = gerstnerWave(vec2(1.0, 0.3), 0.25*height, 10.0, posT.xz, speed)91 + gerstnerWave(vec2(0.5, 1.0), 0.2*height, 7.0, posT.xz, speed*1.1)92 + gerstnerWave(vec2(-0.3, 0.7), 0.15*height, 5.0, posT.xz, speed*0.9)93 + gerstnerWave(vec2(0.8, -0.5), 0.1*height, 3.5, posT.xz, speed*1.3)94 + gerstnerWave(vec2(-0.6, -0.3), 0.08*height, 2.5, posT.xz, speed*1.5);95 posT += dT;96 97 vec3 dB = gerstnerWave(vec2(1.0, 0.3), 0.25*height, 10.0, posB.xz, speed)98 + gerstnerWave(vec2(0.5, 1.0), 0.2*height, 7.0, posB.xz, speed*1.1)99 + gerstnerWave(vec2(-0.3, 0.7), 0.15*height, 5.0, posB.xz, speed*0.9)100 + gerstnerWave(vec2(0.8, -0.5), 0.1*height, 3.5, posB.xz, speed*1.3)101 + gerstnerWave(vec2(-0.6, -0.3), 0.08*height, 2.5, posB.xz, speed*1.5);102 posB += dB;103 104 vec3 tangent = normalize(posT - pos);105 vec3 bitangent = normalize(posB - pos);106 vNormal = normalize(cross(bitangent, tangent));107 108 gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);109 }110`;111 112const oceanFragmentShader = /* glsl */ `113 uniform vec3 uDeepColor;114 uniform vec3 uShallowColor;115 uniform vec3 uFoamColor;116 uniform float uFoamThreshold;117 118 varying vec3 vWorldPosition;119 varying vec3 vNormal;120 varying float vElevation;121 122 void main() {123 vec3 lightDir = normalize(vec3(0.5, 0.8, 0.3));124 vec3 viewDir = normalize(cameraPosition - vWorldPosition);125 vec3 halfDir = normalize(lightDir + viewDir);126 127 float NdotL = max(dot(vNormal, lightDir), 0.0);128 float NdotH = max(dot(vNormal, halfDir), 0.0);129 float specular = pow(NdotH, 128.0);130 131 float fresnel = pow(1.0 - max(dot(vNormal, viewDir), 0.0), 3.0);132 133 float depthFactor = smoothstep(-1.5, 1.5, vElevation);134 vec3 waterColor = mix(uDeepColor, uShallowColor, depthFactor);135 136 float foam = smoothstep(uFoamThreshold, uFoamThreshold + 0.3, vElevation);137 foam *= 0.6;138 139 vec3 skyReflect = mix(vec3(0.1, 0.2, 0.35), vec3(0.3, 0.5, 0.7), fresnel);140 vec3 color = mix(waterColor, skyReflect, fresnel * 0.4);141 142 color += NdotL * 0.3 * uShallowColor;143 color += specular * vec3(1.0, 0.95, 0.8) * 0.8;144 color = mix(color, uFoamColor, foam);145 146 float fogFactor = smoothstep(20.0, 80.0, length(vWorldPosition - cameraPosition));147 vec3 fogColor = vec3(0.1, 0.18, 0.28);148 color = mix(color, fogColor, fogFactor);149 150 gl_FragColor = vec4(color, 0.95);151 }152`;153 154const oceanParams = {155 waveHeight: 1.0,156 waveSpeed: 1.0,157};158 159const oceanGeometry = new THREE.PlaneGeometry(100, 100, 256, 256);160oceanGeometry.rotateX(-Math.PI / 2);161 162const oceanMaterial = new THREE.ShaderMaterial({163 vertexShader: oceanVertexShader,164 fragmentShader: oceanFragmentShader,165 uniforms: {166 uTime: { value: 0 },167 uWaveHeight: { value: oceanParams.waveHeight },168 uWaveSpeed: { value: oceanParams.waveSpeed },169 uDeepColor: { value: new THREE.Color(0x021a2b) },170 uShallowColor: { value: new THREE.Color(0x1a6a8a) },171 uFoamColor: { value: new THREE.Color(0xd8eaf4) },172 uFoamThreshold: { value: 0.8 },173 },174 transparent: true,175 side: THREE.DoubleSide,176});177 178const ocean = new THREE.Mesh(oceanGeometry, oceanMaterial);179scene.add(ocean);180 181const uiOverlay = document.createElement('div');182uiOverlay.id = 'ui-overlay';183 184const fpsCounter = document.createElement('div');185fpsCounter.id = 'fps-counter';186fpsCounter.textContent = '-- fps';187uiOverlay.appendChild(fpsCounter);188 189const label = document.createElement('div');190label.id = 'label-identity';191label.textContent = 'model run';192uiOverlay.appendChild(label);193 194const controls = document.createElement('div');195controls.id = 'controls';196 197const title = document.createElement('h3');198title.textContent = 'Ocean Controls';199controls.appendChild(title);200 201function createSlider(labelText, min, max, step, initial, onChange) {202 const row = document.createElement('div');203 row.className = 'control-row';204 205 const lbl = document.createElement('label');206 lbl.textContent = labelText;207 row.appendChild(lbl);208 209 const slider = document.createElement('input');210 slider.type = 'range';211 slider.min = min;212 slider.max = max;213 slider.step = step;214 slider.value = initial;215 row.appendChild(slider);216 217 const val = document.createElement('span');218 val.className = 'value';219 val.textContent = parseFloat(initial).toFixed(1);220 row.appendChild(val);221 222 slider.addEventListener('input', () => {223 const v = parseFloat(slider.value);224 val.textContent = v.toFixed(1);225 onChange(v);226 });227 228 return row;229}230 231controls.appendChild(232 createSlider('Wave Height', 0.1, 3.0, 0.1, oceanParams.waveHeight, (v) => {233 oceanParams.waveHeight = v;234 oceanMaterial.uniforms.uWaveHeight.value = v;235 })236);237 238controls.appendChild(239 createSlider('Wave Speed', 0.1, 3.0, 0.1, oceanParams.waveSpeed, (v) => {240 oceanParams.waveSpeed = v;241 oceanMaterial.uniforms.uWaveSpeed.value = v;242 })243);244 245const pauseBtn = document.createElement('button');246pauseBtn.id = 'btn-pause';247pauseBtn.textContent = 'Pause';248let paused = false;249pauseBtn.addEventListener('click', () => {250 paused = !paused;251 pauseBtn.textContent = paused ? 'Resume' : 'Pause';252});253controls.appendChild(pauseBtn);254 255uiOverlay.appendChild(controls);256document.body.appendChild(uiOverlay);257 258let elapsed = 0;259let lastTime = performance.now();260let frameCount = 0;261let fpsTime = 0;262 263function animate() {264 requestAnimationFrame(animate);265 266 const now = performance.now();267 const delta = (now - lastTime) / 1000;268 lastTime = now;269 270 frameCount++;271 fpsTime += delta;272 if (fpsTime >= 1.0) {273 fpsCounter.textContent = Math.round(frameCount / fpsTime) + ' fps';274 frameCount = 0;275 fpsTime = 0;276 }277 278 if (!paused) {279 elapsed += delta;280 oceanMaterial.uniforms.uTime.value = elapsed;281 }282 283 camera.position.x = Math.sin(elapsed * 0.05) * 2;284 camera.position.y = 8 + Math.sin(elapsed * 0.1) * 0.5;285 camera.lookAt(0, 0, 0);286 287 renderer.render(scene, camera);288}289 290animate();291 292window.addEventListener('resize', () => {293 camera.aspect = window.innerWidth / window.innerHeight;294 camera.updateProjectionMatrix();295 renderer.setSize(window.innerWidth, window.innerHeight);296});297
CSS
src/styles.css
1* {2 box-sizing: border-box;3}4 5html,6body,7#app {8 width: 100%;9 height: 100%;10 margin: 0;11}12 13body {14 font-family: system-ui, sans-serif;15 overflow: hidden;16 background: #0a1628;17}18 19canvas {20 display: block;21}22 23#ui-overlay {24 position: fixed;25 top: 0;26 left: 0;27 width: 100%;28 height: 100%;29 pointer-events: none;30 z-index: 10;31}32 33#controls {34 position: absolute;35 bottom: 20px;36 left: 20px;37 background: rgba(10, 22, 40, 0.85);38 backdrop-filter: blur(8px);39 border: 1px solid rgba(100, 180, 255, 0.2);40 border-radius: 12px;41 padding: 16px 20px;42 pointer-events: auto;43 color: #c8ddf0;44 min-width: 240px;45 max-width: 320px;46}47 48#controls h3 {49 margin: 0 0 12px 0;50 font-size: 13px;51 text-transform: uppercase;52 letter-spacing: 1px;53 color: rgba(100, 200, 255, 0.8);54}55 56.control-row {57 display: flex;58 align-items: center;59 justify-content: space-between;60 margin-bottom: 10px;61}62 63.control-row label {64 font-size: 12px;65 color: #8ab4d8;66 flex-shrink: 0;67 width: 80px;68}69 70.control-row input[type="range"] {71 flex: 1;72 margin: 0 8px;73 accent-color: #4aa8e0;74 height: 4px;75}76 77.control-row .value {78 font-size: 11px;79 color: #6a9ec0;80 width: 32px;81 text-align: right;82}83 84#btn-pause {85 width: 100%;86 padding: 8px 12px;87 margin-top: 4px;88 background: rgba(74, 168, 224, 0.2);89 border: 1px solid rgba(74, 168, 224, 0.4);90 border-radius: 6px;91 color: #a0d8f0;92 font-size: 12px;93 cursor: pointer;94 text-transform: uppercase;95 letter-spacing: 1px;96 transition: background 0.2s;97}98 99#btn-pause:hover {100 background: rgba(74, 168, 224, 0.35);101}102 103#label-identity {104 position: absolute;105 top: 16px;106 right: 16px;107 background: rgba(10, 22, 40, 0.7);108 backdrop-filter: blur(6px);109 border: 1px solid rgba(100, 180, 255, 0.15);110 border-radius: 8px;111 padding: 6px 12px;112 pointer-events: auto;113 color: rgba(160, 210, 240, 0.7);114 font-size: 11px;115 letter-spacing: 0.5px;116}117 118#fps-counter {119 position: absolute;120 top: 16px;121 left: 16px;122 color: rgba(160, 210, 240, 0.5);123 font-size: 11px;124 font-family: monospace;125 pointer-events: none;126}127 128@media (max-width: 600px) {129 #controls {130 bottom: 12px;131 left: 12px;132 right: 12px;133 min-width: unset;134 max-width: unset;135 padding: 12px 14px;136 }137 138 #label-identity {139 top: 10px;140 right: 10px;141 font-size: 10px;142 }143}144
Package
package.json
1{2 "name": "ocean-ui-model-run",3 "version": "0.1.0",4 "private": true,5 "type": "module",6 "scripts": {7 "dev": "vite --host 127.0.0.1",8 "build": "vite build",9 "preview": "vite preview --host 127.0.0.1"10 },11 "dependencies": {12 "three": "^0.171.0",13 "vite": "^6.0.7"14 },15 "devDependencies": {}16}17