Photorealistic Rendering of Product Packaging using three.js


I am trying to build a product imaging pipeline using three.js (@pmndrs/react-three-fiber). I do not care about the performance penalties for rendering but I do want to render a high quality product image, with high quality internal shadows. There will be no animation as the output is a 2D image.

The rationale is that I want to load in decals for each product image based on URL parameters, this will save a huge amount of time in rending everything through blender. I am using puppeteer to capture the eventual screenshots of the DOM element that contains the render.

I am having some success with AccumulativeShadows and RandomizedLight. But to get the photorealism I desire, what tricks and tips would you recommend? I realise that competing with a dedicated renderer like blender is a tough ask, because of the light handing.

I have seen a few approaches, but what would the best pipeline be in your esteemed opinions! :slight_smile:

In your case, wouldn’t it be easier to use Blender’s python API to background render your scene?
That way you could point to a directory with decals, have the script load up a chromeless blender, update the material with the next decal image, save the render (with whatever render settings you had configured in the blend file), and repeat.

The time trying to make THREE look like Cycles is probably better spent writing the Blender script.

This might get you started (not tested)

import os
import sys

# Get blend file path from command line arguments
blend_file_path = sys.argv[5]

# Start Blender in background mode and load the blend file
blender_command = 'blender -b {} --python {}'.format(blend_file_path, __file__)

# Define the function to change material's base texture
def change_material_base_texture(material_name, texture_path):
    mat =
    if mat is not None:
        nodes = mat.node_tree.nodes
        texture_node = nodes.get('Image Texture')
        if texture_node is not None:
            texture_node.image =
            return True
    return False

# Get material name and texture path from command line arguments
material_name = 'MaterialName'  # Replace with the actual material name in your Blender file
texture_path = sys.argv[-1]

# Change material's base texture
if change_material_base_texture(material_name, texture_path):
    print("Material's base texture changed successfully.")
    print("Material or texture node not found.")

# Set render engine to Cycles
bpy.context.scene.render.engine = 'CYCLES'

# Render out an image through Cycles

# Exit Blender

Make sure to replace ‘MaterialName’ with the actual name of the material you want to modify in your Blender file.

To run
python /path/to/your/blend_file.blend /path/to/your/texture.png

1 Like

you can use raycasting GitHub - gkjohnson/three-gpu-pathtracer: Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.

or ssgi GitHub - 0beqz/realism-effects: SSGI, Motion Blur, TRAA - Effects to enhance your three.js scene's realism

as for building a cli pipeline, that’s not so hard, here’s one buerli-starter/packages/with-solid-puppeteer at main · awv-informatik/buerli-starter · GitHub remove buerli cad stuff and you have it.

1 Like