render op• Data kinds: mesh → rgbimage
• Call: import fullseye as fs; fs.ledger.render_beauty(V, F, *, pose=None, intrinsics=None, size: 'int' = 512, ss: 'int' = 2, light: 'Sequence[float]' = (0.3, 0.4, 1.0), albedo: 'Sequence[float]' = (0.8, 0.8, 0.85), material: 'str' = 'plastic', matcap=None, ambient: 'float' = 0.12, ao: 'bool' = True, ground_shadow: 'bool' = True, tonemap: 'str' = 'reinhard', background: 'Sequence[float]' = (0.1, 0.11, 0.13), exposure: 'float' = 1.0, shininess: 'Optional[float]' = None, ao_samples: 'int' = 32, shadow_res: 'int' = 512, penumbra: 'float' = 2.5, shadow_samples: 'int' = 12, shadow_pcf: 'int' = 1, brdf: 'str' = 'phong', brdf_params=None, shadow_method: 'str' = 'map', sun_angular_diameter_deg: 'float' = 0.0, self_illumination: 'float' = 0.0, albedo_variation: 'float' = 0.0, albedo_scale=None, seed: 'int' = 0, smooth_normals: 'bool' = False, bump=None, vertex_normals=None, vertex_albedo=None, surface: 'str' = 'none', surface_params=None) -> 'np.ndarray' (to call the implementation directly, import render_beauty; render_beauty.render_beauty(V, F, *, pose=None, intrinsics=None, size: 'int' = 512, ss: 'int' = 2, light: 'Sequence[float]' = (0.3, 0.4, 1.0), albedo: 'Sequence[float]' = (0.8, 0.8, 0.85), material: 'str' = 'plastic', matcap=None, ambient: 'float' = 0.12, ao: 'bool' = True, ground_shadow: 'bool' = True, tonemap: 'str' = 'reinhard', background: 'Sequence[float]' = (0.1, 0.11, 0.13), exposure: 'float' = 1.0, shininess: 'Optional[float]' = None, ao_samples: 'int' = 32, shadow_res: 'int' = 512, penumbra: 'float' = 2.5, shadow_samples: 'int' = 12, shadow_pcf: 'int' = 1, brdf: 'str' = 'phong', brdf_params=None, shadow_method: 'str' = 'map', sun_angular_diameter_deg: 'float' = 0.0, self_illumination: 'float' = 0.0, albedo_variation: 'float' = 0.0, albedo_scale=None, seed: 'int' = 0, smooth_normals: 'bool' = False, bump=None, vertex_normals=None, vertex_albedo=None, surface: 'str' = 'none', surface_params=None) -> 'np.ndarray'; from the registry, ops3d.get("render_beauty"))
Render a mesh into one "showcase still 3-D" image with every quality layer combined → RGB (size, size, 3) float [0,1].
Arguments:
• V, F vertices (N,3) and triangles (M,3).
• pose 4x4 object->camera (render3d.look_at). None uses auto_view.
• intrinsics 3x3 pinhole K (for the target size, scaled internally by ss).
• size side length of the output (square). ss supersampling factor (integer >= 1).
• light light direction in world coordinates (scene→light source). Shared by the shading and the ground shadow.
• albedo reflectance colour RGB of the object. material 'plastic' | 'metal' | 'matcap'.
• matcap lit-sphere texture (h,w[,C]), required when material='matcap'.
• ambient ambient-light coefficient. ao whether to apply ambient occlusion.
• ground_shadow whether to bake in a ground plane + ground shadow.
• tonemap 'reinhard' | 'aces' | 'none'. background background colour RGB.
• exposure exposure before tone mapping. shininess gloss (None = material default).
• ao_samples / shadow_res / penumbra / shadow_samples quality/speed tuning (softness of the ground shadow etc.). penumbra is the angular radius of the light source [degrees], and the penumbra width is roughly "height of the occluder × tan(penumbra)". The default of 2.5 degrees gives an object at a height of 1 unit above the ground a penumbra of only 1 to 2 pixels (measured 2026-09-02: in a 320px picture the penumbra covers 283/102400 pixels, and there are only 7 distinct values = shadow_samples+1). If you want soft shadows, raise it to around 10 degrees and, so that the steps do not show, increase shadow_samples along with it.
• shadow_pcf neighbourhood radius [texel] blended when sampling the shadow map (default 1 = 3x3). With a lookup of only 1 point the shadow boundary is quantised to texels and becomes a staircase. Measured (largest change between adjacent pixels, measured on the ground only):
default 2.5 degrees, 12 rays, equivalent to pcf=0: 0.667;
12 degrees, 24 rays, pcf=1: 0.176 (steps above 1/6: 123→2).
• brdf reflectance law of the object. 'phong' (default = Lambert diffuse + cos^n specular as before) / 'lambert' / 'lommel_seeliger' / 'hapke' (planetary photometry, render_shade.brdf_shade). For anything other than phong the specular term is off, and albedo is applied as a tint normalised to mean 1 (the brightness is set by the single-scattering albedo w of brdf_params; it is not applied twice).
• brdf_params dict (w, g, B0, h, roughness_deg, multiple_scattering).
• shadow_method 'map' (default = shadow map + PCF) / 'raycast' (render_shadow.shadow_raycast, no staircase, no acne).
• sun_angular_diameter_deg apparent angular diameter of the light source for raycast (the Sun 0.53°). The penumbra width is "distance to the occluder × tan(diameter/2)" = a few cm on an asteroid (hard shadow).
• self_illumination coefficient of the single-bounce approximation from the terrain (default 0). bounce = coefficient × albedo colour × (1 − AO) × mean radiance of the lit faces -- an approximation in which the neighbouring terrain is visible over the occluded part of the hemisphere and glows with average brightness (not the exact solution of interreflection; requires ao=True). In space there is no ambient light, so with ambient=0 this alone sets the floor of the shadows.
• bump dict(wavelengths, amplitudes[, seed, nyquist, fade, complement_edges]) → perturbs the shading normals of the object pixels with render3d.bump_normals_fbm (gradient of a value-noise height field). The geometry (depth/shadow/AO) is unchanged. With complement_edges=True the local mesh edge length under each pixel is passed in by barycentric interpolation, and only the complement of the displacement's band gate goes into the bump (the same wavelength is not added twice).
fail-closed: bad shape, non-finite, empty, ss<1, invalid material/tonemap, invalid colour/light/exposure raise ValueError. Deterministic (no randomness).
• blender_interop — Using Blender alongside — build the shape, measure it with fullseye (pitfalls: axes, units, ground truth)
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• anatomical_hand — py -3.11 examples_3d/anatomical_hand.py
• render_beauty — py -3.11 examples_3d/render_beauty.py
rgbimage as input)render)project_points · render_point_depth · render_volume_projection · render_shaded · ambient_occlusion · cast_shadow · phong_shade · matcap_shade
*Provenance: render_beauty.py — 3D operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.