diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-03-08 22:00:09 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-03-09 03:30:26 +0300 |
commit | 3b91989a093aef874b601efcffd247cf61e73bad (patch) | |
tree | f5e8df6b3aad70c71e8002c0e3775b768dbd22fc | |
parent | d9f42e5fab6a13ce200665b9a89291aa34ff6c09 (diff) |
Draw Manager: structural change
All engines are now called by the draw manager. Engines are separate entities that cannot interfer with each others.
Also separated draw_mode_pass.c into the mode engines.
22 files changed, 1650 insertions, 1649 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index cb2681fcf81..c04063d22f8 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -52,7 +52,7 @@ set(INC_SYS set(SRC intern/draw_manager.c - intern/draw_mode_pass.c + intern/draw_common.c intern/draw_cache.c intern/draw_view.c intern/draw_armature.c @@ -62,13 +62,11 @@ set(SRC modes/object_mode.c intern/DRW_render.h - intern/draw_mode_pass.h + intern/draw_common.h intern/draw_cache.h intern/draw_view.h engines/clay/clay.h - modes/edit_armature_mode.h - modes/edit_mesh_mode.h - modes/object_mode.h + modes/draw_mode_engines.h ./DRW_engine.h ) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 05ecc7390d1..e8dc47245e3 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -30,10 +30,27 @@ struct CollectionEngineSettings; struct DRWPass; struct Material; struct Scene; +struct DrawEngineType; +struct bContext; +struct Object; -void DRW_engines_init(void); +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *depth; +} DefaultTextureList; + +void DRW_engines_register(void); void DRW_engines_free(void); +void DRW_engine_register(struct DrawEngineType *draw_engine_type); + +void DRW_draw_view(const struct bContext *C); + /* This is here because GPUViewport needs it */ void DRW_pass_free(struct DRWPass *pass); diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c index cd19595b107..a91027cb314 100644 --- a/source/blender/draw/engines/clay/clay.c +++ b/source/blender/draw/engines/clay/clay.c @@ -124,6 +124,15 @@ typedef struct CLAY_PassList { struct DRWPass *clay_pass; } CLAY_PassList; +typedef struct CLAY_Data { + char engine_name[32]; + CLAY_FramebufferList *fbl; + CLAY_TextureList *txl; + CLAY_PassList *psl; + CLAY_StorageList *stl; +} CLAY_Data; + + //#define GTAO /* Functions */ @@ -262,20 +271,12 @@ RenderEngineSettings *CLAY_render_settings_create(void) return (RenderEngineSettings *)settings; } -MaterialEngineSettings *CLAY_material_settings_create(void) -{ - MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay"); - - clay_material_settings_init(settings); - - return (MaterialEngineSettings *)settings; -} - static void CLAY_engine_init(void) { - CLAY_StorageList *stl = DRW_engine_storage_list_get(); - CLAY_TextureList *txl = DRW_engine_texture_list_get(); - CLAY_FramebufferList *fbl = DRW_engine_framebuffer_list_get(); + CLAY_Data *vedata = DRW_viewport_engine_data_get("Clay"); + CLAY_StorageList *stl = vedata->stl; + CLAY_TextureList *txl = vedata->txl; + CLAY_FramebufferList *fbl = vedata->fbl; /* Create Texture Array */ if (!data.matcap_array) { @@ -428,10 +429,11 @@ static void CLAY_engine_init(void) static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *material_id) { + CLAY_Data *vedata = DRW_viewport_engine_data_get("Clay"); + CLAY_TextureList *txl = vedata->txl; const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3; DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass); - CLAY_TextureList *txl = DRW_engine_texture_list_get(); DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_buffer(grp, "depthtex", &txl->depth_dup, depthloc); @@ -599,9 +601,9 @@ static DRWShadingGroup *depth_shgrp_cull; static void CLAY_cache_init(void) { - CLAY_PassList *psl = DRW_engine_pass_list_get(); - CLAY_StorageList *stl = DRW_engine_storage_list_get(); - + CLAY_Data *vedata = DRW_viewport_engine_data_get("Clay"); + CLAY_PassList *psl = vedata->psl; + CLAY_StorageList *stl = vedata->stl; /* Depth Pass */ { @@ -622,100 +624,46 @@ static void CLAY_cache_init(void) static void CLAY_cache_populate(Object *ob) { - const bContext *C = DRW_get_context(); - int mode = CTX_data_mode_enum(C); - CLAY_StorageList *stl = DRW_engine_storage_list_get(); - CLAY_PassList *psl = DRW_engine_pass_list_get(); + CLAY_Data *vedata = DRW_viewport_engine_data_get("Clay"); + CLAY_PassList *psl = vedata->psl; + CLAY_StorageList *stl = vedata->stl; + struct Batch *geom; DRWShadingGroup *clay_shgrp; - bool do_occlude_wire = false; - bool do_cull = false; - CollectionEngineSettings *ces_mode_ed, *ces_mode_ob; - - switch (mode) { - case CTX_MODE_EDIT_MESH: - case CTX_MODE_EDIT_CURVE: - case CTX_MODE_EDIT_SURFACE: - case CTX_MODE_EDIT_TEXT: - case CTX_MODE_EDIT_ARMATURE: - case CTX_MODE_EDIT_METABALL: - case CTX_MODE_EDIT_LATTICE: - case CTX_MODE_POSE: - case CTX_MODE_SCULPT: - case CTX_MODE_PAINT_WEIGHT: - case CTX_MODE_PAINT_VERTEX: - case CTX_MODE_PAINT_TEXTURE: - case CTX_MODE_PARTICLE: - ces_mode_ed = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, ""); - do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire"); - break; - case CTX_MODE_OBJECT: - ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, ""); - do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling"); - break; - } - if (do_occlude_wire) + if (!DRW_is_object_renderable(ob)) return; - switch (ob->type) { - case OB_MESH: - geom = DRW_cache_surface_get(ob); + CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, ""); + bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling"); - /* Depth Prepass */ - DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull : depth_shgrp, geom, ob->obmat); + /* TODO all renderable */ + if (ob->type == OB_MESH) { + geom = DRW_cache_surface_get(ob); - /* Shading */ - clay_shgrp = CLAY_object_shgrp_get(ob, stl, psl); - DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); - break; + /* Depth Prepass */ + DRW_shgroup_call_add((do_cull) ? depth_shgrp_cull : depth_shgrp, geom, ob->obmat); + + /* Shading */ + clay_shgrp = CLAY_object_shgrp_get(ob, stl, psl); + DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); } } static void CLAY_cache_finish(void) { - CLAY_StorageList *stl = DRW_engine_storage_list_get(); + CLAY_Data *vedata = DRW_viewport_engine_data_get("Clay"); + CLAY_StorageList *stl = vedata->stl; DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage); } -static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context) +static void CLAY_draw_scene(void) { - DRW_viewport_init(context); - - /* This function may run for multiple viewports - * so get the current viewport buffers */ - CLAY_PassList *psl = DRW_engine_pass_list_get(); - CLAY_FramebufferList *fbl = DRW_engine_framebuffer_list_get(); - - CLAY_engine_init(); - DRW_mode_init(); - - /* TODO : tag to refresh by the deps graph */ - /* ideally only refresh when objects are added/removed */ - /* or render properties / materials change */ - if (DRW_viewport_cache_is_dirty()) { - - SceneLayer *sl = CTX_data_scene_layer(context); - - CLAY_cache_init(); - DRW_mode_cache_init(); - - DEG_OBJECT_ITER(sl, ob); - { - CLAY_cache_populate(ob); - DRW_mode_cache_populate(ob); - } - DEG_OBJECT_ITER_END - - CLAY_cache_finish(); - DRW_mode_cache_finish(); - } - - /* Start Drawing */ - DRW_draw_background(); - - DRW_draw_callbacks_pre_scene(); + CLAY_Data *vedata = DRW_viewport_engine_data_get("Clay"); + CLAY_PassList *psl = vedata->psl; + CLAY_FramebufferList *fbl = vedata->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); /* Pass 1 : Depth pre-pass */ DRW_draw_pass(psl->depth_pass); @@ -723,19 +671,10 @@ static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context /* Pass 2 : Duplicate depth */ /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */ - DRW_framebuffer_blit(fbl->default_fb, fbl->dupli_depth, true); + DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true); /* Pass 3 : Shading */ DRW_draw_pass(psl->clay_pass); - - /* Pass 4 : Overlays */ - /* At this point all shaded geometry should have been rendered and their depth written */ - DRW_draw_mode_overlays(); - - DRW_draw_callbacks_post_scene(); - - /* Always finish by this */ - DRW_state_reset(); } static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces) @@ -753,30 +692,39 @@ static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), Collec BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f); } -void CLAY_engine_free(void) +static void CLAY_engine_free(void) { - /* data.depth_sh Is builtin so it's automaticaly freed */ if (data.clay_sh) { DRW_shader_free(data.clay_sh); } - if (data.matcap_array) { DRW_texture_free(data.matcap_array); } - if (data.jitter_tx) { DRW_texture_free(data.jitter_tx); } - if (data.sampling_tx) { DRW_texture_free(data.sampling_tx); } } +DrawEngineType draw_engine_clay_type = { + NULL, NULL, + N_("Clay"), + &CLAY_engine_init, + &CLAY_engine_free, + &CLAY_cache_init, + &CLAY_cache_populate, + &CLAY_cache_finish, + NULL, + &CLAY_draw_scene +}; + RenderEngineType viewport_clay_type = { NULL, NULL, CLAY_ENGINE, N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE, - NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create, + NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create, + &draw_engine_clay_type, {NULL, NULL, NULL} }; diff --git a/source/blender/draw/engines/clay/clay.h b/source/blender/draw/engines/clay/clay.h index 34dd74b9500..1afe1ac5ea8 100644 --- a/source/blender/draw/engines/clay/clay.h +++ b/source/blender/draw/engines/clay/clay.h @@ -31,6 +31,4 @@ extern RenderEngineType viewport_clay_type; struct RenderEngineSettings *CLAY_render_settings_create(void); struct MaterialEngineSettings *CLAY_material_settings_create(void); -void CLAY_engine_free(void); - #endif /* __CLAY_H__ */ diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 77687ebfaa4..27515686fd2 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -44,7 +44,7 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" -#include "draw_mode_pass.h" +#include "draw_common.h" #include "draw_cache.h" #include "draw_view.h" @@ -59,12 +59,42 @@ struct GPUTexture; struct GPUUniformBuffer; struct Object; struct Batch; +struct DefaultFramebufferList; +struct DefaultTextureList; typedef struct DRWUniform DRWUniform; typedef struct DRWInterface DRWInterface; typedef struct DRWPass DRWPass; typedef struct DRWShadingGroup DRWShadingGroup; +typedef struct DrawEngineType { + struct DrawEngineType *next, *prev; + + char idname[32]; + + void (*engine_init)(void); + void (*engine_free)(void); + + void (*cache_init)(void); + void (*cache_populate)(struct Object *ob); + void (*cache_finish)(void); + + void (*draw_background)(void); + void (*draw_scene)(void); +} DrawEngineType; + +#ifndef __DRW_ENGINE_H__ +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *depth; +} DefaultTextureList; +#endif + /* Textures */ typedef enum { @@ -199,27 +229,26 @@ typedef enum { void DRW_viewport_init(const bContext *C); void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type); +void DRW_viewport_engine_data_set(const char *engine_name, void *fbl, void *txl, void *psl, void *stl); +void *DRW_viewport_engine_data_get(const char *engine_name); float *DRW_viewport_size_get(void); float *DRW_viewport_screenvecs_get(void); float *DRW_viewport_pixelsize_get(void); bool DRW_viewport_is_persp_get(void); bool DRW_viewport_cache_is_dirty(void); +struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void); +struct DefaultTextureList *DRW_viewport_texture_list_get(void); + /* Settings */ +bool DRW_is_object_renderable(struct Object *ob); #ifndef __DRW_ENGINE_H__ void *DRW_material_settings_get(Material *ma, const char *engine_name); void *DRW_render_settings_get(Scene *scene, const char *engine_name); #endif /* __DRW_ENGINE_H__ */ -/* Cache */ -void DRW_mode_init(void); -void DRW_mode_cache_init(void); -void DRW_mode_cache_populate(struct Object *ob); -void DRW_mode_cache_finish(void); - /* Draw commands */ void DRW_draw_pass(DRWPass *pass); -void DRW_draw_mode_overlays(void); void DRW_draw_callbacks_pre_scene(void); void DRW_draw_callbacks_post_scene(void); @@ -229,12 +258,4 @@ void DRW_state_reset(void); /* Other */ void DRW_get_dfdy_factors(float dfdyfac[2]); const struct bContext *DRW_get_context(void); -void *DRW_engine_pass_list_get(void); -void *DRW_engine_storage_list_get(void); -void *DRW_engine_texture_list_get(void); -void *DRW_engine_framebuffer_list_get(void); -void *DRW_mode_pass_list_get(void); -void *DRW_mode_storage_list_get(void); -void *DRW_mode_texture_list_get(void); -void *DRW_mode_framebuffer_list_get(void); #endif /* __DRW_RENDER_H__ */ diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 24a183d38ca..51c269a7b97 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -35,6 +35,8 @@ #include "DNA_view3d_types.h" #include "DNA_object_types.h" +#include "DRW_render.h" + #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_dlrbTree.h" @@ -56,11 +58,83 @@ #include "UI_resources.h" -#include "draw_mode_pass.h" +#include "draw_common.h" #define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var)) #define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag)) +static Object *current_armature; +/* Reset when changing current_armature */ +static DRWShadingGroup *bone_octahedral_solid; +static DRWShadingGroup *bone_octahedral_wire; +static DRWShadingGroup *bone_point_solid; +static DRWShadingGroup *bone_point_wire; +static DRWShadingGroup *bone_axes; +static DRWShadingGroup *relationship_lines; + +static DRWPass *bone_solid; +static DRWPass *bone_wire; + +/* Octahedral */ +static void DRW_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_octahedral_solid == NULL) { + struct Batch *geom = DRW_cache_bone_octahedral_get(); + bone_octahedral_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_octahedral_solid, bone_mat, color); +} + +static void DRW_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_octahedral_wire == NULL) { + struct Batch *geom = DRW_cache_bone_octahedral_wire_outline_get(); + bone_octahedral_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_octahedral_wire, bone_mat, color); +} + +/* Head and tail sphere */ +static void DRW_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_point_solid == NULL) { + struct Batch *geom = DRW_cache_bone_point_get(); + bone_point_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_point_solid, bone_mat, color); +} + +static void DRW_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_point_wire == NULL) { + struct Batch *geom = DRW_cache_bone_point_wire_outline_get(); + bone_point_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_point_wire, bone_mat, color); +} + +/* Axes */ +static void DRW_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4]) +{ + if (bone_axes == NULL) { + struct Batch *geom = DRW_cache_bone_arrows_get(); + bone_axes = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); + } + + DRW_shgroup_dynamic_call_add(bone_axes, bone_mat, color); +} + +/* Relationship lines */ +static void UNUSED_FUNCTION(DRW_shgroup_bone_relationship_lines)(const float head[3], const float tail[3]) +{ + DRW_shgroup_dynamic_call_add(relationship_lines, head); + DRW_shgroup_dynamic_call_add(relationship_lines, tail); +} + /* *************** Armature Drawing - Coloring API ***************************** */ static float colorBoneSolid[4]; @@ -246,7 +320,7 @@ static void draw_bone_octahedral(EditBone *eBone, bPoseChannel *pchan, bArmature draw_points(eBone, pchan, arm); } -void draw_armature_edit(Object *ob) +static void draw_armature_edit(Object *ob) { EditBone *eBone; bArmature *arm = ob->data; @@ -280,7 +354,7 @@ void draw_armature_edit(Object *ob) } /* if const_color is NULL do pose mode coloring */ -void draw_armature_pose(Object *ob, const float const_color[4]) +static void draw_armature_pose(Object *ob, const float const_color[4]) { bArmature *arm = ob->data; bPoseChannel *pchan; @@ -325,4 +399,45 @@ void draw_armature_pose(Object *ob, const float const_color[4]) } } } +} + +/* this function set the object space to use + * for all subsequent DRW_shgroup_bone_*** calls */ +static void DRW_shgroup_armature( + Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines) +{ + current_armature = ob; + bone_octahedral_solid = NULL; + bone_octahedral_wire = NULL; + bone_point_solid = NULL; + bone_point_wire = NULL; + bone_axes = NULL; + + bone_solid = pass_bone_solid; + bone_wire = pass_bone_wire; + relationship_lines = shgrp_relationship_lines; +} + +void DRW_shgroup_armature_object( + Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines) +{ + float *color; + DRW_object_wire_theme_get(ob, &color); + + DRW_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, shgrp_relationship_lines); + draw_armature_pose(ob, color); +} + +void DRW_shgroup_armature_pose( + Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines) +{ + DRW_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, shgrp_relationship_lines); + draw_armature_pose(ob, NULL); +} + +void DRW_shgroup_armature_edit( + Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines) +{ + DRW_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, shgrp_relationship_lines); + draw_armature_edit(ob); }
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c new file mode 100644 index 00000000000..b9c73e8c352 --- /dev/null +++ b/source/blender/draw/intern/draw_common.c @@ -0,0 +1,315 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_common.c + * \ingroup draw + */ + +#include "DRW_render.h" + +#include "GPU_shader.h" + +#include "UI_resources.h" + +#include "BKE_global.h" + +#include "draw_common.h" + +/* Colors & Constant */ +GlobalsUboStorage ts; +struct GPUUniformBuffer *globals_ubo = NULL; + +void DRW_globals_update(void) +{ + UI_GetThemeColor4fv(TH_WIRE, ts.colorWire); + UI_GetThemeColor4fv(TH_WIRE_EDIT, ts.colorWireEdit); + UI_GetThemeColor4fv(TH_ACTIVE, ts.colorActive); + UI_GetThemeColor4fv(TH_SELECT, ts.colorSelect); + UI_GetThemeColor4fv(TH_TRANSFORM, ts.colorTransform); + UI_GetThemeColor4fv(TH_GROUP_ACTIVE, ts.colorGroupActive); + UI_GetThemeColor4fv(TH_GROUP, ts.colorGroup); + UI_GetThemeColor4fv(TH_LAMP, ts.colorLamp); + UI_GetThemeColor4fv(TH_SPEAKER, ts.colorSpeaker); + UI_GetThemeColor4fv(TH_CAMERA, ts.colorCamera); + UI_GetThemeColor4fv(TH_EMPTY, ts.colorEmpty); + UI_GetThemeColor4fv(TH_VERTEX, ts.colorVertex); + UI_GetThemeColor4fv(TH_VERTEX_SELECT, ts.colorVertexSelect); + UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, ts.colorEditMeshActive); + UI_GetThemeColor4fv(TH_EDGE_SELECT, ts.colorEdgeSelect); + UI_GetThemeColor4fv(TH_EDGE_SEAM, ts.colorEdgeSeam); + UI_GetThemeColor4fv(TH_EDGE_SHARP, ts.colorEdgeSharp); + UI_GetThemeColor4fv(TH_EDGE_CREASE, ts.colorEdgeCrease); + UI_GetThemeColor4fv(TH_EDGE_BEVEL, ts.colorEdgeBWeight); + UI_GetThemeColor4fv(TH_EDGE_FACESEL, ts.colorEdgeFaceSelect); + UI_GetThemeColor4fv(TH_FACE, ts.colorFace); + UI_GetThemeColor4fv(TH_FACE_SELECT, ts.colorFaceSelect); + UI_GetThemeColor4fv(TH_NORMAL, ts.colorNormal); + UI_GetThemeColor4fv(TH_VNORMAL, ts.colorVNormal); + UI_GetThemeColor4fv(TH_LNORMAL, ts.colorLNormal); + UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot); + + UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, ts.colorDeselect); + UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, ts.colorOutline); + UI_GetThemeColorShadeAlpha4fv(TH_LAMP, 0, 255, ts.colorLampNoAlpha); + + ts.sizeLampCenter = (U.obcenter_dia + 1.5f) * U.pixelsize; + ts.sizeLampCircle = U.pixelsize * 9.0f; + ts.sizeLampCircleShadow = ts.sizeLampCircle + U.pixelsize * 3.0f; + + /* M_SQRT2 to be at least the same size of the old square */ + ts.sizeVertex = UI_GetThemeValuef(TH_VERTEX_SIZE) * M_SQRT2 / 2.0f; + ts.sizeFaceDot = UI_GetThemeValuef(TH_FACEDOT_SIZE) * M_SQRT2; + ts.sizeEdge = 1.0f / 2.0f; /* TODO Theme */ + ts.sizeEdgeFix = 0.5f + 2.0f * (2.0f * (MAX2(ts.sizeVertex, ts.sizeEdge)) * M_SQRT1_2); + ts.sizeNormal = 1.0f; /* TODO compute */ + + /* TODO Waiting for notifiers to invalidate cache */ + if (globals_ubo) { + DRW_uniformbuffer_free(globals_ubo); + } + + globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts); +} + +/* ********************************* SHGROUP ************************************* */ + +DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + + return grp; +} + +DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_uniform_float(grp, "size", size, 1); + DRW_shgroup_state_set(grp, DRW_STATE_POINT); + + return grp; +} + +DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + + return grp; +} + +DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_state_set(grp, DRW_STATE_POINT); + + return grp; +} + +DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom, float *size) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); + DRW_shgroup_attrib_float(grp, "world_pos", 3); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_uniform_float(grp, "size", size, 1); + DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1); + DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2); + DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3); + + return grp; +} + +DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Batch *geom, float (*obmat)[4]) +{ + 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); + + 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, "ModelMatrix", (float *)obmat); + DRW_shgroup_uniform_vec3(grp, "light", light, 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Batch *geom, float (*obmat)[4]) +{ + 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, "ModelMatrix", (float *)obmat); + + return grp; +} + +DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "size", 1); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2); + + return grp; +} + +DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "size", 1); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + + return grp; +} + +DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "corners", 8); + DRW_shgroup_attrib_float(grp, "depth", 1); + DRW_shgroup_attrib_float(grp, "tria", 4); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + + return grp; +} + +DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES); + static float point_size = 4.0f; + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "start", 1); + DRW_shgroup_attrib_float(grp, "end", 1); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_uniform_float(grp, "size", &point_size, 1); + + return grp; +} + +DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR); + static bool True = true; + static bool False = false; + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1); + + return grp; +} + +/* ******************************************** WIRES *********************************************** */ + +/* TODO FINISH */ +/* Get the wire color theme_id of an object based on it's state + * **color is a way to get a pointer to the static color var associated */ +int DRW_object_wire_theme_get(Object *ob, float **color) +{ + const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0; + /* confusing logic here, there are 2 methods of setting the color + * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. + * + * note: no theme yet for 'colindex' */ + int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE; + + if (//(scene->obedit == NULL) && + ((G.moving & G_TRANSFORM_OBJ) != 0) && + ((ob->base_flag & BASE_SELECTED) != 0)) + { + theme_id = TH_TRANSFORM; + } + else { + /* Sets the 'theme_id' or fallback to wire */ + if ((ob->flag & OB_FROMGROUP) != 0) { + if ((ob->base_flag & BASE_SELECTED) != 0) { + /* uses darker active color for non-active + selected */ + theme_id = TH_GROUP_ACTIVE; + + // if (scene->basact != base) { + // theme_shade = -16; + // } + } + else { + theme_id = TH_GROUP; + } + } + else { + if ((ob->base_flag & BASE_SELECTED) != 0) { + theme_id = //scene->basact == base ? TH_ACTIVE : + TH_SELECT; + } + else { + if (ob->type == OB_LAMP) theme_id = TH_LAMP; + else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER; + else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA; + else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY; + /* fallback to TH_WIRE */ + } + } + } + + if (color != NULL) { + switch (theme_id) { + case TH_WIRE_EDIT: *color = ts.colorTransform; break; + case TH_ACTIVE: *color = ts.colorActive; break; + case TH_SELECT: *color = ts.colorSelect; break; + case TH_GROUP: *color = ts.colorGroup; break; + case TH_GROUP_ACTIVE: *color = ts.colorGroupActive; break; + case TH_TRANSFORM: *color = ts.colorTransform; break; + case OB_SPEAKER: *color = ts.colorSpeaker; break; + case OB_CAMERA: *color = ts.colorCamera; break; + case OB_EMPTY: *color = ts.colorEmpty; break; + case OB_LAMP: *color = ts.colorLamp; break; + default: *color = ts.colorWire; break; + } + } + + return theme_id; +} diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_common.h index fd66120f48d..400a7e73998 100644 --- a/source/blender/draw/intern/draw_mode_pass.h +++ b/source/blender/draw/intern/draw_common.h @@ -19,14 +19,15 @@ * */ -/** \file draw_mode_pass.h +/** \file draw_common.h * \ingroup draw */ -#ifndef __DRAW_MODE_PASS_H__ -#define __DRAW_MODE_PASS_H__ +#ifndef __DRAW_COMMON__ +#define __DRAW_COMMON__ struct DRWPass; +struct DRWShadingGroup; struct Batch; struct Object; @@ -72,37 +73,34 @@ typedef struct GlobalsUboStorage { } GlobalsUboStorage; /* Keep in sync with globalsBlock in shaders */ -void DRW_update_global_values(void); +void DRW_globals_update(void); -void DRW_mode_passes_setup(struct DRWPass **psl_wire_overlay, - struct DRWPass **psl_wire_overlay_hidden_wire, - struct DRWPass **psl_wire_outline, - struct DRWPass **psl_non_meshes, - struct DRWPass **psl_ob_center, - struct DRWPass **psl_bone_solid, - struct DRWPass **psl_bone_wire); +struct DRWShadingGroup *shgroup_dynlines_uniform_color(struct DRWPass *pass, float color[4]); +struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size); +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 Batch *geom, float *size); +struct DRWShadingGroup *shgroup_instance_objspace_solid(struct DRWPass *pass, struct Batch *geom, float (*obmat)[4]); +struct DRWShadingGroup *shgroup_instance_objspace_wire(struct DRWPass *pass, struct Batch *geom, float (*obmat)[4]); +struct DRWShadingGroup *shgroup_instance_axis_names(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); +struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Batch *geom); +struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Batch *geom); -void DRW_shgroup_wire_outline(struct Object *ob, const bool do_front, const bool do_back, const bool do_outline); -void DRW_shgroup_lamp(struct Object *ob); -void DRW_shgroup_camera(struct Object *ob); -void DRW_shgroup_empty(struct Object *ob); -void DRW_shgroup_speaker(struct Object *ob); -void DRW_shgroup_relationship_lines(struct Object *ob); -void DRW_shgroup_object_center(struct Object *ob); +int DRW_object_wire_theme_get(struct Object *ob, float **color); -void DRW_shgroup_armature_object(struct Object *ob); -void DRW_shgroup_armature_edit(struct Object *ob); -void DRW_shgroup_armature_pose(struct Object *ob); +/* draw_armature.c */ +void DRW_shgroup_armature_object( + struct Object *ob, struct DRWPass *pass_bone_solid, + struct DRWPass *pass_bone_wire, struct DRWShadingGroup *shgrp_relationship_lines); -void DRW_shgroup_bone_octahedral_solid(const float (*arm_mat)[4], const float color[4]); -void DRW_shgroup_bone_octahedral_wire(const float (*arm_mat)[4], const float color[4]); -void DRW_shgroup_bone_point_solid(const float (*arm_mat)[4], const float color[4]); -void DRW_shgroup_bone_point_wire(const float (*arm_mat)[4], const float color[4]); -void DRW_shgroup_bone_relationship_lines(const float head[3], const float tail[3]); -void DRW_shgroup_bone_axes(const float (*arm_mat)[4], const float color[4]); +void DRW_shgroup_armature_pose( + struct Object *ob, struct DRWPass *pass_bone_solid, + struct DRWPass *pass_bone_wire, struct DRWShadingGroup *shgrp_relationship_lines); -/* draw_armature.c */ -void draw_armature_edit(struct Object *ob); -void draw_armature_pose(struct Object *ob, const float const_color[4]); +void DRW_shgroup_armature_edit( + struct Object *ob, struct DRWPass *pass_bone_solid, + struct DRWPass *pass_bone_wire, struct DRWShadingGroup *shgrp_relationship_lines); -#endif /* __DRAW_MODE_PASS_H__ */
\ No newline at end of file +#endif /* __DRAW_COMMON__ */
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 381414f06dc..54e5fa5440c 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -39,6 +39,7 @@ #include "DRW_render.h" #include "DNA_view3d_types.h" +#include "DNA_screen_types.h" #include "ED_space_api.h" @@ -55,9 +56,7 @@ #include "UI_resources.h" -#include "object_mode.h" -#include "edit_armature_mode.h" -#include "edit_mesh_mode.h" +#include "draw_mode_engines.h" #include "clay.h" #define MAX_ATTRIB_NAME 32 @@ -163,21 +162,25 @@ enum { /* Render State */ static struct DRWGlobalState { + /* Rendering state */ GPUShader *shader; - struct GPUFrameBuffer *default_framebuffer; - FramebufferList *fbl, *fbl_mode; - TextureList *txl, *txl_mode; - PassList *psl, *psl_mode; - StorageList *stl, *stl_mode; ListBase bound_texs; int tex_bind_id; + + /* Per viewport */ + GPUViewport *viewport; + struct GPUFrameBuffer *default_framebuffer; float size[2]; float screenvecs[2][3]; float pixsize; - /* Current rendering context set by DRW_viewport_init */ + + /* Current rendering context */ const struct bContext *context; + ListBase enabled_engines; /* RenderEngineType */ } DST = {NULL}; +ListBase DRW_engines = {NULL, NULL}; + /* ***************************************** TEXTURES ******************************************/ static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *data_type, int *channels) { @@ -1067,28 +1070,6 @@ void DRW_state_reset(void) set_state(state); } -void DRW_draw_mode_overlays(void) -{ - const bContext *C = DRW_get_context(); - int mode = CTX_data_mode_enum(C); - - DRW_draw_grid(); - - switch (mode) { - case CTX_MODE_EDIT_MESH: - EDIT_MESH_draw(); - break; - case CTX_MODE_EDIT_ARMATURE: - EDIT_ARMATURE_draw(); - break; - case CTX_MODE_OBJECT: - OBJECT_draw(); - break; - } - - DRW_draw_manipulator(); - DRW_draw_region_info(); -} #else void DRW_draw_pass(DRWPass *UNUSED(pass)) { @@ -1096,79 +1077,26 @@ void DRW_draw_pass(DRWPass *UNUSED(pass)) #endif -/* ******************************************* Mode Engine Cache ****************************************** */ +/* ****************************************** Settings ******************************************/ -void DRW_mode_init(void) +bool DRW_is_object_renderable(Object *ob) { - const bContext *C = DRW_get_context(); - int mode = CTX_data_mode_enum(C); - - switch (mode) { - case CTX_MODE_EDIT_MESH: - EDIT_MESH_init(); - break; - case CTX_MODE_EDIT_ARMATURE: - break; - case CTX_MODE_OBJECT: - break; - } -} + Scene *scene = CTX_data_scene(DST.context); + Object *obedit = scene->obedit; -void DRW_mode_cache_init(void) -{ - const bContext *C = DRW_get_context(); - int mode = CTX_data_mode_enum(C); + if (ob->type == OB_MESH) { + if (ob == obedit) { + CollectionEngineSettings *ces_mode_ed = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, ""); + bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire"); - switch (mode) { - case CTX_MODE_EDIT_MESH: - EDIT_MESH_cache_init(); - break; - case CTX_MODE_EDIT_ARMATURE: - EDIT_ARMATURE_cache_init(); - break; - case CTX_MODE_OBJECT: - OBJECT_cache_init(); - break; - } -} - -void DRW_mode_cache_populate(Object *ob) -{ - const bContext *C = DRW_get_context(); - int mode = CTX_data_mode_enum(C); - - switch (mode) { - case CTX_MODE_EDIT_MESH: - EDIT_MESH_cache_populate(ob); - break; - case CTX_MODE_EDIT_ARMATURE: - EDIT_ARMATURE_cache_populate(ob); - break; - case CTX_MODE_OBJECT: - OBJECT_cache_populate(ob); - break; + if (do_occlude_wire) + return false; + } } -} - -void DRW_mode_cache_finish(void) -{ - const bContext *C = DRW_get_context(); - int mode = CTX_data_mode_enum(C); - switch (mode) { - case CTX_MODE_EDIT_MESH: - EDIT_MESH_cache_finish(); - break; - case CTX_MODE_EDIT_ARMATURE: - EDIT_ARMATURE_cache_finish(); - break; - case CTX_MODE_OBJECT: - OBJECT_cache_finish(); - break; - } + return true; } -/* ****************************************** Settings ******************************************/ void *DRW_material_settings_get(Material *ma, const char *engine_name) { MaterialEngineSettings *ms = NULL; @@ -1184,7 +1112,8 @@ void *DRW_material_settings_get(Material *ma, const char *engine_name) /* TODO make render_settings_create a polymorphic function */ if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) { - ms->data = CLAY_material_settings_create(); + /* No material support */ + BLI_assert(false); } else { /* No engine matched */ @@ -1309,6 +1238,15 @@ void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer } /* ****************************************** Viewport ******************************************/ +void *DRW_viewport_engine_data_get(const char *engine_name) +{ + void *data = GPU_viewport_engine_data_get(DST.viewport, engine_name); + + if (data == NULL) { + data = GPU_viewport_engine_data_create(DST.viewport, engine_name); + } + return data; +} float *DRW_viewport_size_get(void) { @@ -1325,20 +1263,21 @@ float *DRW_viewport_pixelsize_get(void) return &DST.pixsize; } -void DRW_viewport_init(const bContext *C) +/* It also stores viewport variable to an immutable place: DST + * This is because a cache uniform only store reference + * to its value. And we don't want to invalidate the cache + * if this value change per viewport */ +static void DRW_viewport_var_init(const bContext *C) { RegionView3D *rv3d = CTX_wm_region_view3d(C); - GPUViewport *viewport = rv3d->viewport; - - GPU_viewport_get_engine_data(viewport, &DST.fbl, &DST.txl, &DST.psl, &DST.stl); - GPU_viewport_get_mode_data(viewport, &DST.fbl_mode, &DST.txl_mode, &DST.psl_mode, &DST.stl_mode); /* Refresh DST.size */ - DefaultTextureList *txl = (DefaultTextureList *)DST.txl; - DST.size[0] = (float)GPU_texture_width(txl->color); - DST.size[1] = (float)GPU_texture_height(txl->color); + int size[2]; + GPU_viewport_size_get(DST.viewport, size); + DST.size[0] = size[0]; + DST.size[1] = size[1]; - DefaultFramebufferList *fbl = (DefaultFramebufferList *)DST.fbl; + DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport); DST.default_framebuffer = fbl->default_fb; /* Refresh DST.screenvecs */ @@ -1352,8 +1291,6 @@ void DRW_viewport_init(const bContext *C) /* Save context for all later needs */ DST.context = C; - - DRW_update_global_values(); } void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) @@ -1374,77 +1311,251 @@ bool DRW_viewport_is_persp_get(void) return rv3d->is_persp; } -bool DRW_viewport_cache_is_dirty(void) +DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void) { - /* TODO Use a dirty flag */ - return (DST.psl->passes[0] == NULL); + return GPU_viewport_framebuffer_list_get(DST.viewport); } -/* ****************************************** OTHER ***************************************** */ +DefaultTextureList *DRW_viewport_texture_list_get(void) +{ + return GPU_viewport_texture_list_get(DST.viewport); +} -const bContext *DRW_get_context(void) +/* **************************************** RENDERING ************************************** */ + +static void DRW_engines_init(void) { - return DST.context; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + if (engine->engine_init) { + engine->engine_init(); + } + } } -void *DRW_engine_pass_list_get(void) +static void DRW_engines_cache_init(void) { - return DST.psl; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + if (engine->cache_init) { + engine->cache_init(); + } + } } -void *DRW_engine_storage_list_get(void) +static void DRW_engines_cache_populate(Object *ob) { - return DST.stl; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + if (engine->cache_populate) { + engine->cache_populate(ob); + } + } } -void *DRW_engine_texture_list_get(void) +static void DRW_engines_cache_finish(void) { - return DST.txl; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + if (engine->cache_finish) { + engine->cache_finish(); + } + } } -void *DRW_engine_framebuffer_list_get(void) +static void DRW_engines_draw_background(void) { - return DST.fbl; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + if (engine->draw_background) { + engine->draw_background(); + return; + } + } + + /* No draw_background found, doing default background */ + DRW_draw_background(); } -void *DRW_mode_pass_list_get(void) +static void DRW_engines_draw_scene(void) { - return DST.psl_mode; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + if (engine->draw_scene) { + engine->draw_scene(); + } + } } -void *DRW_mode_storage_list_get(void) +static void use_drw_engine(DrawEngineType *engine) { - return DST.stl_mode; + LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data"); + ld->data = engine; + BLI_addtail(&DST.enabled_engines, ld); } -void *DRW_mode_texture_list_get(void) +/* TODO revisit this when proper layering is implemented */ +/* Gather all draw engines needed and store them in DST.enabled_engines + * That also define the rendering order of engines */ +static void DRW_engines_enable(const bContext *C) { - return DST.txl_mode; + /* TODO layers */ + Scene *scene = CTX_data_scene(C); + RenderEngineType *type = RE_engines_find(scene->r.engine); + use_drw_engine(type->draw_engine); + + /* TODO Refine the folowing logic based on objects states + * not on global state. + * Order is important */ + use_drw_engine(&draw_engine_object_type); + + switch (CTX_data_mode_enum(C)) { + case CTX_MODE_EDIT_MESH: + use_drw_engine(&draw_engine_edit_mesh_type); + break; + case CTX_MODE_EDIT_CURVE: + break; + case CTX_MODE_EDIT_SURFACE: + break; + case CTX_MODE_EDIT_TEXT: + break; + case CTX_MODE_EDIT_ARMATURE: + use_drw_engine(&draw_engine_edit_armature_type); + break; + case CTX_MODE_EDIT_METABALL: + break; + case CTX_MODE_EDIT_LATTICE: + break; + case CTX_MODE_POSE: + break; + case CTX_MODE_SCULPT: + break; + case CTX_MODE_PAINT_WEIGHT: + break; + case CTX_MODE_PAINT_VERTEX: + break; + case CTX_MODE_PAINT_TEXTURE: + break; + case CTX_MODE_PARTICLE: + break; + case CTX_MODE_OBJECT: + break; + } } -void *DRW_mode_framebuffer_list_get(void) +static void DRW_engines_disable(void) { - return DST.fbl_mode; + BLI_freelistN(&DST.enabled_engines); +} + +static int DRW_engines_get_hash(void) +{ + unsigned int hash = 0; + /* The cache depends on enabled engines */ + /* FIXME : if collision occurs ... segfault */ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + hash += BLI_ghashutil_strhash_p(engine->idname); + } + + return hash; +} + +/* Everything starts here. + * This function takes care of calling all cache and rendering functions + * for each relevant engine / mode engine. */ +void DRW_draw_view(const bContext *C) +{ + bool cache_is_dirty; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + View3D *v3d = CTX_wm_view3d(C); + DST.viewport = rv3d->viewport; + v3d->zbuf = true; + + /* Get list of enabled engines */ + DRW_engines_enable(C); + + /* Setup viewport */ + cache_is_dirty = GPU_viewport_cache_validate(DST.viewport, DRW_engines_get_hash()); + DRW_viewport_var_init(C); + + /* Update ubos */ + DRW_globals_update(); + + /* Init engines */ + DRW_engines_init(); + + /* TODO : tag to refresh by the deps graph */ + /* ideally only refresh when objects are added/removed */ + /* or render properties / materials change */ + if (cache_is_dirty) { + SceneLayer *sl = CTX_data_scene_layer(C); + + DRW_engines_cache_init(); + DEG_OBJECT_ITER(sl, ob); + { + DRW_engines_cache_populate(ob); + } + DEG_OBJECT_ITER_END + DRW_engines_cache_finish(); + } + + /* Start Drawing */ + DRW_engines_draw_background(); + + DRW_draw_callbacks_pre_scene(); + DRW_engines_draw_scene(); + DRW_draw_callbacks_post_scene(); + + DRW_draw_region_info(); + + DRW_state_reset(); + DRW_engines_disable(); + + /* Unbind fbo and draw result */ + GPU_viewport_unbind(DST.viewport); +} + +/* ****************************************** OTHER ***************************************** */ + +const bContext *DRW_get_context(void) +{ + return DST.context; } /* ****************************************** INIT ***************************************** */ -void DRW_engines_init(void) +void DRW_engine_register(DrawEngineType *draw_engine_type) +{ + BLI_addtail(&DRW_engines, draw_engine_type); +} + +void DRW_engines_register(void) { #ifdef WITH_CLAY_ENGINE RE_engines_register(NULL, &viewport_clay_type); + + DRW_engine_register(&draw_engine_object_type); + DRW_engine_register(&draw_engine_edit_mesh_type); + DRW_engine_register(&draw_engine_edit_armature_type); #endif } -extern struct GPUUniformBuffer *globals_ubo; /* draw_mode_pass.c */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ void DRW_engines_free(void) { #ifdef WITH_CLAY_ENGINE - CLAY_engine_free(); + DRW_shape_cache_free(); - EDIT_MESH_engine_free(); + DrawEngineType *next; + for (DrawEngineType *type = DRW_engines.first; type; type = next) { + next = type->next; + BLI_remlink(&R_engines, type); - DRW_shape_cache_free(); + if (type->engine_free) { + type->engine_free(); + } + } if (globals_ubo) GPU_uniformbuffer_free(globals_ubo); diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c deleted file mode 100644 index b21e6a23b72..00000000000 --- a/source/blender/draw/intern/draw_mode_pass.c +++ /dev/null @@ -1,974 +0,0 @@ -/* - * Copyright 2016, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Institute - * - */ - -/** \file blender/draw/intern/draw_mode_pass.c - * \ingroup draw - */ - -#include "DNA_camera_types.h" -#include "DNA_userdef_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" - -#include "GPU_shader.h" - -#include "UI_resources.h" - -#include "BKE_global.h" -#include "BKE_camera.h" - -#include "DRW_render.h" - -#include "draw_mode_pass.h" - -/* ************************** OBJECT MODE ******************************* */ - -/* Store list of shading group for easy access*/ - -/* Empties */ -static DRWShadingGroup *plain_axes; -static DRWShadingGroup *cube; -static DRWShadingGroup *circle; -static DRWShadingGroup *sphere; -static DRWShadingGroup *cone; -static DRWShadingGroup *single_arrow; -static DRWShadingGroup *single_arrow_line; -static DRWShadingGroup *arrows; -static DRWShadingGroup *axis_names; - -/* Speaker */ -static DRWShadingGroup *speaker; - -/* Lamps */ -static DRWShadingGroup *lamp_center; -static DRWShadingGroup *lamp_center_group; -static DRWShadingGroup *lamp_groundpoint; -static DRWShadingGroup *lamp_groundline; -static DRWShadingGroup *lamp_circle; -static DRWShadingGroup *lamp_circle_shadow; -static DRWShadingGroup *lamp_sunrays; -static DRWShadingGroup *lamp_distance; -static DRWShadingGroup *lamp_buflimit; -static DRWShadingGroup *lamp_buflimit_points; -static DRWShadingGroup *lamp_area; -static DRWShadingGroup *lamp_hemi; -static DRWShadingGroup *lamp_spot_cone; -static DRWShadingGroup *lamp_spot_blend; -static DRWShadingGroup *lamp_spot_pyramid; -static DRWShadingGroup *lamp_spot_blend_rect; - -/* Helpers */ -static DRWShadingGroup *relationship_lines; - -/* Objects Centers */ -static DRWShadingGroup *center_active; -static DRWShadingGroup *center_selected; -static DRWShadingGroup *center_deselected; - -/* Camera */ -static DRWShadingGroup *camera; -static DRWShadingGroup *camera_tria; -static DRWShadingGroup *camera_focus; -static DRWShadingGroup *camera_clip; -static DRWShadingGroup *camera_clip_points; -static DRWShadingGroup *camera_mist; -static DRWShadingGroup *camera_mist_points; - -/* Colors & Constant */ -GlobalsUboStorage ts; -struct GPUUniformBuffer *globals_ubo = NULL; - -void DRW_update_global_values(void) -{ - UI_GetThemeColor4fv(TH_WIRE, ts.colorWire); - UI_GetThemeColor4fv(TH_WIRE_EDIT, ts.colorWireEdit); - UI_GetThemeColor4fv(TH_ACTIVE, ts.colorActive); - UI_GetThemeColor4fv(TH_SELECT, ts.colorSelect); - UI_GetThemeColor4fv(TH_TRANSFORM, ts.colorTransform); - UI_GetThemeColor4fv(TH_GROUP_ACTIVE, ts.colorGroupActive); - UI_GetThemeColor4fv(TH_GROUP, ts.colorGroup); - UI_GetThemeColor4fv(TH_LAMP, ts.colorLamp); - UI_GetThemeColor4fv(TH_SPEAKER, ts.colorSpeaker); - UI_GetThemeColor4fv(TH_CAMERA, ts.colorCamera); - UI_GetThemeColor4fv(TH_EMPTY, ts.colorEmpty); - UI_GetThemeColor4fv(TH_VERTEX, ts.colorVertex); - UI_GetThemeColor4fv(TH_VERTEX_SELECT, ts.colorVertexSelect); - UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, ts.colorEditMeshActive); - UI_GetThemeColor4fv(TH_EDGE_SELECT, ts.colorEdgeSelect); - UI_GetThemeColor4fv(TH_EDGE_SEAM, ts.colorEdgeSeam); - UI_GetThemeColor4fv(TH_EDGE_SHARP, ts.colorEdgeSharp); - UI_GetThemeColor4fv(TH_EDGE_CREASE, ts.colorEdgeCrease); - UI_GetThemeColor4fv(TH_EDGE_BEVEL, ts.colorEdgeBWeight); - UI_GetThemeColor4fv(TH_EDGE_FACESEL, ts.colorEdgeFaceSelect); - UI_GetThemeColor4fv(TH_FACE, ts.colorFace); - UI_GetThemeColor4fv(TH_FACE_SELECT, ts.colorFaceSelect); - UI_GetThemeColor4fv(TH_NORMAL, ts.colorNormal); - UI_GetThemeColor4fv(TH_VNORMAL, ts.colorVNormal); - UI_GetThemeColor4fv(TH_LNORMAL, ts.colorLNormal); - UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot); - - UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, ts.colorDeselect); - UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, ts.colorOutline); - UI_GetThemeColorShadeAlpha4fv(TH_LAMP, 0, 255, ts.colorLampNoAlpha); - - ts.sizeLampCenter = (U.obcenter_dia + 1.5f) * U.pixelsize; - ts.sizeLampCircle = U.pixelsize * 9.0f; - ts.sizeLampCircleShadow = ts.sizeLampCircle + U.pixelsize * 3.0f; - - /* M_SQRT2 to be at least the same size of the old square */ - ts.sizeVertex = UI_GetThemeValuef(TH_VERTEX_SIZE) * M_SQRT2 / 2.0f; - ts.sizeFaceDot = UI_GetThemeValuef(TH_FACEDOT_SIZE) * M_SQRT2; - ts.sizeEdge = 1.0f / 2.0f; /* TODO Theme */ - ts.sizeEdgeFix = 0.5f + 2.0f * (2.0f * (MAX2(ts.sizeVertex, ts.sizeEdge)) * M_SQRT1_2); - ts.sizeNormal = 1.0f; /* TODO compute */ - - /* TODO Waiting for notifiers to invalidate cache */ - if (globals_ubo) { - DRW_uniformbuffer_free(globals_ubo); - } - - globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts); -} - -/* Store list of passes for easy access */ -static DRWPass *wire_overlay; -static DRWPass *wire_overlay_hidden_wire; -static DRWPass *wire_outline; -static DRWPass *non_meshes; -static DRWPass *ob_center; -static DRWPass *bone_solid; -static DRWPass *bone_wire; - -static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4]) -{ - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - - DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", color, 1); - - return grp; -} - -static DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size) -{ - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - - DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", color, 1); - DRW_shgroup_uniform_float(grp, "size", size, 1); - DRW_shgroup_state_set(grp, DRW_STATE_POINT); - - return grp; -} - -static DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4]) -{ - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE); - - DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", color, 1); - - return grp; -} - -static DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4]) -{ - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT); - - DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", color, 1); - DRW_shgroup_state_set(grp, DRW_STATE_POINT); - - return grp; -} - -static DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom, float *size) -{ - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR); - - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "world_pos", 3); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_uniform_float(grp, "size", size, 1); - DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1); - DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2); - DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3); - - return grp; -} - -static DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Batch *geom, float (*obmat)[4]) -{ - 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); - - 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, "ModelMatrix", (float *)obmat); - DRW_shgroup_uniform_vec3(grp, "light", light, 1); - - return grp; -} - -static DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Batch *geom, float (*obmat)[4]) -{ - 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, "ModelMatrix", (float *)obmat); - - return grp; -} - -static DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Batch *geom) -{ - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); - - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2); - - return grp; -} - -static DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Batch *geom) -{ - GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); - - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "size", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - - return grp; -} - -static DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Batch *geom) -{ - GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA); - - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "corners", 8); - DRW_shgroup_attrib_float(grp, "depth", 1); - DRW_shgroup_attrib_float(grp, "tria", 4); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - - return grp; -} - -static DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Batch *geom) -{ - GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES); - static float point_size = 4.0f; - - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "start", 1); - DRW_shgroup_attrib_float(grp, "end", 1); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_uniform_float(grp, "size", &point_size, 1); - - return grp; -} - -static DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Batch *geom) -{ - GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR); - static bool True = true; - static bool False = false; - - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); - DRW_shgroup_attrib_float(grp, "color", 3); - DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); - DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1); - DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1); - DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1); - - return grp; -} - -/* This Function setup the passes needed for the mode rendering. - * The passes are populated by the rendering engines using the DRW_shgroup_* functions. - * If a pass is not needed use NULL instead of the pass pointer */ -void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, - DRWPass **psl_wire_overlay_hidden_wire, - DRWPass **psl_wire_outline, - DRWPass **psl_non_meshes, - DRWPass **psl_ob_center, - DRWPass **psl_bone_solid, - DRWPass **psl_bone_wire) -{ - - - if (psl_wire_overlay) { - /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND; - *psl_wire_overlay = DRW_pass_create("Wire Overlays Pass", state); - } - - if (psl_wire_overlay_hidden_wire) { - /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; - *psl_wire_overlay_hidden_wire = DRW_pass_create("Wire Overlays Pass", state); - } - - if (psl_wire_outline) { - /* This pass can draw mesh outlines and/or fancy wireframe */ - /* Fancy wireframes are not meant to be occluded (without Z offset) */ - /* Outlines and Fancy Wires use the same VBO */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; - *psl_wire_outline = DRW_pass_create("Wire + Outlines Pass", state); - } - - if (psl_bone_solid) { - /* Solid bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; - *psl_bone_solid = DRW_pass_create("Bone Solid Pass", state); - } - - if (psl_bone_wire) { - /* Wire bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; - *psl_bone_wire = DRW_pass_create("Bone Wire Pass", state); - } - - if (psl_non_meshes) { - /* Non Meshes Pass (Camera, empties, lamps ...) */ - struct Batch *geom; - - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_POINT; - state |= DRW_STATE_WIRE; - *psl_non_meshes = DRW_pass_create("Non Meshes Pass", state); - - /* Empties */ - geom = DRW_cache_plain_axes_get(); - plain_axes = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_cube_get(); - cube = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_circle_get(); - circle = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_empty_sphere_get(); - sphere = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_empty_cone_get(); - cone = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_single_arrow_get(); - single_arrow = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_single_line_get(); - single_arrow_line = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_arrows_get(); - arrows = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_axis_names_get(); - axis_names = shgroup_instance_axis_names(*psl_non_meshes, geom); - - /* Speaker */ - geom = DRW_cache_speaker_get(); - speaker = shgroup_instance(*psl_non_meshes, geom); - - /* Camera */ - geom = DRW_cache_camera_get(); - camera = shgroup_camera_instance(*psl_non_meshes, geom); - - geom = DRW_cache_camera_tria_get(); - camera_tria = shgroup_camera_instance(*psl_non_meshes, geom); - - geom = DRW_cache_plain_axes_get(); - camera_focus = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_single_line_get(); - camera_clip = shgroup_distance_lines_instance(*psl_non_meshes, geom); - camera_mist = shgroup_distance_lines_instance(*psl_non_meshes, geom); - - geom = DRW_cache_single_line_endpoints_get(); - camera_clip_points = shgroup_distance_lines_instance(*psl_non_meshes, geom); - camera_mist_points = shgroup_distance_lines_instance(*psl_non_meshes, geom); - - /* Lamps */ - /* TODO - * for now we create multiple times the same VBO with only lamp center coordinates - * but ideally we would only create it once */ - - /* start with buflimit because we don't want stipples */ - geom = DRW_cache_single_line_get(); - lamp_buflimit = shgroup_distance_lines_instance(*psl_non_meshes, geom); - - lamp_center = shgroup_dynpoints_uniform_color(*psl_non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter); - lamp_center_group = shgroup_dynpoints_uniform_color(*psl_non_meshes, ts.colorGroup, &ts.sizeLampCenter); - - geom = DRW_cache_lamp_get(); - lamp_circle = shgroup_instance_screenspace(*psl_non_meshes, geom, &ts.sizeLampCircle); - lamp_circle_shadow = shgroup_instance_screenspace(*psl_non_meshes, geom, &ts.sizeLampCircleShadow); - - geom = DRW_cache_lamp_sunrays_get(); - lamp_sunrays = shgroup_instance_screenspace(*psl_non_meshes, geom, &ts.sizeLampCircle); - - lamp_groundline = shgroup_groundlines_uniform_color(*psl_non_meshes, ts.colorLamp); - lamp_groundpoint = shgroup_groundpoints_uniform_color(*psl_non_meshes, ts.colorLamp); - - geom = DRW_cache_lamp_area_get(); - lamp_area = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_lamp_hemi_get(); - lamp_hemi = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_single_line_get(); - lamp_distance = shgroup_distance_lines_instance(*psl_non_meshes, geom); - - geom = DRW_cache_single_line_endpoints_get(); - lamp_buflimit_points = shgroup_distance_lines_instance(*psl_non_meshes, geom); - - geom = DRW_cache_lamp_spot_get(); - lamp_spot_cone = shgroup_spot_instance(*psl_non_meshes, geom); - - geom = DRW_cache_circle_get(); - lamp_spot_blend = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_lamp_spot_square_get(); - lamp_spot_pyramid = shgroup_instance(*psl_non_meshes, geom); - - geom = DRW_cache_square_get(); - lamp_spot_blend_rect = shgroup_instance(*psl_non_meshes, geom); - - /* Relationship Lines */ - relationship_lines = shgroup_dynlines_uniform_color(*psl_non_meshes, ts.colorWire); - DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3); - } - - if (psl_ob_center) { - /* Object Center pass grouped by State */ - DRWShadingGroup *grp; - static float outlineWidth, size; - - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT; - *psl_ob_center = DRW_pass_create("Obj Center Pass", state); - - outlineWidth = 1.0f * U.pixelsize; - size = U.obcenter_dia * U.pixelsize + outlineWidth; - - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); - - /* Active */ - grp = DRW_shgroup_point_batch_create(sh, *psl_ob_center); - DRW_shgroup_uniform_float(grp, "size", &size, 1); - DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1); - DRW_shgroup_uniform_vec4(grp, "color", ts.colorActive, 1); - DRW_shgroup_uniform_vec4(grp, "outlineColor", ts.colorOutline, 1); - center_active = grp; - - /* Select */ - grp = DRW_shgroup_point_batch_create(sh, *psl_ob_center); - DRW_shgroup_uniform_vec4(grp, "color", ts.colorSelect, 1); - center_selected = grp; - - /* Deselect */ - grp = DRW_shgroup_point_batch_create(sh, *psl_ob_center); - DRW_shgroup_uniform_vec4(grp, "color", ts.colorDeselect, 1); - center_deselected = grp; - } - - /* Save passes refs */ - wire_overlay = (psl_wire_overlay) ? *psl_wire_overlay : NULL; - wire_overlay_hidden_wire = (psl_wire_overlay_hidden_wire) ? *psl_wire_overlay_hidden_wire : NULL; - wire_outline = (psl_wire_outline) ? *psl_wire_outline : NULL; - non_meshes = (psl_non_meshes) ? *psl_non_meshes : NULL; - ob_center = (psl_ob_center) ? *psl_ob_center : NULL; - bone_solid = (psl_bone_solid) ? *psl_bone_solid : NULL; - bone_wire = (psl_bone_wire) ? *psl_bone_wire : NULL; -} - -/* ******************************************** WIRES *********************************************** */ - -/* TODO FINISH */ -/* Get the wire color theme_id of an object based on it's state - * **color is a way to get a pointer to the static color var associated */ -static int draw_object_wire_theme(Object *ob, float **color) -{ - const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0; - /* confusing logic here, there are 2 methods of setting the color - * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. - * - * note: no theme yet for 'colindex' */ - int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE; - - if (//(scene->obedit == NULL) && - ((G.moving & G_TRANSFORM_OBJ) != 0) && - ((ob->base_flag & BASE_SELECTED) != 0)) - { - theme_id = TH_TRANSFORM; - } - else { - /* Sets the 'theme_id' or fallback to wire */ - if ((ob->flag & OB_FROMGROUP) != 0) { - if ((ob->base_flag & BASE_SELECTED) != 0) { - /* uses darker active color for non-active + selected */ - theme_id = TH_GROUP_ACTIVE; - - // if (scene->basact != base) { - // theme_shade = -16; - // } - } - else { - theme_id = TH_GROUP; - } - } - else { - if ((ob->base_flag & BASE_SELECTED) != 0) { - theme_id = //scene->basact == base ? TH_ACTIVE : - TH_SELECT; - } - else { - if (ob->type == OB_LAMP) theme_id = TH_LAMP; - else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER; - else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA; - else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY; - /* fallback to TH_WIRE */ - } - } - } - - if (color != NULL) { - switch (theme_id) { - case TH_WIRE_EDIT: *color = ts.colorTransform; break; - case TH_ACTIVE: *color = ts.colorActive; break; - case TH_SELECT: *color = ts.colorSelect; break; - case TH_GROUP: *color = ts.colorGroup; break; - case TH_GROUP_ACTIVE: *color = ts.colorGroupActive; break; - case TH_TRANSFORM: *color = ts.colorTransform; break; - case OB_SPEAKER: *color = ts.colorSpeaker; break; - case OB_CAMERA: *color = ts.colorCamera; break; - case OB_EMPTY: *color = ts.colorEmpty; break; - case OB_LAMP: *color = ts.colorLamp; break; - default: *color = ts.colorWire; break; - } - } - - return theme_id; -} - -void DRW_shgroup_wire_outline(Object *ob, const bool do_front, const bool do_back, const bool do_outline) -{ - GPUShader *sh; - struct Batch *geom = DRW_cache_wire_outline_get(ob); - - float *color; - draw_object_wire_theme(ob, &color); - -#if 1 /* New wire */ - - bool is_perps = DRW_viewport_is_persp_get(); - static bool bTrue = true; - static bool bFalse = false; - - /* Note (TODO) : this requires cache to be discarded on ortho/perp switch - * It may be preferable (or not depending on performance implication) - * to introduce a shader uniform switch */ - if (is_perps) { - sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP); - } - else { - sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO); - } - - if (do_front || do_back) { - bool *bFront = (do_front) ? &bTrue : &bFalse; - bool *bBack = (do_back) ? &bTrue : &bFalse; - - DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline); - DRW_shgroup_state_set(grp, DRW_STATE_WIRE); - DRW_shgroup_uniform_vec4(grp, "frontColor", color, 1); - DRW_shgroup_uniform_vec4(grp, "backColor", color, 1); - DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1); - DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1); - DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1); - DRW_shgroup_call_add(grp, geom, ob->obmat); - } - - if (do_outline) { - DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline); - DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE); - DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1); - DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1); - DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1); - DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1); - - DRW_shgroup_call_add(grp, geom, ob->obmat); - } - -#else /* Old (flat) wire */ - - sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline); - DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE); - DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1); - - DRW_shgroup_call_add(grp, geom, ob->obmat); -#endif - -} - -/* ***************************** NON MESHES ********************** */ - -void DRW_shgroup_lamp(Object *ob) -{ - Lamp *la = ob->data; - float *color; - int theme_id = draw_object_wire_theme(ob, &color); - static float zero = 0.0f; - - /* Don't draw the center if it's selected or active */ - if (theme_id == TH_GROUP) - DRW_shgroup_dynamic_call_add(lamp_center_group, ob->obmat[3]); - else if (theme_id == TH_LAMP) - DRW_shgroup_dynamic_call_add(lamp_center, ob->obmat[3]); - - /* First circle */ - DRW_shgroup_dynamic_call_add(lamp_circle, ob->obmat[3], color); - - /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ - if (la->type != LA_HEMI) { - if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) { - DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color); - } - } - - /* Distance */ - if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) { - DRW_shgroup_dynamic_call_add(lamp_distance, color, &zero, &la->dist, ob->obmat); - } - - copy_m4_m4(la->shapemat, ob->obmat); - - if (la->type == LA_SUN) { - DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color); - } - else if (la->type == LA_SPOT) { - float size[3], sizemat[4][4]; - static float one = 1.0f; - float blend = 1.0f - pow2f(la->spotblend); - - size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist; - size[2] = cosf(la->spotsize * 0.5f) * la->dist; - - size_to_mat4(sizemat, size); - mul_m4_m4m4(la->spotconemat, ob->obmat, sizemat); - - size[0] = size[1] = blend; size[2] = 1.0f; - size_to_mat4(sizemat, size); - translate_m4(sizemat, 0.0f, 0.0f, -1.0f); - rotate_m4(sizemat, 'X', M_PI / 2.0f); - mul_m4_m4m4(la->spotblendmat, la->spotconemat, sizemat); - - if (la->mode & LA_SQUARE) { - DRW_shgroup_dynamic_call_add(lamp_spot_pyramid, color, &one, la->spotconemat); - - /* hide line if it is zero size or overlaps with outer border, - * previously it adjusted to always to show it but that seems - * confusing because it doesn't show the actual blend size */ - if (blend != 0.0f && blend != 1.0f) { - DRW_shgroup_dynamic_call_add(lamp_spot_blend_rect, color, &one, la->spotblendmat); - } - } - else { - DRW_shgroup_dynamic_call_add(lamp_spot_cone, color, la->spotconemat); - - /* hide line if it is zero size or overlaps with outer border, - * previously it adjusted to always to show it but that seems - * confusing because it doesn't show the actual blend size */ - if (blend != 0.0f && blend != 1.0f) { - DRW_shgroup_dynamic_call_add(lamp_spot_blend, color, &one, la->spotblendmat); - } - } - - normalize_m4(la->shapemat); - DRW_shgroup_dynamic_call_add(lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); - DRW_shgroup_dynamic_call_add(lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); - } - else if (la->type == LA_HEMI) { - static float hemisize = 2.0f; - DRW_shgroup_dynamic_call_add(lamp_hemi, color, &hemisize, la->shapemat); - } - else if (la->type == LA_AREA) { - float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; - - if (la->area_shape == LA_AREA_RECT) { - size[1] = la->area_sizey / la->area_size; - size_to_mat4(sizemat, size); - mul_m4_m4m4(la->shapemat, la->shapemat, sizemat); - } - - DRW_shgroup_dynamic_call_add(lamp_area, color, &la->area_size, la->shapemat); - } - - /* Line and point going to the ground */ - DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]); - DRW_shgroup_dynamic_call_add(lamp_groundpoint, ob->obmat[3]); -} - -void DRW_shgroup_camera(Object *ob) -{ - const struct bContext *C = DRW_get_context(); - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - - Camera *cam = ob->data; - const bool is_active = (ob == v3d->camera); - float *color; - draw_object_wire_theme(ob, &color); - - float vec[4][3], asp[2], shift[2], scale[3], drawsize; - - scale[0] = 1.0f / len_v3(ob->obmat[0]); - scale[1] = 1.0f / len_v3(ob->obmat[1]); - scale[2] = 1.0f / len_v3(ob->obmat[2]); - - BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale, - asp, shift, &drawsize, vec); - - // /* Frame coords */ - copy_v2_v2(cam->drwcorners[0], vec[0]); - copy_v2_v2(cam->drwcorners[1], vec[1]); - copy_v2_v2(cam->drwcorners[2], vec[2]); - copy_v2_v2(cam->drwcorners[3], vec[3]); - - /* depth */ - cam->drwdepth = vec[0][2]; - - /* tria */ - cam->drwtria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]); - cam->drwtria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); - cam->drwtria[1][0] = shift[0]; - cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); - - DRW_shgroup_dynamic_call_add(camera, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat); - - /* Active cam */ - if (is_active) { - DRW_shgroup_dynamic_call_add(camera_tria, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat); - } - - /* draw the rest in normalize object space */ - copy_m4_m4(cam->drwnormalmat, ob->obmat); - normalize_m4(cam->drwnormalmat); - - if (cam->flag & CAM_SHOWLIMITS) { - static float col[3] = {0.5f, 0.5f, 0.25f}, col_hi[3] = {1.0f, 1.0f, 0.5f}; - float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f}; - float focusdist = BKE_camera_object_dof_distance(ob); - - copy_m4_m4(cam->drwfocusmat, cam->drwnormalmat); - translate_m4(cam->drwfocusmat, 0.0f, 0.0f, -focusdist); - size_to_mat4(sizemat, size); - mul_m4_m4m4(cam->drwfocusmat, cam->drwfocusmat, sizemat); - - DRW_shgroup_dynamic_call_add(camera_focus, (is_active ? col_hi : col), &cam->drawsize, cam->drwfocusmat); - - DRW_shgroup_dynamic_call_add(camera_clip, color, &cam->clipsta, &cam->clipend, cam->drwnormalmat); - DRW_shgroup_dynamic_call_add(camera_clip_points, (is_active ? col_hi : col), &cam->clipsta, &cam->clipend, cam->drwnormalmat); - } - - if (cam->flag & CAM_SHOWMIST) { - World *world = scene->world; - - if (world) { - static float col[3] = {0.5f, 0.5f, 0.5f}, col_hi[3] = {1.0f, 1.0f, 1.0f}; - world->mistend = world->miststa + world->mistdist; - DRW_shgroup_dynamic_call_add(camera_mist, color, &world->miststa, &world->mistend, cam->drwnormalmat); - DRW_shgroup_dynamic_call_add(camera_mist_points, (is_active ? col_hi : col), &world->miststa, &world->mistend, cam->drwnormalmat); - } - } -} - -void DRW_shgroup_empty(Object *ob) -{ - float *color; - draw_object_wire_theme(ob, &color); - - switch (ob->empty_drawtype) { - case OB_PLAINAXES: - DRW_shgroup_dynamic_call_add(plain_axes, color, &ob->empty_drawsize, ob->obmat); - break; - case OB_SINGLE_ARROW: - DRW_shgroup_dynamic_call_add(single_arrow, color, &ob->empty_drawsize, ob->obmat); - DRW_shgroup_dynamic_call_add(single_arrow_line, color, &ob->empty_drawsize, ob->obmat); - break; - case OB_CUBE: - DRW_shgroup_dynamic_call_add(cube, color, &ob->empty_drawsize, ob->obmat); - break; - case OB_CIRCLE: - DRW_shgroup_dynamic_call_add(circle, color, &ob->empty_drawsize, ob->obmat); - break; - case OB_EMPTY_SPHERE: - DRW_shgroup_dynamic_call_add(sphere, color, &ob->empty_drawsize, ob->obmat); - break; - case OB_EMPTY_CONE: - DRW_shgroup_dynamic_call_add(cone, color, &ob->empty_drawsize, ob->obmat); - break; - case OB_ARROWS: - DRW_shgroup_dynamic_call_add(arrows, color, &ob->empty_drawsize, ob->obmat); - DRW_shgroup_dynamic_call_add(axis_names, color, &ob->empty_drawsize, ob->obmat); - break; - } -} - -void DRW_shgroup_speaker(Object *ob) -{ - float *color; - static float one = 1.0f; - draw_object_wire_theme(ob, &color); - - DRW_shgroup_dynamic_call_add(speaker, color, &one, ob->obmat); -} - -void DRW_shgroup_relationship_lines(Object *ob) -{ - if (ob->parent) { - DRW_shgroup_dynamic_call_add(relationship_lines, ob->obmat[3]); - DRW_shgroup_dynamic_call_add(relationship_lines, ob->parent->obmat[3]); - } -} - -/* ***************************** COMMON **************************** */ - -void DRW_shgroup_object_center(Object *ob) -{ - if ((ob->base_flag & BASE_SELECTED) != 0) { - DRW_shgroup_dynamic_call_add(center_selected, ob->obmat[3]); - } - else if (0) { - DRW_shgroup_dynamic_call_add(center_deselected, ob->obmat[3]); - } -} - -/* *************************** ARMATURES ***************************** */ - -static Object *current_armature; -/* Reset when changing current_armature */ -static DRWShadingGroup *bone_octahedral_solid; -static DRWShadingGroup *bone_octahedral_wire; -static DRWShadingGroup *bone_point_solid; -static DRWShadingGroup *bone_point_wire; -static DRWShadingGroup *bone_axes; - -/* this function set the object space to use - * for all subsequent DRW_shgroup_bone_*** calls */ -static void DRW_shgroup_armature(Object *ob) -{ - current_armature = ob; - bone_octahedral_solid = NULL; - bone_octahedral_wire = NULL; - bone_point_solid = NULL; - bone_point_wire = NULL; - bone_axes = NULL; -} - -void DRW_shgroup_armature_object(Object *ob) -{ - float *color; - draw_object_wire_theme(ob, &color); - - DRW_shgroup_armature(ob); - draw_armature_pose(ob, color); -} - -void DRW_shgroup_armature_pose(Object *ob) -{ - DRW_shgroup_armature(ob); - draw_armature_pose(ob, NULL); -} - -void DRW_shgroup_armature_edit(Object *ob) -{ - DRW_shgroup_armature(ob); - draw_armature_edit(ob); -} - -/* Octahedral */ -void DRW_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const float color[4]) -{ - if (bone_octahedral_solid == NULL) { - struct Batch *geom = DRW_cache_bone_octahedral_get(); - bone_octahedral_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat); - } - - DRW_shgroup_dynamic_call_add(bone_octahedral_solid, bone_mat, color); -} - -void DRW_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4]) -{ - if (bone_octahedral_wire == NULL) { - struct Batch *geom = DRW_cache_bone_octahedral_wire_outline_get(); - bone_octahedral_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); - } - - DRW_shgroup_dynamic_call_add(bone_octahedral_wire, bone_mat, color); -} - -/* Head and tail sphere */ -void DRW_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4]) -{ - if (bone_point_solid == NULL) { - struct Batch *geom = DRW_cache_bone_point_get(); - bone_point_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat); - } - - DRW_shgroup_dynamic_call_add(bone_point_solid, bone_mat, color); -} - -void DRW_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4]) -{ - if (bone_point_wire == NULL) { - struct Batch *geom = DRW_cache_bone_point_wire_outline_get(); - bone_point_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); - } - - DRW_shgroup_dynamic_call_add(bone_point_wire, bone_mat, color); -} - -/* Axes */ -void DRW_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4]) -{ - if (bone_axes == NULL) { - struct Batch *geom = DRW_cache_bone_arrows_get(); - bone_axes = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat); - } - - DRW_shgroup_dynamic_call_add(bone_axes, bone_mat, color); -} - - -void DRW_shgroup_bone_relationship_lines(const float head[3], const float tail[3]) -{ - DRW_shgroup_dynamic_call_add(relationship_lines, head); - DRW_shgroup_dynamic_call_add(relationship_lines, tail); -} diff --git a/source/blender/draw/modes/object_mode.h b/source/blender/draw/modes/draw_mode_engines.h index fda9096203d..01af249b736 100644 --- a/source/blender/draw/modes/object_mode.h +++ b/source/blender/draw/modes/draw_mode_engines.h @@ -19,19 +19,15 @@ * */ -/** \file blender/draw/modes/object_mode.h +/** \file blender/draw/modes/draw_mode_engines.h * \ingroup draw */ -#ifndef __OBJECT_MODE_H__ -#define __OBJECT_MODE_H__ +#ifndef __DRAW_MODES_ENGINES_H__ +#define __DRAW_MODES_ENGINES_H__ -struct Object; +extern DrawEngineType draw_engine_object_type; +extern DrawEngineType draw_engine_edit_mesh_type; +extern DrawEngineType draw_engine_edit_armature_type; -void OBJECT_cache_init(void); -void OBJECT_cache_populate(struct Object *ob); -void OBJECT_cache_finish(void); - -void OBJECT_draw(void); - -#endif /* __OBJECT_MODE_H__ */
\ No newline at end of file +#endif /* __DRAW_MODES_ENGINES_H__ */
\ No newline at end of file diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c index 5f1418340d1..f2f19eacf2d 100644 --- a/source/blender/draw/modes/edit_armature_mode.c +++ b/source/blender/draw/modes/edit_armature_mode.c @@ -28,85 +28,80 @@ #include "DNA_armature_types.h" -#include "draw_mode_pass.h" +#include "draw_common.h" -#include "edit_armature_mode.h" +#include "draw_mode_engines.h" /* keep it under MAX_PASSES */ typedef struct EDIT_ARMATURE_PassList { - struct DRWPass *non_meshes_pass; - struct DRWPass *ob_center_pass; - struct DRWPass *wire_outline_pass; - struct DRWPass *bone_solid_pass; - struct DRWPass *bone_wire_pass; + struct DRWPass *bone_solid; + struct DRWPass *bone_wire; + struct DRWPass *relationship; } EDIT_ARMATURE_PassList; -void EDIT_ARMATURE_cache_init(void) +typedef struct EDIT_ARMATURE_Data { + char engine_name[32]; + void *fbl; + void *txl; + EDIT_ARMATURE_PassList *psl; + void *stl; +} EDIT_ARMATURE_Data; + +static DRWShadingGroup *relationship_lines; + +extern GlobalsUboStorage ts; + +static EDIT_ARMATURE_Data *vedata; + +static void EDIT_ARMATURE_cache_init(void) { - EDIT_ARMATURE_PassList *psl = DRW_mode_pass_list_get(); - static struct GPUShader *depth_sh; + vedata = DRW_viewport_engine_data_get("EditArmatureMode"); + EDIT_ARMATURE_PassList *psl = vedata->psl; - if (!depth_sh) { - depth_sh = DRW_shader_create_3D_depth_only(); + { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); } - DRW_mode_passes_setup(NULL, - NULL, - &psl->wire_outline_pass, - &psl->non_meshes_pass, - &psl->ob_center_pass, - &psl->bone_solid_pass, - &psl->bone_wire_pass); -} + { + /* Wire bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->bone_wire = DRW_pass_create("Bone Wire Pass", state); + } -void EDIT_ARMATURE_cache_populate(Object *ob) -{ - bArmature *arm = ob->data; + { + /* Non Meshes Pass (Camera, empties, lamps ...) */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE; + psl->relationship = DRW_pass_create("Bone Relationship Pass", state); - switch (ob->type) { - case OB_ARMATURE: - /* detect Edit Armature mode */ - if (arm->edbo) - DRW_shgroup_armature_edit(ob); - else - DRW_shgroup_armature_object(ob); - break; - case OB_MESH: - break; - case OB_LAMP: - DRW_shgroup_lamp(ob); - break; - case OB_CAMERA: - DRW_shgroup_camera(ob); - break; - case OB_EMPTY: - DRW_shgroup_empty(ob); - break; - case OB_SPEAKER: - DRW_shgroup_speaker(ob); - break; - default: - break; + /* Relationship Lines */ + relationship_lines = shgroup_dynlines_uniform_color(psl->relationship, ts.colorWire); + DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3); } - DRW_shgroup_object_center(ob); - DRW_shgroup_relationship_lines(ob); } -void EDIT_ARMATURE_cache_finish(void) +static void EDIT_ARMATURE_cache_populate(Object *ob) { - /* Do nothing */ + bArmature *arm = ob->data; + EDIT_ARMATURE_PassList *psl = vedata->psl; + + if (ob->type == OB_ARMATURE) { + if (arm->edbo) { + DRW_shgroup_armature_edit(ob, psl->bone_solid, psl->bone_wire, relationship_lines); + } + } } -void EDIT_ARMATURE_draw(void) +static void EDIT_ARMATURE_draw_scene(void) { - EDIT_ARMATURE_PassList *psl = DRW_mode_pass_list_get(); + EDIT_ARMATURE_Data *ved = DRW_viewport_engine_data_get("EditArmatureMode"); + EDIT_ARMATURE_PassList *psl = ved->psl; - DRW_draw_pass(psl->bone_solid_pass); - DRW_draw_pass(psl->bone_wire_pass); - DRW_draw_pass(psl->wire_outline_pass); - DRW_draw_pass(psl->non_meshes_pass); - DRW_draw_pass(psl->ob_center_pass); + DRW_draw_pass(psl->bone_solid); + DRW_draw_pass(psl->bone_wire); + DRW_draw_pass(psl->relationship); } void EDIT_ARMATURE_collection_settings_create(CollectionEngineSettings *ces) @@ -114,3 +109,15 @@ void EDIT_ARMATURE_collection_settings_create(CollectionEngineSettings *ces) BLI_assert(ces); //BKE_collection_engine_property_add_int(ces, "show_occlude_wire", false); } + +DrawEngineType draw_engine_edit_armature_type = { + NULL, NULL, + N_("EditArmatureMode"), + NULL, + NULL, + &EDIT_ARMATURE_cache_init, + &EDIT_ARMATURE_cache_populate, + NULL, + NULL, + &EDIT_ARMATURE_draw_scene +}; diff --git a/source/blender/draw/modes/edit_armature_mode.h b/source/blender/draw/modes/edit_armature_mode.h deleted file mode 100644 index 89354cdf938..00000000000 --- a/source/blender/draw/modes/edit_armature_mode.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2016, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Institute - * - */ - -/** \file blender/draw/modes/edit_armature_mode.h - * \ingroup draw - */ - -#ifndef __EDIT_ARMATURE_MODE_H__ -#define __EDIT_ARMATURE_MODE_H__ - -struct Object; - -void EDIT_ARMATURE_cache_init(void); -void EDIT_ARMATURE_cache_populate(struct Object *ob); -void EDIT_ARMATURE_cache_finish(void); - -void EDIT_ARMATURE_draw(void); - -#endif /* __EDIT_ARMATURE_MODE_H__ */
\ No newline at end of file diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index 3736369f396..e671e9f059b 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -27,18 +27,14 @@ #include "DRW_render.h" #include "GPU_shader.h" -#include "GPU_viewport.h" #include "DNA_view3d_types.h" -#include "draw_mode_pass.h" +#include "draw_common.h" -#include "edit_mesh_mode.h" +#include "draw_mode_engines.h" /* keep it under MAX_PASSES */ typedef struct EDIT_MESH_PassList { - struct DRWPass *non_meshes_pass; - struct DRWPass *ob_center_pass; - struct DRWPass *wire_outline_pass; struct DRWPass *depth_pass_hidden_wire; struct DRWPass *edit_face_overlay_pass; struct DRWPass *edit_face_occluded_pass; @@ -57,6 +53,14 @@ typedef struct EDIT_MESH_TextureList { struct GPUTexture *occlude_wire_color_tx; } EDIT_MESH_TextureList; +typedef struct EDIT_MESH_Data { + char engine_name[32]; + EDIT_MESH_FramebufferList *fbl; + EDIT_MESH_TextureList *txl; + EDIT_MESH_PassList *psl; + void *stl; +} EDIT_MESH_Data; + static DRWShadingGroup *depth_shgrp_hidden_wire; static DRWShadingGroup *face_overlay_shgrp; @@ -70,7 +74,7 @@ static DRWShadingGroup *lverts_occluded_shgrp; static DRWShadingGroup *facedot_occluded_shgrp; static DRWShadingGroup *facefill_occluded_shgrp; -extern struct GPUUniformBuffer *globals_ubo; /* draw_mode_pass.c */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ static struct GPUShader *overlay_tri_sh = NULL; static struct GPUShader *overlay_tri_fast_sh = NULL; @@ -95,10 +99,11 @@ extern char datatoc_edit_overlay_mix_frag_glsl[]; extern char datatoc_edit_overlay_facefill_vert_glsl[]; extern char datatoc_edit_overlay_facefill_frag_glsl[]; -void EDIT_MESH_init(void) +static void EDIT_MESH_engine_init(void) { - EDIT_MESH_TextureList *txl = DRW_mode_texture_list_get(); - EDIT_MESH_FramebufferList *fbl = DRW_mode_framebuffer_list_get(); + EDIT_MESH_Data *vedata = DRW_viewport_engine_data_get("EditMeshMode"); + EDIT_MESH_TextureList *txl = vedata->txl; + EDIT_MESH_FramebufferList *fbl = vedata->fbl; float *viewport_size = DRW_viewport_size_get(); @@ -209,9 +214,13 @@ static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWS static float backwire_opacity; static float face_mod; -void EDIT_MESH_cache_init(void) +static void EDIT_MESH_cache_init(void) { - EDIT_MESH_PassList *psl = DRW_mode_pass_list_get(); + EDIT_MESH_Data *vedata = DRW_viewport_engine_data_get("EditMeshMode"); + EDIT_MESH_TextureList *txl = vedata->txl; + EDIT_MESH_PassList *psl = vedata->psl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const struct bContext *C = DRW_get_context(); View3D *v3d = CTX_wm_view3d(C); @@ -242,12 +251,9 @@ void EDIT_MESH_cache_init(void) DRW_shgroup_uniform_block(facefill_occluded_shgrp, "globalsBlock", globals_ubo, 0); /* we need a full screen pass to combine the result */ - EDIT_MESH_TextureList *txl = DRW_mode_texture_list_get(); - DefaultTextureList *dtxl = DRW_engine_texture_list_get(); struct Batch *quad = DRW_cache_fullscreen_quad_get(); static float mat[4][4]; /* not even used but avoid crash */ - psl->mix_occlude_pass = DRW_pass_create("Mix Occluded Wires", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); DRWShadingGroup *mix_shgrp = DRW_shgroup_create(overlay_mix_sh, psl->mix_occlude_pass); DRW_shgroup_call_add(mix_shgrp, quad, mat); @@ -256,14 +262,6 @@ void EDIT_MESH_cache_init(void) DRW_shgroup_uniform_buffer(mix_shgrp, "wireDepth", &txl->occlude_wire_depth_tx, 2); DRW_shgroup_uniform_buffer(mix_shgrp, "sceneDepth", &dtxl->depth, 3); } - - DRW_mode_passes_setup(NULL, - NULL, - &psl->wire_outline_pass, - &psl->non_meshes_pass, - &psl->ob_center_pass, - NULL, - NULL); } static void edit_mesh_add_ob_to_pass(Scene *scene, Object *ob, DRWShadingGroup *face_shgrp, DRWShadingGroup *ledges_shgrp, @@ -288,7 +286,7 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, Object *ob, DRWShadingGroup * } } -void EDIT_MESH_cache_populate(Object *ob) +static void EDIT_MESH_cache_populate(Object *ob) { const struct bContext *C = DRW_get_context(); View3D *v3d = CTX_wm_view3d(C); @@ -296,64 +294,38 @@ void EDIT_MESH_cache_populate(Object *ob) Object *obedit = scene->obedit; struct Batch *geom; - CollectionEngineSettings *ces_mode_ed = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, ""); - bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire"); - backwire_opacity = BKE_collection_engine_property_value_get_float(ces_mode_ed, "backwire_opacity"); /* should be done only once */ - - face_mod = (do_occlude_wire) ? 0.0f : 1.0f; - - switch (ob->type) { - case OB_MESH: - if (ob == obedit) { - if (do_occlude_wire) { - geom = DRW_cache_surface_get(ob); - DRW_shgroup_call_add(depth_shgrp_hidden_wire, geom, ob->obmat); - } - - if ((v3d->flag & V3D_ZBUF_SELECT) == 0) { - edit_mesh_add_ob_to_pass(scene, ob, face_occluded_shgrp, ledges_occluded_shgrp, - lverts_occluded_shgrp, facedot_occluded_shgrp, facefill_occluded_shgrp); - } - else { - edit_mesh_add_ob_to_pass(scene, ob, face_overlay_shgrp, ledges_overlay_shgrp, - lverts_overlay_shgrp, facedot_overlay_shgrp, NULL); - } - } - break; - case OB_LAMP: - DRW_shgroup_lamp(ob); - break; - case OB_CAMERA: - DRW_shgroup_camera(ob); - break; - case OB_EMPTY: - DRW_shgroup_empty(ob); - break; - case OB_SPEAKER: - DRW_shgroup_speaker(ob); - break; - case OB_ARMATURE: - DRW_shgroup_armature_object(ob); - break; - default: - break; - } + if (ob->type == OB_MESH) { + if (ob == obedit) { + CollectionEngineSettings *ces_mode_ed = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, ""); + bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire"); + backwire_opacity = BKE_collection_engine_property_value_get_float(ces_mode_ed, "backwire_opacity"); /* should be done only once */ - DRW_shgroup_object_center(ob); - DRW_shgroup_relationship_lines(ob); -} + face_mod = (do_occlude_wire) ? 0.0f : 1.0f; -void EDIT_MESH_cache_finish(void) -{ - /* Do nothing */ + if (do_occlude_wire) { + geom = DRW_cache_surface_get(ob); + DRW_shgroup_call_add(depth_shgrp_hidden_wire, geom, ob->obmat); + } + + if ((v3d->flag & V3D_ZBUF_SELECT) == 0) { + edit_mesh_add_ob_to_pass(scene, ob, face_occluded_shgrp, ledges_occluded_shgrp, + lverts_occluded_shgrp, facedot_occluded_shgrp, facefill_occluded_shgrp); + } + else { + edit_mesh_add_ob_to_pass(scene, ob, face_overlay_shgrp, ledges_overlay_shgrp, + lverts_overlay_shgrp, facedot_overlay_shgrp, NULL); + } + } + } } -void EDIT_MESH_draw(void) +static void EDIT_MESH_draw_scene(void) { - EDIT_MESH_PassList *psl = DRW_mode_pass_list_get(); - EDIT_MESH_FramebufferList *fbl = DRW_mode_framebuffer_list_get(); - DefaultFramebufferList *dfbl = DRW_engine_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_engine_texture_list_get(); + EDIT_MESH_Data *vedata = DRW_viewport_engine_data_get("EditMeshMode"); + EDIT_MESH_PassList *psl = vedata->psl; + EDIT_MESH_FramebufferList *fbl = vedata->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); DRW_draw_pass(psl->depth_pass_hidden_wire); @@ -380,10 +352,6 @@ void EDIT_MESH_draw(void) else { DRW_draw_pass(psl->edit_face_overlay_pass); } - - DRW_draw_pass(psl->wire_outline_pass); - DRW_draw_pass(psl->non_meshes_pass); - DRW_draw_pass(psl->ob_center_pass); } void EDIT_MESH_collection_settings_create(CollectionEngineSettings *ces) @@ -393,7 +361,7 @@ void EDIT_MESH_collection_settings_create(CollectionEngineSettings *ces) BKE_collection_engine_property_add_float(ces, "backwire_opacity", 0.5); } -void EDIT_MESH_engine_free(void) +static void EDIT_MESH_engine_free(void) { if (overlay_tri_sh) DRW_shader_free(overlay_tri_sh); @@ -415,4 +383,16 @@ void EDIT_MESH_engine_free(void) DRW_shader_free(overlay_mix_sh); if (overlay_facefill_sh) DRW_shader_free(overlay_facefill_sh); -}
\ No newline at end of file +} + +DrawEngineType draw_engine_edit_mesh_type = { + NULL, NULL, + N_("EditMeshMode"), + &EDIT_MESH_engine_init, + &EDIT_MESH_engine_free, + &EDIT_MESH_cache_init, + &EDIT_MESH_cache_populate, + NULL, + NULL, + &EDIT_MESH_draw_scene +}; diff --git a/source/blender/draw/modes/edit_mesh_mode.h b/source/blender/draw/modes/edit_mesh_mode.h deleted file mode 100644 index 508685bd033..00000000000 --- a/source/blender/draw/modes/edit_mesh_mode.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2016, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Blender Institute - * - */ - -/** \file blender/draw/modes/edit_mesh_mode.h - * \ingroup draw - */ - -#ifndef __EDIT_MESH_MODE_H__ -#define __EDIT_MESH_MODE_H__ - -struct Object; - -void EDIT_MESH_init(void); - -void EDIT_MESH_cache_init(void); -void EDIT_MESH_cache_populate(struct Object *ob); -void EDIT_MESH_cache_finish(void); - -void EDIT_MESH_draw(void); - -void EDIT_MESH_engine_free(void); - -#endif /* __EDIT_MESH_MODE_H__ */
\ No newline at end of file diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 25c4bf932e4..ecfde38f5be 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -26,34 +26,543 @@ #include "DRW_engine.h" #include "DRW_render.h" -#include "draw_mode_pass.h" +#include "DNA_userdef_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" -#include "object_mode.h" +#include "BKE_camera.h" +#include "BKE_global.h" + +#include "GPU_shader.h" + +#include "UI_resources.h" + +#include "draw_mode_engines.h" +#include "draw_common.h" /* keep it under MAX_PASSES */ typedef struct OBJECT_PassList { - struct DRWPass *non_meshes_pass; - struct DRWPass *ob_center_pass; - struct DRWPass *wire_outline_pass; - struct DRWPass *bone_solid_pass; - struct DRWPass *bone_wire_pass; + struct DRWPass *non_meshes; + struct DRWPass *ob_center; + struct DRWPass *wire_outline; + struct DRWPass *bone_solid; + struct DRWPass *bone_wire; } OBJECT_PassList; -void OBJECT_cache_init(void) +typedef struct OBJECT_Data { + char engine_name[32]; + void *fbl; + void *txl; + OBJECT_PassList *psl; + void *stl; +} OBJECT_Data; + +/* Empties */ +static DRWShadingGroup *plain_axes; +static DRWShadingGroup *cube; +static DRWShadingGroup *circle; +static DRWShadingGroup *sphere; +static DRWShadingGroup *cone; +static DRWShadingGroup *single_arrow; +static DRWShadingGroup *single_arrow_line; +static DRWShadingGroup *arrows; +static DRWShadingGroup *axis_names; + +/* Speaker */ +static DRWShadingGroup *speaker; + +/* Lamps */ +static DRWShadingGroup *lamp_center; +static DRWShadingGroup *lamp_center_group; +static DRWShadingGroup *lamp_groundpoint; +static DRWShadingGroup *lamp_groundline; +static DRWShadingGroup *lamp_circle; +static DRWShadingGroup *lamp_circle_shadow; +static DRWShadingGroup *lamp_sunrays; +static DRWShadingGroup *lamp_distance; +static DRWShadingGroup *lamp_buflimit; +static DRWShadingGroup *lamp_buflimit_points; +static DRWShadingGroup *lamp_area; +static DRWShadingGroup *lamp_hemi; +static DRWShadingGroup *lamp_spot_cone; +static DRWShadingGroup *lamp_spot_blend; +static DRWShadingGroup *lamp_spot_pyramid; +static DRWShadingGroup *lamp_spot_blend_rect; + +/* Helpers */ +static DRWShadingGroup *relationship_lines; + +/* Objects Centers */ +static DRWShadingGroup *center_active; +static DRWShadingGroup *center_selected; +static DRWShadingGroup *center_deselected; + +/* Camera */ +static DRWShadingGroup *camera; +static DRWShadingGroup *camera_tria; +static DRWShadingGroup *camera_focus; +static DRWShadingGroup *camera_clip; +static DRWShadingGroup *camera_clip_points; +static DRWShadingGroup *camera_mist; +static DRWShadingGroup *camera_mist_points; + +extern GlobalsUboStorage ts; + +static OBJECT_Data *vedata; + +static void OBJECT_cache_init(void) +{ + /* DRW_viewport_engine_data_get is rather slow, better not do it on every objects */ + vedata = DRW_viewport_engine_data_get("ObjectMode"); + OBJECT_PassList *psl = vedata->psl; + + { + /* This pass can draw mesh outlines and/or fancy wireframe */ + /* Fancy wireframes are not meant to be occluded (without Z offset) */ + /* Outlines and Fancy Wires use the same VBO */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->wire_outline = DRW_pass_create("Wire + Outlines Pass", state); + } + + { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); + } + + { + /* Wire bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->bone_wire = DRW_pass_create("Bone Wire Pass", state); + } + + { + /* Non Meshes Pass (Camera, empties, lamps ...) */ + struct Batch *geom; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_POINT; + state |= DRW_STATE_WIRE; + psl->non_meshes = DRW_pass_create("Non Meshes Pass", state); + + /* Empties */ + geom = DRW_cache_plain_axes_get(); + plain_axes = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_cube_get(); + cube = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_circle_get(); + circle = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_empty_sphere_get(); + sphere = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_empty_cone_get(); + cone = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_arrow_get(); + single_arrow = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_get(); + single_arrow_line = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_arrows_get(); + arrows = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_axis_names_get(); + axis_names = shgroup_instance_axis_names(psl->non_meshes, geom); + + /* Speaker */ + geom = DRW_cache_speaker_get(); + speaker = shgroup_instance(psl->non_meshes, geom); + + /* Camera */ + geom = DRW_cache_camera_get(); + camera = shgroup_camera_instance(psl->non_meshes, geom); + + geom = DRW_cache_camera_tria_get(); + camera_tria = shgroup_camera_instance(psl->non_meshes, geom); + + geom = DRW_cache_plain_axes_get(); + camera_focus = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_get(); + camera_clip = shgroup_distance_lines_instance(psl->non_meshes, geom); + camera_mist = shgroup_distance_lines_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_endpoints_get(); + camera_clip_points = shgroup_distance_lines_instance(psl->non_meshes, geom); + camera_mist_points = shgroup_distance_lines_instance(psl->non_meshes, geom); + + /* Lamps */ + /* TODO + * for now we create multiple times the same VBO with only lamp center coordinates + * but ideally we would only create it once */ + + /* start with buflimit because we don't want stipples */ + geom = DRW_cache_single_line_get(); + lamp_buflimit = shgroup_distance_lines_instance(psl->non_meshes, geom); + + lamp_center = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter); + lamp_center_group = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorGroup, &ts.sizeLampCenter); + + geom = DRW_cache_lamp_get(); + lamp_circle = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle); + lamp_circle_shadow = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircleShadow); + + geom = DRW_cache_lamp_sunrays_get(); + lamp_sunrays = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle); + + lamp_groundline = shgroup_groundlines_uniform_color(psl->non_meshes, ts.colorLamp); + lamp_groundpoint = shgroup_groundpoints_uniform_color(psl->non_meshes, ts.colorLamp); + + geom = DRW_cache_lamp_area_get(); + lamp_area = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_hemi_get(); + lamp_hemi = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_get(); + lamp_distance = shgroup_distance_lines_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_endpoints_get(); + lamp_buflimit_points = shgroup_distance_lines_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_spot_get(); + lamp_spot_cone = shgroup_spot_instance(psl->non_meshes, geom); + + geom = DRW_cache_circle_get(); + lamp_spot_blend = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_spot_square_get(); + lamp_spot_pyramid = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_square_get(); + lamp_spot_blend_rect = shgroup_instance(psl->non_meshes, geom); + + /* Relationship Lines */ + relationship_lines = shgroup_dynlines_uniform_color(psl->non_meshes, ts.colorWire); + DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3); + } + + { + /* Object Center pass grouped by State */ + DRWShadingGroup *grp; + static float outlineWidth, size; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT; + psl->ob_center = DRW_pass_create("Obj Center Pass", state); + + outlineWidth = 1.0f * U.pixelsize; + size = U.obcenter_dia * U.pixelsize + outlineWidth; + + struct GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + + /* Active */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_float(grp, "size", &size, 1); + DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorActive, 1); + DRW_shgroup_uniform_vec4(grp, "outlineColor", ts.colorOutline, 1); + center_active = grp; + + /* Select */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorSelect, 1); + center_selected = grp; + + /* Deselect */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorDeselect, 1); + center_deselected = grp; + } +} + +static void DRW_shgroup_wire_outline(Object *ob, const bool do_wire, const bool do_outline) +{ + struct GPUShader *sh; + OBJECT_PassList *psl = vedata->psl; + struct Batch *geom = DRW_cache_wire_outline_get(ob); + + float *color; + DRW_object_wire_theme_get(ob, &color); + + bool is_perps = DRW_viewport_is_persp_get(); + static bool bTrue = true; + static bool bFalse = false; + + /* Note (TODO) : this requires cache to be discarded on ortho/perp switch + * It may be preferable (or not depending on performance implication) + * to introduce a shader uniform switch */ + if (is_perps) { + sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + else { + sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + } + + if (do_wire) { + bool *bFront = (do_wire) ? &bTrue : &bFalse; + bool *bBack = (do_wire) ? &bTrue : &bFalse; + + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->wire_outline); + DRW_shgroup_state_set(grp, DRW_STATE_WIRE); + DRW_shgroup_uniform_vec4(grp, "frontColor", color, 1); + DRW_shgroup_uniform_vec4(grp, "backColor", color, 1); + DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1); + DRW_shgroup_call_add(grp, geom, ob->obmat); + } + + if (do_outline) { + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->wire_outline); + DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE); + DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1); + DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1); + + DRW_shgroup_call_add(grp, geom, ob->obmat); + } +} + +static void DRW_shgroup_lamp(Object *ob) { - OBJECT_PassList *psl = DRW_mode_pass_list_get(); - - DRW_mode_passes_setup(NULL, - NULL, - &psl->wire_outline_pass, - &psl->non_meshes_pass, - &psl->ob_center_pass, - &psl->bone_solid_pass, - &psl->bone_wire_pass); + Lamp *la = ob->data; + float *color; + int theme_id = DRW_object_wire_theme_get(ob, &color); + static float zero = 0.0f; + + /* Don't draw the center if it's selected or active */ + if (theme_id == TH_GROUP) + DRW_shgroup_dynamic_call_add(lamp_center_group, ob->obmat[3]); + else if (theme_id == TH_LAMP) + DRW_shgroup_dynamic_call_add(lamp_center, ob->obmat[3]); + + /* First circle */ + DRW_shgroup_dynamic_call_add(lamp_circle, ob->obmat[3], color); + + /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ + if (la->type != LA_HEMI) { + if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) { + DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color); + } + } + + /* Distance */ + if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) { + DRW_shgroup_dynamic_call_add(lamp_distance, color, &zero, &la->dist, ob->obmat); + } + + copy_m4_m4(la->shapemat, ob->obmat); + + if (la->type == LA_SUN) { + DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color); + } + else if (la->type == LA_SPOT) { + float size[3], sizemat[4][4]; + static float one = 1.0f; + float blend = 1.0f - pow2f(la->spotblend); + + size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist; + size[2] = cosf(la->spotsize * 0.5f) * la->dist; + + size_to_mat4(sizemat, size); + mul_m4_m4m4(la->spotconemat, ob->obmat, sizemat); + + size[0] = size[1] = blend; size[2] = 1.0f; + size_to_mat4(sizemat, size); + translate_m4(sizemat, 0.0f, 0.0f, -1.0f); + rotate_m4(sizemat, 'X', M_PI / 2.0f); + mul_m4_m4m4(la->spotblendmat, la->spotconemat, sizemat); + + if (la->mode & LA_SQUARE) { + DRW_shgroup_dynamic_call_add(lamp_spot_pyramid, color, &one, la->spotconemat); + + /* hide line if it is zero size or overlaps with outer border, + * previously it adjusted to always to show it but that seems + * confusing because it doesn't show the actual blend size */ + if (blend != 0.0f && blend != 1.0f) { + DRW_shgroup_dynamic_call_add(lamp_spot_blend_rect, color, &one, la->spotblendmat); + } + } + else { + DRW_shgroup_dynamic_call_add(lamp_spot_cone, color, la->spotconemat); + + /* hide line if it is zero size or overlaps with outer border, + * previously it adjusted to always to show it but that seems + * confusing because it doesn't show the actual blend size */ + if (blend != 0.0f && blend != 1.0f) { + DRW_shgroup_dynamic_call_add(lamp_spot_blend, color, &one, la->spotblendmat); + } + } + + normalize_m4(la->shapemat); + DRW_shgroup_dynamic_call_add(lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); + DRW_shgroup_dynamic_call_add(lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); + } + else if (la->type == LA_HEMI) { + static float hemisize = 2.0f; + DRW_shgroup_dynamic_call_add(lamp_hemi, color, &hemisize, la->shapemat); + } + else if (la->type == LA_AREA) { + float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; + + if (la->area_shape == LA_AREA_RECT) { + size[1] = la->area_sizey / la->area_size; + size_to_mat4(sizemat, size); + mul_m4_m4m4(la->shapemat, la->shapemat, sizemat); + } + + DRW_shgroup_dynamic_call_add(lamp_area, color, &la->area_size, la->shapemat); + } + + /* Line and point going to the ground */ + DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]); + DRW_shgroup_dynamic_call_add(lamp_groundpoint, ob->obmat[3]); } -void OBJECT_cache_populate(Object *ob) +static void DRW_shgroup_camera(Object *ob) { + const struct bContext *C = DRW_get_context(); + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + + Camera *cam = ob->data; + const bool is_active = (ob == v3d->camera); + float *color; + DRW_object_wire_theme_get(ob, &color); + + float vec[4][3], asp[2], shift[2], scale[3], drawsize; + + scale[0] = 1.0f / len_v3(ob->obmat[0]); + scale[1] = 1.0f / len_v3(ob->obmat[1]); + scale[2] = 1.0f / len_v3(ob->obmat[2]); + + BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale, + asp, shift, &drawsize, vec); + + // /* Frame coords */ + copy_v2_v2(cam->drwcorners[0], vec[0]); + copy_v2_v2(cam->drwcorners[1], vec[1]); + copy_v2_v2(cam->drwcorners[2], vec[2]); + copy_v2_v2(cam->drwcorners[3], vec[3]); + + /* depth */ + cam->drwdepth = vec[0][2]; + + /* tria */ + cam->drwtria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]); + cam->drwtria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); + cam->drwtria[1][0] = shift[0]; + cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); + + DRW_shgroup_dynamic_call_add(camera, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat); + + /* Active cam */ + if (is_active) { + DRW_shgroup_dynamic_call_add(camera_tria, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat); + } + + /* draw the rest in normalize object space */ + copy_m4_m4(cam->drwnormalmat, ob->obmat); + normalize_m4(cam->drwnormalmat); + + if (cam->flag & CAM_SHOWLIMITS) { + static float col[3] = {0.5f, 0.5f, 0.25f}, col_hi[3] = {1.0f, 1.0f, 0.5f}; + float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f}; + float focusdist = BKE_camera_object_dof_distance(ob); + + copy_m4_m4(cam->drwfocusmat, cam->drwnormalmat); + translate_m4(cam->drwfocusmat, 0.0f, 0.0f, -focusdist); + size_to_mat4(sizemat, size); + mul_m4_m4m4(cam->drwfocusmat, cam->drwfocusmat, sizemat); + + DRW_shgroup_dynamic_call_add(camera_focus, (is_active ? col_hi : col), &cam->drawsize, cam->drwfocusmat); + + DRW_shgroup_dynamic_call_add(camera_clip, color, &cam->clipsta, &cam->clipend, cam->drwnormalmat); + DRW_shgroup_dynamic_call_add(camera_clip_points, (is_active ? col_hi : col), &cam->clipsta, &cam->clipend, cam->drwnormalmat); + } + + if (cam->flag & CAM_SHOWMIST) { + World *world = scene->world; + + if (world) { + static float col[3] = {0.5f, 0.5f, 0.5f}, col_hi[3] = {1.0f, 1.0f, 1.0f}; + world->mistend = world->miststa + world->mistdist; + DRW_shgroup_dynamic_call_add(camera_mist, color, &world->miststa, &world->mistend, cam->drwnormalmat); + DRW_shgroup_dynamic_call_add(camera_mist_points, (is_active ? col_hi : col), &world->miststa, &world->mistend, cam->drwnormalmat); + } + } +} + +static void DRW_shgroup_empty(Object *ob) +{ + float *color; + DRW_object_wire_theme_get(ob, &color); + + switch (ob->empty_drawtype) { + case OB_PLAINAXES: + DRW_shgroup_dynamic_call_add(plain_axes, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_SINGLE_ARROW: + DRW_shgroup_dynamic_call_add(single_arrow, color, &ob->empty_drawsize, ob->obmat); + DRW_shgroup_dynamic_call_add(single_arrow_line, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_CUBE: + DRW_shgroup_dynamic_call_add(cube, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_CIRCLE: + DRW_shgroup_dynamic_call_add(circle, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_SPHERE: + DRW_shgroup_dynamic_call_add(sphere, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_CONE: + DRW_shgroup_dynamic_call_add(cone, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_ARROWS: + DRW_shgroup_dynamic_call_add(arrows, color, &ob->empty_drawsize, ob->obmat); + DRW_shgroup_dynamic_call_add(axis_names, color, &ob->empty_drawsize, ob->obmat); + break; + } +} + +static void DRW_shgroup_speaker(Object *ob) +{ + float *color; + static float one = 1.0f; + DRW_object_wire_theme_get(ob, &color); + + DRW_shgroup_dynamic_call_add(speaker, color, &one, ob->obmat); +} + +static void DRW_shgroup_relationship_lines(Object *ob) +{ + if (ob->parent) { + DRW_shgroup_dynamic_call_add(relationship_lines, ob->obmat[3]); + DRW_shgroup_dynamic_call_add(relationship_lines, ob->parent->obmat[3]); + } +} + +static void DRW_shgroup_object_center(Object *ob) +{ + if ((ob->base_flag & BASE_SELECTED) != 0) { + DRW_shgroup_dynamic_call_add(center_selected, ob->obmat[3]); + } + else if (0) { + DRW_shgroup_dynamic_call_add(center_deselected, ob->obmat[3]); + } +} + +static void OBJECT_cache_populate(Object *ob) +{ + const struct bContext *C = DRW_get_context(); + Scene *scene = CTX_data_scene(C); + CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, ""); bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire"); @@ -61,7 +570,12 @@ void OBJECT_cache_populate(Object *ob) switch (ob->type) { case OB_MESH: - DRW_shgroup_wire_outline(ob, do_wire, false, do_outlines); + { + Object *obedit = scene->obedit; + if (ob != obedit) { + DRW_shgroup_wire_outline(ob, do_wire, do_outlines); + } + } break; case OB_LAMP: DRW_shgroup_lamp(ob); @@ -76,7 +590,14 @@ void OBJECT_cache_populate(Object *ob) DRW_shgroup_speaker(ob); break; case OB_ARMATURE: - DRW_shgroup_armature_object(ob); + { + bArmature *arm = ob->data; + if (arm->edbo == NULL) { + DRW_shgroup_armature_object(ob, vedata->psl->bone_solid, + vedata->psl->bone_wire, + relationship_lines); + } + } break; default: break; @@ -86,20 +607,16 @@ void OBJECT_cache_populate(Object *ob) DRW_shgroup_relationship_lines(ob); } -void OBJECT_cache_finish(void) +static void OBJECT_draw_scene(void) { - /* Do nothing */ -} - -void OBJECT_draw(void) -{ - OBJECT_PassList *psl = DRW_mode_pass_list_get(); + OBJECT_Data *ved = DRW_viewport_engine_data_get("ObjectMode"); + OBJECT_PassList *psl = ved->psl; - DRW_draw_pass(psl->bone_wire_pass); - DRW_draw_pass(psl->bone_solid_pass); - DRW_draw_pass(psl->wire_outline_pass); - DRW_draw_pass(psl->non_meshes_pass); - DRW_draw_pass(psl->ob_center_pass); + DRW_draw_pass(psl->bone_wire); + DRW_draw_pass(psl->bone_solid); + DRW_draw_pass(psl->wire_outline); + DRW_draw_pass(psl->non_meshes); + DRW_draw_pass(psl->ob_center); } void OBJECT_collection_settings_create(CollectionEngineSettings *ces) @@ -108,3 +625,15 @@ void OBJECT_collection_settings_create(CollectionEngineSettings *ces) BKE_collection_engine_property_add_int(ces, "show_wire", false); BKE_collection_engine_property_add_int(ces, "show_backface_culling", false); } + +DrawEngineType draw_engine_object_type = { + NULL, NULL, + N_("ObjectMode"), + NULL, + NULL, + &OBJECT_cache_init, + &OBJECT_cache_populate, + NULL, + NULL, + &OBJECT_draw_scene +}; diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index f6d5cf6e5d2..34b68a80a0f 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../draw ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f41d7d68288..21d07761cf5 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -60,6 +60,8 @@ #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" +#include "DRW_engine.h" + #include "ED_keyframing.h" #include "ED_armature.h" #include "ED_keyframing.h" @@ -2330,34 +2332,18 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data #endif } -static void view3d_render_pass(const bContext *C, ARegion *UNUSED(ar)) -{ - Scene *scene = CTX_data_scene(C); - RenderEngineType *type = RE_engines_find(scene->r.engine); /* In the future we should get that from Layers */ - - if (type->flag & RE_USE_OGL_PIPELINE) { - type->view_draw(NULL, C); - } - else { - // Offline Render engine - } -} - static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data)) { - view3d_draw_setup_view(C, ar); /* Only 100% compliant on new spec goes bellow */ - view3d_render_pass(C, ar); + DRW_draw_view(C); } - void view3d_main_region_draw(const bContext *C, ARegion *ar) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - int mode = CTX_data_mode_enum(C); RegionView3D *rv3d = ar->regiondata; /* TODO layers - In the future we should get RE from Layers */ RenderEngineType *type = RE_engines_find(scene->r.engine); @@ -2370,21 +2356,19 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) if (!rv3d->viewport) rv3d->viewport = GPU_viewport_create(); - GPU_viewport_bind(rv3d->viewport, &ar->winrct, scene->r.engine, mode); - /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c * before we even call the drawing routine, but let's move on for now (dfelinto) * but this is a provisory way to start seeing things in the viewport */ DrawData draw_data; view3d_draw_data_init(C, ar, rv3d, &draw_data); + GPU_viewport_bind(rv3d->viewport, &ar->winrct); + if (type->flag & RE_USE_OGL_PIPELINE) view3d_draw_view_new(C, ar, &draw_data); else view3d_draw_view(C, ar, &draw_data); - GPU_viewport_unbind(rv3d->viewport); - v3d->flag |= V3D_INVALID_BACKBUF; } diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index f0e991fdac2..64f003badb7 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -63,28 +63,27 @@ typedef struct StorageList { void *storage[MAX_STORAGE]; /* custom structs from the engine */ } StorageList; -/* Buffer and textures used by the viewport by default */ -typedef struct DefaultFramebufferList { - struct GPUFrameBuffer *default_fb; -} DefaultFramebufferList; +typedef struct ViewportEngineData { + char engine_name[32]; -typedef struct DefaultTextureList { - struct GPUTexture *color; - struct GPUTexture *depth; -} DefaultTextureList; - -typedef struct DefaultPassList { - struct DRWPass *non_meshes_pass; - struct DRWPass *ob_center_pass; -} DefaultPassList; + FramebufferList *fbl; + TextureList *txl; + PassList *psl; + StorageList *stl; +} ViewportEngineData; GPUViewport *GPU_viewport_create(void); -void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine, int mode); +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect); void GPU_viewport_unbind(GPUViewport *viewport); void GPU_viewport_free(GPUViewport *viewport); -void GPU_viewport_get_engine_data(GPUViewport *viewport, FramebufferList **fbs, TextureList **txs, PassList **pss, StorageList **str); -void GPU_viewport_get_mode_data(GPUViewport *viewport, FramebufferList **fbs, TextureList **txs, PassList **pss, StorageList **str); +void *GPU_viewport_engine_data_create(GPUViewport *viewport, const char *engine_name); +void *GPU_viewport_engine_data_get(GPUViewport *viewport, const char *engine_name); +void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport); +void *GPU_viewport_texture_list_get(GPUViewport *viewport); +void GPU_viewport_size_get(GPUViewport *viewport, int *size); + +bool GPU_viewport_cache_validate(GPUViewport *viewport, int hash); /* debug */ bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]); diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index c8e60c089d3..fc5c3ce3613 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -33,6 +33,7 @@ #include <string.h> +#include "BLI_listbase.h" #include "BLI_rect.h" #include "BLI_string.h" @@ -57,20 +58,11 @@ struct GPUViewport { GPUTexture *debug_depth; int size[2]; - /* Viewport Buffer Storage */ + ListBase data; /* ViewportEngineData wrapped in LinkData */ + int data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */ + FramebufferList *fbl; TextureList *txl; - PassList *psl; - StorageList *stl; - - char engine_name[32]; - - /* Mode storage */ - FramebufferList *fbl_mode; - TextureList *txl_mode; - PassList *psl_mode; - StorageList *stl_mode; - int mode; }; static void GPU_viewport_buffers_free(FramebufferList *fbl, TextureList *txl); @@ -82,66 +74,118 @@ GPUViewport *GPU_viewport_create(void) GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList"); - viewport->psl = MEM_callocN(sizeof(PassList), "PassList"); - viewport->stl = MEM_callocN(sizeof(StorageList), "StorageList"); - viewport->fbl_mode = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); - viewport->txl_mode = MEM_callocN(sizeof(TextureList), "TextureList"); - viewport->psl_mode = MEM_callocN(sizeof(PassList), "PassList"); - viewport->stl_mode = MEM_callocN(sizeof(StorageList), "StorageList"); viewport->size[0] = viewport->size[1] = -1; return viewport; } -void GPU_viewport_get_engine_data(GPUViewport *viewport, FramebufferList **fbs, TextureList **txs, PassList **pss, StorageList **str) +void *GPU_viewport_engine_data_create(GPUViewport *viewport, const char *engine_name) { - *fbs = viewport->fbl; - *txs = viewport->txl; - *pss = viewport->psl; - *str = viewport->stl; + LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData"); + ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); + BLI_strncpy(data->engine_name, engine_name, 32); + + data->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); + data->txl = MEM_callocN(sizeof(TextureList), "TextureList"); + data->psl = MEM_callocN(sizeof(PassList), "PassList"); + data->stl = MEM_callocN(sizeof(StorageList), "StorageList"); + + ld->data = data; + BLI_addtail(&viewport->data, ld); + + return data; } -void GPU_viewport_get_mode_data(GPUViewport *viewport, FramebufferList **fbs, TextureList **txs, PassList **pss, StorageList **str) +static void GPU_viewport_engines_data_free(GPUViewport *viewport) { - *fbs = viewport->fbl_mode; - *txs = viewport->txl_mode; - *pss = viewport->psl_mode; - *str = viewport->stl_mode; + LinkData *next; + for (LinkData *link = viewport->data.first; link; link = next) { + next = link->next; + ViewportEngineData *data = link->data; + + GPU_viewport_buffers_free(data->fbl, data->txl); + GPU_viewport_passes_free(data->psl); + GPU_viewport_storage_free(data->stl); + + MEM_freeN(data->fbl); + MEM_freeN(data->txl); + MEM_freeN(data->psl); + MEM_freeN(data->stl); + + MEM_freeN(data); + + BLI_remlink(&viewport->data, link); + MEM_freeN(link); + } } -void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine, int mode) +void *GPU_viewport_engine_data_get(GPUViewport *viewport, const char *engine_name) { - DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl; - DefaultTextureList *dtxl = (DefaultTextureList *)viewport->txl; + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *vdata = link->data; + if (STREQ(engine_name, vdata->engine_name)) { + return vdata; + } + } + return NULL; +} - /* add one pixel because of scissor test */ - int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1; +void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport) +{ + return viewport->fbl; +} + +void *GPU_viewport_texture_list_get(GPUViewport *viewport) +{ + return viewport->txl; +} + +void GPU_viewport_size_get(GPUViewport *viewport, int *size) +{ + size[0] = viewport->size[0]; + size[1] = viewport->size[1]; +} +bool GPU_viewport_cache_validate(GPUViewport *viewport, int hash) +{ + bool dirty = false; + + /* TODO for testing only, we need proper cache invalidation */ if (G.debug_value != 666 && G.debug_value != 667) { - /* TODO for testing only, we need proper cache invalidation */ - GPU_viewport_passes_free(viewport->psl); - GPU_viewport_passes_free(viewport->psl_mode); + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *data = link->data; + GPU_viewport_passes_free(data->psl); + } + dirty = true; } - if (!STREQ(engine, viewport->engine_name)) { - GPU_viewport_storage_free(viewport->stl); - GPU_viewport_buffers_free(viewport->fbl, viewport->txl); - - BLI_strncpy(viewport->engine_name, engine, 32); + if (viewport->data_hash != hash) { + GPU_viewport_engines_data_free(viewport); + dirty = true; } - if (mode != viewport->mode) { - GPU_viewport_buffers_free(viewport->fbl_mode, viewport->txl_mode); - GPU_viewport_passes_free(viewport->psl_mode); - GPU_viewport_storage_free(viewport->stl_mode); + viewport->data_hash = hash; - viewport->mode = mode; - } + return dirty; +} + +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) +{ + DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl; + DefaultTextureList *dtxl = (DefaultTextureList *)viewport->txl; + + /* add one pixel because of scissor test */ + int rect_w = BLI_rcti_size_x(rect) + 1; + int rect_h = BLI_rcti_size_y(rect) + 1; if (dfbl->default_fb) { if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) { GPU_viewport_buffers_free(viewport->fbl, viewport->txl); - GPU_viewport_buffers_free(viewport->fbl_mode, viewport->txl_mode); + + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *data = link->data; + GPU_viewport_buffers_free(data->fbl, data->txl); + } } } @@ -211,12 +255,11 @@ static void draw_ofs_to_screen(GPUViewport *viewport) unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); - GPU_texture_bind(color, 0); immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - immBegin(GL_QUADS, 4); + immBegin(GL_TRIANGLE_STRIP, 4); immAttrib2f(texcoord, 0.0f, 0.0f); immVertex2f(pos, 0.0f, 0.0f); @@ -224,12 +267,12 @@ static void draw_ofs_to_screen(GPUViewport *viewport) immAttrib2f(texcoord, 1.0f, 0.0f); immVertex2f(pos, w, 0.0f); - immAttrib2f(texcoord, 1.0f, 1.0f); - immVertex2f(pos, w, h); - immAttrib2f(texcoord, 0.0f, 1.0f); immVertex2f(pos, 0.0f, h); + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + immEnd(); GPU_texture_unbind(color); @@ -296,25 +339,13 @@ static void GPU_viewport_passes_free(PassList *psl) void GPU_viewport_free(GPUViewport *viewport) { - GPU_viewport_debug_depth_free(viewport); + GPU_viewport_engines_data_free(viewport); GPU_viewport_buffers_free(viewport->fbl, viewport->txl); - GPU_viewport_passes_free(viewport->psl); - GPU_viewport_storage_free(viewport->stl); - - GPU_viewport_buffers_free(viewport->fbl_mode, viewport->txl_mode); - GPU_viewport_passes_free(viewport->psl_mode); - GPU_viewport_storage_free(viewport->stl_mode); - MEM_freeN(viewport->fbl); MEM_freeN(viewport->txl); - MEM_freeN(viewport->psl); - MEM_freeN(viewport->stl); - MEM_freeN(viewport->fbl_mode); - MEM_freeN(viewport->txl_mode); - MEM_freeN(viewport->psl_mode); - MEM_freeN(viewport->stl_mode); + GPU_viewport_debug_depth_free(viewport); } /****************** debug ********************/ @@ -360,7 +391,7 @@ void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, con immUniform1f("zfar", zfar); immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - immBegin(GL_QUADS, 4); + immBegin(GL_TRIANGLE_STRIP, 4); immAttrib2f(texcoord, 0.0f, 0.0f); immVertex2f(pos, 0.0f, 0.0f); @@ -368,12 +399,12 @@ void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, con immAttrib2f(texcoord, 1.0f, 0.0f); immVertex2f(pos, w, 0.0f); - immAttrib2f(texcoord, 1.0f, 1.0f); - immVertex2f(pos, w, h); - immAttrib2f(texcoord, 0.0f, 1.0f); immVertex2f(pos, 0.0f, h); + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + immEnd(); GPU_texture_unbind(viewport->debug_depth); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index f1b3534b40a..74d96ce69d1 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -102,6 +102,8 @@ typedef struct RenderEngineType { void (*collection_settings_create)(struct RenderEngine *engine, struct CollectionEngineSettings *ces); + struct DrawEngineType *draw_engine; + /* RNA integration */ ExtensionRNA ext; } RenderEngineType; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 1744d88a14f..8c1cdb3dc8a 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -71,7 +71,7 @@ static RenderEngineType internal_render_type = { NULL, NULL, "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -80,7 +80,7 @@ static RenderEngineType internal_render_type = { static RenderEngineType internal_game_type = { NULL, NULL, "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -94,7 +94,7 @@ void RE_engines_init(void) #ifdef WITH_GAMEENGINE RE_engines_register(NULL, &internal_game_type); #endif - DRW_engines_init(); + DRW_engines_register(); } void RE_engines_exit(void) @@ -121,6 +121,9 @@ void RE_engines_exit(void) void RE_engines_register(Main *bmain, RenderEngineType *render_type) { + if (render_type->draw_engine) { + DRW_engine_register(render_type->draw_engine); + } if (render_type->collection_settings_create) { BKE_layer_collection_engine_settings_callback_register(bmain, render_type->idname, render_type->collection_settings_create); } |