Key Concepts
A material in 3dverse defines the visual appearance of an entity. It is an asset, like scenes or meshes, and wraps a specific shader program along with its parameter bindings. More precisely, a material acts as a binding to a shader: it selects which shader to use and provides values for that shader’s inputs (uniforms and textures).
Materials provide the link between shaders and scene data: they declare which shader is used, and how its parameters are set.
Entities and Materials
To be visible in a scene, an entity must at least have:
- a mesh_ref component that references the geometry, and
- either:
- a material component, or
- a material_ref component.
Without these, the renderer cannot produce pixels for the entity.
When using the material
component, the shader inputs are stored inline on the entity.
When using the material_ref
component, they are stored in a dedicated material asset, outside of the scene.
Material vs Material Reference
There are two ways to assign materials to entities:
material
- Declares a material inline on the entity.
- References a shader directly and provides values for its attributes.
- Changes affect only this entity.
Use this when you need a one-off instance (e.g., make a single cube bright red without touching other cubes).
material_ref
- Points to a material asset stored in the project.
- The asset itself references a shader and defines its attributes.
- Multiple entities can share the same
material_ref
. - Updating the material asset propagates the changes to all entities referencing it.
This enables material reuse, allowing multiple entities to look consistent while being driven by a single shared asset.
Use this when you want consistent look across instances (e.g., all walls share a single “Concrete” material).
Diagram
material
→ inline, entity-local, changes affect only this entity.material_ref
→ points to a material asset in the project, changes propagate to all referencing entities.
Both connect to shaders, but the key difference is scope: local vs shared, entity data vs asset data.
Shader Parameters
A material exposes a set of uniform parameters and textures defined by its shader:
- Scalars & vectors (e.g., roughness, emissiveFactor).
- Textures (e.g., albedoMap, normalMap).
When you edit a material in the editor:
- For
material_ref
, you're editing the asset's parameters — changes apply to all references. - For
material
, you're editing local values stored directly on the entity.
Default PBR Shaders
3dverse ships with a default set of physically based rendering (PBR) shaders. They implement industry-standard workflows:
- Metallic–Roughness model (albedo, metallic, roughness, normal, occlusion, emissive).
- Energy conservation and Fresnel handling.
- Compatible with both rasterization and ray tracing pipelines.
You can use them directly, or extend them with custom shaders.
Material Assignment Strategy
The split between material
and material_ref
components is designed for efficient scene authoring:
- Use
material_ref
when many entities must share the same look, since the asset can be updated once and propagate everywhere. - Use
material
when the shader and parameters are defined directly on the entity itself, typically for unique or experimental cases.
This design enables you to balance consistency (centralized assets) and flexibility (per-entity definitions without asset duplication).
Imagine a scene with 100 chairs:
- Each chair entity has a
mesh_ref
→ChairMesh
. - All chairs share a
material_ref
→WoodVarnished
. - One chair has an inline
material
where you setalbedo = red
.
Now:
- Updating
WoodVarnished
in the asset browser will update 99 chairs. - The red chair stays red.
Recommended Practices
- Use material assets (
material_ref
component) for anything repeated. - Use inline materials (
material
component) for special cases or quick testing, since the data lives only on that entity. - Extend the default PBR shaders with custom ones when you need advanced effects.
Materials and Render Graphs
A material created for one render graph cannot be used in another with a different output contract. For example, a material targeting the Deferred PBR graph won’t be valid in a stylized forward graph.
A material is not universal — it only makes sense for the render graph it was created for.
The render graph defines the sequence of passes, attachments, and shader programs that produce the final frame. When you assign a material to an entity, you are effectively binding that entity’s attributes (uniforms, textures) into the shader inputs, while the render graph enforces a strict contract on the shader outputs.
The contract
-
Shader outputs must conform
- The number and semantics of the render targets a shader writes to are dictated by the render graph.
- Example: “the first render target must be albedo, the second must be normals.”
- Any shader used in materials for this render graph must write exactly those outputs, in that order.
- Failure to conform will result in the material being rejected or rendering incorrectly.
-
Inputs are flexible
- The inputs of a shader (its uniforms, textures) are defined entirely by the shader itself.
- A render graph may expose additional global resources (e.g. an SSAO buffer), but these are optional.
- A material may choose to use them or ignore them — this does not affect validity, as long as the outputs remain correct.
Consider two render graphs:
-
Deferred PBR graph
- Output contract:
- Render Target 0 → Albedo
- Render Target 1 → Normals
- Render Target 2 → Material properties (metallic, roughness, AO)
- Optional inputs provided: SSAO texture, shadow mask, reflection probes.
A PBR shader compiled for this graph must write values to all three render targets, in the specified order. It may use the SSAO or shadow mask if needed, but it can also ignore them — as long as the outputs are valid.
- Output contract:
-
Stylized forward graph
- Output contract:
- Render Target 0 → Final shaded color
- Optional inputs provided: None.
A cel-shading shader for this graph only needs to write one output (color). It may define its own inputs such as
tintColor
,rampTexture
, oroutlineWidth
. These inputs are completely under the shader’s control and are satisfied by the material. - Output contract:
Result: A material designed for the Deferred PBR graph cannot be reused in the Stylized graph because their output contracts differ. But within a given graph, different materials can define very different inputs — as long as their shaders write the expected outputs.
Key Takeaway
- Inputs: Defined by the shader author. These include uniforms and textures like
albedo
,roughness
, etc. Materials provide values for these. - Outputs: Dictated by the render graph. These define how the shader writes data to the pipeline (e.g. albedo, normals) and must be strictly matched.