Skip to content

Commit dc98490

Browse files
committed
Routed skinned model picking through PickingFallback
1 parent 70543a7 commit dc98490

2 files changed

Lines changed: 95 additions & 17 deletions

File tree

Resources/Editor/Shaders/PickingFallback.ovfx

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
#pass PICKING_PASS
2+
#feature SKINNING
3+
14
#shader vertex
25
#version 450 core
36

47
layout (location = 0) in vec3 geo_Pos;
8+
layout (location = 5) in vec4 geo_BoneIDs;
9+
layout (location = 6) in vec4 geo_BoneWeights;
510

611
layout (std140) uniform EngineUBO
712
{
@@ -12,9 +17,65 @@ layout (std140) uniform EngineUBO
1217
float ubo_Time;
1318
};
1419

20+
layout(std430, binding = 2) buffer SkinningSSBO
21+
{
22+
mat4 ssbo_Bones[];
23+
};
24+
25+
mat4 ComputeSkinningMatrix(vec4 p_boneIDs, vec4 p_boneWeights)
26+
{
27+
const int boneCount = ssbo_Bones.length();
28+
29+
mat4 skinning = mat4(0.0);
30+
float appliedWeight = 0.0;
31+
32+
#define OV_APPLY_BONE(BONE_ID, BONE_WEIGHT) \
33+
{ \
34+
const float w = (BONE_WEIGHT); \
35+
if (w > 0.0) \
36+
{ \
37+
const int index = int(floor((BONE_ID) + 0.5)); \
38+
if (index >= 0 && index < boneCount) \
39+
{ \
40+
skinning += ssbo_Bones[index] * w; \
41+
appliedWeight += w; \
42+
} \
43+
} \
44+
}
45+
46+
OV_APPLY_BONE(p_boneIDs.x, p_boneWeights.x);
47+
OV_APPLY_BONE(p_boneIDs.y, p_boneWeights.y);
48+
OV_APPLY_BONE(p_boneIDs.z, p_boneWeights.z);
49+
OV_APPLY_BONE(p_boneIDs.w, p_boneWeights.w);
50+
51+
#undef OV_APPLY_BONE
52+
53+
if (appliedWeight <= 0.0)
54+
{
55+
return mat4(1.0);
56+
}
57+
58+
if (appliedWeight < 1.0)
59+
{
60+
return skinning + mat4(1.0) * (1.0 - appliedWeight);
61+
}
62+
63+
if (appliedWeight > 1.0)
64+
{
65+
return skinning / appliedWeight;
66+
}
67+
68+
return skinning;
69+
}
70+
1571
void main()
1672
{
17-
gl_Position = ubo_Projection * ubo_View * ubo_Model * vec4(geo_Pos, 1.0);
73+
mat4 skinningMatrix = mat4(1.0);
74+
#if defined(SKINNING)
75+
skinningMatrix = ComputeSkinningMatrix(geo_BoneIDs, geo_BoneWeights);
76+
#endif
77+
78+
gl_Position = ubo_Projection * ubo_View * ubo_Model * skinningMatrix * vec4(geo_Pos, 1.0);
1879
}
1980

2081
#shader fragment

Sources/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
*/
66

77
#include <ranges>
8+
#include <string>
89

910
#include <OvCore/ECS/Components/CMaterialRenderer.h>
11+
#include <OvCore/ECS/Components/CSkinnedMeshRenderer.h>
1012
#include <OvCore/Rendering/EngineDrawableDescriptor.h>
1113
#include <OvCore/Rendering/FramebufferUtil.h>
14+
#include <OvCore/Rendering/SkinningUtils.h>
1215

1316
#include <OvEditor/Core/EditorActions.h>
1417
#include <OvEditor/Rendering/DebugModelRenderFeature.h>
@@ -20,6 +23,8 @@
2023

2124
namespace
2225
{
26+
const std::string kPickingPassName = "PICKING_PASS";
27+
2328
void PreparePickingMaterial(
2429
const OvCore::ECS::Actor& p_actor,
2530
OvRendering::Data::Material& p_material,
@@ -161,30 +166,42 @@ void OvEditor::Rendering::PickingRenderPass::DrawPickableModels(
161166
auto drawPickableModels = [&](auto drawables) {
162167
for (auto& drawable : drawables)
163168
{
164-
const std::string pickingPassName = "PICKING_PASS";
169+
const auto& actor = drawable.template GetDescriptor<OvCore::Rendering::SceneRenderer::SceneDrawableDescriptor>().actor;
170+
const auto skinnedRenderer = actor.GetComponent<OvCore::ECS::Components::CSkinnedMeshRenderer>();
171+
const bool hasSkinning = OvCore::Rendering::SkinningUtils::IsSkinningActive(skinnedRenderer);
172+
173+
if (hasSkinning)
174+
{
175+
auto& targetMaterial = m_actorPickingFallbackMaterial;
176+
177+
PreparePickingMaterial(actor, targetMaterial);
178+
179+
OvRendering::Entities::Drawable finalDrawable = drawable;
180+
finalDrawable.material = &targetMaterial;
181+
finalDrawable.stateMask = targetMaterial.GenerateStateMask();
182+
finalDrawable.stateMask.frontfaceCulling = false;
183+
finalDrawable.stateMask.backfaceCulling = false;
184+
finalDrawable.pass = kPickingPassName;
185+
186+
OvCore::Rendering::SkinningUtils::ApplyToDrawable(finalDrawable, *skinnedRenderer, &targetMaterial.GetFeatures());
187+
m_renderer.DrawEntity(p_pso, finalDrawable);
188+
continue;
189+
}
165190

166-
// If the material has picking pass, use it, otherwise use the picking fallback material
167191
auto& targetMaterial =
168-
(drawable.material && drawable.material->IsValid() && drawable.material->HasPass(pickingPassName)) ?
192+
drawable.material &&
193+
drawable.material->IsValid() &&
194+
drawable.material->HasPass(kPickingPassName) ?
169195
drawable.material.value() :
170196
m_actorPickingFallbackMaterial;
171197

172-
const auto& actor = drawable.template GetDescriptor<OvCore::Rendering::SceneRenderer::SceneDrawableDescriptor>().actor;
173-
174198
PreparePickingMaterial(actor, targetMaterial);
175199

176-
// Prioritize using the actual material state mask.
177-
auto stateMask =
178-
drawable.material && drawable.material->IsValid() ?
179-
drawable.material->GenerateStateMask() :
180-
targetMaterial.GenerateStateMask();
181-
182200
OvRendering::Entities::Drawable finalDrawable = drawable;
183-
finalDrawable.material = targetMaterial;
184-
finalDrawable.stateMask = stateMask;
185-
finalDrawable.stateMask.frontfaceCulling = false;
186-
finalDrawable.stateMask.backfaceCulling = false;
187-
finalDrawable.pass = pickingPassName;
201+
finalDrawable.material = &targetMaterial;
202+
finalDrawable.stateMask = targetMaterial.GenerateStateMask();
203+
finalDrawable.pass = kPickingPassName;
204+
finalDrawable.featureSetOverride = std::nullopt;
188205

189206
m_renderer.DrawEntity(p_pso, finalDrawable);
190207
}

0 commit comments

Comments
 (0)