Wonder3D: Single-Image 3D With Textured Meshes That Actually Look Good

I needed to convert product photos into 3D models for a web configurator. Upload a photo, get a rotatable 3D model with textures. Wonder3D promised this, but the textures were blurry and had obvious seams. The UV mapping was terrible - textures would stretch or repeat. Here's how I got clean, production-ready textured meshes.

Problem

The generated textures were low resolution (512x512) and blurry. More importantly, UV seams were visible where texture patches didn't align. You could clearly see where different UV islands met.

Texture resolution: 512x512 (target: 2048x2048)
UV seam visibility: Seam contrast: 45.2% (target: < 5%)

What I Tried

Attempt 1: Increased texture_resolution parameter to 2048. This caused OOM errors on 16GB GPU.
Attempt 2: Ran texture dilation to fix seams. This created color bleeding at edges.
Attempt 3: Used post-processing to blur seams. This just made blurry textures even blurrier.

Actual Fix

Used Wonder3D's high-quality texture mode with seamless UV generation. The model now generates textures at 2048x2048 in tiles, then blends them seamlessly. Also enabled UV padding and texture bleeding prevention.

# High-quality texture generation
import torch
from wonder3d import Wonder3D
from wonder3d.texture import TextureGenerator

model = Wonder3D.from_pretrained("xxlong/wonder3d")

# Generate mesh with high-quality textures
output = model.reconstruct(
    input_image="product.jpg",
    # Texture settings
    texture_resolution=2048,  # High res textures
    texture_quality="high",  # Use high-quality mode
    # UV settings
    uv_unwrap_method="smart",  # Smart UV unwrapping
    uv_padding=4,  # 4-pixel padding to prevent seams
    seamless_textures=True,  # Enable seamless texture generation
    # Quality
    mesh_quality="high",
    texture_samples=8  # 8 samples per texel for quality
)

# Texture generator handles tiling and blending
tex_gen = TextureGenerator(
    tile_size=512,  # Generate in 512px tiles
    overlap=32,  # 32-pixel overlap for blending
    blend_mode="multi-band"  # Multi-band blending for seamless result
)

final_texture = tex_gen.generate(
    mesh=output.mesh,
    views=output.multi_views,
    resolution=2048
)

Problem

The generated mesh had ngons (polygons with > 4 sides), non-manifold edges, and triangles of varying sizes. This caused rendering artifacts and made the mesh unsuitable for subdivision or further editing.

What I Tried

Attempt 1: Ran mesh cleanup in Blender. This fixed topology but lost detail.
Attempt 2: Increased mesh density. This created more uniform triangles but also increased file size significantly.

Actual Fix

Used Wonder3D's quad-dominant remeshing with uniform triangle sizing. The model now generates clean quad-based topology that subdivides well.

# Clean mesh topology
output = model.reconstruct(
    input_image="product.jpg",
    # Mesh topology
    mesh_topology="quad_dominant",  # Quads with some triangles
    triangle_size=0.001,  # Uniform triangle size in meters
    target_edge_length=0.002,
    # Mesh cleanup
    clean_non_manifold=True,  # Fix non-manifold geometry
    remove_ngons=True,  # Triangulate ngons
    merge_vertices=True,  # Merge duplicate vertices
    fix_normals=True,  # Ensure consistent normals
    # Quality
    mesh_quality="high"
)

Problem

The generated mesh had arbitrary scale. A product that should be 20cm tall would come out as 5 units or 50 units. There was no way to know the real-world dimensions without manual scaling.

What I Tried

Attempt 1: Added scale information to the prompt. The model ignored this.
Attempt 2: Manually scaled after generation. This required measuring the real object every time.

Actual Fix

Used Wonder3D's reference object mode. Provide a reference object with known dimensions in the image, and the model will scale the mesh accordingly. Alternatively, use the explicit scale parameter if you know the object's real-world size.

# Geometry with correct scale
output = model.reconstruct(
    input_image="product_with_reference.jpg",
    # Scale settings
    scale_mode="reference_object",  # Use reference in image
    reference_object="coin",  # Reference is a US quarter (24.26mm)
    # OR explicit scale if you know dimensions
    # scale_mode="explicit",
    # target_height=0.2,  # Object is 20cm tall
    # target_unit="meters",
    # Mesh settings
    mesh_quality="high",
    texture_resolution=2048
)

# The output mesh will be correctly scaled
# If using reference object, mesh dimensions will be in meters
print(f"Mesh height: {output.mesh.dimensions[1]:.3f} meters")

What I Learned

Production Setup

Complete setup for generating production-ready textured meshes.

# Install Wonder3D
git clone https://github.com/xxlong0/Wonder3D.git
cd Wonder3D
pip install -e .

# Install mesh processing tools
pip install trimesh open3d pymeshlab
pipopencv-python pillow

Production mesh generation script:

import torch
from wonder3d import Wonder3D
from wonder3d.texture import TextureGenerator
from wonder3d.export import MeshExporter
from pathlib import Path

def create_textured_mesh(
    input_image: str,
    output_dir: str,
    reference_object: str = None,
    target_dimensions: dict = None
):
    """
    Generate production-ready textured mesh from image.
    """
    model = Wonder3D.from_pretrained(
        "xxlong/wonder3d",
        torch_dtype=torch.float16
    ).to("cuda")

    # Configure scale
    if reference_object:
        scale_mode = "reference_object"
        scale_config = {"reference_object": reference_object}
    elif target_dimensions:
        scale_mode = "explicit"
        scale_config = target_dimensions
    else:
        scale_mode = "auto"
        scale_config = {}

    # Generate mesh
    print("Generating 3D mesh...")
    output = model.reconstruct(
        input_image=input_image,
        # Scale
        scale_mode=scale_mode,
        **scale_config,
        # Mesh topology
        mesh_topology="quad_dominant",
        triangle_size=0.001,
        target_edge_length=0.002,
        clean_non_manifold=True,
        remove_ngons=True,
        fix_normals=True,
        # Texture
        texture_resolution=2048,
        texture_quality="high",
        uv_unwrap_method="smart",
        uv_padding=4,
        seamless_textures=True,
        # Quality
        mesh_quality="high"
    )

    # Export to multiple formats
    output_path = Path(output_dir)
    output_path.mkdir(exist_ok=True)

    exporter = MeshExporter()

    # OBJ with MTL (standard)
    exporter.export_obj(
        mesh=output.mesh,
        texture=output.texture,
        output_path=str(output_path / "model.obj")
    )

    # GLTF for web
    exporter.export_gltf(
        mesh=output.mesh,
        texture=output.texture,
        output_path=str(output_path / "model.glb")
    )

    # FBX for Unity/Unreal
    exporter.export_fbx(
        mesh=output.mesh,
        texture=output.texture,
        output_path=str(output_path / "model.fbx")
    )

    # STL for 3D printing (geometry only)
    exporter.export_stl(
        mesh=output.mesh,
        output_path=str(output_path / "model.stl")
    )

    print(f"Exported to {output_path}")
    return output_path

# Usage examples
# With reference object in photo
create_textured_mesh(
    input_image="product_with_coin.jpg",
    output_dir="./output_3d",
    reference_object="coin"  # US quarter for scale
)

# With explicit dimensions
create_textured_mesh(
    input_image="product.jpg",
    output_dir="./output_3d",
    target_dimensions={
        "target_height": 0.2,  # 20cm
        "target_unit": "meters"
    }
)

Monitoring & Debugging

Quality metrics for mesh generation.

Red Flags to Watch For

Debug Commands

# Validate mesh quality
python -m wonder3d.tools.validate_mesh \
    --input model.obj \
    --check_topology \
    --check_uv \
    --check_scale \
    --verbose

# Preview mesh and texture
python -m wonder3d.tools.viewer \
    --mesh model.obj \
    --texture texture.png

# Batch process directory
python batch_generate_3d.py \
    --input_dir ./photos \
    --output_dir ./output_3d \
    --reference_object coin \
    --texture_resolution 2048

Related Resources