diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-05-20 15:57:47 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-05-20 16:17:50 +0300 |
commit | 8e3cefd0d5f9d6ec874012db68f5c4b497af9d35 (patch) | |
tree | 3b3d757628cad8cef3091cd71ae68e2d488dea5c /source | |
parent | 65aab6cdae822822122f5e180baf10e39f600bf2 (diff) |
DwM: Object mode empty-image support
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 44 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 1 | ||||
-rw-r--r-- | source/blender/draw/modes/object_mode.c | 169 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/object_empty_image_frag.glsl | 21 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/object_empty_image_vert.glsl | 38 |
7 files changed, 274 insertions, 3 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index ac648fe1e5b..a7432211160 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -154,6 +154,8 @@ data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_lattice_overlay_loosevert_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC) +data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC) data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC) diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index db1565c8e96..a75b1434721 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -53,6 +53,8 @@ static struct DRWShapeCache { Batch *drw_empty_cone; Batch *drw_arrows; Batch *drw_axis_names; + Batch *drw_image_plane; + Batch *drw_image_plane_wire; Batch *drw_field_wind; Batch *drw_field_force; Batch *drw_field_vortex; @@ -100,6 +102,8 @@ void DRW_shape_cache_free(void) BATCH_DISCARD_ALL_SAFE(SHC.drw_empty_cone); BATCH_DISCARD_ALL_SAFE(SHC.drw_arrows); BATCH_DISCARD_ALL_SAFE(SHC.drw_axis_names); + BATCH_DISCARD_ALL_SAFE(SHC.drw_image_plane); + BATCH_DISCARD_ALL_SAFE(SHC.drw_image_plane_wire); BATCH_DISCARD_ALL_SAFE(SHC.drw_field_wind); BATCH_DISCARD_ALL_SAFE(SHC.drw_field_force); BATCH_DISCARD_ALL_SAFE(SHC.drw_field_vortex); @@ -723,6 +727,46 @@ Batch *DRW_cache_axis_names_get(void) return SHC.drw_axis_names; } +Batch *DRW_cache_image_plane_get(void) +{ + if (!SHC.drw_image_plane) { + const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + static VertexFormat format = { 0 }; + static struct { uint pos, texCoords; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT); + attr_id.texCoords = VertexFormat_add_attrib(&format, "texCoord", COMP_F32, 2, KEEP_FLOAT); + } + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 4); + for (uint j = 0; j < 4; j++) { + VertexBuffer_set_attrib(vbo, attr_id.pos, j, quad[j]); + VertexBuffer_set_attrib(vbo, attr_id.texCoords, j, quad[j]); + } + SHC.drw_image_plane = Batch_create(PRIM_TRIANGLE_FAN, vbo, NULL); + } + return SHC.drw_image_plane; +} + +Batch *DRW_cache_image_plane_wire_get(void) +{ + if (!SHC.drw_image_plane_wire) { + const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + static VertexFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT); + } + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 4); + for (uint j = 0; j < 4; j++) { + VertexBuffer_set_attrib(vbo, attr_id.pos, j, quad[j]); + } + SHC.drw_image_plane_wire = Batch_create(PRIM_LINE_LOOP, vbo, NULL); + } + return SHC.drw_image_plane_wire; +} + /* Force Field */ Batch *DRW_cache_field_wind_get(void) { diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index a37b9998ff6..b440f9969b3 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -53,6 +53,8 @@ struct Batch *DRW_cache_empty_sphere_get(void); struct Batch *DRW_cache_empty_cone_get(void); struct Batch *DRW_cache_arrows_get(void); struct Batch *DRW_cache_axis_names_get(void); +struct Batch *DRW_cache_image_plane_get(void); +struct Batch *DRW_cache_image_plane_wire_get(void); /* Force Field */ struct Batch *DRW_cache_field_wind_get(void); diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 04c64357cf3..2c597a175ff 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -96,6 +96,7 @@ struct DRWShadingGroup *shgroup_instance_objspace_solid(struct DRWPass *pass, st struct DRWShadingGroup *shgroup_instance_objspace_wire(struct DRWPass *pass, struct Batch *geom, float (*obmat)[4]); struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct Batch *geom); struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Batch *geom); +struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct Batch *geom); struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass, struct Batch *geom); struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Batch *geom); struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Batch *geom); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index bc1a69fd4ed..89e085423d4 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -35,16 +35,20 @@ #include "DNA_view3d_types.h" #include "DNA_world_types.h" +#include "BIF_gl.h" + #include "BKE_anim.h" #include "BKE_camera.h" #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_particle.h" +#include "BKE_image.h" #include "ED_view3d.h" #include "ED_view3d.h" #include "GPU_shader.h" +#include "GPU_texture.h" #include "UI_resources.h" @@ -60,6 +64,8 @@ extern char datatoc_object_outline_detect_frag_glsl[]; extern char datatoc_object_outline_expand_frag_glsl[]; extern char datatoc_object_grid_frag_glsl[]; extern char datatoc_object_grid_vert_glsl[]; +extern char datatoc_object_empty_image_frag_glsl[]; +extern char datatoc_object_empty_image_vert_glsl[]; extern char datatoc_particle_prim_vert_glsl[]; extern char datatoc_particle_prim_frag_glsl[]; extern char datatoc_common_globals_lib_glsl[]; @@ -101,6 +107,13 @@ typedef struct OBJECT_Data { OBJECT_StorageList *stl; } OBJECT_Data; +/* per-image shading groups for image-type empty objects */ +struct EmptyImageShadingGroupData { + DRWShadingGroup *shgrp_image; + DRWShadingGroup *shgrp_wire; + float image_aspect[2]; +}; + /* *********** STATIC *********** */ typedef struct OBJECT_PrivateData{ @@ -114,6 +127,8 @@ typedef struct OBJECT_PrivateData{ DRWShadingGroup *single_arrow_line; DRWShadingGroup *arrows; DRWShadingGroup *axis_names; + /* GPUTexture -> EmptyImageShadingGroupData */ + GHash *image_plane_map; /* Force Field */ DRWShadingGroup *field_wind; @@ -187,9 +202,14 @@ typedef struct OBJECT_PrivateData{ } OBJECT_PrivateData; /* Transient data */ static struct { + /* fullscreen shaders */ GPUShader *outline_resolve_sh; GPUShader *outline_detect_sh; GPUShader *outline_fade_sh; + + /* regular shaders */ + GPUShader *object_empty_image_sh; + GPUShader *object_empty_image_wire_sh; GPUShader *grid_sh; GPUShader *part_dot_sh; GPUShader *part_prim_sh; @@ -256,6 +276,21 @@ static void OBJECT_engine_init(void *vedata) e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL); } + if (!e_data.object_empty_image_sh) { + e_data.object_empty_image_sh = DRW_shader_create_with_lib( + datatoc_object_empty_image_vert_glsl, NULL, + datatoc_object_empty_image_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } + + if (!e_data.object_empty_image_wire_sh) { + e_data.object_empty_image_wire_sh = DRW_shader_create_with_lib( + datatoc_object_empty_image_vert_glsl, NULL, + datatoc_object_empty_image_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define USE_WIRE\n"); + } + if (!e_data.grid_sh) { e_data.grid_sh = DRW_shader_create_with_lib( datatoc_object_grid_vert_glsl, NULL, @@ -412,6 +447,8 @@ static void OBJECT_engine_free(void) DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh); DRW_SHADER_FREE_SAFE(e_data.outline_fade_sh); + DRW_SHADER_FREE_SAFE(e_data.object_empty_image_sh); + DRW_SHADER_FREE_SAFE(e_data.object_empty_image_wire_sh); DRW_SHADER_FREE_SAFE(e_data.grid_sh); DRW_SHADER_FREE_SAFE(e_data.part_prim_sh); } @@ -467,6 +504,118 @@ static DRWShadingGroup *shgroup_theme_id_to_wire_or( } } +static void image_calc_aspect(Image *ima, ImageUser *iuser, float r_image_aspect[2]) +{ + float ima_x, ima_y; + if (ima) { + int w, h; + BKE_image_get_size(ima, iuser, &w, &h); + ima_x = w; + ima_y = h; + } + else { + /* if no image, make it a 1x1 empty square, honor scale & offset */ + ima_x = ima_y = 1.0f; + } + /* Get the image aspect even if the buffer is invalid */ + float sca_x = 1.0f, sca_y = 1.0f; + if (ima) { + if (ima->aspx > ima->aspy) { + sca_y = ima->aspy / ima->aspx; + } + else if (ima->aspx < ima->aspy) { + sca_x = ima->aspx / ima->aspy; + } + } + + const float scale_x_inv = ima_x * sca_x; + const float scale_y_inv = ima_y * sca_y; + if (scale_x_inv > scale_y_inv) { + r_image_aspect[0] = 1.0f; + r_image_aspect[1] = scale_y_inv / scale_x_inv; + } + else { + r_image_aspect[0] = scale_x_inv / scale_y_inv; + r_image_aspect[1] = 1.0f; + } +} + +static void DRW_shgroup_empty_image( + OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, float color[4]) +{ + /* TODO: 'StereoViews', see draw_empty_image. */ + + if (stl->g_data->image_plane_map == NULL) { + stl->g_data->image_plane_map = BLI_ghash_ptr_new(__func__); + } + + struct EmptyImageShadingGroupData *empty_image_data; + + GPUTexture *tex = ob->data ? + GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, false, false) : NULL; + void **val_p; + + /* Create on demand, 'tex' may be NULL. */ + if (BLI_ghash_ensure_p(stl->g_data->image_plane_map, tex, &val_p)) { + empty_image_data = *val_p; + } + else { + empty_image_data = MEM_mallocN(sizeof(*empty_image_data), __func__); + + image_calc_aspect(ob->data, ob->iuser, empty_image_data->image_aspect); + + if (tex) { + struct Batch *geom = DRW_cache_image_plane_get(); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + e_data.object_empty_image_sh, psl->non_meshes, geom); + DRW_shgroup_attrib_float(grp, "objectColor", 4); + DRW_shgroup_attrib_float(grp, "size", 1); + DRW_shgroup_attrib_float(grp, "offset", 2); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + + DRW_shgroup_uniform_texture(grp, "image", tex); + DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1); + + empty_image_data->shgrp_image = grp; + } + else { + empty_image_data->shgrp_image = NULL; + } + + { + struct Batch *geom = DRW_cache_image_plane_wire_get(); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + e_data.object_empty_image_wire_sh, psl->non_meshes, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "size", 1); + DRW_shgroup_attrib_float(grp, "offset", 2); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + + DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1); + + empty_image_data->shgrp_wire = grp; + } + + *val_p = empty_image_data; + } + + 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); + } + + 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) { OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; @@ -668,6 +817,9 @@ static void OBJECT_cache_init(void *vedata) geom = DRW_cache_axis_names_get(); stl->g_data->axis_names = shgroup_instance_axis_names(psl->non_meshes, geom); + /* initialize on first use */ + stl->g_data->image_plane_map = NULL; + /* Force Field */ geom = DRW_cache_field_wind_get(); stl->g_data->field_wind = shgroup_instance_scaled(psl->non_meshes, geom); @@ -1054,7 +1206,7 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, SceneLayer * } } -static void DRW_shgroup_empty(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl) +static void DRW_shgroup_empty(OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, SceneLayer *sl) { float *color; DRW_object_wire_theme_get(ob, sl, &color); @@ -1083,6 +1235,9 @@ static void DRW_shgroup_empty(OBJECT_StorageList *stl, Object *ob, SceneLayer *s DRW_shgroup_call_dynamic_add(stl->g_data->arrows, color, &ob->empty_drawsize, ob->obmat); DRW_shgroup_call_dynamic_add(stl->g_data->axis_names, color, &ob->empty_drawsize, ob->obmat); break; + case OB_EMPTY_IMAGE: + DRW_shgroup_empty_image(stl, psl, ob, color); + break; } } @@ -1351,7 +1506,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) DRW_shgroup_camera(stl, ob, sl); break; case OB_EMPTY: - DRW_shgroup_empty(stl, ob, sl); + DRW_shgroup_empty(stl, psl, ob, sl); break; case OB_SPEAKER: DRW_shgroup_speaker(stl, ob, sl); @@ -1398,6 +1553,14 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) } } +static void OBJECT_cache_finish(void *vedata) +{ + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + if (stl->g_data->image_plane_map) { + BLI_ghash_free(stl->g_data->image_plane_map, NULL, MEM_freeN); + } +} + static void OBJECT_draw_scene(void *vedata) { @@ -1486,7 +1649,7 @@ DrawEngineType draw_engine_object_type = { &OBJECT_engine_free, &OBJECT_cache_init, &OBJECT_cache_populate, - NULL, + &OBJECT_cache_finish, NULL, &OBJECT_draw_scene }; diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl new file mode 100644 index 00000000000..eab107354d1 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl @@ -0,0 +1,21 @@ + +flat in vec4 finalColor; + +#ifndef USE_WIRE +in vec2 texCoord_interp; +#endif + +out vec4 fragColor; + +#ifndef USE_WIRE +uniform sampler2D image; +#endif + +void main() +{ +#ifdef USE_WIRE + fragColor = finalColor; +#else + fragColor = finalColor * texture(image, texCoord_interp); +#endif +} diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl new file mode 100644 index 00000000000..c629fdcb7ef --- /dev/null +++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl @@ -0,0 +1,38 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec2 aspect; + +/* ---- Instanciated Attribs ---- */ +in vec2 texCoord; +in vec2 pos; +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; + +#ifdef USE_WIRE +in vec3 color; +#else +in vec4 objectColor; +#endif + +in float size; +in vec2 offset; + +flat out vec4 finalColor; + +#ifndef USE_WIRE +out vec2 texCoord_interp; +#endif + +void main() +{ + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4( + (pos[0] + offset[0]) * (size * aspect[0]), + (pos[1] + offset[1]) * (size * aspect[1]), + 0.0, 1.0); +#ifdef USE_WIRE + finalColor = vec4(color, 1.0); +#else + texCoord_interp = texCoord; + finalColor = objectColor; +#endif +} |