Anass Kartit
← Writing / / 17 min read / Updated

Free AI Image-to-3D on a Kaggle T4: a TRELLIS Car in a three.js Racer

TRELLIS image to 3D on a free Kaggle T4: 39.4 s to a textured car with 12,444 faces, cut to a 300 KB GLB and raced in a three.js game you can play here.

image to 3dtrelliskaggle t4free gpuai generated 3d modelthree.js gamewebgl racing gamecannon-eslyria 3 proonline leaderboard2026

NEON RUN is a night racer that runs in your browser, and its car started as a single AI image. On 23 September 2026 I ran TRELLIS image-to-3D on a free Kaggle Tesla T4. It turned a 1536 × 1024 PNG into a textured car with 12,444 faces in 39.4 s, plus 37.0 s to export the GLB. A Blender script split off the wheels, and gltf-transform shrank the file from 1.54 MB to 300 KB. The car now races six rivals in a three.js game you can play below. The game has cannon-es physics, Lyria 3 Pro music, a Gemini 3.8 Flash TTS announcer and an online leaderboard on Cloudflare KV. This post covers the whole pipeline with measured numbers, how TRELLIS compares with TripoSR, TripoSG and Hunyuan3D on the same image, the paint shader behind the garage colour picker, and the caveats.

Key facts (quick answer)

FactValue (and the run it comes from)
Image-to-3D modelTRELLIS image-to-3D, seed=1, simplify=0.95, texture_size=1024
GPUKaggle Tesla T4, 14,911 MB VRAM, free tier (probe/out_trellis/result.json)
Generate / GLB export39.4 s / 37.0 s (model load 74.6 s)
Peak VRAM13,885 MB (nvidia-smi), 10,519 MB (torch)
First-run install676.5 s
Raw output1,535,932 bytes, 9,755 vertices, 12,444 faces, one 1024 px texture
Game asset299,700 bytes after JPEG texture + meshopt (racer/tools/make_car.mjs)
Wheel split4 of 4 wheels found automatically, radii 0.350 to 0.358 m, 42.5 s in headless Blender 5.1.1
Whole game5,765,913 bytes in 53 files: 4.33 MB of audio, 0.99 MB of three.js r160 and cannon-es 0.20.0, 115 KB of minified game code (racer/publish_blog.sh, 24 September 2026)
Physicscannon-es 0.20.0 RaycastVehicle, 1,200 kg chassis, fixed 1/60 s steps (racer/vehicle.js)
Music and voiceLyria 3 Pro: 4 tracks, 57 to 96 s each; Gemini 3.8 Flash TTS, Fenrir voice: 14 lines (audio/lyria_log.json, audio/voice/tts_log.json)
Online leaderboardCloudflare Worker + KV, top 100 per board, manual and AI assisted boards
Desktop frame rate94 to 120 fps at 1280 × 720 in headless Chromium on my Mac (racer/test/shots/log.txt)
Cost$0 for the 3D part (Kaggle free tier)

TL;DR

  • One image in, one car out: TRELLIS generated a textured car in 39.4 s on a free T4, and the full image-to-3D stage took 231.5 s including model load and export.
  • It barely fits: peak VRAM hit 13,885 MB on a card that reports 14,911 MB.
  • Best of four on this image: TRELLIS gave 12,444 faces with a texture. TripoSR gave 93,368 faces with vertex colours. TripoSG gave 1,696,424 faces and no colour.
  • 5.1× smaller for the web: 1,535,932 bytes raw, 299,700 bytes in the game, with the same 12,444 faces.
  • Wheels without a rig: a Blender script found all 4 wheels from silhouettes and split them in 42.5 s.
  • Play it here: 5.77 MB for the whole game, keyboard or touch, with a garage that repaints the baked texture in 8 colours plus a custom one.
  • Race for a rank: pick a nickname, finish 3 laps, and your time lands on an online leaderboard stored in Cloudflare KV.

Play NEON RUN

Click the poster to load the game. Nothing loads until you do, so the page stays light. Press Fullscreen for the best view, or open the game in its own tab.

Open in a new tab ↗

Keyboard: W/ gas · S/ brake · A D/ steer · Space handbrake drift · Shift nitro · E super neon · T AI mode · C camera · R reset to track · M mute

Touch: the left pads steer; GAS, BRAKE, DRIFT and NITRO are on the right. Drifting refills the nitro. Pick a paint in the Garage before the race; your choice and your nickname are saved in this browser. Your time goes to the online Leaderboard when you finish.

How did one AI image become a 3D car?

In four steps: an image, TRELLIS on Kaggle, a Blender pass for the wheels, and a web export.

The AI-generated source image: a red sports car in three-quarter view on a white background

  1. The image. Codex image generation on my ChatGPT subscription produced a 1536 × 1024 PNG. The prompt asked for “a single small red sports car, stylized clean 3D render, three-quarter front view from slightly above”, all four wheels visible, on a pure white background with no shadow. It also said “This image will be converted into a 3D model, so keep the shape clear and the edges clean”. That line matters: image-to-3D models copy whatever clutter they are given.
  2. TRELLIS on a free T4. A script pushes a private Kaggle notebook with the T4 accelerator, the notebook runs TRELLIS on a 1024 × 682 copy of the image, and the Kaggle CLI pulls the GLB back. Nothing is exposed publicly.
  3. Wheels. TRELLIS returns one mesh. A headless Blender script finds the wheels and splits them into four objects that can spin and steer.
  4. Web export. gltf-transform keeps only the car, re-encodes the texture as a 1024 px JPEG at quality 82 and compresses the geometry with meshopt.

How long does TRELLIS take on a free Kaggle T4?

About 40 seconds to generate, and 231.5 s for the full image-to-3D stage. Every number below comes from probe/out_trellis/result.json, the Kaggle run of 23 September 2026.

StageSeconds
Environment check5.5
Install dependencies (first run)676.5
Load the TRELLIS image pipeline74.6
Generate (pipe.run, seed=1)39.4
Export GLB (to_glb, simplify=0.95, texture_size=1024)37.0
Image-to-3D stage total231.5
Whole job (also ran text-to-3D, 145.0 s)1,058.5

The GPU reported 14,911 MB of VRAM and CUDA 12.8 with torch 2.10.0. Peak use was 13,885 MB by nvidia-smi and 10,519 MB by torch’s own counter. The install dominates, so batch several images into one Kaggle session instead of starting a session per image.

TRELLIS vs TripoSR vs TripoSG vs Hunyuan3D: which free model makes the best car?

TRELLIS, for a game. It was the only one to give a clean textured mesh at a face count a browser can draw seven times per frame. All four ran on the same image on a free Kaggle T4.

TripoSR, TripoSG and TRELLIS outputs of the same car image, rendered from the front, three-quarter and back

Model (Kaggle T4)GeneratePeak VRAMOutput GLBFacesColour
TRELLIS image-to-3D39.4 s + 37.0 s export13.9 GB1.54 MB12,4441024 px texture
TripoSR65.6 s3.2 GB1.87 MB93,368vertex colours (texture bake failed)
TripoSG181.2 s10.8 GB30.54 MB1,696,424none
Hunyuan3D-2mini (shape + paint)101.8 s shape + 33.7 s paint13.2 GB3.58 MB40,000 (cut from 658,842)texture

Sources: probe/out_trellis/result.json, probe/out_triposr/result.json, probe/out_triposg/result.json and probe/out_hunyuan/result.json. The Hunyuan job also generated other assets, so only its car stages are listed.

TripoSG has the most geometric detail, but it has no colour and 136 times TRELLIS’s face count. TripoSR is light on VRAM, but its colours are blurry, and its texture bake crashed on Kaggle with XOpenDisplay: cannot open display because the baker needs an X11 display. Hunyuan3D-2mini produced a textured car too, but its licence excludes the EU, the UK and South Korea, and I work from the EU.

How do the wheels turn on a single AI-generated mesh?

A Blender script finds them from the geometry alone and cuts them out. It does not use a rig or manual selection.

  • The script orients and scales the car to 4.40 × 2.14 × 1.25 m.
  • It finds the axles from where the lower edge of the body touches the ground.
  • It casts rays at the side silhouette. The depth jump between the tyre and the wheel arch marks the tyre edge, and it fits a circle to about 70 of those edge points per wheel.
  • Faces inside each wheel cylinder move into their own object, pivoted on the hub.

On this car it found 4 of 4 wheels from silhouettes with no overrides. The radii were 0.358, 0.350, 0.356 and 0.350 m. The body kept 8,125 faces and the wheels got 1,073, 1,105, 1,039 and 1,102. The run took 42.5 s in Blender 5.1.1, including a 192-frame test render (car_anim/out_trellis/detect.json).

How does the garage recolour a baked AI texture?

With a mask computed per pixel in the shader. TRELLIS bakes everything into one 1024 px texture: red paint, black tyres, grey glass and silver rims. On that texture, 33% of texels are paint. They are all red, with a median brightness of 0.76 on a 0 to 1 scale, and almost no other texels are saturated.

The same AI-generated car repainted electric blue, gold and hot pink in the NEON RUN garage

The fragment shader, added to three.js’s standard material with onBeforeCompile, does four things:

  • Mask the paint using saturation, red hue and a minimum brightness, so tyres, glass and rims stay as they are.
  • Repaint as new colour × (texel brightness / 0.76), which keeps the baked panel shading and highlights. A flat tint would erase them.
  • Drive the material from the same mask: paint gets its own roughness and metalness, dark rubber goes rough and grey glass goes glossy.
  • Clearcoat the paint only, on the player car, for the metallic finish. Matte turns the clearcoat off and raises the roughness.

The choice is saved in localStorage. Rivals pick from the same palette but skip colours close to yours.

What is the game built with?

three.js r160, cannon-es 0.20.0 for the physics, and 2,399 lines of JavaScript in 10 modules. There is no bundler: the source runs as it is, and the copy on this site is only minified with terser.

  • Physics: the car is a cannon-es RaycastVehicle: a 1,200 kg chassis on four raycast wheels with springs, dampers and a friction circle per tyre, stepped at a fixed 1/60 s. So it leans in corners, dives under braking and runs wide when it is too fast. Arcade help (speed-sensitive steering, auto countersteer, a yaw limiter) acts through the steering, never by moving the body.
  • Track: a closed Catmull-Rom spline sampled at 1,600 points, about 2.2 km per lap. On 24 September 2026 the lap bot (racer/test/lapbot.mjs auto) measured a 47.94 s first lap in AI AUTO mode from a standing start, with 2 wall hits and a 281 km/h top speed. A full 3-lap AUTO race (racer/test/leaderboard.mjs auto) ran 42.72, 49.23 and 41.22 s laps, and the keyboard-only bot’s best lap in its race was 52.08 s.
  • Rivals: six AI cars that brake from the curvature ahead and change lanes when blocked.
  • Look: instanced buildings, a shader sky with a striped synthwave sun, bloom, and a speed shader for nitro. Headlines, numbers and buttons use a fan-made Need for Speed style font (“NFS by JLTV”).
  • Cameras: C cycles four views: chase, far chase, hood and a cockpit view with a neon dash and a steering wheel that turns with yours.
  • Intro: a Need for Speed style cinematic on the title screen. Four timed camera shots (a headlight dolly, a wheel-height side track, a crane drop and a pull-back) run behind letterbox bars, and the pull-back lands on the drop of the intro track. Any key skips it.
  • Performance: the renderer drops its pixel ratio when the frame rate stays under 40 fps, and then turns off bloom and shadows. In headless Chromium at 960 × 540 on my Mac, the lap bot logged 120 fps through a full lap (racer/test/lapbot.mjs, 23 September 2026).

The build is 53 static files with relative paths, so the same folder runs from a laptop or from /games/neon-run/ on this site.

What do the AI ASSIST, AI AUTO and SUPER NEON modes do?

They are driving aids that use the same controls and physics as you. T cycles MANUAL, ASSIST and AUTO.

  • ASSIST blends your steering with the autopilot, brakes before corners you take too fast and steers you away from the walls.
  • AUTO drives by itself with the rivals’ recipe: a look-ahead point on the spline and a speed limit from the curvature ahead. You keep nitro and SUPER NEON.
  • SUPER NEON (E) fills from drifting and overtaking. It gives 3.5 s at 1.35 times the top speed with more grip, and the car turns into a neon ghost that passes through rivals.

A race where you switched on ASSIST or AUTO at any point counts as assisted on the leaderboard.

What does NEON RUN sound like, and what made the audio?

Generated music and voice, and a synthesized engine.

SoundMade withMeasured (source)
Music: intro, menu, race, final lapLyria 3 Pro (lyria-3-pro-preview)57, 59.2, 96 and 62 s, 3.9 MB together as AAC (ffprobe on audio/music_*.m4a)
One-shots: crash, lap, final lap, winLyria 3 Pro, trimmed0.45 to 3.78 s each
AnnouncerGemini 3.8 Flash TTS, voice Fenrir14 lines, 27.75 s of speech (audio/voice/tts_log.json)
Engine, tyres, wind, scrapesWeb Audio API synthesisdriven live by RPM, throttle and slip

The Lyria log (audio/lyria_log.json) holds 13 generation calls at a logged $0.08 each, $1.04 in total. Two came back with no audio. Three generated effects (the nitro whoosh, the barrier scrape and the countdown beeps) failed my listening check, so those stay synthesized. The music crossfades between the menu, race and final-lap tracks, and the announcer has per-line cooldowns so overtakes and drifts do not spam it.

How does the online leaderboard work?

You pick a nickname on the start card, and your total 3-lap time is posted when you cross the line. The finish card then shows your rank and the top 10 with your row lit up. The leaderboard only ever shows the nickname.

  • Backend: one Cloudflare Worker (neon-run-leaderboard) and one Cloudflare KV namespace. GET /top returns the best times, one entry per nickname. POST /score validates a finished race and returns the rank.
  • Two boards: only races driven in MANUAL mode rank on the main board. Races that used AI ASSIST or AI AUTO go to an AI assisted board, tagged with the mode.
  • Signed races: when the countdown starts, the game asks the Worker for a race token, an HMAC-signed timestamp. The score must carry that token, the time since it was issued must be at least the race time claimed, and each token works once. A score typed by hand without playing is refused.
  • Time floor: every lap must take at least 30 s and the laps must add up to the total. For scale, AI AUTO drove a 47.94 s first lap from a standing start (racer/test/lapbot.mjs, 24 September 2026). A 30 s lap would mean averaging about 250 km/h round corners of 28 to 100 m radius.
  • Other checks: nicknames are 1 to 16 letters, digits, spaces, _, . or -, with a small profanity filter. The Worker only answers the kartit.net origins, refuses POSTs from anywhere else, returns the same short error for every bad score, and each IP can post 10 scores per 10 minutes.
  • Storage: each board is a single JSON value holding the top 100. KV is eventually consistent and has no compare-and-swap, so two finishes in the same second can overwrite each other, and a new time can take up to a minute to appear at other edge locations. At the traffic of a blog game that trade is fine.
  • Offline: if the Worker cannot be reached, the panels say “LEADERBOARD OFFLINE” and the game plays normally.

The start card also has an optional email field for news about new posts and games, sent only if you tick the consent box. It goes to the same list as the form at the end of this post, stored in a Cloudflare D1 database in the EU, and never appears on the leaderboard. What is stored and how to leave.

Caveats

  • One image, one seed. These are single runs with seed=1. Another image or seed can change the ranking.
  • VRAM is tight. TRELLIS peaked at 13,885 MB of the T4’s 14,911 MB. A bigger texture_size or a heavier model may not fit.
  • Hidden sides are guesses. The model only sees one side of the car. The back and the underside are invented, and the texture has smeared patches on the parts the image did not show.
  • The recolour depends on the source. The mask works because the car is pure red and nothing else in the texture is saturated. A car with red tail lights and blue paint would need another mask.
  • Unmeasured: phone frame rates. The adaptive resolution is there for phones, but I have not logged phone numbers yet.
  • The leaderboard still trusts the browser in the end. The race token proves a race lasted as long as the time claimed, so hand-typed scores fail. It cannot prove how the car was driven: someone who scripts the page can still post a plausible time after waiting it out. There is no replay of the inputs.

My take

Free image-to-3D is now good enough for a game prop if you treat the output as raw material. The model took 39 seconds. The work that made it playable was engineering around it: prompting for a clean input image, a geometric pass to free the wheels, a 5× smaller export, and a shader that understands what the baked texture contains. The free T4 is the right place to try this. The 11-minute install is the real cost, so batch your images.

Sources

Independent write-up by Anass Kartit. Not affiliated with Microsoft, Kaggle, VAST AI Research, Tencent, Google, Cloudflare, Electronic Arts or three.js.

Newsletter

Get the next post and game in your inbox

One email when I publish something new: measured write-ups on AI, local models and cloud, plus games like NEON RUN.

Your email is never shown or shared. What is stored and how to leave