Mesh¶
Description¶
Mesh is the base class for all renderable 3D objects. It exposes the material system (color, texture, PBR material), shadow casting and receiving, transparency control, face culling, automatic detail levels, and GPU instancing (including distance fade and per-view instance culling) for drawing thousands of objects in a single draw call.
Inherits: Object → EntityHandle
Constructors¶
Available in C++ and Lua:
Mesh(Scene* scene)— creates a new entity.Mesh(Scene* scene, Entity entity)— wraps an existing entity without taking ownership.
In Lua, use Mesh(scene, entity) to access an existing mesh. The entity must
already have the components required by this type; wrapping does not add them.
See EntityHandle ownership.
Properties¶
| Type | Name | Default | Languages |
|---|---|---|---|
| Vector4 | color | (1,1,1,1) |
C++ | Lua |
| float | alpha | 1.0 |
C++ | Lua |
| Material | material | default | C++ | Lua |
| PrimitiveType | primitiveType | TRIANGLES |
C++ | Lua |
| bool | faceCulling | true |
C++ | Lua |
| CullingMode | cullingMode | BACK |
C++ | Lua |
| WindingOrder | windingOrder | CCW |
C++ | Lua |
| bool | receiveLights | true |
C++ | Lua |
| bool | receiveIBL | false |
C++ | Lua |
| bool | castShadows | true |
C++ | Lua |
| bool | receiveShadows | true |
C++ | Lua |
| bool | lodEnabled | true |
C++ | Lua |
| float | lodBias | 1.0 |
C++ | Lua |
| bool | shadowsBillboard | true |
C++ | Lua |
| bool | renderInReflectionProbes | true |
C++ | Lua |
| bool | castShadowsWithTexture | false |
C++ | Lua |
| bool | transparent | false |
C++ | Lua |
| bool | autoTransparency | true |
C++ | Lua |
| string | customShader | "" |
C++ | Lua |
| string | customDepthShader | "" |
C++ | Lua |
| unsigned int | maxInstances | 100 |
C++ | Lua |
| bool | instancedBillboard | false |
C++ | Lua |
| bool | instancedCylindricalBillboard | false |
C++ | Lua |
| bool | distanceFade | false |
C++ | Lua |
| float | fadeStart | 0 |
C++ | Lua |
| float | fadeEnd | 0 |
C++ | Lua |
| bool | cullInstances | true |
C++ | Lua |
| float | cullDistance | 0 |
C++ | Lua |
Methods¶
| Returns | Name | Languages |
|---|---|---|
| bool | load | C++ | Lua |
| void | setTexture | C++ | Lua |
| void | setColor | C++ | Lua |
| Vector4 | getColor | C++ | Lua |
| void | setAlpha | C++ | Lua |
| float | getAlpha | C++ | Lua |
| void | setMaterial | C++ | Lua |
| Material | getMaterial | C++ | Lua |
| void | setPrimitiveType | C++ | Lua |
| PrimitiveType | getPrimitiveType | C++ | Lua |
| void | setFaceCulling | C++ | Lua |
| bool | isFaceCulling | C++ | Lua |
| void | setCullingMode | C++ | Lua |
| CullingMode | getCullingMode | C++ | Lua |
| void | setWindingOrder | C++ | Lua |
| WindingOrder | getWindingOrder | C++ | Lua |
| AABB | getAABB | C++ | Lua |
| AABB | getVerticesAABB | C++ | Lua |
| AABB | getWorldAABB | C++ | Lua |
| unsigned int | getNumSubmeshes | C++ | Lua |
| void | setReceiveLights | C++ | Lua |
| bool | isReceiveLights | C++ | Lua |
| void | setCastShadows | C++ | Lua |
| bool | isCastShadows | C++ | Lua |
| void | setReceiveShadows | C++ | Lua |
| bool | isReceiveShadows | C++ | Lua |
| void | setLodEnabled | C++ | Lua |
| bool | isLodEnabled | C++ | Lua |
| void | setLodBias | C++ | Lua |
| float | getLodBias | C++ | Lua |
| void | setShadowsBillboard | C++ | Lua |
| bool | isShadowsBillboard | C++ | Lua |
| void | setCastShadowsWithTexture | C++ | Lua |
| bool | isCastShadowsWithTexture | C++ | Lua |
| void | setTransparent | C++ | Lua |
| bool | isTransparent | C++ | Lua |
| void | setAutoTransparency | C++ | Lua |
| bool | isAutoTransparency | C++ | Lua |
| void | setCustomShader | C++ | Lua |
| string | getCustomShader | C++ | Lua |
| void | setCustomDepthShader | C++ | Lua |
| string | getCustomDepthShader | C++ | Lua |
| void | setShaderUniform | C++ | Lua |
| Vector4 | getShaderUniform | C++ | Lua |
| bool | removeShaderUniform | C++ | Lua |
| void | setAsMirror | C++ | Lua |
| void | removeMirror | C++ | Lua |
| bool | isMirror | C++ | Lua |
| void | createInstancedMesh | C++ | Lua |
| void | removeInstancedMesh | C++ | Lua |
| bool | hasInstancedMesh | C++ | Lua |
| void | addInstance | C++ | Lua |
| InstanceData& | getInstance | C++ | Lua |
| void | updateInstance | C++ | Lua |
| void | removeInstance | C++ | Lua |
| bool | isInstanceVisible | C++ | Lua |
| void | setInstanceVisible | C++ | Lua |
| void | updateInstances | C++ | Lua |
| size_t | getNumInstances | C++ | Lua |
| void | clearInstances | C++ | Lua |
| void | setInstancedBillboard | C++ | Lua |
| bool | isInstancedBillboard | C++ | Lua |
| void | setInstancedCylindricalBillboard | C++ | Lua |
| bool | isInstancedCylindricalBillboard | C++ | Lua |
| void | setMaxInstances | C++ | Lua |
| unsigned int | getMaxInstances | C++ | Lua |
| void | setDistanceFade | C++ | Lua |
| bool | isDistanceFade | C++ | Lua |
| void | setFadeRange | C++ | Lua |
| void | setFadeStart | C++ | Lua |
| float | getFadeStart | C++ | Lua |
| void | setFadeEnd | C++ | Lua |
| float | getFadeEnd | C++ | Lua |
| void | setCullInstances | C++ | Lua |
| bool | isCullInstances | C++ | Lua |
| void | setCullDistance | C++ | Lua |
| float | getCullDistance | C++ | Lua |
Enumerations¶
PrimitiveType¶
- TRIANGLES — Solid triangle meshes (default).
- TRIANGLE_STRIP — Triangle strip.
- POINTS — Renders each vertex as a point.
- LINES — Renders edges as lines.
CullingMode¶
- BACK — Culls back faces (default, outward-facing normals).
- FRONT — Culls front faces (useful for inside-out rendering).
WindingOrder¶
- CCW — Counter-clockwise winding defines the front face (OpenGL convention, default).
- CW — Clockwise winding defines the front face.
Property details¶
color¶
- Setter:
void setColor(Vector4 color) - Setter:
void setColor(float red, float green, float blue, float alpha) - Setter:
void setColor(float red, float green, float blue) - Getter:
Vector4 getColor() const
Tint color multiplied with the material texture. (1,1,1,1) means no tint.
alpha¶
- Setter:
void setAlpha(float alpha) - Getter:
float getAlpha() const
Shorthand for the alpha channel of color. Values below 1.0 require transparent to be enabled for correct rendering order.
material¶
- Setter:
void setMaterial(const Material& material)(all submeshes) - Setter:
void setMaterial(unsigned int submesh, const Material& material)(per submesh) - Getter:
Material getMaterial() const - Getter:
Material getMaterial(unsigned int submesh) const
PBR material descriptor. Contains base color, metallic/roughness factors, normal map, emissive settings, and shader overrides.
primitiveType¶
- Setter:
void setPrimitiveType(PrimitiveType primitiveType) - Getter:
PrimitiveType getPrimitiveType() const
GPU draw mode. Overloads are available per submesh.
faceCulling¶
- Setter:
void setFaceCulling(bool faceCulling) - Getter:
bool isFaceCulling() const
Enables or disables back-face culling globally for this mesh. Disable for double-sided geometry (e.g. leaves, cards): back faces are then lit with their normal flipped toward the viewer, as glTF double-sided materials are.
castShadows / receiveShadows¶
- Setter:
void setCastShadows(bool castShadows)/void setReceiveShadows(bool receiveShadows) - Getter:
bool isCastShadows() const/bool isReceiveShadows() const
Shadow participation flags. Enabling both adds depth-map cost; disable on distant or small objects for performance.
lodEnabled / lodBias¶
- lodEnabled Setter:
void setLodEnabled(bool lodEnabled) - lodEnabled Getter:
bool isLodEnabled() const - lodBias Setter:
void setLodBias(float lodBias) - lodBias Getter:
float getLodBias() const
Mesh detail levels. lodEnabled (default true) lets this mesh follow the scene's detail levels; turn it off to keep it at full detail, for example a hero asset whose silhouette must never change. Toggling it reloads the mesh. lodBias (default 1) scales how far detail is kept: above 1 keeps the source longer, below 1 drops to a coarser level sooner.
Nothing happens until the scene has meshLodEnabled on, which is off by default. Terrain and tilemaps ignore these flags and keep their own LOD.
renderInReflectionProbes¶
- Setter:
void setRenderInReflectionProbes(bool renderInReflectionProbes) - Getter:
bool isRenderInReflectionProbes() const
Whether the mesh is drawn into ReflectionProbe captures. Turn it off when an object surrounds or sits on a probe and would otherwise show up inside its own reflection. Normal rendering is unaffected — this only controls the capture pass.
Changing it re-captures every probe in the scene: a probe that already baked its cubemap keeps the old contents until it captures again.
receiveIBL¶
- Setter:
void setReceiveIBL(bool receiveIBL) - Getter:
bool isReceiveIBL() const
When true, the mesh samples image-based lighting: diffuse irradiance plus specular
reflections on top of punctual lights. The source is the scene's Sky environment, a
Reflection Probe whose volume covers the mesh, or both. Sky
lighting needs a Sky entity with a cubemap texture; probes need none. Also requires
Receive Lights enabled and surface normals.
Also settable in the editor on the Mesh component (Receive IBL); the flag is serialized with the scene. Metallic, low-roughness materials show the strongest reflections.
Beyond reflective materials, this is what keeps unlit sides of an object from going
flat. A surface no light reaches falls back to the scene's global illumination, which is
a single flat colour — with a bright white ambient it washes out to a pale grey. With
receiveIBL the same surface takes its colour from the sky instead. This shows up most
in mirrors, which
show the side of an object facing the mirror — usually the side the key light misses.
transparent / autoTransparency¶
- transparent Setter:
void setTransparent(bool transparent) - autoTransparency Setter:
void setAutoTransparency(bool autoTransparency)
transparent marks the mesh for the transparent render pass (sorted back-to-front). autoTransparency detects blending from the material (BLEND, or AUTO when the texture or factor is translucent) and enables the transparent pass automatically. A blended submesh keeps depth testing but disables depth writes in the colour pass so overlapping translucent surfaces composite correctly.
customShader¶
- Setter:
void setCustomShader(const std::string& path) - Getter:
std::string getCustomShader() const
Project-relative base path of a forked shader used for this mesh's colour pass — "shaders/wave" resolves to shaders/wave.vert and shaders/wave.frag, or "a.vert|b.frag" names the two files separately. Empty (default) uses the scene's defaultMeshShader, or the engine built-in when the scene has none. Changing it reloads the mesh. The engine loads the compiled shader; the sources are only needed by the editor. See Custom Shaders.
Like colour and material, this is per Mesh component: a multi-node glTF Model renders through its part entities, so assign the shader (and its uniforms) on the parts — Mesh(scene, partEntity) — not on the Model root, whose own Mesh is empty unless the model is merged or single-node.
customDepthShader¶
- Setter:
void setCustomDepthShader(const std::string& path) - Getter:
std::string getCustomDepthShader() const
Project-relative base path of a forked depth shader — the one the mesh is drawn with into shadow maps, into the optional scene depth prepass, and into the depth pre-pass that feeds SSAO and post-process depth while SSR is off. Same path forms as customShader; empty (default) uses the engine built-in, and there is no scene default. Fork it when the colour fork displaces vertices or discards fragments, so the shadow follows; it reads the same shader uniforms. Changing it reloads the mesh. See Custom Shaders — The Depth Shader row.
maxInstances¶
- Setter:
void setMaxInstances(unsigned int maxInstances) - Getter:
unsigned int getMaxInstances() const
Slots in the GPU instance buffer, 100 by default. Drawing clamps to it, but addInstance grows the cap as the list outgrows it — reloading the mesh each time — so the clamp only bites when the instance list is filled without going through addInstance. Set the capacity up front when the count is already known, to skip those reloads. Unlike the billboard setters, this one logs an error if the mesh is not instanced yet — call createInstancedMesh first.
instancedBillboard / instancedCylindricalBillboard¶
- Setter:
void setInstancedBillboard(bool billboard) - Setter:
void setInstancedBillboard(bool billboard, bool cylindrical) - Getters:
bool isInstancedBillboard() const,bool isInstancedCylindricalBillboard() const
Turns every instance to face the camera, the per-instance counterpart of Object.billboard. Both default to false, and instancedCylindricalBillboard only matters while instancedBillboard is on. The setters create the instanced mesh if it does not exist yet.
Cylindrical is not Y-only yet
The instanced path builds its rotation from the inverse view matrix whichever flag is set, so instanced cylindrical facing currently matches the spherical one. Object.cylindricalBillboard does constrain to Y.
distanceFade / fadeStart / fadeEnd¶
- distanceFade Setter:
void setDistanceFade(bool distanceFade) - distanceFade Getter:
bool isDistanceFade() const - Setter:
void setFadeRange(float fadeStart, float fadeEnd) - fadeStart Setter / Getter:
void setFadeStart(float fadeStart)/float getFadeStart() const - fadeEnd Setter / Getter:
void setFadeEnd(float fadeEnd)/float getFadeEnd() const
Instanced-mesh distance fade. When distanceFade is on, instances shrink toward their base between fadeStart and fadeEnd, both model-space distances from the camera. Toggling the flag reloads the mesh (shader variant Ifd); the two distances are uniforms and can change without a reload. Fade End must be greater than Fade Start. Logs an error if the mesh is not instanced yet.
On the built-in triangle shaders, instances past fadeEnd are also omitted from the draw. Custom shaders and the SSR G-buffer still submit them and rely on the vertex scale.
cullInstances¶
- Setter:
void setCullInstances(bool cullInstances) - Getter:
bool isCullInstances() const
When true (default), instances outside the main camera or a shadow atlas slot are left out of that view. Turn it off when a shader moves instances away from the bounds the CPU computed; the whole entity then skips frustum culling too. Logs an error if the mesh is not instanced yet. See Culling granularity.
cullDistance¶
- Setter:
void setCullDistance(float distance) - Getter:
float getCullDistance() const
World-space distance from the main camera past which instances are dropped from the culled views (main camera and shadow slots). 0 (default) means unlimited; negative or non-finite values are ignored. A hard cut, unlike distanceFade: instances keep their size until they vanish, and it applies with custom shaders and SSR too, so hide it with fog. Requires cullInstances. Logs an error if the mesh is not instanced yet.
Method details¶
load¶
bool load()
Uploads geometry and material resources to the GPU. Must be called after building or modifying geometry programmatically. Subclasses like Sprite call this internally when needed.
setTexture¶
void setTexture(const std::string& path)void setTexture(const std::string& id, TextureData data)void setTexture(Framebuffer* framebuffer)
Assigns the diffuse/base-color texture. Accepts a file path, raw TextureData, or a framebuffer render target.
setAsMirror / removeMirror / isMirror¶
void setAsMirror()— turn this flat mesh into a planar reflection surface, using the default+Znormal (matching a Wall).void setAsMirror(Vector3 normal)— same, with an explicit surface normal in local space (e.g.Vector3(0, 1, 0)for acreatePlanefloor).void removeMirror()— stop being a mirror.bool isMirror() const— whether this mesh is currently a mirror.
The engine creates and drives the reflection camera internally and feeds its render
target to the mesh's base texture — no camera setup is required. Set receiveLights to
false for a reflection shown without surface shading. See
Rendering Pipeline — Mirrors.
Use these to make an existing mesh reflective. To create a mirror outright, the Mirror class does both steps at once and exposes the surface normal as a property.
setShaderUniform¶
void setShaderUniform(const std::string& name, const Vector4& value)void setShaderUniform(const std::string& name, const Vector3& value)void setShaderUniform(const std::string& name, const Vector2& value)void setShaderUniform(const std::string& name, float value)Vector4 getShaderUniform(const std::string& name) constbool removeShaderUniform(const std::string& name)
Values for the members of the custom shader's u_vs_customParams / u_fs_customParams
blocks, keyed by member name (see Custom Shaders — Shader uniforms).
A value is stored on the mesh and applied to every submesh — of the colour fork and of the
depth fork alike; a narrower value leaves the
remaining components at zero, and an int member takes the truncated value. Setting a
value only rewrites the uploaded block, so it can be called every frame. Names the shader
does not declare are kept but unused, and a member with no value reads zero.
getShaderUniform returns the stored value (zero when unset) — the value list, not the
uploaded block, so an int member set to 3.7 reads back 3.7 while the shader sees 3,
and the engine-written names are not in it. removeShaderUniform drops a value and returns
whether it existed; the member reads zero again. Matrix and array members take no value.
Two names are reserved and written by the engine every frame — time (wall-clock seconds
since startup, the same clock as Engine.systemTime; it does not
stop for a pause) and resolution
(xy = size of the render target the mesh is drawn into, zw = 1 / size); setting
either logs an error. For a glTF model, call this on the part entities (see
customShader).
getAABB / getVerticesAABB / getWorldAABB¶
AABB getAABB() const— Axis-aligned bounding box of the mesh in local space.AABB getVerticesAABB() const— AABB computed from raw vertex positions, ignoring the transform.AABB getWorldAABB() const— AABB in world space after applying the full transform chain.
Useful for frustum culling, click picking, and physics proxy fitting.
getNumSubmeshes¶
unsigned int getNumSubmeshes() const
Returns the number of submeshes. Each submesh can have its own material, primitive type, and culling settings.
createInstancedMesh¶
void createInstancedMesh()
Enables GPU instancing for this mesh. After calling this, use addInstance / updateInstance to populate the instance list, then updateInstances to flush changes to the GPU.
Instancing draws geometry on this entity only. Multi-node GLTF models that keep child mesh entities need static merge first (or use a single-mesh / procedural mesh).
addInstance¶
void addInstance(InstanceData instance)void addInstance(Vector3 position)void addInstance(float x, float y, float z)void addInstance(Vector3 position, Quaternion rotation, Vector3 scale)void addInstance(Vector3 position, Quaternion rotation, Vector3 scale, Vector4 color)void addInstance(Vector3 position, Quaternion rotation, Vector3 scale, Vector4 color, Rect textureRect)
Appends a new instance with the specified transform, creating the instanced mesh if the entity does not have one yet. Growing past maxInstances doubles the capacity and reloads the mesh.
updateInstance¶
void updateInstance(size_t index, InstanceData instance)(and overloads)
Replaces the data for an existing instance at index. Call updateInstances afterwards to sync changes to the GPU.
updateInstances¶
void updateInstances()
Uploads all pending instance data changes to the GPU vertex buffer. Must be called after any addInstance or updateInstance calls.
clearInstances¶
void clearInstances()
Removes all instances from the instance list. The mesh geometry is preserved; call updateInstances afterwards.