Overview
RenderableManager is the factory and manager for renderables, which are entities that can be drawn. Renderables are bundles of primitives, each of which has its own geometry and material. All primitives in a particular renderable share a set of rendering attributes, such as whether they cast shadows or use vertex skinning.
Key Concepts
- Renderables: Entities that can be drawn in a Scene
- Primitives: Individual geometry components within a renderable
- Instance: A temporary handle to access renderable state
Builder
The Builder class is used to add renderable components to entities.
Constructor
explicit Builder(size_t count) noexcept
Creates a builder for renderable components.
The number of primitives that will be supplied to the builder
Example:
// Create renderable with 2 primitives
RenderableManager::Builder builder(2);
Geometry Methods
geometry
Builder& geometry(
size_t index,
PrimitiveType type,
VertexBuffer* vertices,
IndexBuffer* indices,
size_t offset,
size_t minIndex,
size_t maxIndex,
size_t count
) noexcept
Specifies the geometry data for a primitive.
Zero-based index of the primitive, must be less than count passed to constructor
The topology of the primitive (e.g., TRIANGLES, LINES, POINTS)
The vertex buffer containing vertex attributes
The index buffer (either uint16 or uint32)
Where in the index buffer to start reading (expressed as number of indices)
Minimum index contained in the index buffer
Maximum index contained in the index buffer
Number of indices to read (for triangles, should be multiple of 3)
Returns: Reference to this Builder for chaining calls.
PrimitiveType enum values:
POINTS - Point primitives
LINES - Line primitives
LINE_STRIP - Line strip
TRIANGLES - Triangle primitives
TRIANGLE_STRIP - Triangle strip
Simplified overloads:
Builder& geometry(
size_t index,
PrimitiveType type,
VertexBuffer* vertices,
IndexBuffer* indices,
size_t offset,
size_t count
) noexcept
Builder& geometry(
size_t index,
PrimitiveType type,
VertexBuffer* vertices,
IndexBuffer* indices
) noexcept
geometryType
Builder& geometryType(GeometryType type) noexcept
Specifies the type of geometry for this renderable.
Returns: Reference to this Builder for chaining calls.
GeometryType enum values:
DYNAMIC - Dynamic geometry has no restrictions (default)
STATIC_BOUNDS - Bounds and world-space transform are immutable
STATIC - Skinning/morphing not allowed and VertexBuffer/IndexBuffer immutable
material
Builder& material(
size_t index,
MaterialInstance const* materialInstance
) noexcept
Binds a material instance to the specified primitive.
Zero-based index of the primitive
materialInstance
MaterialInstance const*
required
The material to bind
Returns: Reference to this Builder for chaining calls.
If no material is specified for a primitive, Filament will fall back to a basic default material.
Bounding Box
boundingBox
Builder& boundingBox(const Box& axisAlignedBoundingBox) noexcept
Sets the axis-aligned bounding box of the renderable.
Object-space AABB used for frustum culling
Returns: Reference to this Builder for chaining calls.
This is an object-space AABB used for frustum culling. For skinning and morphing, this should encompass all possible vertex positions. It is mandatory unless culling is disabled.
Example:
builder.boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }});
Layer and Visibility
layerMask
Builder& layerMask(uint8_t select, uint8_t values) noexcept
Sets bits in a visibility mask. By default, this is 0x1.
The set of bits to affect
The replacement values for the affected bits
Returns: Reference to this Builder for chaining calls.
Example:
// Set bit 1 and reset bits 0 and 2 while leaving other bits unaffected
builder.layerMask(7, 2);
Drawing Order
priority
Builder& priority(uint8_t priority) noexcept
Provides coarse-grained control over draw order.
Priority value clamped to range [0..7], defaults to 4. Higher values mean lower priority (rendered last)
Returns: Reference to this Builder for chaining calls.
Priority is applied separately for opaque and translucent objects. Opaque objects are always drawn before translucent objects regardless of priority. The Skybox uses priority 7 (lowest).
channel
Builder& channel(uint8_t channel) noexcept
Sets the channel this renderable is associated with.
Channel value clamped to range [0..7], defaults to 2
Returns: Reference to this Builder for chaining calls.
All renderables in a given channel are rendered together, regardless of anything else. Channels enforce the strongest ordering. The default channel is 2.
Channels 0 and 1 may not have render primitives using a material with refractionType set to screenspace.
blendOrder
Builder& blendOrder(size_t primitiveIndex, uint16_t order) noexcept
Sets the drawing order for blended primitives.
The primitive of interest
Draw order number (0 by default). Only the lowest 15 bits are used
Returns: Reference to this Builder for chaining calls.
globalBlendOrderEnabled
Builder& globalBlendOrderEnabled(size_t primitiveIndex, bool enabled) noexcept
Sets whether the blend order is global or local to this Renderable.
The primitive of interest
true for global, false for local blend ordering (default)
Returns: Reference to this Builder for chaining calls.
Culling and Visibility
culling
Builder& culling(bool enable) noexcept
Controls frustum culling, true by default.
Whether to enable frustum culling
Returns: Reference to this Builder for chaining calls.
Do not confuse frustum culling with backface culling. Backface culling is controlled via the material.
lightChannel
Builder& lightChannel(unsigned int channel, bool enable = true) noexcept
Enables or disables a light channel. Light channel 0 is enabled by default.
Light channel to enable or disable, between 0 and 7
Whether to enable or disable the light channel (default true)
Returns: Reference to this Builder for chaining calls.
Shadows
castShadows
Builder& castShadows(bool enable) noexcept
Controls if this renderable casts shadows, false by default.
Whether to enable shadow casting
Returns: Reference to this Builder for chaining calls.
If the View’s shadow type is set to ShadowType::VSM, castShadows should only be disabled if either receiveShadows is also disabled OR the object is guaranteed to not cast shadows on itself or other objects.
receiveShadows
Builder& receiveShadows(bool enable) noexcept
Controls if this renderable receives shadows, true by default.
Whether to enable shadow receiving
Returns: Reference to this Builder for chaining calls.
Builder& screenSpaceContactShadows(bool enable) noexcept
Controls if this renderable uses screen-space contact shadows (off by default).
Whether to enable screen-space contact shadows
Returns: Reference to this Builder for chaining calls.
This is more expensive but can improve shadow quality, especially in large scenes.
Skinning
enableSkinningBuffers
Builder& enableSkinningBuffers(bool enabled = true) noexcept
Allows bones to be swapped out and shared using SkinningBuffer.
If true, enables buffer object mode. False by default
Returns: Reference to this Builder for chaining calls.
If skinning buffer mode is enabled, clients must call setSkinningBuffer() rather than setBones().
skinning (with SkinningBuffer)
Builder& skinning(
SkinningBuffer* skinningBuffer,
size_t count,
size_t offset
) noexcept
Enables GPU vertex skinning for up to 255 bones using a SkinningBuffer.
The SkinningBuffer to use
Number of bone transforms (up to 255)
Offset in the SkinningBuffer
Returns: Reference to this Builder for chaining calls.
Skinning Buffer mode must be enabled. Each vertex can be affected by up to 4 bones. The VertexBuffer must provide BONE_INDICES (uvec4) and BONE_WEIGHTS (float4).
Builder& skinning(size_t boneCount, math::mat4f const* transforms) noexcept
Builder& skinning(size_t boneCount, Bone const* bones) noexcept
Builder& skinning(size_t boneCount) noexcept
Enables GPU vertex skinning for up to 255 bones using transform matrices or Bone structures.
Number of bone transforms (0 to disable, up to 255)
The initial set of transforms (one for each bone)
The initial set of bones (quaternion + translation)
Returns: Reference to this Builder for chaining calls.
Bone structure:
struct Bone {
math::quatf unitQuaternion = { 1.f, 0.f, 0.f, 0.f };
math::float3 translation = { 0.f, 0.f, 0.f };
float reserved = 0;
};
boneIndicesAndWeights
Builder& boneIndicesAndWeights(
size_t primitiveIndex,
math::float2 const* indicesAndWeights,
size_t count,
size_t bonesPerVertex
) noexcept
Defines bone indices and weights pairs for advanced vertex skinning.
Zero-based index of the primitive
indicesAndWeights
math::float2 const*
required
Pairs of bone index and bone weight for all vertices sequentially. The x component is the bone index, y is the weight
Number of all pairs, must be a multiple of vertexCount. count = vertexCount * bonesPerVertex
Number of bone pairs per vertex (can exceed 4)
Returns: Reference to this Builder for chaining calls.
This substitutes BONE_INDICES and BONE_WEIGHTS defined in VertexBuffer. All bone weights of one vertex should sum to one; otherwise they will be normalized.
Morphing
morphing (legacy)
Builder& morphing(size_t targetCount) noexcept
Enables legacy vertex morphing targets (up to 4 targets).
Number of morph targets (0 to disable, up to 4)
Returns: Reference to this Builder for chaining calls.
Legacy morphing only supports up to 4 morph targets and will be deprecated. Use MorphTargetBuffer instead for standard morphing.
morphing (standard)
Builder& morphing(MorphTargetBuffer* morphTargetBuffer) noexcept
Enables standard vertex morphing using a MorphTargetBuffer.
morphTargetBuffer
MorphTargetBuffer*
required
The morph target buffer to use
Returns: Reference to this Builder for chaining calls.
Standard morphing supports up to CONFIG_MAX_MORPH_TARGET_COUNT targets.
Builder& morphing(
uint8_t level,
size_t primitiveIndex,
size_t offset
) noexcept
Specifies the range of the MorphTargetBuffer to use with a primitive.
The level of detail (only 0 can be specified currently)
Zero-based index of the primitive
Offset in the morph target buffer (expressed as number of vertices)
Returns: Reference to this Builder for chaining calls.
Fog
fog
Builder& fog(bool enabled = true) noexcept
Controls if this renderable is affected by large-scale fog.
If true, enables large-scale fog on this object (default is true)
Returns: Reference to this Builder for chaining calls.
Instancing
instances (count only)
Builder& instances(size_t instanceCount) noexcept
Specifies the number of draw instances of this renderable.
The number of instances, silently clamped between 1 and 32767
Returns: Reference to this Builder for chaining calls.
All instances are culled using the same bounding box. The material must set its instanced parameter to true to use getInstanceIndex() in shaders.
instances (with InstanceBuffer)
Builder& instances(
size_t instanceCount,
InstanceBuffer* instanceBuffer
) noexcept
Specifies the number of instances and an InstanceBuffer containing their local transforms.
The number of instances, clamped between 1 and Engine::getMaxAutomaticInstances()
An InstanceBuffer containing at least instanceCount transforms
Returns: Reference to this Builder for chaining calls.
Only the VERTEX_DOMAIN_OBJECT vertex domain is supported.
build
Result build(Engine& engine, utils::Entity entity)
Adds the Renderable component to an entity.
Reference to the filament::Engine to associate this Renderable with
Entity to add the Renderable component to
Returns: Success if the component was created successfully, Error otherwise.
If this component already exists on the given entity and the construction is successful, it is first destroyed. In case of error, the existing component is unmodified.
Example:
utils::Entity entity = utils::EntityManager::get().create();
RenderableManager::Builder(1)
.boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }})
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES,
vertexBuffer, indexBuffer, 0, 3)
.receiveShadows(false)
.build(*engine, entity);
scene->addEntity(entity);
RenderableManager Methods
Component Management
hasComponent
bool hasComponent(utils::Entity e) const noexcept
Checks if the given entity already has a renderable component.
Returns: true if the entity has a renderable component.
getInstance
Instance getInstance(utils::Entity e) const noexcept
Gets a temporary handle that can be used to access the renderable state.
Entity to get instance for
Returns: Non-zero Instance handle if the entity has a renderable component, 0 otherwise.
getEntity
utils::Entity getEntity(Instance i) const noexcept
Retrieves the Entity of the component from its Instance.
Instance of the component obtained from getInstance()
Returns: The entity associated with the instance.
destroy
void destroy(utils::Entity e) noexcept
Destroys the renderable component in the given entity.
Entity to remove renderable from
Bounding Box
setAxisAlignedBoundingBox
void setAxisAlignedBoundingBox(Instance instance, const Box& aabb)
Changes the bounding box used for frustum culling.
Instance of the component
New axis-aligned bounding box
The renderable must not have static geometry enabled.
getAxisAlignedBoundingBox
const Box& getAxisAlignedBoundingBox(Instance instance) const noexcept
Gets the bounding box used for frustum culling.
Instance of the component
Returns: The current axis-aligned bounding box.
Layer Mask and Priority
setLayerMask
void setLayerMask(Instance instance, uint8_t select, uint8_t values) noexcept
Changes the visibility bits.
Instance of the component
New values for selected bits
getLayerMask
uint8_t getLayerMask(Instance instance) const noexcept
Gets the visibility bits.
Instance of the component
Returns: The current layer mask.
setPriority
void setPriority(Instance instance, uint8_t priority) noexcept
Changes the coarse-level draw ordering.
Instance of the component
getPriority
uint8_t getPriority(Instance instance) const noexcept
Gets the coarse-level draw ordering.
Instance of the component
Returns: The current priority.
setChannel
void setChannel(Instance instance, uint8_t channel) noexcept
Changes the channel a renderable is associated with.
Instance of the component
getChannel
uint8_t getChannel(Instance instance) const noexcept
Gets the channel a renderable is associated with.
Instance of the component
Returns: The current channel.
Culling and Visibility
setCulling
void setCulling(Instance instance, bool enable) noexcept
Changes whether frustum culling is on.
Instance of the component
Whether to enable culling
isCullingEnabled
bool isCullingEnabled(Instance instance) const noexcept
Gets whether frustum culling is on.
Instance of the component
Returns: true if culling is enabled.
setFogEnabled
void setFogEnabled(Instance instance, bool enable) noexcept
Changes whether large-scale fog is applied to this renderable.
Instance of the component
getFogEnabled
bool getFogEnabled(Instance instance) const noexcept
Returns whether large-scale fog is enabled for this renderable.
Instance of the component
Returns: true if fog is enabled.
setLightChannel
void setLightChannel(Instance instance, unsigned int channel, bool enable) noexcept
Enables or disables a light channel.
Instance of the component
Whether to enable the channel
getLightChannel
bool getLightChannel(Instance instance, unsigned int channel) const noexcept
Returns whether a light channel is enabled.
Instance of the component
Light channel to query (0-7)
Returns: true if the light channel is enabled.
Shadow Methods
setCastShadows
void setCastShadows(Instance instance, bool enable) noexcept
Changes whether the renderable casts shadows.
Instance of the component
Whether to enable shadow casting
setReceiveShadows
void setReceiveShadows(Instance instance, bool enable) noexcept
Changes whether the renderable can receive shadows.
Instance of the component
Whether to enable shadow receiving
void setScreenSpaceContactShadows(Instance instance, bool enable) noexcept
Changes whether the renderable can use screen-space contact shadows.
Instance of the component
Whether to enable screen-space contact shadows
isShadowCaster
bool isShadowCaster(Instance instance) const noexcept
Checks if the renderable can cast shadows.
Instance of the component
Returns: true if shadow casting is enabled.
isShadowReceiver
bool isShadowReceiver(Instance instance) const noexcept
Checks if the renderable can receive shadows.
Instance of the component
Returns: true if shadow receiving is enabled.
bool isScreenSpaceContactShadowsEnabled(Instance instance) const noexcept
Checks if the renderable can use screen-space contact shadows.
Instance of the component
Returns: true if screen-space contact shadows are enabled.
Skinning Methods
setBones
void setBones(
Instance instance,
Bone const* transforms,
size_t boneCount = 1,
size_t offset = 0
)
void setBones(
Instance instance,
math::mat4f const* transforms,
size_t boneCount = 1,
size_t offset = 0
)
Updates the bone transforms in the range [offset, offset + boneCount).
Instance of the component
transforms
Bone const* or math::mat4f const*
required
Array of bone transforms
Number of bones to update (default 1)
Starting offset for update (default 0)
The bones must be pre-allocated using Builder::skinning().
setSkinningBuffer
void setSkinningBuffer(
Instance instance,
SkinningBuffer* skinningBuffer,
size_t count,
size_t offset
)
Associates a region of a SkinningBuffer to a renderable instance.
Instance of the component
Skinning buffer to associate
Size of the region in bones (must be less than or equal to 256)
Start offset of the region in bones
Due to hardware limitations, offset + 256 must be smaller or equal to skinningBuffer->getBoneCount().
Morphing Methods
setMorphWeights
void setMorphWeights(
Instance instance,
float const* weights,
size_t count,
size_t offset = 0
)
Updates the vertex morphing weights on a renderable.
Instance of the component
Pointer to morph target weights to update
Number of morph target weights
Index of the first morph target weight to set (default 0)
The renderable must be built with morphing enabled. In legacy morphing mode, only the first 4 weights are considered.
setMorphTargetBufferOffsetAt
void setMorphTargetBufferOffsetAt(
Instance instance,
uint8_t level,
size_t primitiveIndex,
size_t offset
)
Associates a MorphTargetBuffer to the given primitive.
Instance of the component
Level of detail (only 0 is currently supported)
getMorphTargetBuffer
MorphTargetBuffer* getMorphTargetBuffer(Instance instance) const noexcept
Gets the MorphTargetBuffer for the given renderable or null if it doesn’t exist.
Instance of the component
Returns: Pointer to MorphTargetBuffer or nullptr.
getMorphTargetCount
size_t getMorphTargetCount(Instance instance) const noexcept
Gets the number of morphing targets in the given entity.
Instance of the component
Returns: Number of morph targets.
Primitive Methods
getPrimitiveCount
size_t getPrimitiveCount(Instance instance) const noexcept
Gets the immutable number of primitives in the given renderable.
Instance of the component
Returns: Number of primitives.
setMaterialInstanceAt
void setMaterialInstanceAt(
Instance instance,
size_t primitiveIndex,
MaterialInstance const* materialInstance
)
Changes the material instance binding for the given primitive.
Instance of the component
materialInstance
MaterialInstance const*
required
New material instance to bind
getMaterialInstanceAt
MaterialInstance* getMaterialInstanceAt(
Instance instance,
size_t primitiveIndex
) const noexcept
Retrieves the material instance that is bound to the given primitive.
Instance of the component
Returns: Pointer to the MaterialInstance or nullptr.
setGeometryAt
void setGeometryAt(
Instance instance,
size_t primitiveIndex,
PrimitiveType type,
VertexBuffer* vertices,
IndexBuffer* indices,
size_t offset,
size_t count
) noexcept
Changes the geometry for the given primitive.
Instance of the component
setBlendOrderAt
void setBlendOrderAt(
Instance instance,
size_t primitiveIndex,
uint16_t order
) noexcept
Changes the drawing order for blended primitives.
Instance of the component
Draw order number (only lowest 15 bits used)
getBlendOrderAt
uint16_t getBlendOrderAt(
Instance instance,
size_t primitiveIndex
) const noexcept
Gets the drawing order for blended primitives.
Instance of the component
Returns: The blend order value.
setGlobalBlendOrderEnabledAt
void setGlobalBlendOrderEnabledAt(
Instance instance,
size_t primitiveIndex,
bool enabled
) noexcept
Changes whether the blend order is global or local to this Renderable.
Instance of the component
true for global, false for local blend ordering
getEnabledAttributesAt
AttributeBitset getEnabledAttributesAt(
Instance instance,
size_t primitiveIndex
) const noexcept
Retrieves the set of enabled attribute slots in the given primitive’s VertexBuffer.
Instance of the component
Returns: Bitset of enabled attributes.
Utility Methods
computeAABB
template<typename VECTOR, typename INDEX>
static Box computeAABB(
VECTOR const* vertices,
INDEX const* indices,
size_t count,
size_t stride = sizeof(VECTOR)
) noexcept
Utility method that computes the axis-aligned bounding box from a set of vertices.
Pointer to vertex data (float3, float4, half3, or half4)
Pointer to index data (uint16_t or uint32_t)
Stride between vertices in bytes (default is sizeof(VECTOR))
Returns: Computed axis-aligned bounding box.
Example:
math::float3 vertices[] = { /* ... */ };
uint16_t indices[] = { /* ... */ };
Box aabb = RenderableManager::computeAABB(
vertices, indices, sizeof(indices) / sizeof(uint16_t)
);
Example Usage
#include <filament/Engine.h>
#include <filament/RenderableManager.h>
#include <filament/VertexBuffer.h>
#include <filament/IndexBuffer.h>
#include <filament/Material.h>
#include <filament/Scene.h>
#include <utils/EntityManager.h>
// Create entity
utils::Entity entity = utils::EntityManager::get().create();
// Create vertex and index buffers
VertexBuffer* vb = VertexBuffer::Builder()
.vertexCount(3)
.bufferCount(1)
.attribute(VertexAttribute::POSITION, 0,
VertexBuffer::AttributeType::FLOAT2, 0, 12)
.attribute(VertexAttribute::COLOR, 0,
VertexBuffer::AttributeType::UBYTE4, 8, 12)
.normalized(VertexAttribute::COLOR)
.build(*engine);
IndexBuffer* ib = IndexBuffer::Builder()
.indexCount(3)
.bufferType(IndexBuffer::IndexType::USHORT)
.build(*engine);
// Build renderable
RenderableManager::Builder(1)
.boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }})
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vb, ib, 0, 3)
.receiveShadows(false)
.castShadows(false)
.culling(false)
.build(*engine, entity);
// Add to scene
scene->addEntity(entity);
// Get instance and modify at runtime
auto& rcm = engine->getRenderableManager();
auto instance = rcm.getInstance(entity);
rcm.setCastShadows(instance, true);
rcm.setPriority(instance, 6);
// Cleanup
rcm.destroy(entity);
utils::EntityManager::get().destroy(entity);