DRW: Fix T53583 Armature instances not drawing.

Was due to the fact that the instances don't have a "static" obmat that can be referenced to use as a uniform.
Solution : precompute the full matrix for each bone and pass it as instance data. (theses are copied into a buffer and can be discarded right away)

Note: this could be optimized further and make only one drawcall (shgroup) to draw all bone instance of one type (vs. one call per armature).
This commit is contained in:
Clément Foucault 2018-01-11 19:35:56 +01:00
parent 31782609f4
commit da97b6930b
Notes: blender-bot 2023-02-14 06:19:34 +01:00
Referenced by issue #53583, Crash when instancing a group with an armature (might be only on mesa/intel GPUs ?).
6 changed files with 69 additions and 63 deletions

View File

@ -102,20 +102,22 @@ static void drw_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const
{
if (g_data.bone_octahedral_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get();
g_data.bone_octahedral_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
g_data.bone_octahedral_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, final_bonemat, color);
}
static void drw_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_octahedral_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_outline_get();
g_data.bone_octahedral_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_octahedral_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_wire, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_wire, final_bonemat, color);
}
/* Box / B-Bone */
@ -123,20 +125,22 @@ static void drw_shgroup_bone_box_solid(const float (*bone_mat)[4], const float c
{
if (g_data.bone_box_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_box_get();
g_data.bone_box_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
g_data.bone_box_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, color);
}
static void drw_shgroup_bone_box_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_box_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_box_wire_outline_get();
g_data.bone_box_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_box_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_box_wire, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_box_wire, final_bonemat, color);
}
/* Wire */
@ -144,10 +148,11 @@ static void drw_shgroup_bone_wire_wire(const float (*bone_mat)[4], const float c
{
if (g_data.bone_wire_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_wire_wire_outline_get();
g_data.bone_wire_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_wire_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, final_bonemat, color);
}
/* Envelope */
@ -159,10 +164,11 @@ static void drw_shgroup_bone_envelope_distance(
if (g_data.bone_envelope_distance == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_distance_outline_get();
/* Note: bone_wire draw pass is not really working, think we need another one here? */
g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom, g_data.ob->obmat);
g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, bone_mat, color, radius_head, radius_tail, distance);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, final_bonemat, color, radius_head, radius_tail, distance);
}
}
@ -172,10 +178,11 @@ static void drw_shgroup_bone_envelope_solid(
{
if (g_data.bone_envelope_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_solid_get();
g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, bone_mat, color, radius_head, radius_tail);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, final_bonemat, color, radius_head, radius_tail);
}
static void drw_shgroup_bone_envelope_wire(
@ -184,10 +191,11 @@ static void drw_shgroup_bone_envelope_wire(
{
if (g_data.bone_envelope_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_wire_outline_get();
g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, bone_mat, color, radius_head, radius_tail, distance);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, final_bonemat, color, radius_head, radius_tail, distance);
}
static void drw_shgroup_bone_envelope_head_wire(
@ -196,10 +204,11 @@ static void drw_shgroup_bone_envelope_head_wire(
{
if (g_data.bone_envelope_head_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_head_wire_outline_get();
g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, bone_mat, color, radius_head, radius_tail, distance);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, final_bonemat, color, radius_head, radius_tail, distance);
}
/* Custom (geometry) */
@ -209,8 +218,10 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const floa
/* grr, not re-using instances! */
struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom);
if (geom) {
DRWShadingGroup *shgrp_geom_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
DRW_shgroup_call_dynamic_add(shgrp_geom_solid, bone_mat, color);
DRWShadingGroup *shgrp_geom_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, color);
}
}
@ -219,8 +230,10 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float
/* grr, not re-using instances! */
struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom);
if (geom) {
DRWShadingGroup *shgrp_geom_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
DRW_shgroup_call_dynamic_add(shgrp_geom_wire, bone_mat, color);
DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, color);
}
}
@ -229,20 +242,22 @@ static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float
{
if (g_data.bone_point_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_point_get();
g_data.bone_point_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
g_data.bone_point_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, color);
}
static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_point_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get();
g_data.bone_point_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_point_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, color);
}
/* Axes */
@ -250,10 +265,11 @@ static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[
{
if (g_data.bone_axes == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_arrows_get();
g_data.bone_axes = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
g_data.bone_axes = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
DRW_shgroup_call_dynamic_add(g_data.bone_axes, bone_mat, color);
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color);
}
/* Relationship lines */

View File

@ -215,7 +215,7 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g
return grp;
}
DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom)
{
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR);
@ -223,20 +223,18 @@ DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Gwn_Batch
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
DRW_shgroup_attrib_float(grp, "color", 4);
DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
return grp;
}
DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
DRW_shgroup_attrib_float(grp, "color", 4);
DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
return grp;
}
@ -336,7 +334,7 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE);
@ -346,12 +344,11 @@ DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_B
DRW_shgroup_attrib_float(grp, "radius_head", 1);
DRW_shgroup_attrib_float(grp, "radius_tail", 1);
DRW_shgroup_attrib_float(grp, "distance", 1);
DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
return grp;
}
DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_Batch *geom)
{
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID);
@ -361,7 +358,6 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_
DRW_shgroup_attrib_float(grp, "color", 4);
DRW_shgroup_attrib_float(grp, "radius_head", 1);
DRW_shgroup_attrib_float(grp, "radius_tail", 1);
DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
return grp;

View File

@ -106,8 +106,8 @@ struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, fl
struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, float color[4]);
struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, float color[4]);
struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct Gwn_Batch *geom, float *size);
struct DRWShadingGroup *shgroup_instance_objspace_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
struct DRWShadingGroup *shgroup_instance_objspace_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct Gwn_Batch *geom);
@ -116,8 +116,8 @@ struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Gwn_Batch
struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_mball_helpers(struct DRWPass *pass, struct Gwn_Batch *geom);
int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color);

View File

@ -7,7 +7,6 @@
uniform mat4 ViewMatrix;
uniform mat4 ObjectModelMatrix;
uniform mat4 ViewProjectionMatrix;
@ -38,7 +37,7 @@ void main()
bone_mat[1] = normalize(bone_mat[1]);
bone_mat[2] = normalize(bone_mat[2]);
mat3 nor_mat = transpose(inverse(mat3(ViewMatrix * ObjectModelMatrix) * bone_mat));
mat3 nor_mat = transpose(inverse(mat3(ViewMatrix) * bone_mat));
/* Where does this comes from???? Don't know why, but is mandatory anyway... :/ */
const float size = 2.0f;
@ -116,7 +115,7 @@ void main()
ob_pos.xyz = bone_mat * ob_pos.xyz;
ob_pos.w = 1.0f;
gl_Position = ViewProjectionMatrix * ObjectModelMatrix * (ob_pos + ob_bone_origin);
gl_Position = ViewProjectionMatrix * (ob_pos + ob_bone_origin);
normal = normalize(nor_mat * nor);
finalColor = color;
}

View File

@ -7,11 +7,8 @@
* Note that if one of head/tail radius is negative, it assumes it only works on the other end of the bone
* (used to draw head/tail spheres). */
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 ObjectModelMatrix;
/* ---- Instanciated Attribs ---- */
in vec4 pos; /* z encodes head (== 0.0f), tail (== 1.0f) or in-between; w encodes inner (0.0f) or outer border. */
@ -36,7 +33,7 @@ void main()
vec4 tail = bone_mat * vec4(0.0f, 1.0f, 0.0f, 1.0f);
/* We generate our XY axes in object space, Y axis being aligned with bone in view space. */
mat4 obview_mat = ViewMatrix * ObjectModelMatrix;
mat4 obview_mat = ViewMatrix;
mat4 iobview_mat = inverse(obview_mat);
vec4 view_bone_vec = obview_mat * normalize(tail - head);

View File

@ -1,7 +1,6 @@
uniform mat4 ViewMatrix;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ObjectModelMatrix;
/* ---- Instanciated Attribs ---- */
in vec3 pos;
@ -16,11 +15,10 @@ flat out vec4 finalColor;
void main()
{
mat4 FinalModelMatrix = ObjectModelMatrix * InstanceModelMatrix;
mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * FinalModelMatrix;
mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * InstanceModelMatrix;
/* This is slow and run per vertex, but it's still faster than
* doing it per instance on CPU and sending it on via instance attrib */
mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * FinalModelMatrix)));
mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
normal = NormalMatrix * nor;