Skip to content

Commit

Permalink
Fix multi-materials on VoxelLodTerrain (not full support).
Browse files Browse the repository at this point in the history
This allows using VoxelMesherBlocky materials.
If a non-ShaderMaterial is set on the terrain, it acts as override.
If a ShaderMaterial is assigned on the terrain, things might not work.
Multi-material requires that we also detect whether each of them is
a ShaderMaterial in order to support LOD features such as:
- Per block info
- Transition masks
- Detail textures
- Fading
When using the blocky mesher, not all of this is useful, so it won't be
trivial to implement this in an optimal way. Per-instance uniforms
are still an option eventually, but not every renderer supports them and
they seem to require adjustment (buffer size) otherwise they throw errors
  • Loading branch information
Zylann committed Jun 9, 2024
1 parent 9e110fc commit 7eb9aec
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 25 deletions.
35 changes: 19 additions & 16 deletions terrain/variable_lod/voxel_lod_terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,7 @@ void VoxelLodTerrain::set_material(Ref<Material> p_material) {
// No visuals loaded (collision only?)
return;
}
block.set_shader_material(Ref<ShaderMaterial>());

Ref<Mesh> mesh = block.get_mesh();
if (mesh.is_valid()) {
const int surface_count = mesh->get_surface_count();
for (int surface_index = 0; surface_index < surface_count; ++surface_index) {
mesh->surface_set_material(surface_index, p_material);
}
}
block.set_material_override(p_material);
});
}
}
Expand Down Expand Up @@ -1833,22 +1825,30 @@ void VoxelLodTerrain::apply_mesh_update(VoxelEngine::BlockMeshOutput &ob) {

Ref<ArrayMesh> mesh;
if (ob.visual_was_required && visual_expected) {
// TODO Candidate for temp allocator
StdVector<uint16_t> material_indices;
if (ob.has_mesh_resource) {
// The mesh was already built as part of the threaded task
mesh = ob.mesh;
// It can be empty
if (mesh.is_valid()) {
const unsigned int surface_count = mesh->get_surface_count();
for (unsigned int surface_index = 0; surface_index < surface_count; ++surface_index) {
mesh->surface_set_material(surface_index, _material);
}
}
material_indices = std::move(ob.mesh_material_indices);
} else {
// Can't build meshes in threads, do it here
mesh = build_mesh(
to_span_const(mesh_data.surfaces), mesh_data.primitive_type, mesh_data.mesh_flags, _material
to_span_const(ob.surfaces.surfaces),
mesh_data.primitive_type,
mesh_data.mesh_flags,
material_indices
);
}
if (mesh.is_valid()) {
const unsigned int surface_count = mesh->get_surface_count();
for (unsigned int surface_index = 0; surface_index < surface_count; ++surface_index) {
const unsigned int material_index = material_indices[surface_index];
Ref<Material> material = _mesher->get_material_by_index(material_index);
mesh->surface_set_material(surface_index, material);
}
}
}

// TODO We could simplify this by having a flag returned by MeshTask saying it's actually empty
Expand Down Expand Up @@ -1935,6 +1935,9 @@ void VoxelLodTerrain::apply_mesh_update(VoxelEngine::BlockMeshOutput &ob) {
// Set individual shader material, because each block can have dynamic parameters,
// used to smooth seams without re-uploading meshes and allow to implement LOD fading
block->set_shader_material(sm);

} else if (_material.is_valid()) {
block->set_material_override(_material);
}

block->set_transition_mask(transition_mask);
Expand Down
33 changes: 24 additions & 9 deletions terrain/variable_lod/voxel_mesh_block_vlt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,23 +214,38 @@ void VoxelMeshBlockVLT::_set_visible(bool visible) {
void VoxelMeshBlockVLT::set_shader_material(Ref<ShaderMaterial> material) {
_shader_material = material;

set_material_override_internal(material);

if (_shader_material.is_valid()) {
const Transform3D local_transform(Basis(), _position_in_voxels);
const VoxelStringNames &sn = VoxelStringNames::get_singleton();
_shader_material->set_shader_parameter(sn.u_block_local_transform, local_transform);
_shader_material->set_shader_parameter(sn.u_voxel_virtual_texture_offset_scale, Vector4(0, 0, 0, 1));
}
}

void VoxelMeshBlockVLT::set_material_override(Ref<Material> material) {
#ifdef DEBUG_ENABLED
Ref<ShaderMaterial> sm = material;
if (sm.is_valid()) {
ZN_PRINT_ERROR("Internal bug: should use set_shader_material instead of set_material_override");
}
#endif
_shader_material = Ref<ShaderMaterial>();
set_material_override_internal(material);
}

void VoxelMeshBlockVLT::set_material_override_internal(Ref<Material> material) {
if (_mesh_instance.is_valid()) {
_mesh_instance.set_material_override(_shader_material);
_mesh_instance.set_material_override(material);

for (int dir = 0; dir < Cube::SIDE_COUNT; ++dir) {
DirectMeshInstance &mi = _transition_mesh_instances[dir];
if (mi.is_valid()) {
mi.set_material_override(_shader_material);
mi.set_material_override(material);
}
}
}

if (_shader_material.is_valid()) {
const Transform3D local_transform(Basis(), _position_in_voxels);
const VoxelStringNames &sn = VoxelStringNames::get_singleton();
_shader_material->set_shader_parameter(sn.u_block_local_transform, local_transform);
_shader_material->set_shader_parameter(sn.u_voxel_virtual_texture_offset_scale, Vector4(0, 0, 0, 1));
}
}

// void VoxelMeshBlock::set_transition_bit(uint8_t side, bool value) {
Expand Down
4 changes: 4 additions & 0 deletions terrain/variable_lod/voxel_mesh_block_vlt.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class VoxelMeshBlockVLT : public VoxelMeshBlock {
return _shader_material;
}

// To be used only if the material override on the terrain is not a ShaderMaterial
void set_material_override(Ref<Material> material);

// Transform

void set_parent_transform(const Transform3D &parent_transform);
Expand All @@ -102,6 +105,7 @@ class VoxelMeshBlockVLT : public VoxelMeshBlock {
}

private:
void set_material_override_internal(Ref<Material> material);
void _set_visible(bool visible);

inline bool _is_transition_visible(unsigned int side) const {
Expand Down

0 comments on commit 7eb9aec

Please sign in to comment.