← ALL NOTES
METHOD·2026.09·5 MIN READ
Rendering Compatibility for User-Uploaded 3D Models
3d-visualization3d-design
The Problem

When a 3D scene is built around a fixed set of bundled assets, many rendering parameters naturally become tuned to those assets. As long as the content does not change, those values start to look like general system defaults.

That changes once users can upload their own models. GLB files from different sources can use different normal directions, material setups, and texture workflows. A rendering rule that works perfectly for one controlled asset set may fail as soon as the input changes.

I ran into this after adding custom GLB upload to a 3D prototype. The scene already had double-sided rendering and lighting values tuned for its built-in objects. Testing with a real room scan exposed two issues in sequence: from a top view, the interior was covered by a large white surface; after fixing that, the textures still looked heavily overexposed.

Both problems came from the same underlying pattern: assumptions that were valid for fixed internal assets had been treated as if they were valid for every uploaded model.

The root-cause analysis and implementation fixes mainly came from Claude Code. My role was to validate them with real scan data and identify the limits of the resulting behavior.

Hidden Assumption 1: Every Face Should Be Rendered

The first version enabled double-sided rendering for uploaded models as a compatibility measure. The logic seemed reasonable: if a model had unexpected normal directions, rendering both sides would reduce the chance of surfaces disappearing.

The room scan showed why that assumption was too broad.

This type of model behaves more like an interior shell. Its normals facing inward are not necessarily incorrect; they match the fact that the scanned space is meant to be viewed from inside. Once both sides were rendered, surfaces that should have remained invisible from the outside were drawn as well. From above, the back side of the ceiling covered the interior and appeared as a large white layer.

The fix was to render only front-facing surfaces and let back-face culling work again. From the top view, the ceiling's back side no longer blocked the room interior.

The important change was not correcting a single normal. It was correcting the compatibility rule itself: rendering more geometry is not always safer, because it can remove spatial visibility rules that the asset relies on.

Hidden Assumption 2: The Model Needs Scene Lighting

After the face-rendering issue was fixed, the scan still looked washed out. Texture detail and contrast were noticeably reduced.

The existing scene lighting had been tuned for simple solid-colored 3D objects. Those objects rely on scene lights to create form, so the lighting setup made sense for them.

The uploaded scan used a different visual pipeline. Its texture already contained much of the lighting information captured during scanning. Applying the scene lighting again effectively added another layer of illumination on top of an already lit texture, producing the overexposed result.

The current solution renders uploaded scan materials without additional scene-light calculations while preserving their original textures, vertex colors, transparency, and related information. This allows the lighting already present in the texture to remain intact.

Again, the useful lesson is broader than the specific material setting: scene lighting is not independent of the asset. It depends on how that asset already represents light and shading.

Limits of the Current Solution

This fix does not mean that arbitrary GLB files will now render correctly.

A conventional 3D model may not have lighting baked into its textures at all. It may depend on real-time scene lighting to show volume and surface form. If that model is forced into the same unlit treatment as the scan, it can appear flat.

So the current approach is better suited to the scan assets used in this test. It is still a trade-off between different asset types rather than a universal rendering rule.

If the product eventually needs to support both workflows, a better direction would be to let different assets use different rendering strategies — for example, allowing a choice between preserving the model's original lighting behavior and ignoring additional scene lighting.

That has not been implemented yet, so I prefer to document it as a boundary of the current solution rather than present the upload pipeline as fully general.

Moving from Controlled Assets to Open Input

Neither issue appeared while the scene only used its original built-in models, because the rendering setup had been tuned around those assets from the beginning.

User upload changed the nature of the system. Once the source of the content was no longer controlled, previously invisible assumptions became part of the product surface:

  • how front and back faces are expected to behave;
  • whether materials depend on scene lighting;
  • whether lighting is already baked into textures;
  • whether other scene parameters depend on specific asset characteristics.

Supporting uploads therefore involves more than adding a file picker. It also means asking: which of the current defaults are genuinely general, and which are only properties of the original asset set?

Takeaways
  1. Audit asset assumptions before opening a scene to user uploads. Normals, materials, baked lighting, and model scale are all worth rechecking if they were only validated against fixed content.
  2. Do not assume that a more permissive rendering rule is automatically more compatible. Double-sided rendering can solve one class of normal issues while exposing surfaces that should remain hidden.
  3. Evaluate lighting together with the asset's material pipeline. A baked scan and a model that relies on real-time lighting should not automatically share the same lighting behavior.
  4. Test with genuinely different external assets. Hidden assumptions are often invisible until the input type changes, not merely the file.
  5. Document the boundary of each fix. Solving the scan-model case does not mean every GLB now has a correct rendering path.
About the Design Decision

The specific technical diagnosis and fixes were mainly developed with Claude Code. My responsibility was to validate them against real uploaded models and to identify what new trade-offs each fix introduced.

The reusable lesson is not whether double-sided rendering should be enabled, or whether uploaded models should ignore lighting. Those answers depend on the asset.

The more durable question is: once a system accepts input that it no longer controls, which of its existing defaults are actually hidden assumptions about the old content?

CONTINUE READING
Translating Figma Component Properties into Code Props2026.09Engineering a Figma Design System into Production Assets2026.09