Performance and High Quality Visuals Best Practices

3D Assets

The total number of assets along with their total download size significantly impact load time. It is best to keep the total number of assets loaded as well as their total size to a minimum while still achieving your desired quality. It is also best to minimize the instances of assets and reuse existing instances.

  • Very Fast load times will be had when total assets are under 5MB.
  • Acceptable load times can be had when total assets are under 10MB.
  • More than 10MB and many users will report the experience as fairly slow.


Number of Materials

There is a cost to both fetching and compiling each material for the GPU. This can add up to 200 ms per material on low end machines. Thus it is best to avoid unnecessary materials. It is also best to minimize the instances of materials and reuse the existing instances.


Number of Unique Textures

There is a cost to fetching each texture and loading it into the GPU. Thus it is best to minimize the number of textures. Threekit only loads a texture once even if it is specified multiple times. Make sure that the textures are all identical and not slightly different versions.

Texture Download Size

All textures must be downloaded. It is best to keep the size of each texture file as small as possible. Preferring to use JPGs instead of PNG unless necessary.

Texture Resolution

Threekit decodes each texture to its original size and then upload this to the GPU. This means that the size of textures matters in terms of their resolution, no matter what their actual download size is. 512x512 is preferable to 1024x1024 or 2048x2048 textures - smaller is always best if you can get away with it.

A large number of textures that are large in size can cause mobile devices, in particular iOS-based devices, to crash. Android and desktop machines are more robust in the case of large textures sets.

There is an overhead per texture, so 4 2048x2048 textures is preferable to 16 1024x1024 textures even though the total number of pixels is the same.


Number of Elements

The size of meshes, their count in faces and vertices, significantly impacts the download size of these meshes. The less faces and vertices the better.

The number of UV sets also impacts the file size significantly. The larger the number of vertices, the larger the impact of multiple UV sets, where each additional UV set can add one or more MB to the file size.

Note that Threekit does integrate with RapidCompact to optimize assets at scale. Contact us to learn more.

Number of Distinct Meshes

Threekit automatically recognizes when a mesh is used multiple times and it avoids allocating additional memory for the copies. It only does this when the meshes are exactly the same. If you can ensure that you duplicate meshes when possible instead of making slightly different meshes, you’ll save both GPU memory as well as avoid unnecessary downloads.


Avoid Loading Non-Visible Assets

Sometimes configurator are set up to load a number of assets and never display them. This can be a default texture used in a picture frame that is never shown. Or it can be items in a scene that just are never made visible. These items if they are forced to load can significantly slow down a configurator’s load time while serving no use.

Custom Scripts

Because custom scripts can allow for arbitrary operations, often there are slowdowns because of the nature of the options done in the custom scripts. Examples include long queries to Threekit or other services that can add seconds to the load time of a configurator. Be aware of what you are doing in these custom scripts, see if you can rewrite them more efficiently.


Initialize Player Quickly

It is best to initialize the player as soon as possible on the client site. The sooner the player is initialized the sooner it will start to load and also complete loading.

Use Cache Keys on Production Site

Threekit's player currently supports cache keys that will ensure that everything in the configurator is loaded into the nearby CDN for quickest possible results. Once you have stopped regular editing of your configurator, it is best to start to use a cache key in our implementation. Remember to update the cache key when you make changes, otherwise they will not go live.

authToken: <token>,
assetId: <assetId>, 
  cache: {
    maxAge: 31536000, //how aggressive do you want the caching to be
    scope: 'v1.0' //name it whatever you want


const api = window.threekitPLayer(... cache:{ maxAge: 500, scope: '1234' });

Use Preset or Empty Configuration

There is a cost when an empty configuration is loaded and then immediately upon the player being initialized another configuration is loaded. It is best to load a configuration preset or an empty configuration.

This is important for Threekit's "asset prefetching" feature that tries to predict the requests to accelerate loading.

Enable Player Thumbnails

Threekit allows for a preview thumbnail to be displayed while the 3D content of the player is loading. While this does not speed up the actual loading of the 3D content, it does make it appear to the user that the player is mostly loaded at a much earlier time. Learn more about it here.


Draw calls

  • The number of independent objects. Mobile is much more affected by this than desktop machines. For some mobile devices you have limits around 6000 draw calls per second, thus 200 per frame if you want to achieve 30 fps.
  • To help deal with this the editor has the ability to automatically merge together objects during import that share the same material. This reduces the number of draw calls required to draw the scene, sometimes significantly.

Vertex shaders -- number of vertices.

  • Each vertex needs to be processed by the vertex shader no matter how many resulting pixels the triangles it is part of are rendered. For mobile devices this can be significant. It is best to use as few vertices as possible.
  • Keeping the vertex count <= 100K is a good guideline to follow.

Fragment shaders

  • Our shaders are adaptive and do less work the less lights there are in the scene. The simplest case is to use a single IBL map (discussed later.)
  • Generally, this should not be an issue unless you have many lights.

Post effects

  • The mirror effect, when enabled, does cause the scene to be rendered twice rather than just once. It does it at a lower resolution, thus the fragment shaders will not be a bottleneck, but the vertex shaders and the draw calls can be.
  • We have the ability to do a number of post effects. Some of the post effects can be costly on mobile devices. Setup tests for performance on such device at the beginning of a project, to determine what is usable and what isn’t.

Video memory - GPU RAM

Limited GPU RAM - particularly on mobile devices. This can be a strong limiting factor to the number of textures and texture resolution used. When textures are loaded into video ram, they get loaded uncompressed. Thus, a 4k texture may be only 1MB in file size compressed, but it gets loaded as 64MB of RAM. On mobile devices, the video memory is typically shared with the system memory. Thus, on devices with just 2GB RAM, the video may end up getting a much smaller amount of memory, and it needs to store the geometry as well.

Screen resolution and size of rendering region in that screen.

  • Higher screen resolutions have more pixels, often significantly more. A 4K monitor has 8.3M pixels, where as a Full HD monitor only has 2M. 8.3M pixels will take roughly 4x more time to render than 2M pixels. While many people that have 4K monitors will bre driving them from high end GPUs, that isn’t always the case. Particularly problematic is the current generation mobile phones that have been released with 3K and 4K screens while having underpowered mobile GPUs.
  • To overcome these issues our viewer technology utilizes the device pixel ratio or device text scaling parameter and it will automatically reduce its render resolution below the screen resolution, thus achieve high performance even on mobile.

Impacts to visual quality:



Sufficient vertex count. For curved objects you should have enough vertices in order to show that the object is curved and not sharp. The number of vertices generally varies based on the visual prominence and subject-matter importance of the objects.


  • To create surfaces, we need to connect the vertices together into faces. We support polygons natively within the editor and viewer.
  • We require those polygons to be planar. Non-planar polygons are bad. The reason is that GPUs only render triangles, and thus we need to convert the polygons into triangles to render them. We can not guarantee that our viewer will generate the same triangulation as generated in your design tool and thus you risk our results are likely to look different than yours.
  • We only support weakly concave polygons. In order to maintain render speed we do not support arbitrarily concave polygons, as concave triangulation schemes are time consuming, these will be triangulated incorrectly. We can support at most a single concave corner.
  • For subdivision, it is necessary to export polygons to FBX and to avoid pre-triangulation. Pre-triangulation combined with subdivision will lead to artifacts.


  • Normals determine the surface orientation during the shading calculations.
  • There can be one or more normals per vertex. There can be as many normals at a vertex as there are faces making use of that face.
  • Normals can be specified in a few different ways. They can either be specified explicitly, they can be implied from the normal map’s topology where hard edges have unique normals per face along an even when positions are shared, normals can be defined by face-based smoothing groups (specific to 3DS Max), or they can be specified by edge hardness weights or booleans (supported by both Maya and 3DS Max.)
  • We prefer to have explicit normals, and failing that we support face-based smoothing groups from 3DS Max (be sure they are exported in the FBX files.) We are in the process of adding edge hardness weights.

NOTE: The new auto-merging FBX importer does not yet support smoothing groups, it only supports explicit normals.


  • We currently support up to 10 UV channels in the editor UI.
  • Using multiple UV channels allows you to use tiled textures for the diffuse and other attributes, in conjunction with baked lighting such as AO or lightmaps. The only limitation here is that the iOS ArKit unfortunately has a limitation with this feature, as it only allows one UV channel to be exported.


  • Light has unbounded intensity, because a light bulb can be as bright as the energy it is producing. There is no upper limit.
  • We use high-dynamic range rendering to achieve the most realistic result.
  • We use tone mapping combined with exposure controls to bring that back to the standard 0-1 range. By default we have the scene set to use the Filmic tonemapping setting, as it produces a more pleasing result. You can set this in the scene settings.
  • The typical lighting workflow for WebGL is to use a pre-generated HDR texture inside the Environment Map Asset slot of the scene settings. There are many free as well as paid libraries available out there for such HDR images, but they can also be easily created inside 3D software tools using spherical/panoramic cameras, or with tools such as Lightmap’s HDR Light Studio.
  • The Shadow Plane Tool, available under the Lights button in the toolbar allows you to create a direct planar projection of a shadow. It can be angled and skewed. A scene can contain a combination of several such Planar Shadows. Objects can be ignored by the Planar Shadow tool through the use of the Cast Shadows property on the mesh.

Special Effects

  • Mirrors. We support rendering a single mirror surface. This can be enabled in the “Scene > Player > Mirror” settings. You can set its roughness and its fresnel value. This can be a nice visual effect.
  • Scalable Ambient Occlusion (SAO). SAO allows for the simulation of global illumination effects without any pre-processing. You can enable this in the scene settings. The SAO Post Effect ignores objects that have a material which already uses an AO map. The SAO is also not currently designed to work with transparent surfaces, as it is a depth map based post effect. Additionally, SAO only works with an HDR and does not export to AR.
Share this