@@ -136,6 +136,40 @@ bool HasRaytracingSourceMeshes(frame::LevelInterface& level)
136136 return !GetRaytracingSourceMeshMaterials (level).empty ();
137137}
138138
139+ bool CanUseSharedRaytraceSceneTransform (
140+ frame::LevelInterface& level,
141+ double time_seconds)
142+ {
143+ const auto source_mesh_materials = GetRaytracingSourceMeshMaterials (level);
144+ if (source_mesh_materials.empty ())
145+ {
146+ return false ;
147+ }
148+
149+ std::optional<glm::mat4> shared_model = std::nullopt ;
150+ for (const auto & [source_node_id, source_material_id] : source_mesh_materials)
151+ {
152+ (void )source_material_id;
153+ auto * node =
154+ dynamic_cast <NodeMesh*>(&level.GetSceneNodeFromId (source_node_id));
155+ if (!node)
156+ {
157+ return false ;
158+ }
159+ const glm::mat4 model = node->GetLocalModel (time_seconds);
160+ if (!shared_model)
161+ {
162+ shared_model = model;
163+ continue ;
164+ }
165+ if (*shared_model != model)
166+ {
167+ return false ;
168+ }
169+ }
170+ return true ;
171+ }
172+
139173std::vector<std::pair<EntityId, std::string>> GetActiveTextureBindings (
140174 const MaterialInterface& material,
141175 const ProgramInterface& program)
@@ -863,6 +897,35 @@ std::vector<std::uint8_t> BuildWorldSpaceRaytraceInstanceBytes(
863897 return EncodeRaytraceInstanceData (instances);
864898}
865899
900+ std::vector<std::uint8_t > BuildSharedTransformRaytraceInstanceBytes (
901+ const glm::mat4& shared_model,
902+ std::uint32_t transmissive_triangle_count,
903+ std::uint32_t opaque_triangle_count)
904+ {
905+ std::vector<RaytraceInstanceData> instances = {};
906+ const float determinant = glm::determinant (glm::mat3 (shared_model));
907+ const glm::mat4 world_to_object =
908+ std::abs (determinant) > 1 .0e-8f ? glm::inverse (shared_model)
909+ : glm::mat4 (1 .0f );
910+ const auto append_instance =
911+ [&](std::uint32_t material_id,
912+ std::uint32_t triangle_count) {
913+ if (triangle_count == 0 )
914+ {
915+ return ;
916+ }
917+ RaytraceInstanceData instance = {};
918+ instance.object_to_world = shared_model;
919+ instance.world_to_object = world_to_object;
920+ instance.metadata =
921+ glm::uvec4 (0u , material_id, 0u , triangle_count);
922+ instances.push_back (std::move (instance));
923+ };
924+ append_instance (kRaytraceMaterialTransmissive , transmissive_triangle_count);
925+ append_instance (kRaytraceMaterialOpaque , opaque_triangle_count);
926+ return EncodeRaytraceInstanceData (instances);
927+ }
928+
866929} // namespace
867930
868931Renderer::Renderer (LevelInterface& level, glm::uvec4 viewport)
@@ -956,6 +1019,9 @@ void Renderer::UpdateAggregateRaytraceSceneBuffers()
9561019{
9571020 const bool use_world_space_buffers =
9581021 RaytraceSceneRequiresWorldSpaceBuffers (level_);
1022+ const bool use_shared_scene_transform =
1023+ !use_world_space_buffers &&
1024+ CanUseSharedRaytraceSceneTransform (level_, delta_time_);
9591025 const auto scene_entries = CollectRaytraceSceneEntries (level_, delta_time_);
9601026 if (scene_entries.empty ())
9611027 {
@@ -1001,6 +1067,20 @@ void Renderer::UpdateAggregateRaytraceSceneBuffers()
10011067 std::vector<std::uint8_t > raytrace_instances = {};
10021068 const bool update_instance_buffer =
10031069 geometry_changed || !use_world_space_buffers;
1070+ const auto count_triangles =
1071+ [&](bool transmissive) -> std::uint32_t {
1072+ std::uint32_t triangle_count = 0 ;
1073+ for (const auto & entry : scene_entries)
1074+ {
1075+ if (entry.transmissive == transmissive)
1076+ {
1077+ triangle_count += entry.triangle_count ;
1078+ }
1079+ }
1080+ return triangle_count;
1081+ };
1082+ const std::uint32_t transmissive_triangle_count = count_triangles (true );
1083+ const std::uint32_t opaque_triangle_count = count_triangles (false );
10041084 if (geometry_changed)
10051085 {
10061086 const auto prepared_entries = PrepareRaytraceSceneEntries (
@@ -1018,6 +1098,15 @@ void Renderer::UpdateAggregateRaytraceSceneBuffers()
10181098 transmissive_triangles,
10191099 opaque_triangles);
10201100 }
1101+ else if (use_shared_scene_transform)
1102+ {
1103+ transmissive_bvh = BuildAggregateBvhBytes (transmissive_triangles);
1104+ opaque_bvh = BuildAggregateBvhBytes (opaque_triangles);
1105+ raytrace_instances = BuildSharedTransformRaytraceInstanceBytes (
1106+ scene_entries.front ().model ,
1107+ transmissive_triangle_count,
1108+ opaque_triangle_count);
1109+ }
10211110 else
10221111 {
10231112 transmissive_bvh =
@@ -1028,7 +1117,12 @@ void Renderer::UpdateAggregateRaytraceSceneBuffers()
10281117 }
10291118 if (!use_world_space_buffers)
10301119 {
1031- raytrace_instances = BuildPerMeshRaytraceInstanceBytes (scene_entries);
1120+ raytrace_instances = use_shared_scene_transform
1121+ ? BuildSharedTransformRaytraceInstanceBytes (
1122+ scene_entries.front ().model ,
1123+ transmissive_triangle_count,
1124+ opaque_triangle_count)
1125+ : BuildPerMeshRaytraceInstanceBytes (scene_entries);
10321126 }
10331127
10341128 for (const auto & [node_id, material_id] :
0 commit comments