DwM: Object mode empty-image support

This commit is contained in:
Campbell Barton 2017-05-20 22:57:47 +10:00
parent 65aab6cdae
commit 8e3cefd0d5
7 changed files with 274 additions and 3 deletions

View File

@ -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)

View File

@ -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)
{

View File

@ -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);

View File

@ -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);

View File

@ -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
};

View File

@ -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
}

View File

@ -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
}