Image Empties: Potential Fix for T57696

So far this makes a new pass for image empties that does not write to the depth buffer.

Todo:
- Sort empties using `DRW_pass_sort_shgroup_z`.
- Calculate correct bounding boxes.
- fix bounding box memory leak.

Reviewers: fclem

Differential Revision: https://developer.blender.org/D3922
This commit is contained in:
Clément Foucault 2018-11-22 18:22:34 +01:00
parent e16ef56a0d
commit f30271e3d4
2 changed files with 58 additions and 111 deletions

View File

@ -106,6 +106,7 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
/* *********** LISTS *********** */
typedef struct OBJECT_PassList {
struct DRWPass *non_meshes[2];
struct DRWPass *image_empties[2];
struct DRWPass *spot_shapes[2];
struct DRWPass *ob_center;
struct DRWPass *outlines;
@ -147,6 +148,7 @@ typedef struct OBJECT_Data {
typedef struct OBJECT_ShadingGroupList {
/* Reference only */
struct DRWPass *non_meshes;
struct DRWPass *image_empties;
struct DRWPass *spot_shapes;
struct DRWPass *bone_solid;
struct DRWPass *bone_outline;
@ -167,8 +169,6 @@ typedef struct OBJECT_ShadingGroupList {
DRWShadingGroup *single_arrow;
DRWShadingGroup *single_arrow_line;
DRWShadingGroup *empty_axes;
/* GPUTexture -> EmptyImageShadingGroupData */
GHash *image_plane_map;
/* Force Field */
DRWShadingGroup *field_wind;
@ -856,95 +856,48 @@ static void image_calc_aspect(Image *ima, ImageUser *iuser, float r_image_aspect
}
}
/* per-image shading groups for image-type empty objects */
struct EmptyImageShadingGroupData {
DRWShadingGroup *shgrp_image;
DRWShadingGroup *shgrp_wire;
float image_aspect[2];
};
static void DRW_shgroup_empty_image(
OBJECT_ShadingGroupList *sgl, Object *ob, const float color[3], RegionView3D *rv3d)
{
/* TODO: 'StereoViews', see draw_empty_image. */
if (!BKE_image_empty_visible_in_view3d(ob, rv3d)) return;
if (sgl->image_plane_map == NULL) {
sgl->image_plane_map = BLI_ghash_ptr_new(__func__);
}
struct EmptyImageShadingGroupData *empty_image_data;
if (!BKE_image_empty_visible_in_view3d(ob, rv3d))
return;
GPUTexture *tex = ob->data ?
GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, 0.0f) : NULL;
void **val_p;
GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, 0.0f) :
NULL;
/* Create on demand, 'tex' may be NULL. */
if (BLI_ghash_ensure_p(sgl->image_plane_map, tex, &val_p)) {
empty_image_data = *val_p;
}
else {
empty_image_data = MEM_mallocN(sizeof(*empty_image_data), __func__);
float image_aspect[2];
image_calc_aspect(ob->data, ob->iuser, image_aspect);
image_calc_aspect(ob->data, ob->iuser, empty_image_data->image_aspect);
/* OPTI(fclem) We need sorting only for transparent images. If an image as no alpha channel and
* ob->col[3] == 1.0f, we could remove it from the sorting pass. */
if (tex) {
DRW_shgroup_instance_format(e_data.empty_image_format, {
{"objectColor", DRW_ATTRIB_FLOAT, 4},
{"size", DRW_ATTRIB_FLOAT, 1},
{"offset", DRW_ATTRIB_FLOAT, 2},
{"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
});
struct GPUBatch *geom = DRW_cache_image_plane_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(
e_data.object_empty_image_sh, sgl->non_meshes, geom, e_data.empty_image_format);
DRW_shgroup_uniform_texture(grp, "image", tex);
DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
DRW_shgroup_uniform_int_copy(grp, "depthMode", ob->empty_image_depth);
empty_image_data->shgrp_image = grp;
}
else {
empty_image_data->shgrp_image = NULL;
}
{
DRW_shgroup_instance_format(e_data.empty_image_wire_format, {
{"color", DRW_ATTRIB_FLOAT, 4},
{"size", DRW_ATTRIB_FLOAT, 1},
{"offset", DRW_ATTRIB_FLOAT, 2},
{"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}
});
struct GPUBatch *geom = DRW_cache_image_plane_wire_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(
e_data.object_empty_image_wire_sh, sgl->non_meshes, geom, e_data.empty_image_wire_format);
DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
DRW_shgroup_uniform_int_copy(grp, "depthMode", ob->empty_image_depth);
empty_image_data->shgrp_wire = grp;
}
*val_p = empty_image_data;
if (tex && (ob->col[3] > 0.0f)) {
DRWShadingGroup *grp = DRW_shgroup_create(e_data.object_empty_image_sh, sgl->image_empties);
DRW_shgroup_uniform_texture(grp, "image", tex);
/* TODO(fclem) implement DRW_shgroup_uniform_vec2_copy */
DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]);
DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]);
DRW_shgroup_uniform_int_copy(grp, "depthMode", ob->empty_image_depth);
DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1);
DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1);
DRW_shgroup_uniform_vec4(grp, "objectColor", ob->col, 1);
DRW_shgroup_call_add(grp, DRW_cache_image_plane_get(), ob->obmat);
}
if (empty_image_data->shgrp_image != NULL) {
DRW_shgroup_call_dynamic_add(
empty_image_data->shgrp_image,
ob->col,
&ob->empty_drawsize,
ob->ima_ofs,
ob->obmat);
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.object_empty_image_wire_sh, sgl->non_meshes);
/* TODO(fclem) implement DRW_shgroup_uniform_vec2_copy */
DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]);
DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]);
DRW_shgroup_uniform_int_copy(grp, "depthMode", ob->empty_image_depth);
DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1);
DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_call_add(grp, DRW_cache_image_plane_wire_get(), ob->obmat);
}
DRW_shgroup_call_dynamic_add(
empty_image_data->shgrp_wire,
color,
&ob->empty_drawsize,
ob->ima_ofs,
ob->obmat);
}
static void OBJECT_cache_init(void *vedata)
@ -1130,6 +1083,10 @@ static void OBJECT_cache_init(void *vedata)
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_POINT | DRW_STATE_WIRE;
sgl->non_meshes = psl->non_meshes[i] = DRW_pass_create("Non Meshes Pass", state);
state = DRW_STATE_WRITE_COLOR |
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE;
sgl->image_empties = psl->image_empties[i] = DRW_pass_create("Image Empties", state);
/* Empties */
geom = DRW_cache_plain_axes_get();
sgl->plain_axes = shgroup_instance(sgl->non_meshes, geom);
@ -1167,9 +1124,6 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_bone_arrows_get();
sgl->empty_axes = shgroup_instance_empty_axes(sgl->non_meshes, geom);
/* initialize on first use */
sgl->image_plane_map = NULL;
/* Force Field */
geom = DRW_cache_field_wind_get();
sgl->field_wind = shgroup_instance_scaled(sgl->non_meshes, geom);
@ -2875,9 +2829,16 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
}
}
static void OBJECT_cache_finish(void *vedata)
{
OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
DRW_pass_sort_shgroup_z(stl->g_data->sgl.image_empties);
DRW_pass_sort_shgroup_z(stl->g_data->sgl_ghost.image_empties);
}
static void OBJECT_draw_scene(void *vedata)
{
OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
@ -2909,6 +2870,7 @@ static void OBJECT_draw_scene(void *vedata)
DRW_draw_pass(stl->g_data->sgl.bone_outline);
DRW_draw_pass(stl->g_data->sgl.non_meshes);
DRW_draw_pass(psl->particle);
DRW_draw_pass(stl->g_data->sgl.image_empties);
DRW_draw_pass(stl->g_data->sgl.bone_axes);
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl)
@ -2963,12 +2925,6 @@ static void OBJECT_draw_scene(void *vedata)
}
}
/* This has to be freed only after drawing empties! */
if (stl->g_data->sgl.image_plane_map) {
BLI_ghash_free(stl->g_data->sgl.image_plane_map, NULL, MEM_freeN);
stl->g_data->sgl.image_plane_map = NULL;
}
volumes_free_smoke_textures();
batch_camera_path_free(&stl->g_data->sgl.camera_path);
@ -2976,6 +2932,7 @@ static void OBJECT_draw_scene(void *vedata)
!DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_wire) ||
!DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_outline) ||
!DRW_pass_is_empty(stl->g_data->sgl_ghost.non_meshes) ||
!DRW_pass_is_empty(stl->g_data->sgl_ghost.image_empties) ||
!DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_axes))
{
if (DRW_state_is_fbo()) {
@ -3005,6 +2962,7 @@ static void OBJECT_draw_scene(void *vedata)
DRW_draw_pass(stl->g_data->sgl_ghost.bone_wire);
DRW_draw_pass(stl->g_data->sgl_ghost.bone_outline);
DRW_draw_pass(stl->g_data->sgl_ghost.non_meshes);
DRW_draw_pass(stl->g_data->sgl_ghost.image_empties);
DRW_draw_pass(stl->g_data->sgl_ghost.bone_axes);
if (DRW_state_is_select()) {
@ -3013,11 +2971,6 @@ static void OBJECT_draw_scene(void *vedata)
}
batch_camera_path_free(&stl->g_data->sgl_ghost.camera_path);
/* This has to be freed only after drawing empties! */
if (stl->g_data->sgl_ghost.image_plane_map) {
BLI_ghash_free(stl->g_data->sgl_ghost.image_plane_map, NULL, MEM_freeN);
stl->g_data->sgl_ghost.image_plane_map = NULL;
}
DRW_draw_pass(psl->ob_center);
}
@ -3032,7 +2985,7 @@ DrawEngineType draw_engine_object_type = {
&OBJECT_engine_free,
&OBJECT_cache_init,
&OBJECT_cache_populate,
NULL,
&OBJECT_cache_finish,
NULL,
&OBJECT_draw_scene,
NULL,

View File

@ -1,21 +1,16 @@
uniform mat4 ViewProjectionMatrix;
uniform vec2 aspect;
/* ---- Instantiated Attribs ---- */
in vec2 texCoord;
in vec2 pos;
/* ---- Per instance Attribs ---- */
in mat4 InstanceModelMatrix;
uniform mat4 ModelViewProjectionMatrix;
uniform float aspectX;
uniform float aspectY;
uniform float size;
uniform vec2 offset;
#ifdef USE_WIRE
in vec3 color;
uniform vec3 color;
#else
in vec4 objectColor;
uniform vec4 objectColor;
#endif
in float size;
in vec2 offset;
in vec2 texCoord;
in vec2 pos;
flat out vec4 finalColor;
@ -25,9 +20,8 @@ out vec2 texCoord_interp;
void main()
{
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(
(pos[0] + offset[0]) * (size * aspect[0]),
(pos[1] + offset[1]) * (size * aspect[1]),
gl_Position = ModelViewProjectionMatrix * vec4(
(pos + offset) * (size * vec2(aspectX, aspectY)),
0.0, 1.0);
#ifdef USE_WIRE
finalColor = vec4(color, 1.0);