Quick Summary

  • No reference photo? Use Neural4D Image Generator to create one from a text prompt before starting

  • Generate a production-ready 3D model in Neural4D Image to 3D, export as GLB with PBR textures in 2 minutes or more

  • Paste the full Gemini prompt from this article to get a complete working HTML + JS file in one shot

  • Put all files in one folder and run python3 -m http.server 8080 to preview locally; GLB requires HTTP, not file://

  • If the model fails to load, screenshot the browser console error and send it back to Gemini to fix

Table of Contents

Format note: GLTF is the JSON version that references external texture files. GLB is the self-contained binary bundle. Neural4D exports GLB with all PBR maps embedded, so there are no external texture paths to break and no manual re-packing step before upload.

💡 Angle matters: A top-down or 3/4 view gives the Direct3D-S2 engine reference points to calculate accurate depth on all sides. A flat front-facing photo tends to produce a correct front but a guessed, flatter back.

Generate Your 3D Asset in Minutes

Upload a photo, configure textures, export a web-ready GLB. No 3D modeling experience required.

Free plan includes 50 credits per week. No credit card required.

Gemini prompt (from the Neural4D tutorial):

You are a senior front-end development engineer and WebGL (Three.js) expert. Please help me create a single-page interactive 3D birthday cake webpage (or include a standalone main.js). Users can blow out the 3D candles on the screen using the microphone on their computer or mobile device, triggering a celebration effect.

Tech Stack: HTML5, CSS3, vanilla JavaScript (ESM modules), Three.js (imported via CDN), canvas-confetti (for confetti effects).

3D Scene Setup: Initialize the scene, camera, and renderer using Three.js. Load the cake model using GLTFLoader from the cake.glb file in the same directory. Add OrbitControls to allow users to rotate and view the model.

Candles and Flames: Simulate candle flames in the 3D scene (can use emissive sprite or particle system). Position the candles directly on top of the cake model so that the bottom of each candle aligns with the top of the cake.

Microphone Listening: Request microphone permission using navigator.mediaDevices.getUserMedia. Use the Web Audio API (AnalyserNode) to monitor audio input. When the audio frequency exceeds a defined threshold for several consecutive frames (simulating a blowing action), determine that the candles have been successfully blown out.

Success Feedback: Extinguish the 3D candle flames. Trigger full-screen confetti using canvas-confetti. Fade in a birthday greeting card in the center of the screen. Fade in a “Make a Wish Again” button in the bottom-right corner.

Make a Wish Again: Clicking the button resets the greeting card state, relights the 3D candles, and prepares for the next blowing detection.

Visual Design: Overall style: medieval dark retro color scheme (background #2c2520), with #d4bc96 as the primary text color. Import Google Fonts: Great Vibes (elegant script) for English and Noto Serif SC for Chinese. Interface elements use a premium frosted glass Glassmorphism effect with subtle glow and shadows. Top-left: prompt text “Make a wish, blow out the candles”. Bottom-left: full-screen button. Bottom-right: “Make a Wish Again” button (initially hidden). Bottom center: floating toast notification. Center of screen: birthday greeting card (initial opacity 0) containing large stylized English text “happy birthday”, subtitle “Wishing you a wonderful new year”, and right-aligned signature “cc”. Please directly output the complete HTML and JavaScript (main.js) code with good comments. Instruct it to load the .glb model file from the same directory. [Customize greeting text and UI style as needed. To add background music, specify the audio file name and behavior in the prompt.]

Prompt: “Add a click event listener to the canvas. When clicked, animate the loaded model to spin 360 degrees around the Y axis over 1.5 seconds using a linear easing. After the animation completes, return the model to its original rotation.”

Prompt: “Add a button labeled ‘Blow Out Candles’. When clicked, start the browser’s SpeechRecognition API. If the user says ‘blow’ or blows into the microphone (detect audio level above 0.4 using AudioContext and AnalyserNode), trigger an animation that fades the candle flame objects from visible to invisible over 0.8 seconds.”

Command: python3 -m http.server 8080

Then open http://localhost:8080 in your browser. The model loads because the request goes over HTTP, not a blocked local file path.

Command: gltf-pipeline -i model.glb -o model-compressed.glb --draco.compressionLevel 7

Then in Three.js, initialize DRACOLoader and set it on your GLTFLoader before loading the compressed file. Gemini can write this setup if you paste the compressed file name and ask for it.

Neural4D base mesh only (no textures): typically under 2 MB. With PBR textures: 4 to 12 MB before compression. After Draco + KTX2: 1 to 3 MB depending on geometry complexity and texture resolution.

The Neural4D GLB loads fine in gltf.report but the model appears completely black in Three.js. What is wrong?

This is almost always a missing light in the Three.js scene. GLB viewers like gltf.report add default scene lighting automatically; Three.js does not. The fix is two lines: add an AmbientLight at intensity 0.5 and a DirectionalLight positioned above and to the right of the model. If the model still looks dark after adding lights, check that the GLB was exported with PBR textures enabled in Neural4D, not just the base mesh. A base-mesh-only GLB has no material data for Three.js to work with and renders as a flat dark surface regardless of lighting.

Can I embed a Neural4D model in a WordPress page or Shopify product page?

Yes, but with a constraint. WordPress and Shopify block inline <script> tags in standard page editors. The recommended approach is to host the Three.js HTML file on a CDN or static hosting service (Netlify, Vercel, or GitHub Pages are free options), then embed it in your CMS page via an <iframe>. Set the iframe dimensions to match your canvas size and add allow="microphone" if you are using the voice interaction features.

What happens if the GLB file has a missing texture after export?

If a texture fails to pack into the GLB, Three.js renders the affected mesh with a default gray material. To diagnose it, open the exported GLB in an online viewer such as gltf.report or Don McCurdy’s GLTF Viewer before deploying. These tools show which materials are present and whether texture references are embedded or broken. If textures are missing, re-export from Neural4D with “Generate PBR Textures” confirmed active, or use gltf-pipeline to re-pack external texture files into the binary bundle.

Is the Web Speech API reliable across all browsers?

SpeechRecognition is supported in Chrome and Edge as of 2026 but is not part of the standard Safari or Firefox feature set. For cross-browser voice interaction, the fallback is a click button that triggers the same animation without microphone input, which is the pattern shown in the Neural4D + Gemini video. Always implement the click-based fallback before adding voice, so the experience degrades gracefully.

Can I use the same workflow to embed multiple 3D models on one page?

Yes, but each model creates its own WebGL rendering context, and browsers cap the number of active WebGL contexts per page (typically 8 to 16). If you need more than 3 or 4 models on a single page, the recommended pattern is a shared Three.js scene with multiple models loaded into it rather than separate renderer instances per model. Ask Gemini to generate a single scene that loads an array of GLB filenames, positions each model at a specified offset, and switches camera focus on click. This keeps context count at 1 regardless of how many models are loaded.

The mobile browser denied microphone permission. How should the code handle that gracefully?

Wrap the getUserMedia call in a try/catch and handle two distinct failure cases separately. A NotAllowedError means the user explicitly denied permission or the browser’s site settings block the microphone; show a UI message explaining that microphone access is required and provide a fallback button that triggers the blow-out animation manually. A NotFoundError means no microphone hardware was detected, which is common on some tablets; in this case, skip the audio path entirely and default to the tap-to-extinguish interaction. On iOS Safari, getUserMedia additionally requires the page to be served over HTTPS, not HTTP. If you are testing on a local network, use a tunneling tool like ngrok to expose your local server over a secure URL, otherwise the permission prompt will never appear and the call silently fails.

The candle flame meshes are flickering against the cake surface. How do I fix Z-fighting?

Z-fighting happens when two surfaces occupy nearly identical depth values and the GPU alternates between rendering one or the other frame by frame. For candle flames positioned just above the cake top, the fix is to push the flame geometry slightly further from the surface: increase the Y offset by 0.01 to 0.05 units until the flickering stops. If the flame uses a sprite or a plane geometry, also set depthWrite: false on its material, which tells Three.js not to write the sprite’s depth to the depth buffer, eliminating the conflict with the solid cake mesh underneath. A third option is to increase the renderer’s logarithmicDepthBuffer to true at initialization, which improves depth precision across the whole scene but carries a small performance cost on low-end mobile devices.

Build Your First Interactive 3D Website Today

Generate a web-ready GLB from any photo. No 3D software, no WebGL expertise required.

50 free credits per week. Export GLB on the free plan.

Keep reading