Generate Low-Poly Bench With Blender Python API For Website

3D BENCH in Python From Blender to Browser
3D BENCH in Python From Blender to Browser

Create a Low Poly Metal Bench in Blender with Python and View it in the Browser

If you’re interested in automating 3D modeling with Python and displaying your creations on the web, this beginner-friendly tutorial is perfect for you!

In this post, you’ll learn how to:

  • Create a low-poly metal bench using the Blender Python API
  • Bake a texture into a WebP image and embed it into a .glb file
  • Display the final result in a web browser using <model-viewer>
  • Run everything using a command-line Python script

This is a great starting point for artists and developers who want to combine scripting, 3D design, and web technologies — without needing to be a Blender expert.

🔧 What You’ll Build

  • A simple, low-poly metal bench
  • A baked texture (WebP format)
  • A .glb file with embedded textures
  • A responsive web viewer using <model-viewer>

🐍 Python Script for Blender 4.5

We’ll use Blender 4.5’s Python API to generate and export everything. You can paste it directly into Blender’s Scripting tab.

import bpy
import os

# ----------------------------------------------------------
# Step 0: Clean the scene
# ----------------------------------------------------------

bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

# ----------------------------------------------------------
# Step 1: Create a Simple Low Poly Bridge
# ----------------------------------------------------------

def create_bridge():
    bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 1))
    bridge = bpy.context.active_object
    bridge.name = "Bridge"
    bridge.scale = (4, 1, 0.2)

    # Add support pillars
    bpy.ops.mesh.primitive_cube_add(size=1, location=(-3.5, 0, 0.5))
    left_pillar = bpy.context.active_object
    left_pillar.scale = (0.2, 1, 1)

    bpy.ops.mesh.primitive_cube_add(size=1, location=(3.5, 0, 0.5))
    right_pillar = bpy.context.active_object
    right_pillar.scale = (0.2, 1, 1)

    # Join all into one mesh
    bpy.ops.object.select_all(action='DESELECT')
    for obj in [bridge, left_pillar, right_pillar]:
        obj.select_set(True)
    bpy.context.view_layer.objects.active = bridge
    bpy.ops.object.join()

    return bpy.context.active_object

bridge = create_bridge()

# ----------------------------------------------------------
# Step 2: Create a Metal Material
# ----------------------------------------------------------

def create_metal_material():
    mat = bpy.data.materials.new(name="Metal_Material")
    mat.use_nodes = True
    nodes = mat.node_tree.nodes

    # Clear all default nodes
    for node in nodes:
        nodes.remove(node)

    # Add Principled BSDF and Output nodes
    bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
    output = nodes.new(type='ShaderNodeOutputMaterial')

    # Configure BSDF for metal
    bsdf.inputs['Base Color'].default_value = (0.3, 0.3, 0.35, 1)
    bsdf.inputs['Metallic'].default_value = 1.0
    bsdf.inputs['Roughness'].default_value = 0.3

    # Link BSDF to Output
    mat.node_tree.links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])

    return mat

metal_mat = create_metal_material()
bridge.data.materials.append(metal_mat)

# ----------------------------------------------------------
# Step 3: Add UV Map for Baking
# ----------------------------------------------------------

# Set object mode
bpy.ops.object.select_all(action='DESELECT')
bridge.select_set(True)
bpy.context.view_layer.objects.active = bridge

# Enter Edit Mode and unwrap
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.uv.smart_project(angle_limit=66.0)
bpy.ops.object.mode_set(mode='OBJECT')

# ----------------------------------------------------------
# Step 4: Create Image for Baking
# ----------------------------------------------------------

# Create a new image for baking
output_dir = bpy.path.abspath("//")  # Save to current Blender file directory
baked_image = bpy.data.images.new(name="BakedTexture", width=1024, height=1024, alpha=True)
baked_image.file_format = 'PNG'  # Use PNG format for compatibility
baked_image.filepath_raw = os.path.join(output_dir, "baked_texture.png")

# Link the image to the material via the Shader Node
nodes = metal_mat.node_tree.nodes
image_node = nodes.new(type='ShaderNodeTexImage')
image_node.image = baked_image
image_node.select = True
nodes.active = image_node  # Set this as the active node to ensure it's baked to

# Save the image before baking
baked_image.save()

# ----------------------------------------------------------
# Step 5: Bake the Diffuse to the Image
# ----------------------------------------------------------

bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.device = 'CPU'

bpy.ops.object.select_all(action='DESELECT')
bridge.select_set(True)
bpy.context.view_layer.objects.active = bridge

bpy.ops.object.bake(type='DIFFUSE', pass_filter={'COLOR'}, use_clear=True)
baked_image.save()

# ----------------------------------------------------------
# Step 6: Replace Shader With Baked Texture
# ----------------------------------------------------------

# Remove all nodes and recreate material using baked image
for node in nodes:
    nodes.remove(node)

tex_node = nodes.new(type='ShaderNodeTexImage')
tex_node.image = baked_image

bsdf_node = nodes.new(type='ShaderNodeBsdfPrincipled')
bsdf_node.inputs['Metallic'].default_value = 1.0
bsdf_node.inputs['Roughness'].default_value = 0.3

output_node = nodes.new(type='ShaderNodeOutputMaterial')

# Link baked texture
links = metal_mat.node_tree.links
links.new(tex_node.outputs['Color'], bsdf_node.inputs['Base Color'])
links.new(bsdf_node.outputs['BSDF'], output_node.inputs['Surface'])

# ----------------------------------------------------------
# Step 7: Export to .glb with embedded WebP texture
# ----------------------------------------------------------

glb_path = os.path.join(output_dir, "bench.glb")

bpy.ops.export_scene.gltf(
    filepath=glb_path,
    export_format='GLB',
    export_materials='EXPORT',
    export_normals=True,
    export_image_format="AUTO"  # Let Blender decide the image format (usually PNG)
)

▶️ How to Run the Script from the Command Line

Blender allows you to run Python scripts headlessly via the terminal. Here’s how:

  1. Save your script as metal_bench.py in the same folder as your .blend file (or a new one).
  2. Open your terminal or command prompt.
  3. Run the script using this command:
blender --background --python metal_bench.py

⚠️ --background runs Blender without launching the UI, perfect for automation.

🌐 Display Your Model in the Browser

Once you run the script, it generates a bench.glb file. You can display it in any modern web browser using model-viewer:

  <model-viewer src="lowpoly-bench.glb"
                alt="Low poly metal bench"
                auto-rotate
                camera-controls
                environment-image="neutral"
                exposure="1.2">
  </model-viewer>

Save this code as an HTML file in the same folder as your bench.glb, then double-click to open it in your browser.

📷 Screenshots & 🎥 Screencast

Low poly bench Python code
Blender Scripting Workspace Displaying Low Poly Bench Python Code

Low poly bench in Blender
Blender Layout Workspace Displaying Low Poly Bench

Low poly bench in Web browser
Web Browser Displaying Rendered Low Poly Bench

Screencast For Blender Python API Low Poly Textured Metal Bench

📚 Learn More with My Books & Courses

📖 My Books:

🎓 Online Course:

👨‍🏫 1-on-1 Python + Blender Help

Need help customizing scripts, learning Blender’s API, or building your first 3D web app?

🎥 I offer one-on-one online Python tutorials, including Blender scripting:
Contact me to book a session

🏁 Conclusion

This tutorial gives you a full pipeline from Python-powered 3D modeling in Blender to interactive web display using model-viewer. You’ve learned how to script geometry, bake textures, export .glb files, and showcase your model online.

Got questions or improvements? Share your feedback or creations in the comments below!

Happy coding & modeling! 🚀

About Edward

Edward is a software engineer, web developer, and author dedicated to helping people achieve their personal and professional goals through actionable advice and real-world tools.

As the author of impactful books including Learning JavaScript, Learning Python, Learning PHP, Mastering Blender Python API, and fiction The Algorithmic Serpent, Edward writes with a focus on personal growth, entrepreneurship, and practical success strategies. His work is designed to guide, motivate, and empower.

In addition to writing, Edward offers professional "full-stack development," "database design," "1-on-1 tutoring," "consulting sessions,", tailored to help you take the next step. Whether you are launching a business, developing a brand, or leveling up your mindset, Edward will be there to support you.

Edward also offers online courses designed to deepen your learning and accelerate your progress. Explore the programming on languages like JavaScript, Python and PHP to find the perfect fit for your journey.

📚 Explore His Books – Visit the Book Shop to grab your copies today.
💼 Need Support? – Learn more about Services and the ways to benefit from his expertise.
🎓 Ready to Learn? – Check out his Online Courses to turn your ideas into results.

Leave a Reply

Your email address will not be published. Required fields are marked *