Fix #133699: Overlay: Empty as Bone custom shape display error

Add workaround path to process the vertices the same way as
the `overlay_extra_vert` shader.
We nudge the non-origin vertices in the batch to be able
to not require loading the VCLASS attribute. Thus making
the change local to the shader and not requiring another
shader variant.
This commit is contained in:
Clément Foucault
2025-01-31 18:24:56 +01:00
parent 976ed42533
commit a50e07a533
4 changed files with 48 additions and 4 deletions

View File

@@ -288,6 +288,7 @@ class Armatures : Overlay {
sub.shader_set(res.shaders.armature_shape_wire.get());
sub.push_constant("alpha", 1.0f);
sub.push_constant("do_smooth_wire", do_smooth_wire);
sub.push_constant("use_arrow_drawing", false);
opaque_.shape_wire = ⊂
}
if (use_wire_alpha) {
@@ -297,6 +298,7 @@ class Armatures : Overlay {
sub.bind_texture("depthTex", depth_tex);
sub.push_constant("alpha", wire_alpha * 0.6f);
sub.push_constant("do_smooth_wire", do_smooth_wire);
sub.push_constant("use_arrow_drawing", false);
transparent_.shape_wire = ⊂
}
else {
@@ -309,6 +311,7 @@ class Armatures : Overlay {
sub.shader_set(res.shaders.armature_shape_wire_strip.get());
sub.push_constant("alpha", 1.0f);
sub.push_constant("do_smooth_wire", do_smooth_wire);
sub.push_constant("use_arrow_drawing", false);
opaque_.shape_wire_strip = ⊂
}
if (use_wire_alpha) {
@@ -318,6 +321,7 @@ class Armatures : Overlay {
sub.bind_texture("depthTex", depth_tex);
sub.push_constant("alpha", wire_alpha * 0.6f);
sub.push_constant("do_smooth_wire", do_smooth_wire);
sub.push_constant("use_arrow_drawing", false);
transparent_.shape_wire_strip = ⊂
}
else {
@@ -593,6 +597,7 @@ class Armatures : Overlay {
using CustomShapeBuf = MutableMapItem<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>>;
gpu::Batch *arrow_batch = res.shapes.arrows.get();
for (CustomShapeBuf item : bb.custom_shape_fill.items()) {
item.value->end_sync(*bb.shape_fill, item.key);
}
@@ -600,7 +605,19 @@ class Armatures : Overlay {
item.value->end_sync(*bb.shape_outline, item.key, GPU_PRIM_LINES, 1);
}
for (CustomShapeBuf item : bb.custom_shape_wire.items()) {
/* WORKAROUND: This shape needs a special vertex shader path that should be triggered by
* its vclass attribute. However, to avoid many changes in the primitive expansion API,
* we create a specific path inside the shader only for this shape batch and infer the
* value of the `vclass` attribute based on the vertex index. */
if (item.key == arrow_batch) {
bb.shape_wire->push_constant("use_arrow_drawing", true);
}
item.value->end_sync(*bb.shape_wire, item.key, GPU_PRIM_TRIS, 2);
if (item.key == arrow_batch) {
bb.shape_wire->push_constant("use_arrow_drawing", false);
}
}
for (CustomShapeBuf item : bb.custom_shape_wire_strip.items()) {
item.value->end_sync(*bb.shape_wire_strip, item.key, GPU_PRIM_TRIS, 2);

View File

@@ -867,20 +867,23 @@ ShapeCache::ShapeCache()
* Fractional part of Z is a positive offset at axis unit position. */
int flag = VCLASS_EMPTY_AXES | VCLASS_SCREENALIGNED;
/* Center to axis line. */
/* NOTE: overlay_armature_shape_wire_vert.glsl expects the axis verts at the origin to be the
* only ones with this coordinates (it derives the VCLASS from it). */
float pos_on_axis = float(axis) + 1e-8f;
verts.append({{0.0f, 0.0f, 0.0f}, 0});
verts.append({{0.0f, 0.0f, float(axis)}, flag});
verts.append({{0.0f, 0.0f, pos_on_axis}, flag});
/* Axis end marker. */
constexpr int marker_fill_layer = 6;
for (int j = 1; j < marker_fill_layer + 1; j++) {
for (float2 axis_marker_vert : axis_marker) {
verts.append({{axis_marker_vert * ((4.0f * j) / marker_fill_layer), float(axis)}, flag});
verts.append({{axis_marker_vert * ((4.0f * j) / marker_fill_layer), pos_on_axis}, flag});
}
}
/* Axis name. */
const Vector<float2> *axis_names[3] = {&x_axis_name, &y_axis_name, &z_axis_name};
for (float2 axis_name_vert : *(axis_names[axis])) {
int flag = VCLASS_EMPTY_AXES | VCLASS_EMPTY_AXES_NAME | VCLASS_SCREENALIGNED;
verts.append({{axis_name_vert * 4.0f, axis + 0.25f}, flag});
verts.append({{axis_name_vert * 4.0f, pos_on_axis + 0.25f}, flag});
}
}
arrows = BatchPtr(

View File

@@ -134,6 +134,7 @@ PUSH_CONSTANT(BOOL, do_smooth_wire)
STORAGE_BUF_FREQ(0, READ, float, pos[], GEOMETRY)
STORAGE_BUF(1, READ, mat4, data_buf[])
PUSH_CONSTANT(IVEC2, gpu_attr_0)
PUSH_CONSTANT(BOOL, use_arrow_drawing)
VERTEX_OUT(overlay_armature_shape_wire_iface)
VERTEX_SOURCE("overlay_armature_shape_wire_vert.glsl")
FRAGMENT_SOURCE("overlay_armature_shape_wire_frag.glsl")

View File

@@ -38,7 +38,30 @@ VertOut vertex_main(VertIn v_in)
mat4 model_mat = extract_matrix_packed_data(v_in.inst_matrix, state_color, bone_color);
VertOut v_out;
v_out.world_pos = (model_mat * vec4(v_in.lP, 1.0)).xyz;
/* WORKAROUND: This shape needs a special vertex shader path that should be triggered by
* its vclass attribute. However, to avoid many changes in the primitive expansion API,
* we create a specific path inside the shader only for this shape batch and infer the
* value of the `vclass` attribute based on the vertex index. */
if (use_arrow_drawing) {
/* Keep in sync with the arrows shape batch creation. */
/* Adapted from overlay_extra_vert.glsl. */
vec3 vpos = v_in.lP;
vec3 vofs = vec3(0.0);
uint axis = uint(vpos.z);
/* Assumes origin vertices are the only one at Z=0. */
if (vpos.z > 0.0) {
vofs[axis] = (1.0 + fract(vpos.z));
}
/* Scale uniformly by axis length */
vpos *= length(model_mat[axis].xyz);
/* World sized, camera facing geometry. */
vec3 screen_pos = ViewMatrixInverse[0].xyz * vpos.x + ViewMatrixInverse[1].xyz * vpos.y;
v_out.world_pos = (model_mat * vec4(vofs, 1.0)).xyz + screen_pos;
}
else {
v_out.world_pos = (model_mat * vec4(v_in.lP, 1.0)).xyz;
}
v_out.gpu_position = drw_point_world_to_homogenous(v_out.world_pos);
v_out.finalColor.rgb = mix(state_color.rgb, bone_color.rgb, 0.5);