mmatl / pyrender

Easy-to-use glTF 2.0-compliant OpenGL renderer for visualization of 3D scenes.
http://pyrender.readthedocs.io/
MIT License
1.31k stars 226 forks source link

how to achieve meshlab-like face shading effects #285

Open dengchcs opened 5 months ago

dengchcs commented 5 months ago

Hi, I wonder how to achieve meshlab's 'face shading' effects with pyrender, as this image shows: image

Currently what I got with pyrender resembles meshlab's 'shading: None' option, which is very blurry: image

I tried the following code and the ply mesh file is also uploaded here. Any help would be appreciated!

import math
import numpy as np
import trimesh
import pyrender
import matplotlib.pyplot as plt
import trimesh.visual

def get_pose(center, dist, azim, elev):
    elev = math.radians(elev)
    azim = math.radians(azim)
    x = dist * math.cos(elev) * math.sin(azim)
    y = dist * math.sin(elev)
    z = dist * math.cos(elev) * math.cos(azim)
    eye = np.array([x, y, z]) + center
    z_axis = eye - center
    y_axis = np.array([0, 1, 0])
    x_axis = np.cross(y_axis, z_axis)
    y_axis = np.cross(z_axis, x_axis)
    x_axis /= np.linalg.norm(x_axis)
    y_axis /= np.linalg.norm(y_axis)
    z_axis /= np.linalg.norm(z_axis)
    pose = np.eye(4)
    pose[:3, 0] = x_axis
    pose[:3, 1] = y_axis
    pose[:3, 2] = z_axis
    pose[:3, 3] = eye
    pose[3, 3] = 1
    return pose

fuze_trimesh: trimesh.Trimesh = trimesh.load_mesh('room.ply', force='mesh')
bbox = fuze_trimesh.bounds
bbox_min, bbox_max = bbox[0], bbox[1]
center = (bbox_min + bbox_max) / 2.0
scale = np.max(bbox_max - bbox_min)
fuze_trimesh.apply_translation(-center)
fuze_trimesh.apply_scale(1.0 / scale)

mesh = pyrender.Mesh.from_trimesh(fuze_trimesh)
scene = pyrender.Scene(ambient_light=[0.5, 0.5, 0.5], bg_color=[0.0, 0.0, 0.0])
scene.add(mesh)
camera = pyrender.PerspectiveCamera(yfov=np.pi / 2.0, aspectRatio=1.0, znear=0.01, zfar=10.0)
camera_pose = get_pose(center, 0.2, 30.0, 30.0)
scene.add(camera, pose=camera_pose, name="camera")

r = pyrender.OffscreenRenderer(1024, 1024)

color, depth = r.render(scene)
plt.figure()
plt.subplot(1,2,1)
plt.axis('off')
plt.imsave(f"color.png", color)
plt.subplot(1,2,2)
plt.axis('off')
plt.imsave(f"depth.png", depth)
plt.close()