diff options
Diffstat (limited to 'source/blender/draw/modes')
91 files changed, 9223 insertions, 8889 deletions
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c index e2af2f10779..12bf4982ffb 100644 --- a/source/blender/draw/modes/edit_armature_mode.c +++ b/source/blender/draw/modes/edit_armature_mode.c @@ -33,169 +33,170 @@ /* *********** LISTS *********** */ typedef struct EDIT_ARMATURE_PassList { - struct DRWPass *bone_solid[2]; - struct DRWPass *bone_transp[2]; - struct DRWPass *bone_wire[2]; - struct DRWPass *bone_outline[2]; - struct DRWPass *bone_envelope[2]; - struct DRWPass *bone_axes; - struct DRWPass *relationship[2]; + struct DRWPass *bone_solid[2]; + struct DRWPass *bone_transp[2]; + struct DRWPass *bone_wire[2]; + struct DRWPass *bone_outline[2]; + struct DRWPass *bone_envelope[2]; + struct DRWPass *bone_axes; + struct DRWPass *relationship[2]; } EDIT_ARMATURE_PassList; typedef struct EDIT_ARMATURE_StorageList { - struct EDIT_ARMATURE_PrivateData *g_data; + struct EDIT_ARMATURE_PrivateData *g_data; } EDIT_ARMATURE_StorageList; typedef struct EDIT_ARMATURE_Data { - void *engine_type; - DRWViewportEmptyList *fbl; - DRWViewportEmptyList *txl; - EDIT_ARMATURE_PassList *psl; - EDIT_ARMATURE_StorageList *stl; + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + EDIT_ARMATURE_PassList *psl; + EDIT_ARMATURE_StorageList *stl; } EDIT_ARMATURE_Data; /* *********** STATIC *********** */ typedef struct EDIT_ARMATURE_PrivateData { - bool transparent_bones; + bool transparent_bones; } EDIT_ARMATURE_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ static void EDIT_ARMATURE_cache_init(void *vedata) { - EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; - EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - stl->g_data->transparent_bones = (draw_ctx->v3d->shading.type == OB_WIRE); - - for (int i = 0; i < 2; ++i) { - /* Solid bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; - psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state | DRW_STATE_WRITE_DEPTH); - psl->bone_transp[i] = DRW_pass_create("Bone Transp Pass", state | DRW_STATE_BLEND); - - /* Bones Outline */ - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state); - - /* Wire bones */ - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; - psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state); - - /* distance outline around envelope bones */ - state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT; - psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state); - - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_BLEND | DRW_STATE_WIRE; - psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state); - } - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND; - psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); - } + EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; + EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + stl->g_data->transparent_bones = (draw_ctx->v3d->shading.type == OB_WIRE); + + for (int i = 0; i < 2; ++i) { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state | DRW_STATE_WRITE_DEPTH); + psl->bone_transp[i] = DRW_pass_create("Bone Transp Pass", state | DRW_STATE_BLEND); + + /* Bones Outline */ + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state); + + /* Wire bones */ + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND; + psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state); + + /* distance outline around envelope bones */ + state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_CULL_FRONT; + psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state); + + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE; + psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND; + psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); + } } static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob) { - bArmature *arm = ob->data; - - if (ob->type == OB_ARMATURE) { - if (arm->edbo) { - EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; - EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - int ghost = (ob->dtx & OB_DRAWXRAY) ? 1 : 0; - bool transp = (stl->g_data->transparent_bones || (ob->dt <= OB_WIRE)) || XRAY_FLAG_ENABLED(draw_ctx->v3d); - - DRWArmaturePasses passes = { - .bone_solid = (transp) ? psl->bone_transp[ghost] : psl->bone_solid[ghost], - .bone_outline = psl->bone_outline[ghost], - .bone_wire = psl->bone_wire[ghost], - .bone_envelope = psl->bone_envelope[ghost], - .bone_axes = psl->bone_axes, - .relationship_lines = psl->relationship[ghost], - }; - DRW_shgroup_armature_edit(ob, passes, transp); - } - } + bArmature *arm = ob->data; + + if (ob->type == OB_ARMATURE) { + if (arm->edbo) { + EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; + EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + int ghost = (ob->dtx & OB_DRAWXRAY) ? 1 : 0; + bool transp = (stl->g_data->transparent_bones || (ob->dt <= OB_WIRE)) || + XRAY_FLAG_ENABLED(draw_ctx->v3d); + + DRWArmaturePasses passes = { + .bone_solid = (transp) ? psl->bone_transp[ghost] : psl->bone_solid[ghost], + .bone_outline = psl->bone_outline[ghost], + .bone_wire = psl->bone_wire[ghost], + .bone_envelope = psl->bone_envelope[ghost], + .bone_axes = psl->bone_axes, + .relationship_lines = psl->relationship[ghost], + }; + DRW_shgroup_armature_edit(ob, passes, transp); + } + } } static void EDIT_ARMATURE_draw_scene(void *vedata) { - EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - - if (DRW_state_is_select()) { - DRW_draw_pass(psl->bone_outline[0]); - DRW_draw_pass(psl->bone_solid[0]); - DRW_draw_pass(psl->bone_wire[0]); - DRW_draw_pass(psl->bone_outline[1]); - DRW_draw_pass(psl->bone_solid[1]); - DRW_draw_pass(psl->bone_wire[1]); - return; - } - - DRW_draw_pass(psl->bone_envelope[0]); - - /* For performance reason, avoid blending on MS target. */ - DRW_draw_pass(psl->bone_transp[0]); - - MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - - DRW_draw_pass(psl->bone_solid[0]); - DRW_draw_pass(psl->bone_outline[0]); - DRW_draw_pass(psl->bone_wire[0]); - DRW_draw_pass(psl->relationship[0]); - - MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - - if (!DRW_pass_is_empty(psl->bone_envelope[1]) || - !DRW_pass_is_empty(psl->bone_solid[1]) || - !DRW_pass_is_empty(psl->bone_transp[1]) || - !DRW_pass_is_empty(psl->bone_outline[1]) || - !DRW_pass_is_empty(psl->bone_wire[1]) || - !DRW_pass_is_empty(psl->relationship[1])) - { - if (DRW_state_is_fbo()) { - GPU_framebuffer_bind(dfbl->default_fb); - GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); - } - - DRW_draw_pass(psl->bone_envelope[1]); - DRW_draw_pass(psl->bone_solid[1]); - DRW_draw_pass(psl->bone_transp[1]); - DRW_draw_pass(psl->bone_outline[1]); - DRW_draw_pass(psl->bone_wire[1]); - DRW_draw_pass(psl->relationship[1]); - } - - /* Draw axes with linesmooth and outside of multisample buffer. */ - DRW_draw_pass(psl->bone_axes); + EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + if (DRW_state_is_select()) { + DRW_draw_pass(psl->bone_outline[0]); + DRW_draw_pass(psl->bone_solid[0]); + DRW_draw_pass(psl->bone_wire[0]); + DRW_draw_pass(psl->bone_outline[1]); + DRW_draw_pass(psl->bone_solid[1]); + DRW_draw_pass(psl->bone_wire[1]); + return; + } + + DRW_draw_pass(psl->bone_envelope[0]); + + /* For performance reason, avoid blending on MS target. */ + DRW_draw_pass(psl->bone_transp[0]); + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + + DRW_draw_pass(psl->bone_solid[0]); + DRW_draw_pass(psl->bone_outline[0]); + DRW_draw_pass(psl->bone_wire[0]); + DRW_draw_pass(psl->relationship[0]); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); + + if (!DRW_pass_is_empty(psl->bone_envelope[1]) || !DRW_pass_is_empty(psl->bone_solid[1]) || + !DRW_pass_is_empty(psl->bone_transp[1]) || !DRW_pass_is_empty(psl->bone_outline[1]) || + !DRW_pass_is_empty(psl->bone_wire[1]) || !DRW_pass_is_empty(psl->relationship[1])) { + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); + } + + DRW_draw_pass(psl->bone_envelope[1]); + DRW_draw_pass(psl->bone_solid[1]); + DRW_draw_pass(psl->bone_transp[1]); + DRW_draw_pass(psl->bone_outline[1]); + DRW_draw_pass(psl->bone_wire[1]); + DRW_draw_pass(psl->relationship[1]); + } + + /* Draw axes with linesmooth and outside of multisample buffer. */ + DRW_draw_pass(psl->bone_axes); } -static const DrawEngineDataSize EDIT_ARMATURE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_ARMATURE_Data); +static const DrawEngineDataSize EDIT_ARMATURE_data_size = DRW_VIEWPORT_DATA_SIZE( + EDIT_ARMATURE_Data); DrawEngineType draw_engine_edit_armature_type = { - NULL, NULL, - N_("EditArmatureMode"), - &EDIT_ARMATURE_data_size, - NULL, - NULL, - &EDIT_ARMATURE_cache_init, - &EDIT_ARMATURE_cache_populate, - NULL, - NULL, - &EDIT_ARMATURE_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("EditArmatureMode"), + &EDIT_ARMATURE_data_size, + NULL, + NULL, + &EDIT_ARMATURE_cache_init, + &EDIT_ARMATURE_cache_populate, + NULL, + NULL, + &EDIT_ARMATURE_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index a1741c7e967..e47393c88c4 100644 --- a/source/blender/draw/modes/edit_curve_mode.c +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -56,50 +56,49 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; * for EDIT_CURVE_PassList */ typedef struct EDIT_CURVE_PassList { - struct DRWPass *wire_pass; - struct DRWPass *wire_pass_xray; - struct DRWPass *overlay_edge_pass; - struct DRWPass *overlay_vert_pass; + struct DRWPass *wire_pass; + struct DRWPass *wire_pass_xray; + struct DRWPass *overlay_edge_pass; + struct DRWPass *overlay_vert_pass; } EDIT_CURVE_PassList; typedef struct EDIT_CURVE_StorageList { - struct CustomStruct *block; - struct EDIT_CURVE_PrivateData *g_data; + struct CustomStruct *block; + struct EDIT_CURVE_PrivateData *g_data; } EDIT_CURVE_StorageList; typedef struct EDIT_CURVE_Data { - void *engine_type; /* Required */ - DRWViewportEmptyList *fbl; - DRWViewportEmptyList *txl; - EDIT_CURVE_PassList *psl; - EDIT_CURVE_StorageList *stl; + void *engine_type; /* Required */ + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + EDIT_CURVE_PassList *psl; + EDIT_CURVE_StorageList *stl; } EDIT_CURVE_Data; /* *********** STATIC *********** */ - typedef struct EDIT_CURVE_Shaders { - GPUShader *wire_sh; - GPUShader *wire_normals_sh; - GPUShader *overlay_edge_sh; /* handles and nurbs control cage */ - GPUShader *overlay_vert_sh; + GPUShader *wire_sh; + GPUShader *wire_normals_sh; + GPUShader *overlay_edge_sh; /* handles and nurbs control cage */ + GPUShader *overlay_vert_sh; } EDIT_CURVE_Shaders; static struct { - EDIT_CURVE_Shaders sh_data[GPU_SHADER_CFG_LEN]; + EDIT_CURVE_Shaders sh_data[GPU_SHADER_CFG_LEN]; } e_data = {{{NULL}}}; /* Engine data */ typedef struct EDIT_CURVE_PrivateData { - /* resulting curve as 'wire' for curves (and optionally normals) */ - DRWShadingGroup *wire_shgrp; - DRWShadingGroup *wire_shgrp_xray; - DRWShadingGroup *wire_normals_shgrp; - DRWShadingGroup *wire_normals_shgrp_xray; + /* resulting curve as 'wire' for curves (and optionally normals) */ + DRWShadingGroup *wire_shgrp; + DRWShadingGroup *wire_shgrp_xray; + DRWShadingGroup *wire_normals_shgrp; + DRWShadingGroup *wire_normals_shgrp_xray; - DRWShadingGroup *overlay_edge_shgrp; - DRWShadingGroup *overlay_vert_shgrp; + DRWShadingGroup *overlay_edge_shgrp; + DRWShadingGroup *overlay_vert_shgrp; - int show_handles; + int show_handles; } EDIT_CURVE_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -109,223 +108,232 @@ typedef struct EDIT_CURVE_PrivateData { * (Optional) */ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - - if (!sh_data->wire_sh) { - sh_data->wire_sh = GPU_shader_get_builtin_shader_with_config( - GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->sh_cfg); - } - - if (!sh_data->wire_normals_sh) { - sh_data->wire_normals_sh = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_normals_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - } - - if (!sh_data->overlay_edge_sh) { - sh_data->overlay_edge_sh = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_handle_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_edit_curve_overlay_handle_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - } - - if (!sh_data->overlay_vert_sh) { - sh_data->overlay_vert_sh = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); + } + + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + if (!sh_data->wire_sh) { + sh_data->wire_sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_UNIFORM_COLOR, + draw_ctx->sh_cfg); + } + + if (!sh_data->wire_normals_sh) { + sh_data->wire_normals_sh = GPU_shader_create_from_arrays({ + .vert = + (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_normals_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + + if (!sh_data->overlay_edge_sh) { + sh_data->overlay_edge_sh = GPU_shader_create_from_arrays({ + .vert = + (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_handle_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_edit_curve_overlay_handle_geom_glsl, + NULL}, + .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + + if (!sh_data->overlay_vert_sh) { + sh_data->overlay_vert_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_edit_curve_overlay_loosevert_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } } -static void EDIT_CURVE_wire_shgrp_create( - EDIT_CURVE_Shaders *sh_data, - const View3D *v3d, - const RegionView3D *rv3d, - DRWPass *pass, - DRWShadingGroup **wire_shgrp, - DRWShadingGroup **wire_normals_shgrp) +static void EDIT_CURVE_wire_shgrp_create(EDIT_CURVE_Shaders *sh_data, + const View3D *v3d, + const RegionView3D *rv3d, + DRWPass *pass, + DRWShadingGroup **wire_shgrp, + DRWShadingGroup **wire_normals_shgrp) { - DRWShadingGroup *grp = DRW_shgroup_create(sh_data->wire_sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - *wire_shgrp = grp; - - grp = DRW_shgroup_create(sh_data->wire_normals_sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); - DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - *wire_normals_shgrp = grp; + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->wire_sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + *wire_shgrp = grp; + + grp = DRW_shgroup_create(sh_data->wire_normals_sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); + DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + *wire_normals_shgrp = grp; } /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void EDIT_CURVE_cache_init(void *vedata) { - EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; - EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - const RegionView3D *rv3d = draw_ctx->rv3d; - EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - - stl->g_data->show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0; - - { - DRWShadingGroup *grp; - - /* Center-Line (wire) */ - psl->wire_pass = DRW_pass_create( - "Curve Wire", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); - EDIT_CURVE_wire_shgrp_create(sh_data, v3d, rv3d, psl->wire_pass, - &stl->g_data->wire_shgrp, - &stl->g_data->wire_normals_shgrp); - - psl->wire_pass_xray = DRW_pass_create( - "Curve Wire Xray", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_WIRE); - EDIT_CURVE_wire_shgrp_create(sh_data, v3d, rv3d, psl->wire_pass_xray, - &stl->g_data->wire_shgrp_xray, - &stl->g_data->wire_normals_shgrp_xray); - - psl->overlay_edge_pass = DRW_pass_create( - "Curve Handle Overlay", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - - grp = DRW_shgroup_create(sh_data->overlay_edge_sh, psl->overlay_edge_pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_bool(grp, "showCurveHandles", &stl->g_data->show_handles, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - stl->g_data->overlay_edge_shgrp = grp; - - - psl->overlay_vert_pass = DRW_pass_create( - "Curve Vert Overlay", - DRW_STATE_WRITE_COLOR | DRW_STATE_POINT); - - grp = DRW_shgroup_create(sh_data->overlay_vert_sh, psl->overlay_vert_pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - stl->g_data->overlay_vert_shgrp = grp; - } + EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; + EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + const RegionView3D *rv3d = draw_ctx->rv3d; + EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + + stl->g_data->show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0; + + { + DRWShadingGroup *grp; + + /* Center-Line (wire) */ + psl->wire_pass = DRW_pass_create("Curve Wire", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + EDIT_CURVE_wire_shgrp_create(sh_data, + v3d, + rv3d, + psl->wire_pass, + &stl->g_data->wire_shgrp, + &stl->g_data->wire_normals_shgrp); + + psl->wire_pass_xray = DRW_pass_create("Curve Wire Xray", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_ALWAYS | DRW_STATE_WIRE); + EDIT_CURVE_wire_shgrp_create(sh_data, + v3d, + rv3d, + psl->wire_pass_xray, + &stl->g_data->wire_shgrp_xray, + &stl->g_data->wire_normals_shgrp_xray); + + psl->overlay_edge_pass = DRW_pass_create("Curve Handle Overlay", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + + grp = DRW_shgroup_create(sh_data->overlay_edge_sh, psl->overlay_edge_pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_bool(grp, "showCurveHandles", &stl->g_data->show_handles, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + stl->g_data->overlay_edge_shgrp = grp; + + psl->overlay_vert_pass = DRW_pass_create("Curve Vert Overlay", + DRW_STATE_WRITE_COLOR | DRW_STATE_POINT); + + grp = DRW_shgroup_create(sh_data->overlay_vert_sh, psl->overlay_vert_pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + stl->g_data->overlay_vert_shgrp = grp; + } } /* Add geometry to shadingGroups. Execute for each objects */ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob) { - EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - if (ob->type == OB_CURVE) { - if (BKE_object_is_in_editmode(ob)) { - Curve *cu = ob->data; - /* Get geometry cache */ - struct GPUBatch *geom; - - DRWShadingGroup *wire_shgrp, *wire_normals_shgrp; - - if (ob->dtx & OB_DRAWXRAY) { - wire_shgrp = stl->g_data->wire_shgrp_xray; - wire_normals_shgrp = stl->g_data->wire_normals_shgrp_xray; - } - else { - wire_shgrp = stl->g_data->wire_shgrp; - wire_normals_shgrp = stl->g_data->wire_normals_shgrp; - } - - geom = DRW_cache_curve_edge_wire_get(ob); - DRW_shgroup_call_add(wire_shgrp, geom, ob->obmat); - - if ((cu->flag & CU_3D) && (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0) { - static uint instance_len = 2; - geom = DRW_cache_curve_edge_normal_get(ob); - DRW_shgroup_call_instances_add(wire_normals_shgrp, geom, ob->obmat, &instance_len); - } - - geom = DRW_cache_curve_edge_overlay_get(ob); - if (geom) { - DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); - } - - geom = DRW_cache_curve_vert_overlay_get(ob, stl->g_data->show_handles); - DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); - } - } - - if (ob->type == OB_SURF) { - if (BKE_object_is_in_editmode(ob)) { - struct GPUBatch *geom = DRW_cache_curve_edge_overlay_get(ob); - DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); - - geom = DRW_cache_curve_vert_overlay_get(ob, false); - DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); - } - } + EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + if (ob->type == OB_CURVE) { + if (BKE_object_is_in_editmode(ob)) { + Curve *cu = ob->data; + /* Get geometry cache */ + struct GPUBatch *geom; + + DRWShadingGroup *wire_shgrp, *wire_normals_shgrp; + + if (ob->dtx & OB_DRAWXRAY) { + wire_shgrp = stl->g_data->wire_shgrp_xray; + wire_normals_shgrp = stl->g_data->wire_normals_shgrp_xray; + } + else { + wire_shgrp = stl->g_data->wire_shgrp; + wire_normals_shgrp = stl->g_data->wire_normals_shgrp; + } + + geom = DRW_cache_curve_edge_wire_get(ob); + DRW_shgroup_call_add(wire_shgrp, geom, ob->obmat); + + if ((cu->flag & CU_3D) && (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0) { + static uint instance_len = 2; + geom = DRW_cache_curve_edge_normal_get(ob); + DRW_shgroup_call_instances_add(wire_normals_shgrp, geom, ob->obmat, &instance_len); + } + + geom = DRW_cache_curve_edge_overlay_get(ob); + if (geom) { + DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); + } + + geom = DRW_cache_curve_vert_overlay_get(ob, stl->g_data->show_handles); + DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); + } + } + + if (ob->type == OB_SURF) { + if (BKE_object_is_in_editmode(ob)) { + struct GPUBatch *geom = DRW_cache_curve_edge_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); + + geom = DRW_cache_curve_vert_overlay_get(ob, false); + DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); + } + } } /* Draw time ! Control rendering pipeline from here */ static void EDIT_CURVE_draw_scene(void *vedata) { - EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; + EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; - /* Default framebuffer and texture */ - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - if (!DRW_pass_is_empty(psl->wire_pass)) { - MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + if (!DRW_pass_is_empty(psl->wire_pass)) { + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - DRW_draw_pass(psl->wire_pass); + DRW_draw_pass(psl->wire_pass); - MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - } + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); + } - /* Unfortunately this pass cannot be AA'd without - * MULTISAMPLE_SYNC_DISABLE_NO_DEPTH. While it's - * quite unlikely to happen to multi-edit curves - * with a mix of xray enabled/disabled we still - * support this case. */ - if (!DRW_pass_is_empty(psl->wire_pass_xray)) { - MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + /* Unfortunately this pass cannot be AA'd without + * MULTISAMPLE_SYNC_DISABLE_NO_DEPTH. While it's + * quite unlikely to happen to multi-edit curves + * with a mix of xray enabled/disabled we still + * support this case. */ + if (!DRW_pass_is_empty(psl->wire_pass_xray)) { + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - DRW_draw_pass(psl->wire_pass_xray); + DRW_draw_pass(psl->wire_pass_xray); - MULTISAMPLE_SYNC_DISABLE_NO_DEPTH(dfbl, dtxl); - } + MULTISAMPLE_SYNC_DISABLE_NO_DEPTH(dfbl, dtxl); + } - /* Thoses passes don't write to depth and are AA'ed using other tricks. */ - DRW_draw_pass(psl->overlay_edge_pass); - DRW_draw_pass(psl->overlay_vert_pass); + /* Thoses passes don't write to depth and are AA'ed using other tricks. */ + DRW_draw_pass(psl->overlay_edge_pass); + DRW_draw_pass(psl->overlay_vert_pass); - DRW_state_clip_planes_reset(); + DRW_state_clip_planes_reset(); } /* Cleanup when destroying the engine. @@ -333,30 +341,31 @@ static void EDIT_CURVE_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void EDIT_CURVE_engine_free(void) { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - /* Don't free builtins. */ - sh_data->wire_sh = NULL; - GPUShader **sh_data_as_array = (GPUShader **)sh_data; - for (int i = 0; i < (sizeof(EDIT_CURVE_Shaders) / sizeof(GPUShader *)); i++) { - DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); - } - } + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + /* Don't free builtins. */ + sh_data->wire_sh = NULL; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(EDIT_CURVE_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize EDIT_CURVE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_CURVE_Data); DrawEngineType draw_engine_edit_curve_type = { - NULL, NULL, - N_("EditCurveMode"), - &EDIT_CURVE_data_size, - &EDIT_CURVE_engine_init, - &EDIT_CURVE_engine_free, - &EDIT_CURVE_cache_init, - &EDIT_CURVE_cache_populate, - NULL, - NULL, /* draw_background but not needed by mode engines */ - &EDIT_CURVE_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("EditCurveMode"), + &EDIT_CURVE_data_size, + &EDIT_CURVE_engine_init, + &EDIT_CURVE_engine_free, + &EDIT_CURVE_cache_init, + &EDIT_CURVE_cache_populate, + NULL, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_CURVE_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c index 3db167fc1fd..273480b8127 100644 --- a/source/blender/draw/modes/edit_lattice_mode.c +++ b/source/blender/draw/modes/edit_lattice_mode.c @@ -44,68 +44,68 @@ extern char datatoc_edit_lattice_overlay_frag_glsl[]; * for EDIT_LATTICE_PassList */ typedef struct EDIT_LATTICE_PassList { - /* Declare all passes here and init them in - * EDIT_LATTICE_cache_init(). - * Only contains (DRWPass *) */ - struct DRWPass *wire_pass; - struct DRWPass *vert_pass; + /* Declare all passes here and init them in + * EDIT_LATTICE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *wire_pass; + struct DRWPass *vert_pass; } EDIT_LATTICE_PassList; typedef struct EDIT_LATTICE_FramebufferList { - /* Contains all framebuffer objects needed by this engine. - * Only contains (GPUFrameBuffer *) */ - struct GPUFrameBuffer *fb; + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; } EDIT_LATTICE_FramebufferList; typedef struct EDIT_LATTICE_TextureList { - /* Contains all framebuffer textures / utility textures - * needed by this engine. Only viewport specific textures - * (not per object). Only contains (GPUTexture *) */ - struct GPUTexture *texture; + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; } EDIT_LATTICE_TextureList; typedef struct EDIT_LATTICE_StorageList { - /* Contains any other memory block that the engine needs. - * Only directly MEM_(m/c)allocN'ed blocks because they are - * free with MEM_freeN() when viewport is freed. - * (not per object) */ - struct CustomStruct *block; - struct EDIT_LATTICE_PrivateData *g_data; + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct EDIT_LATTICE_PrivateData *g_data; } EDIT_LATTICE_StorageList; typedef struct EDIT_LATTICE_Data { - /* Struct returned by DRW_viewport_engine_data_ensure. - * If you don't use one of these, just make it a (void *) */ - // void *fbl; - void *engine_type; /* Required */ - EDIT_LATTICE_FramebufferList *fbl; - EDIT_LATTICE_TextureList *txl; - EDIT_LATTICE_PassList *psl; - EDIT_LATTICE_StorageList *stl; + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_LATTICE_FramebufferList *fbl; + EDIT_LATTICE_TextureList *txl; + EDIT_LATTICE_PassList *psl; + EDIT_LATTICE_StorageList *stl; } EDIT_LATTICE_Data; typedef struct EDIT_LATTICE_Shaders { - GPUShader *wire; - GPUShader *overlay_vert; + GPUShader *wire; + GPUShader *overlay_vert; } EDIT_LATTICE_Shaders; /* *********** STATIC *********** */ static struct { - /* Custom shaders : - * Add sources to source/blender/draw/modes/shaders - * init in EDIT_LATTICE_engine_init(); - * free in EDIT_LATTICE_engine_free(); */ + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in EDIT_LATTICE_engine_init(); + * free in EDIT_LATTICE_engine_free(); */ - EDIT_LATTICE_Shaders sh_data[GPU_SHADER_CFG_LEN]; + EDIT_LATTICE_Shaders sh_data[GPU_SHADER_CFG_LEN]; } e_data = {{{NULL}}}; /* Engine data */ typedef struct EDIT_LATTICE_PrivateData { - /* This keeps the references of the shading groups for - * easy access in EDIT_LATTICE_cache_populate() */ - DRWShadingGroup *wire_shgrp; - DRWShadingGroup *vert_shgrp; + /* This keeps the references of the shading groups for + * easy access in EDIT_LATTICE_cache_populate() */ + DRWShadingGroup *wire_shgrp; + DRWShadingGroup *vert_shgrp; } EDIT_LATTICE_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -115,157 +115,152 @@ typedef struct EDIT_LATTICE_PrivateData { * (Optional) */ static void EDIT_LATTICE_engine_init(void *vedata) { - EDIT_LATTICE_TextureList *txl = ((EDIT_LATTICE_Data *)vedata)->txl; - EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl; - EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; - - UNUSED_VARS(txl, fbl, stl); - - /* Init Framebuffers like this: order is attachment order (for color texs) */ - /* - * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, - * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; - */ - - /* DRW_framebuffer_init takes care of checking if - * the framebuffer is valid and has the right size*/ - /* - * float *viewport_size = DRW_viewport_size_get(); - * DRW_framebuffer_init(&fbl->occlude_wire_fb, - * (int)viewport_size[0], (int)viewport_size[1], - * tex, 2); - */ - - const DRWContextState *draw_ctx = DRW_context_state_get(); - EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - - if (!sh_data->wire) { - sh_data->wire = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_SMOOTH_COLOR, draw_ctx->sh_cfg); - } - - if (!sh_data->overlay_vert) { - sh_data->overlay_vert = GPU_shader_create_from_arrays({ - .vert = (const char *[]){ - sh_cfg_data->lib, - datatoc_common_globals_lib_glsl, - datatoc_edit_lattice_overlay_loosevert_vert_glsl, - NULL}, - .frag = (const char *[]){ - datatoc_common_globals_lib_glsl, - datatoc_edit_lattice_overlay_frag_glsl, - NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - - } + EDIT_LATTICE_TextureList *txl = ((EDIT_LATTICE_Data *)vedata)->txl; + EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + const DRWContextState *draw_ctx = DRW_context_state_get(); + EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); + } + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + if (!sh_data->wire) { + sh_data->wire = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_SMOOTH_COLOR, + draw_ctx->sh_cfg); + } + + if (!sh_data->overlay_vert) { + sh_data->overlay_vert = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_edit_lattice_overlay_loosevert_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_common_globals_lib_glsl, + datatoc_edit_lattice_overlay_frag_glsl, + NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } } /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void EDIT_LATTICE_cache_init(void *vedata) { - EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; - EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - RegionView3D *rv3d = draw_ctx->rv3d; - EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - { - psl->wire_pass = DRW_pass_create( - "Lattice Wire", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); - stl->g_data->wire_shgrp = DRW_shgroup_create(sh_data->wire, psl->wire_pass); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->wire_shgrp, rv3d); - } - - psl->vert_pass = DRW_pass_create( - "Lattice Verts", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT); - stl->g_data->vert_shgrp = DRW_shgroup_create(sh_data->overlay_vert, psl->vert_pass); - DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vert_shgrp, rv3d); - } - - - } + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + psl->wire_pass = DRW_pass_create("Lattice Wire", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + stl->g_data->wire_shgrp = DRW_shgroup_create(sh_data->wire, psl->wire_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->wire_shgrp, rv3d); + } + + psl->vert_pass = DRW_pass_create( + "Lattice Verts", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT); + stl->g_data->vert_shgrp = DRW_shgroup_create(sh_data->overlay_vert, psl->vert_pass); + DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vert_shgrp, rv3d); + } + } } /* Add geometry to shadingGroups. Execute for each objects */ static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob) { - EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; - EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); - UNUSED_VARS(psl); + UNUSED_VARS(psl); - if (ob->type == OB_LATTICE) { - if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { - /* Get geometry cache */ - struct GPUBatch *geom; + if (ob->type == OB_LATTICE) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { + /* Get geometry cache */ + struct GPUBatch *geom; - geom = DRW_cache_lattice_wire_get(ob, true); - DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + geom = DRW_cache_lattice_wire_get(ob, true); + DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); - geom = DRW_cache_lattice_vert_overlay_get(ob); - DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat); - } - } + geom = DRW_cache_lattice_vert_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat); + } + } } /* Optional: Post-cache_populate callback */ static void EDIT_LATTICE_cache_finish(void *vedata) { - EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; - EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; - /* Do something here! dependent on the objects gathered */ - UNUSED_VARS(psl, stl); + /* Do something here! dependent on the objects gathered */ + UNUSED_VARS(psl, stl); } /* Draw time ! Control rendering pipeline from here */ static void EDIT_LATTICE_draw_scene(void *vedata) { - EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; - EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl; + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl; - /* Default framebuffer and texture */ - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - UNUSED_VARS(fbl); + UNUSED_VARS(fbl); - MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ - /* - * DRW_framebuffer_texture_detach(dtxl->depth); - * DRW_framebuffer_bind(fbl->custom_fb); - * DRW_draw_pass(psl->pass); - * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); - * DRW_framebuffer_bind(dfbl->default_fb); - */ + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ - /* ... or just render passes on default framebuffer. */ - DRW_draw_pass(psl->wire_pass); - DRW_draw_pass(psl->vert_pass); + /* ... or just render passes on default framebuffer. */ + DRW_draw_pass(psl->wire_pass); + DRW_draw_pass(psl->vert_pass); - MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - /* If you changed framebuffer, double check you rebind - * the default one with its textures attached before finishing */ + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ } /* Cleanup when destroying the engine. @@ -273,31 +268,31 @@ static void EDIT_LATTICE_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void EDIT_LATTICE_engine_free(void) { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - /* Don't free builtins. */ - sh_data->wire = NULL; - GPUShader **sh_data_as_array = (GPUShader **)sh_data; - for (int i = 0; i < (sizeof(EDIT_LATTICE_Shaders) / sizeof(GPUShader *)); i++) { - DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); - } - } - + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + /* Don't free builtins. */ + sh_data->wire = NULL; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(EDIT_LATTICE_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize EDIT_LATTICE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_LATTICE_Data); DrawEngineType draw_engine_edit_lattice_type = { - NULL, NULL, - N_("EditLatticeMode"), - &EDIT_LATTICE_data_size, - &EDIT_LATTICE_engine_init, - &EDIT_LATTICE_engine_free, - &EDIT_LATTICE_cache_init, - &EDIT_LATTICE_cache_populate, - &EDIT_LATTICE_cache_finish, - NULL, /* draw_background but not needed by mode engines */ - &EDIT_LATTICE_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("EditLatticeMode"), + &EDIT_LATTICE_data_size, + &EDIT_LATTICE_engine_init, + &EDIT_LATTICE_engine_free, + &EDIT_LATTICE_cache_init, + &EDIT_LATTICE_cache_populate, + &EDIT_LATTICE_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_LATTICE_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index dedf7eac00a..b3b6acf9b7d 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -66,298 +66,316 @@ extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; /* *********** LISTS *********** */ typedef struct EDIT_MESH_PassList { - struct DRWPass *weight_faces; - struct DRWPass *depth_hidden_wire; - struct DRWPass *depth_hidden_wire_in_front; - struct DRWPass *edit_face_overlay; - struct DRWPass *edit_face_overlay_in_front; - struct DRWPass *edit_face_in_front; - struct DRWPass *edit_face_occluded; - struct DRWPass *mix_occlude; - struct DRWPass *facefill_occlude; - struct DRWPass *normals; + struct DRWPass *weight_faces; + struct DRWPass *depth_hidden_wire; + struct DRWPass *depth_hidden_wire_in_front; + struct DRWPass *edit_face_overlay; + struct DRWPass *edit_face_overlay_in_front; + struct DRWPass *edit_face_in_front; + struct DRWPass *edit_face_occluded; + struct DRWPass *mix_occlude; + struct DRWPass *facefill_occlude; + struct DRWPass *normals; } EDIT_MESH_PassList; typedef struct EDIT_MESH_FramebufferList { - struct GPUFrameBuffer *occlude_wire_fb; - struct GPUFrameBuffer *ghost_wire_fb; + struct GPUFrameBuffer *occlude_wire_fb; + struct GPUFrameBuffer *ghost_wire_fb; } EDIT_MESH_FramebufferList; typedef struct EDIT_MESH_StorageList { - struct EDIT_MESH_PrivateData *g_data; + struct EDIT_MESH_PrivateData *g_data; } EDIT_MESH_StorageList; typedef struct EDIT_MESH_Data { - void *engine_type; - EDIT_MESH_FramebufferList *fbl; - DRWViewportEmptyList *txl; - EDIT_MESH_PassList *psl; - EDIT_MESH_StorageList *stl; + void *engine_type; + EDIT_MESH_FramebufferList *fbl; + DRWViewportEmptyList *txl; + EDIT_MESH_PassList *psl; + EDIT_MESH_StorageList *stl; } EDIT_MESH_Data; #define MAX_SHADERS 16 /** Can only contain shaders (freed as array). */ typedef struct EDIT_MESH_Shaders { - /* weight */ - GPUShader *weight_face; - - /* Geometry */ - GPUShader *overlay_vert; - GPUShader *overlay_edge; - GPUShader *overlay_edge_flat; - GPUShader *overlay_face; - GPUShader *overlay_facedot; - - GPUShader *overlay_mix; - GPUShader *overlay_facefill; - GPUShader *normals_face; - GPUShader *normals_loop; - GPUShader *normals; - GPUShader *depth; + /* weight */ + GPUShader *weight_face; + + /* Geometry */ + GPUShader *overlay_vert; + GPUShader *overlay_edge; + GPUShader *overlay_edge_flat; + GPUShader *overlay_face; + GPUShader *overlay_facedot; + + GPUShader *overlay_mix; + GPUShader *overlay_facefill; + GPUShader *normals_face; + GPUShader *normals_loop; + GPUShader *normals; + GPUShader *depth; } EDIT_MESH_Shaders; /* *********** STATIC *********** */ static struct { - EDIT_MESH_Shaders sh_data[GPU_SHADER_CFG_LEN]; + EDIT_MESH_Shaders sh_data[GPU_SHADER_CFG_LEN]; - /* temp buffer texture */ - struct GPUTexture *occlude_wire_depth_tx; - struct GPUTexture *occlude_wire_color_tx; + /* temp buffer texture */ + struct GPUTexture *occlude_wire_depth_tx; + struct GPUTexture *occlude_wire_color_tx; } e_data = {{{NULL}}}; /* Engine data */ typedef struct EDIT_MESH_PrivateData { - /* weight */ - DRWShadingGroup *fweights_shgrp; - DRWShadingGroup *depth_shgrp_hidden_wire; - DRWShadingGroup *depth_shgrp_hidden_wire_in_front; - - DRWShadingGroup *fnormals_shgrp; - DRWShadingGroup *vnormals_shgrp; - DRWShadingGroup *lnormals_shgrp; - - DRWShadingGroup *vert_shgrp; - DRWShadingGroup *edge_shgrp; - DRWShadingGroup *face_shgrp; - DRWShadingGroup *face_cage_shgrp; - DRWShadingGroup *facedot_shgrp; - - DRWShadingGroup *vert_shgrp_in_front; - DRWShadingGroup *edge_shgrp_in_front; - DRWShadingGroup *face_shgrp_in_front; - DRWShadingGroup *face_cage_shgrp_in_front; - DRWShadingGroup *facedot_shgrp_in_front; - - DRWShadingGroup *facefill_occluded_shgrp; - - int data_mask[4]; - int ghost_ob; - int edit_ob; - bool do_zbufclip; - bool do_faces; - bool do_edges; + /* weight */ + DRWShadingGroup *fweights_shgrp; + DRWShadingGroup *depth_shgrp_hidden_wire; + DRWShadingGroup *depth_shgrp_hidden_wire_in_front; + + DRWShadingGroup *fnormals_shgrp; + DRWShadingGroup *vnormals_shgrp; + DRWShadingGroup *lnormals_shgrp; + + DRWShadingGroup *vert_shgrp; + DRWShadingGroup *edge_shgrp; + DRWShadingGroup *face_shgrp; + DRWShadingGroup *face_cage_shgrp; + DRWShadingGroup *facedot_shgrp; + + DRWShadingGroup *vert_shgrp_in_front; + DRWShadingGroup *edge_shgrp_in_front; + DRWShadingGroup *face_shgrp_in_front; + DRWShadingGroup *face_cage_shgrp_in_front; + DRWShadingGroup *facedot_shgrp_in_front; + + DRWShadingGroup *facefill_occluded_shgrp; + + int data_mask[4]; + int ghost_ob; + int edit_ob; + bool do_zbufclip; + bool do_faces; + bool do_edges; } EDIT_MESH_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ - static void EDIT_MESH_engine_init(void *vedata) { - EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - - e_data.occlude_wire_depth_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_edit_mesh_type); - e_data.occlude_wire_color_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_RGBA8, - &draw_engine_edit_mesh_type); - - GPU_framebuffer_ensure_config(&fbl->occlude_wire_fb, { - GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx), - GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx) - }); - - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - - if (!sh_data->weight_face) { - sh_data->weight_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_paint_weight_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_common_globals_lib_glsl, datatoc_paint_weight_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - - char *lib = BLI_string_joinN(sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_common_lib_glsl); - /* Use geometry shader to draw edge wireframe. This ensure us - * the same result accross platforms and more flexibility. But - * we pay the cost of running a geometry shader. - * In the future we might consider using only the vertex shader - * and loading data manually with buffer textures. */ - const bool use_geom_shader = true; - const char *geom_sh_code[] = {lib, datatoc_edit_mesh_overlay_geom_glsl, NULL}; - if (!use_geom_shader) { - geom_sh_code[0] = NULL; - } - const char *use_geom_def = use_geom_shader ? "#define USE_GEOM_SHADER\n" : ""; - const char *use_smooth_def = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) ? "" : "#define USE_SMOOTH_WIRE\n"; - sh_data->overlay_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define FACE\n", NULL}, - }); - sh_data->overlay_edge = GPU_shader_create_from_arrays({ - .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, - .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, use_geom_def, use_smooth_def, "#define EDGE\n", NULL}, - .geom = (use_geom_shader) ? geom_sh_code : NULL, - }); - sh_data->overlay_edge_flat = GPU_shader_create_from_arrays({ - .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, - .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, use_geom_def, use_smooth_def, "#define EDGE\n", "#define FLAT\n", NULL}, - .geom = (use_geom_shader) ? geom_sh_code : NULL, - }); - sh_data->overlay_vert = GPU_shader_create_from_arrays({ - .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define VERT\n", NULL}, - }); - sh_data->overlay_facedot = GPU_shader_create_from_arrays({ - .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define FACEDOT\n", NULL}, - }); - sh_data->overlay_facefill = GPU_shader_create_from_arrays({ - .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_facefill_vert_glsl, NULL}, - .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_facefill_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - MEM_freeN(lib); - - sh_data->overlay_mix = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl, NULL); - - sh_data->normals_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define FACE_NORMALS\n", NULL}, - }); - - sh_data->normals_loop = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define LOOP_NORMALS\n", NULL}, - }); - - sh_data->normals = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - - sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg); - } + EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + e_data.occlude_wire_depth_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_edit_mesh_type); + e_data.occlude_wire_color_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA8, &draw_engine_edit_mesh_type); + + GPU_framebuffer_ensure_config(&fbl->occlude_wire_fb, + {GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx), + GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx)}); + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); + } + + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + if (!sh_data->weight_face) { + sh_data->weight_face = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_paint_weight_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_common_globals_lib_glsl, + datatoc_paint_weight_frag_glsl, + NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + + char *lib = BLI_string_joinN(sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_edit_mesh_overlay_common_lib_glsl); + /* Use geometry shader to draw edge wireframe. This ensure us + * the same result accross platforms and more flexibility. But + * we pay the cost of running a geometry shader. + * In the future we might consider using only the vertex shader + * and loading data manually with buffer textures. */ + const bool use_geom_shader = true; + const char *geom_sh_code[] = {lib, datatoc_edit_mesh_overlay_geom_glsl, NULL}; + if (!use_geom_shader) { + geom_sh_code[0] = NULL; + } + const char *use_geom_def = use_geom_shader ? "#define USE_GEOM_SHADER\n" : ""; + const char *use_smooth_def = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) ? + "" : + "#define USE_SMOOTH_WIRE\n"; + sh_data->overlay_face = GPU_shader_create_from_arrays({ + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define FACE\n", NULL}, + }); + sh_data->overlay_edge = GPU_shader_create_from_arrays({ + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, + .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL}, + .defs = (const char + *[]){sh_cfg_data->def, use_geom_def, use_smooth_def, "#define EDGE\n", NULL}, + .geom = (use_geom_shader) ? geom_sh_code : NULL, + }); + sh_data->overlay_edge_flat = GPU_shader_create_from_arrays({ + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, + .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, + use_geom_def, + use_smooth_def, + "#define EDGE\n", + "#define FLAT\n", + NULL}, + .geom = (use_geom_shader) ? geom_sh_code : NULL, + }); + sh_data->overlay_vert = GPU_shader_create_from_arrays({ + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define VERT\n", NULL}, + }); + sh_data->overlay_facedot = GPU_shader_create_from_arrays({ + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define FACEDOT\n", NULL}, + }); + sh_data->overlay_facefill = GPU_shader_create_from_arrays({ + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_facefill_vert_glsl, NULL}, + .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_facefill_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + MEM_freeN(lib); + + sh_data->overlay_mix = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl, + NULL); + + sh_data->normals_face = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define FACE_NORMALS\n", NULL}, + }); + + sh_data->normals_loop = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define LOOP_NORMALS\n", NULL}, + }); + + sh_data->normals = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + + sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg); + } } -static DRWPass *edit_mesh_create_overlay_pass( - float *face_alpha, int *data_mask, bool do_edges, - DRWState statemod, - DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_face_cage_shgrp, DRWShadingGroup **r_facedot_shgrp, - DRWShadingGroup **r_edge_shgrp, DRWShadingGroup **r_vert_shgrp) +static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, + int *data_mask, + bool do_edges, + DRWState statemod, + DRWShadingGroup **r_face_shgrp, + DRWShadingGroup **r_face_cage_shgrp, + DRWShadingGroup **r_facedot_shgrp, + DRWShadingGroup **r_edge_shgrp, + DRWShadingGroup **r_vert_shgrp) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - RegionView3D *rv3d = draw_ctx->rv3d; - Scene *scene = draw_ctx->scene; - ToolSettings *tsettings = scene->toolsettings; - EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - const bool select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX) != 0; - const bool select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0; - const bool select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0; - const bool show_wide_edge = select_edge && !(draw_ctx->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT); - - float winmat[4][4]; - float viewdist = rv3d->dist; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ - if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { - viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); - } - const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f); - - DRWPass *pass = DRW_pass_create( - "Edit Mesh Face Overlay Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod); - - DRWShadingGroup *grp; - - GPUShader *vert_sh = sh_data->overlay_vert; - GPUShader *edge_sh = (select_vert) ? sh_data->overlay_edge : sh_data->overlay_edge_flat; - GPUShader *face_sh = sh_data->overlay_face; - GPUShader *facedot_sh = sh_data->overlay_facedot; - - /* Faces */ - if (select_face) { - grp = *r_facedot_shgrp = DRW_shgroup_create(facedot_sh, pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - } - - grp = *r_face_shgrp = DRW_shgroup_create(face_sh, pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_float(grp, "faceAlphaMod", face_alpha, 1); - DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); - DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); - DRW_shgroup_uniform_float_copy(grp, "ofs", 0.0f); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - - /* Cage geom needs to be offseted to avoid Z-fighting. */ - grp = *r_face_cage_shgrp = DRW_shgroup_create_sub(*r_face_shgrp); - DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); - - /* Edges */ - grp = *r_edge_shgrp = DRW_shgroup_create(edge_sh, pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); - DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); - DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs); - DRW_shgroup_uniform_float_copy(grp, "edgeScale", show_wide_edge ? 1.75f : 1.0f); - DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); - /* To match blender loop structure. */ - DRW_shgroup_state_enable(grp, DRW_STATE_FIRST_VERTEX_CONVENTION); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - - /* Verts */ - if (select_vert) { - grp = *r_vert_shgrp = DRW_shgroup_create(vert_sh, pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs * 1.5f); - DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE | DRW_STATE_WRITE_DEPTH); - DRW_shgroup_state_disable(grp, DRW_STATE_BLEND); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - } - - return pass; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + Scene *scene = draw_ctx->scene; + ToolSettings *tsettings = scene->toolsettings; + EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + const bool select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX) != 0; + const bool select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0; + const bool select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0; + const bool show_wide_edge = select_edge && + !(draw_ctx->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT); + + float winmat[4][4]; + float viewdist = rv3d->dist; + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ + if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { + viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); + } + const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f); + + DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod); + + DRWShadingGroup *grp; + + GPUShader *vert_sh = sh_data->overlay_vert; + GPUShader *edge_sh = (select_vert) ? sh_data->overlay_edge : sh_data->overlay_edge_flat; + GPUShader *face_sh = sh_data->overlay_face; + GPUShader *facedot_sh = sh_data->overlay_facedot; + + /* Faces */ + if (select_face) { + grp = *r_facedot_shgrp = DRW_shgroup_create(facedot_sh, pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + } + + grp = *r_face_shgrp = DRW_shgroup_create(face_sh, pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float(grp, "faceAlphaMod", face_alpha, 1); + DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); + DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); + DRW_shgroup_uniform_float_copy(grp, "ofs", 0.0f); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + + /* Cage geom needs to be offseted to avoid Z-fighting. */ + grp = *r_face_cage_shgrp = DRW_shgroup_create_sub(*r_face_shgrp); + DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); + + /* Edges */ + grp = *r_edge_shgrp = DRW_shgroup_create(edge_sh, pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); + DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); + DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs); + DRW_shgroup_uniform_float_copy(grp, "edgeScale", show_wide_edge ? 1.75f : 1.0f); + DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); + /* To match blender loop structure. */ + DRW_shgroup_state_enable(grp, DRW_STATE_FIRST_VERTEX_CONVENTION); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + + /* Verts */ + if (select_vert) { + grp = *r_vert_shgrp = DRW_shgroup_create(vert_sh, pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs * 1.5f); + DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE | DRW_STATE_WRITE_DEPTH); + DRW_shgroup_state_disable(grp, DRW_STATE_BLEND); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } + } + + return pass; } static float backwire_opacity; @@ -366,424 +384,427 @@ static float size_normal; static void EDIT_MESH_cache_init(void *vedata) { - EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; - EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - RegionView3D *rv3d = draw_ctx->rv3d; - Scene *scene = draw_ctx->scene; - ToolSettings *tsettings = scene->toolsettings; - EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - static float zero = 0.0f; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - stl->g_data->ghost_ob = 0; - stl->g_data->edit_ob = 0; - stl->g_data->do_faces = true; - stl->g_data->do_edges = true; - - stl->g_data->do_zbufclip = XRAY_FLAG_ENABLED(v3d); - - stl->g_data->data_mask[0] = 0xFF; /* Face Flag */ - stl->g_data->data_mask[1] = 0xFF; /* Edge Flag */ - stl->g_data->data_mask[2] = 0xFF; /* Crease */ - stl->g_data->data_mask[3] = 0xFF; /* BWeight */ - - if (draw_ctx->object_edit->type == OB_MESH) { - if (BKE_object_is_in_editmode(draw_ctx->object_edit)) { - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE) == 0) { - stl->g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACES) == 0) { - stl->g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE); - stl->g_data->do_faces = false; - stl->g_data->do_zbufclip = false; - } - if ((tsettings->selectmode & SCE_SELECT_FACE) == 0) { - stl->g_data->data_mask[0] &= ~VFLAG_FACE_ACTIVE; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SEAMS) == 0) { - stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SHARP) == 0) { - stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE) == 0) { - stl->g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { - if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) { - stl->g_data->data_mask[1] &= ~(VFLAG_EDGE_ACTIVE & VFLAG_EDGE_SELECTED); - stl->g_data->do_edges = false; - } - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CREASES) == 0) { - stl->g_data->data_mask[2] = 0x0; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_BWEIGHTS) == 0) { - stl->g_data->data_mask[3] = 0x0; - } - } - } - - { - psl->weight_faces = DRW_pass_create( - "Weight Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); - - stl->g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces); - - static float alpha = 1.0f; - DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "opacity", &alpha, 1); - DRW_shgroup_uniform_texture(stl->g_data->fweights_shgrp, "colorramp", G_draw.weight_ramp); - DRW_shgroup_uniform_block(stl->g_data->fweights_shgrp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d); - } - } - - { - /* Complementary Depth Pass */ - psl->depth_hidden_wire = DRW_pass_create( - "Depth Pass Hidden Wire", - DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); - stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, psl->depth_hidden_wire); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire, rv3d); - } - - psl->depth_hidden_wire_in_front = DRW_pass_create( - "Depth Pass Hidden Wire In Front", - DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); - stl->g_data->depth_shgrp_hidden_wire_in_front = DRW_shgroup_create(sh_data->depth, psl->depth_hidden_wire_in_front); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire_in_front, rv3d); - } - } - - { - /* Normals */ - psl->normals = DRW_pass_create( - "Edit Mesh Normals Pass", - DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL); - - stl->g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals); - DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1); - DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", G_draw.block.colorNormal, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d); - } - - stl->g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals); - DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1); - DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", G_draw.block.colorVNormal, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d); - } - - stl->g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals); - DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1); - DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", G_draw.block.colorLNormal, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d); - } - } - - /* For in front option */ - psl->edit_face_overlay_in_front = edit_mesh_create_overlay_pass( - &face_mod, stl->g_data->data_mask, stl->g_data->do_edges, - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, - &stl->g_data->face_shgrp_in_front, - &stl->g_data->face_cage_shgrp_in_front, - &stl->g_data->facedot_shgrp_in_front, - &stl->g_data->edge_shgrp_in_front, - &stl->g_data->vert_shgrp_in_front); - - if (!stl->g_data->do_zbufclip) { - psl->edit_face_overlay = edit_mesh_create_overlay_pass( - &face_mod, stl->g_data->data_mask, stl->g_data->do_edges, - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, - &stl->g_data->face_shgrp, - &stl->g_data->face_cage_shgrp, - &stl->g_data->facedot_shgrp, - &stl->g_data->edge_shgrp, - &stl->g_data->vert_shgrp); - } - else { - /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */ - psl->edit_face_occluded = edit_mesh_create_overlay_pass( - &zero, stl->g_data->data_mask, stl->g_data->do_edges, - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH, - &stl->g_data->face_shgrp, - &stl->g_data->face_cage_shgrp, - &stl->g_data->facedot_shgrp, - &stl->g_data->edge_shgrp, - &stl->g_data->vert_shgrp); - - /* however we loose the front faces value (because we need the depth of occluded wires and - * faces are alpha blended ) so we recover them in a new pass. */ - psl->facefill_occlude = DRW_pass_create( - "Front Face Color", - DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); - stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill, psl->facefill_occlude); - DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_ivec4(stl->g_data->facefill_occluded_shgrp, "dataMask", stl->g_data->data_mask, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d); - } - - /* we need a full screen pass to combine the result */ - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); - - psl->mix_occlude = DRW_pass_create( - "Mix Occluded Wires", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude); - DRW_shgroup_call_add(mix_shgrp, quad, NULL); - DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1); - DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx); - DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx); - DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth); - } + EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; + EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + Scene *scene = draw_ctx->scene; + ToolSettings *tsettings = scene->toolsettings; + EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + static float zero = 0.0f; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + stl->g_data->ghost_ob = 0; + stl->g_data->edit_ob = 0; + stl->g_data->do_faces = true; + stl->g_data->do_edges = true; + + stl->g_data->do_zbufclip = XRAY_FLAG_ENABLED(v3d); + + stl->g_data->data_mask[0] = 0xFF; /* Face Flag */ + stl->g_data->data_mask[1] = 0xFF; /* Edge Flag */ + stl->g_data->data_mask[2] = 0xFF; /* Crease */ + stl->g_data->data_mask[3] = 0xFF; /* BWeight */ + + if (draw_ctx->object_edit->type == OB_MESH) { + if (BKE_object_is_in_editmode(draw_ctx->object_edit)) { + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE) == 0) { + stl->g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACES) == 0) { + stl->g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE); + stl->g_data->do_faces = false; + stl->g_data->do_zbufclip = false; + } + if ((tsettings->selectmode & SCE_SELECT_FACE) == 0) { + stl->g_data->data_mask[0] &= ~VFLAG_FACE_ACTIVE; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SEAMS) == 0) { + stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SHARP) == 0) { + stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE) == 0) { + stl->g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { + if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) { + stl->g_data->data_mask[1] &= ~(VFLAG_EDGE_ACTIVE & VFLAG_EDGE_SELECTED); + stl->g_data->do_edges = false; + } + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CREASES) == 0) { + stl->g_data->data_mask[2] = 0x0; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_BWEIGHTS) == 0) { + stl->g_data->data_mask[3] = 0x0; + } + } + } + + { + psl->weight_faces = DRW_pass_create( + "Weight Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces); + + static float alpha = 1.0f; + DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "opacity", &alpha, 1); + DRW_shgroup_uniform_texture(stl->g_data->fweights_shgrp, "colorramp", G_draw.weight_ramp); + DRW_shgroup_uniform_block(stl->g_data->fweights_shgrp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d); + } + } + + { + /* Complementary Depth Pass */ + psl->depth_hidden_wire = DRW_pass_create("Depth Pass Hidden Wire", + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_CULL_BACK); + stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, + psl->depth_hidden_wire); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire, rv3d); + } + + psl->depth_hidden_wire_in_front = DRW_pass_create( + "Depth Pass Hidden Wire In Front", + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); + stl->g_data->depth_shgrp_hidden_wire_in_front = DRW_shgroup_create( + sh_data->depth, psl->depth_hidden_wire_in_front); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire_in_front, rv3d); + } + } + + { + /* Normals */ + psl->normals = DRW_pass_create("Edit Mesh Normals Pass", + DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | + DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals); + DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", G_draw.block.colorNormal, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d); + } + + stl->g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals); + DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", G_draw.block.colorVNormal, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d); + } + + stl->g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals); + DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", G_draw.block.colorLNormal, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d); + } + } + + /* For in front option */ + psl->edit_face_overlay_in_front = edit_mesh_create_overlay_pass( + &face_mod, + stl->g_data->data_mask, + stl->g_data->do_edges, + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, + &stl->g_data->face_shgrp_in_front, + &stl->g_data->face_cage_shgrp_in_front, + &stl->g_data->facedot_shgrp_in_front, + &stl->g_data->edge_shgrp_in_front, + &stl->g_data->vert_shgrp_in_front); + + if (!stl->g_data->do_zbufclip) { + psl->edit_face_overlay = edit_mesh_create_overlay_pass(&face_mod, + stl->g_data->data_mask, + stl->g_data->do_edges, + DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND, + &stl->g_data->face_shgrp, + &stl->g_data->face_cage_shgrp, + &stl->g_data->facedot_shgrp, + &stl->g_data->edge_shgrp, + &stl->g_data->vert_shgrp); + } + else { + /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */ + psl->edit_face_occluded = edit_mesh_create_overlay_pass(&zero, + stl->g_data->data_mask, + stl->g_data->do_edges, + DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_WRITE_DEPTH, + &stl->g_data->face_shgrp, + &stl->g_data->face_cage_shgrp, + &stl->g_data->facedot_shgrp, + &stl->g_data->edge_shgrp, + &stl->g_data->vert_shgrp); + + /* however we loose the front faces value (because we need the depth of occluded wires and + * faces are alpha blended ) so we recover them in a new pass. */ + psl->facefill_occlude = DRW_pass_create( + "Front Face Color", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill, + psl->facefill_occlude); + DRW_shgroup_uniform_block( + stl->g_data->facefill_occluded_shgrp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_ivec4( + stl->g_data->facefill_occluded_shgrp, "dataMask", stl->g_data->data_mask, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d); + } + + /* we need a full screen pass to combine the result */ + struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + + psl->mix_occlude = DRW_pass_create("Mix Occluded Wires", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude); + DRW_shgroup_call_add(mix_shgrp, quad, NULL); + DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth); + } } -static void edit_mesh_add_ob_to_pass( - Scene *scene, Object *ob, - DRWShadingGroup *vert_shgrp, - DRWShadingGroup *edge_shgrp, - DRWShadingGroup *face_shgrp, - DRWShadingGroup *face_cage_shgrp, - DRWShadingGroup *facedot_shgrp, - DRWShadingGroup *facefill_shgrp) +static void edit_mesh_add_ob_to_pass(Scene *scene, + Object *ob, + DRWShadingGroup *vert_shgrp, + DRWShadingGroup *edge_shgrp, + DRWShadingGroup *face_shgrp, + DRWShadingGroup *face_cage_shgrp, + DRWShadingGroup *facedot_shgrp, + DRWShadingGroup *facefill_shgrp) { - struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter; - ToolSettings *tsettings = scene->toolsettings; - - bool has_edit_mesh_cage = false; - /* TODO: Should be its own function. */ - Mesh *me = (Mesh *)ob->data; - BMEditMesh *embm = me->edit_mesh; - if (embm) { - has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); - } - - face_shgrp = (has_edit_mesh_cage) ? face_cage_shgrp : face_shgrp; - face_shgrp = (facefill_shgrp != NULL) ? facefill_shgrp : face_shgrp; - - geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data); - geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data); - DRW_shgroup_call_add(edge_shgrp, geom_edges, ob->obmat); - DRW_shgroup_call_add(face_shgrp, geom_tris, ob->obmat); - - if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { - geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data); - DRW_shgroup_call_add(vert_shgrp, geom_verts, ob->obmat); - } - - if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0) { - geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data); - DRW_shgroup_call_add(facedot_shgrp, geom_fcenter, ob->obmat); - } + struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter; + ToolSettings *tsettings = scene->toolsettings; + + bool has_edit_mesh_cage = false; + /* TODO: Should be its own function. */ + Mesh *me = (Mesh *)ob->data; + BMEditMesh *embm = me->edit_mesh; + if (embm) { + has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); + } + + face_shgrp = (has_edit_mesh_cage) ? face_cage_shgrp : face_shgrp; + face_shgrp = (facefill_shgrp != NULL) ? facefill_shgrp : face_shgrp; + + geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data); + geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data); + DRW_shgroup_call_add(edge_shgrp, geom_edges, ob->obmat); + DRW_shgroup_call_add(face_shgrp, geom_tris, ob->obmat); + + if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { + geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data); + DRW_shgroup_call_add(vert_shgrp, geom_verts, ob->obmat); + } + + if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0) { + geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data); + DRW_shgroup_call_add(facedot_shgrp, geom_fcenter, ob->obmat); + } } static void EDIT_MESH_cache_populate(void *vedata, Object *ob) { - EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; - EDIT_MESH_PrivateData *g_data = stl->g_data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - Scene *scene = draw_ctx->scene; - ToolSettings *tsettings = scene->toolsettings; - struct GPUBatch *geom; - - if (ob->type == OB_MESH) { - if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { - bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; - bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0; - bool do_show_weight = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT) != 0; - bool fnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0; - bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0; - bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0; - - bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0; - - if (g_data->do_faces == false && - g_data->do_edges == false && - (tsettings->selectmode & SCE_SELECT_FACE)) - { - /* Force display of face centers in this case because that's - * the only way to see if a face is selected. */ - show_face_dots = true; - } - - /* Updating uniform */ - backwire_opacity = v3d->overlay.backwire_opacity; - size_normal = v3d->overlay.normals_length; - - face_mod = (do_occlude_wire) ? 0.0f : 1.0f; - - if (!g_data->do_faces) { - face_mod = 0.0f; - } - - if (do_show_weight) { - geom = DRW_cache_mesh_surface_weights_get(ob); - DRW_shgroup_call_add(g_data->fweights_shgrp, geom, ob->obmat); - } - - if (do_occlude_wire || do_in_front) { - geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front - : g_data->depth_shgrp_hidden_wire, - geom, ob->obmat); - } - - if (vnormals_do) { - geom = DRW_mesh_batch_cache_get_edit_vertices(ob->data); - DRW_shgroup_call_add(g_data->vnormals_shgrp, geom, ob->obmat); - } - if (lnormals_do) { - geom = DRW_mesh_batch_cache_get_edit_lnors(ob->data); - DRW_shgroup_call_add(g_data->lnormals_shgrp, geom, ob->obmat); - } - if (fnormals_do) { - geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data); - DRW_shgroup_call_add(g_data->fnormals_shgrp, geom, ob->obmat); - } - - if (g_data->do_zbufclip) { - edit_mesh_add_ob_to_pass( - scene, ob, - g_data->vert_shgrp, - g_data->edge_shgrp, - g_data->face_shgrp, - g_data->face_cage_shgrp, - g_data->facedot_shgrp, - (g_data->do_faces) ? g_data->facefill_occluded_shgrp : NULL); - } - else if (do_in_front) { - edit_mesh_add_ob_to_pass( - scene, ob, - g_data->vert_shgrp_in_front, - g_data->edge_shgrp_in_front, - g_data->face_shgrp_in_front, - g_data->face_cage_shgrp_in_front, - (show_face_dots) ? g_data->facedot_shgrp_in_front : NULL, - NULL); - } - else { - edit_mesh_add_ob_to_pass( - scene, ob, - g_data->vert_shgrp, - g_data->edge_shgrp, - g_data->face_shgrp, - g_data->face_cage_shgrp, - (show_face_dots) ? g_data->facedot_shgrp : NULL, - NULL); - } - - g_data->ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0; - g_data->edit_ob += 1; - - /* 3D text overlay */ - if (v3d->overlay.edit_flag & (V3D_OVERLAY_EDIT_EDGE_LEN | - V3D_OVERLAY_EDIT_FACE_AREA | - V3D_OVERLAY_EDIT_FACE_ANG | - V3D_OVERLAY_EDIT_EDGE_ANG | - V3D_OVERLAY_EDIT_INDICES)) - { - if (DRW_state_show_text()) { - DRW_edit_mesh_mode_text_measure_stats( - draw_ctx->ar, v3d, ob, &scene->unit); - } - } - } - } + EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; + EDIT_MESH_PrivateData *g_data = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + ToolSettings *tsettings = scene->toolsettings; + struct GPUBatch *geom; + + if (ob->type == OB_MESH) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { + bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0; + bool do_show_weight = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT) != 0; + bool fnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0; + bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0; + bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0; + + bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0; + + if (g_data->do_faces == false && g_data->do_edges == false && + (tsettings->selectmode & SCE_SELECT_FACE)) { + /* Force display of face centers in this case because that's + * the only way to see if a face is selected. */ + show_face_dots = true; + } + + /* Updating uniform */ + backwire_opacity = v3d->overlay.backwire_opacity; + size_normal = v3d->overlay.normals_length; + + face_mod = (do_occlude_wire) ? 0.0f : 1.0f; + + if (!g_data->do_faces) { + face_mod = 0.0f; + } + + if (do_show_weight) { + geom = DRW_cache_mesh_surface_weights_get(ob); + DRW_shgroup_call_add(g_data->fweights_shgrp, geom, ob->obmat); + } + + if (do_occlude_wire || do_in_front) { + geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front : + g_data->depth_shgrp_hidden_wire, + geom, + ob->obmat); + } + + if (vnormals_do) { + geom = DRW_mesh_batch_cache_get_edit_vertices(ob->data); + DRW_shgroup_call_add(g_data->vnormals_shgrp, geom, ob->obmat); + } + if (lnormals_do) { + geom = DRW_mesh_batch_cache_get_edit_lnors(ob->data); + DRW_shgroup_call_add(g_data->lnormals_shgrp, geom, ob->obmat); + } + if (fnormals_do) { + geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data); + DRW_shgroup_call_add(g_data->fnormals_shgrp, geom, ob->obmat); + } + + if (g_data->do_zbufclip) { + edit_mesh_add_ob_to_pass(scene, + ob, + g_data->vert_shgrp, + g_data->edge_shgrp, + g_data->face_shgrp, + g_data->face_cage_shgrp, + g_data->facedot_shgrp, + (g_data->do_faces) ? g_data->facefill_occluded_shgrp : NULL); + } + else if (do_in_front) { + edit_mesh_add_ob_to_pass(scene, + ob, + g_data->vert_shgrp_in_front, + g_data->edge_shgrp_in_front, + g_data->face_shgrp_in_front, + g_data->face_cage_shgrp_in_front, + (show_face_dots) ? g_data->facedot_shgrp_in_front : NULL, + NULL); + } + else { + edit_mesh_add_ob_to_pass(scene, + ob, + g_data->vert_shgrp, + g_data->edge_shgrp, + g_data->face_shgrp, + g_data->face_cage_shgrp, + (show_face_dots) ? g_data->facedot_shgrp : NULL, + NULL); + } + + g_data->ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0; + g_data->edit_ob += 1; + + /* 3D text overlay */ + if (v3d->overlay.edit_flag & + (V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_FACE_AREA | V3D_OVERLAY_EDIT_FACE_ANG | + V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)) { + if (DRW_state_show_text()) { + DRW_edit_mesh_mode_text_measure_stats(draw_ctx->ar, v3d, ob, &scene->unit); + } + } + } + } } static void EDIT_MESH_draw_scene(void *vedata) { - EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; - EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; - EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - - DRW_draw_pass(psl->weight_faces); - - DRW_draw_pass(psl->depth_hidden_wire); - - if (stl->g_data->do_zbufclip) { - float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - DRW_draw_pass(psl->depth_hidden_wire_in_front); - - /* render facefill */ - DRW_draw_pass(psl->facefill_occlude); - - /* Render wires on a separate framebuffer */ - GPU_framebuffer_bind(fbl->occlude_wire_fb); - GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f); - DRW_draw_pass(psl->normals); - DRW_draw_pass(psl->edit_face_occluded); - - /* Combine with scene buffer */ - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->mix_occlude); - } - else { - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - DRW_draw_pass(psl->normals); - DRW_draw_pass(psl->edit_face_overlay); - - if (v3d->shading.type == OB_SOLID && !XRAY_FLAG_ENABLED(v3d) && - stl->g_data->ghost_ob == 1 && stl->g_data->edit_ob == 1) - { - /* In the case of single ghost object edit (common case for retopology): - * we clear the depth buffer so that only the depth of the retopo mesh - * is occluding the edit cage. */ - GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); - } - - DRW_draw_pass(psl->depth_hidden_wire_in_front); - DRW_draw_pass(psl->edit_face_overlay_in_front); - } - - DRW_state_clip_planes_reset(); + EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; + EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; + EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + DRW_draw_pass(psl->weight_faces); + + DRW_draw_pass(psl->depth_hidden_wire); + + if (stl->g_data->do_zbufclip) { + float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + DRW_draw_pass(psl->depth_hidden_wire_in_front); + + /* render facefill */ + DRW_draw_pass(psl->facefill_occlude); + + /* Render wires on a separate framebuffer */ + GPU_framebuffer_bind(fbl->occlude_wire_fb); + GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f); + DRW_draw_pass(psl->normals); + DRW_draw_pass(psl->edit_face_occluded); + + /* Combine with scene buffer */ + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->mix_occlude); + } + else { + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + DRW_draw_pass(psl->normals); + DRW_draw_pass(psl->edit_face_overlay); + + if (v3d->shading.type == OB_SOLID && !XRAY_FLAG_ENABLED(v3d) && stl->g_data->ghost_ob == 1 && + stl->g_data->edit_ob == 1) { + /* In the case of single ghost object edit (common case for retopology): + * we clear the depth buffer so that only the depth of the retopo mesh + * is occluding the edit cage. */ + GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); + } + + DRW_draw_pass(psl->depth_hidden_wire_in_front); + DRW_draw_pass(psl->edit_face_overlay_in_front); + } + + DRW_state_clip_planes_reset(); } static void EDIT_MESH_engine_free(void) { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - EDIT_MESH_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - /* Don't free builtins. */ - sh_data->depth = NULL; - GPUShader **sh_data_as_array = (GPUShader **)sh_data; - for (int i = 0; i < (sizeof(EDIT_MESH_Shaders) / sizeof(GPUShader *)); i++) { - DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); - } - } + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + EDIT_MESH_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + /* Don't free builtins. */ + sh_data->depth = NULL; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(EDIT_MESH_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize EDIT_MESH_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_MESH_Data); DrawEngineType draw_engine_edit_mesh_type = { - NULL, NULL, - N_("EditMeshMode"), - &EDIT_MESH_data_size, - &EDIT_MESH_engine_init, - &EDIT_MESH_engine_free, - &EDIT_MESH_cache_init, - &EDIT_MESH_cache_populate, - NULL, - NULL, - &EDIT_MESH_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("EditMeshMode"), + &EDIT_MESH_data_size, + &EDIT_MESH_engine_init, + &EDIT_MESH_engine_free, + &EDIT_MESH_cache_init, + &EDIT_MESH_cache_populate, + NULL, + NULL, + &EDIT_MESH_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/edit_mesh_mode_intern.h b/source/blender/draw/modes/edit_mesh_mode_intern.h index 946615ef66b..706c7b7bd88 100644 --- a/source/blender/draw/modes/edit_mesh_mode_intern.h +++ b/source/blender/draw/modes/edit_mesh_mode_intern.h @@ -27,8 +27,9 @@ struct UnitSettings; struct View3D; /* edit_mesh_mode_text.c */ -void DRW_edit_mesh_mode_text_measure_stats( - struct ARegion *ar, struct View3D *v3d, - struct Object *ob, const UnitSettings *unit); +void DRW_edit_mesh_mode_text_measure_stats(struct ARegion *ar, + struct View3D *v3d, + struct Object *ob, + const UnitSettings *unit); #endif /* __EDIT_MESH_MODE_INTERN_H__ */ diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c index 629cb042562..90396785eb3 100644 --- a/source/blender/draw/modes/edit_mesh_mode_text.c +++ b/source/blender/draw/modes/edit_mesh_mode_text.c @@ -42,310 +42,337 @@ #include "edit_mesh_mode_intern.h" /* own include */ /* Copied from drawobject.c */ -void DRW_edit_mesh_mode_text_measure_stats( - ARegion *ar, View3D *v3d, - Object *ob, const UnitSettings *unit) +void DRW_edit_mesh_mode_text_measure_stats(ARegion *ar, + View3D *v3d, + Object *ob, + const UnitSettings *unit) { - /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.). - * See bug #36090. - */ - struct DRWTextStore *dt = DRW_text_cache_ensure(); - const short txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | (unit->system ? 0 : DRW_TEXT_CACHE_ASCII); - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - float v1[3], v2[3], v3[3], vmid[3], fvec[3]; - char numstr[32]; /* Stores the measurement display text here */ - size_t numstr_len; - const char *conv_float; /* Use a float conversion matching the grid size */ - uchar col[4] = {0, 0, 0, 255}; /* color of the text to draw */ - float area; /* area of the face */ - float grid = unit->system ? unit->scale_length : v3d->grid; - const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0; - const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0; - /* when 2 edge-info options are enabled, space apart */ - const bool do_edge_textpair = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_LEN) && (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_ANG); - const short edge_texpair_sep = (short)(5.0f * U.ui_scale); - float clip_planes[4][4]; - /* allow for displaying shape keys and deform mods */ - BMIter iter; - - /* make the precision of the display value proportionate to the gridsize */ - - if (grid <= 0.01f) { conv_float = "%.6g"; } - else if (grid <= 0.1f) { conv_float = "%.5g"; } - else if (grid <= 1.0f) { conv_float = "%.4g"; } - else if (grid <= 10.0f) { conv_float = "%.3g"; } - else { conv_float = "%.2g"; } - - if (v3d->overlay.edit_flag & (V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)) { - BoundBox bb; - const rcti rect = {0, ar->winx, 0, ar->winy}; - - ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect); - } - - if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_LEN) { - BMEdge *eed; - - UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); - - BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - /* draw selected edges, or edges next to selected verts while dragging */ - if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || - (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)))) - { - float v1_clip[3], v2_clip[3]; - - copy_v3_v3(v1, eed->v1->co); - copy_v3_v3(v2, eed->v2->co); - - if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { - - mid_v3_v3v3(vmid, v1_clip, v2_clip); - mul_m4_v3(ob->obmat, vmid); - - if (do_global) { - mul_mat3_m4_v3(ob->obmat, v1); - mul_mat3_m4_v3(ob->obmat, v2); - } - - if (unit->system) { - numstr_len = bUnit_AsString2( - numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3, - B_UNIT_LENGTH, unit, false); - } - else { - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); - } - - DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, - (do_edge_textpair) ? edge_texpair_sep : 0, - txt_flag, col); - } - } - } - } - - if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_ANG) { - const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS); - BMEdge *eed; - - UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col); - - BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - BMLoop *l_a, *l_b; - if (BM_edge_loop_pair(eed, &l_a, &l_b)) { - /* draw selected edges, or edges next to selected verts while dragging */ - if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || - (do_moving && - (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) || - /* special case, this is useful to show when verts connected to - * this edge via a face are being transformed */ - BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) || - BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) || - BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) || - BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT) - ))) - { - float v1_clip[3], v2_clip[3]; - - copy_v3_v3(v1, eed->v1->co); - copy_v3_v3(v2, eed->v2->co); - - if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { - float no_a[3], no_b[3]; - float angle; - - mid_v3_v3v3(vmid, v1_clip, v2_clip); - mul_m4_v3(ob->obmat, vmid); - - copy_v3_v3(no_a, l_a->f->no); - copy_v3_v3(no_b, l_b->f->no); - - if (do_global) { - mul_mat3_m4_v3(ob->imat, no_a); - mul_mat3_m4_v3(ob->imat, no_b); - normalize_v3(no_a); - normalize_v3(no_b); - } - - angle = angle_normalized_v3v3(no_a, no_b); - - numstr_len = BLI_snprintf_rlen( - numstr, sizeof(numstr), "%.3f%s", (is_rad) ? angle : RAD2DEGF(angle), - (is_rad) ? "r" : "°"); - - DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, - (do_edge_textpair) ? -edge_texpair_sep : 0, - txt_flag, col); - } - } - } - } - } - - if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_AREA) { - /* would be nice to use BM_face_calc_area, but that is for 2d faces - * so instead add up tessellation triangle areas */ - - UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); - - int i, n, numtri; - BMFace *f = NULL; - BM_ITER_MESH_INDEX(f, &iter, em->bm, BM_FACES_OF_MESH, i) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - n = 0; - numtri = f->len - 2; - area = 0; - zero_v3(vmid); - BMLoop *(*l)[3] = &em->looptris[poly_to_tri_count(i, BM_elem_index_get(f->l_first))]; - for (int j = 0; j < numtri; j++) { - copy_v3_v3(v1, l[j][0]->v->co); - copy_v3_v3(v2, l[j][1]->v->co); - copy_v3_v3(v3, l[j][2]->v->co); - - add_v3_v3(vmid, v1); - add_v3_v3(vmid, v2); - add_v3_v3(vmid, v3); - n += 3; - - if (do_global) { - mul_mat3_m4_v3(ob->obmat, v1); - mul_mat3_m4_v3(ob->obmat, v2); - mul_mat3_m4_v3(ob->obmat, v3); - } - - area += area_tri_v3(v1, v2, v3); - } - - mul_v3_fl(vmid, 1.0f / (float)n); - mul_m4_v3(ob->obmat, vmid); - - if (unit->system) { - numstr_len = bUnit_AsString2( - numstr, sizeof(numstr), - (double)(area * unit->scale_length * unit->scale_length), - 3, B_UNIT_AREA, unit, false); - } - else { - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); - } - - DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, 0, txt_flag, col); - } - } - } - - if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_ANG) { - BMFace *efa; - const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS); - - UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT); - - if (is_face_sel || do_moving) { - BMIter liter; - BMLoop *loop; - bool is_first = true; - - BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) { - if (is_face_sel || - (do_moving && - (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) || - BM_elem_flag_test(loop->prev->v, BM_ELEM_SELECT) || - BM_elem_flag_test(loop->next->v, BM_ELEM_SELECT)))) - { - float v2_local[3]; - - /* lazy init center calc */ - if (is_first) { - BM_face_calc_center_bounds(efa, vmid); - is_first = false; - } - copy_v3_v3(v1, loop->prev->v->co); - copy_v3_v3(v2, loop->v->co); - copy_v3_v3(v3, loop->next->v->co); - - copy_v3_v3(v2_local, v2); - - if (do_global) { - mul_mat3_m4_v3(ob->obmat, v1); - mul_mat3_m4_v3(ob->obmat, v2); - mul_mat3_m4_v3(ob->obmat, v3); - } - - float angle = angle_v3v3v3(v1, v2, v3); - - numstr_len = BLI_snprintf_rlen( - numstr, sizeof(numstr), "%.3f%s", (is_rad) ? angle : RAD2DEGF(angle), - (is_rad) ? "r" : "°"); - interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); - mul_m4_v3(ob->obmat, fvec); - DRW_text_cache_add(dt, fvec, numstr, numstr_len, 0, 0, txt_flag, col); - } - } - } - } - } - - /* This option is for mesh ops and addons debugging; only available in UI if Blender starts with --debug */ - if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_INDICES) { - int i; - - /* For now, reuse an appropriate theme color */ - UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); - - if (em->selectmode & SCE_SELECT_VERTEX) { - BMVert *v; - - BM_ITER_MESH_INDEX(v, &iter, em->bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - float vec[3]; - mul_v3_m4v3(vec, ob->obmat, v->co); - - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); - DRW_text_cache_add(dt, vec, numstr, numstr_len, 0, 0, txt_flag, col); - } - } - } - - if (em->selectmode & SCE_SELECT_EDGE) { - BMEdge *e; - - BM_ITER_MESH_INDEX(e, &iter, em->bm, BM_EDGES_OF_MESH, i) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - float v1_clip[3], v2_clip[3]; - - copy_v3_v3(v1, e->v1->co); - copy_v3_v3(v2, e->v2->co); - - if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { - mid_v3_v3v3(vmid, v1_clip, v2_clip); - mul_m4_v3(ob->obmat, vmid); - - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); - DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, 0, txt_flag, col); - } - } - } - } - - if (em->selectmode & SCE_SELECT_FACE) { - BMFace *f; - - BM_ITER_MESH_INDEX(f, &iter, em->bm, BM_FACES_OF_MESH, i) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_face_calc_center_median(f, v1); - mul_m4_v3(ob->obmat, v1); - - numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); - DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, 0, txt_flag, col); - } - } - } - } + /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.). + * See bug #36090. + */ + struct DRWTextStore *dt = DRW_text_cache_ensure(); + const short txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | (unit->system ? 0 : DRW_TEXT_CACHE_ASCII); + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + float v1[3], v2[3], v3[3], vmid[3], fvec[3]; + char numstr[32]; /* Stores the measurement display text here */ + size_t numstr_len; + const char *conv_float; /* Use a float conversion matching the grid size */ + uchar col[4] = {0, 0, 0, 255}; /* color of the text to draw */ + float area; /* area of the face */ + float grid = unit->system ? unit->scale_length : v3d->grid; + const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0; + const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0; + /* when 2 edge-info options are enabled, space apart */ + const bool do_edge_textpair = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_LEN) && + (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_ANG); + const short edge_texpair_sep = (short)(5.0f * U.ui_scale); + float clip_planes[4][4]; + /* allow for displaying shape keys and deform mods */ + BMIter iter; + + /* make the precision of the display value proportionate to the gridsize */ + + if (grid <= 0.01f) { + conv_float = "%.6g"; + } + else if (grid <= 0.1f) { + conv_float = "%.5g"; + } + else if (grid <= 1.0f) { + conv_float = "%.4g"; + } + else if (grid <= 10.0f) { + conv_float = "%.3g"; + } + else { + conv_float = "%.2g"; + } + + if (v3d->overlay.edit_flag & + (V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)) { + BoundBox bb; + const rcti rect = {0, ar->winx, 0, ar->winy}; + + ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect); + } + + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_LEN) { + BMEdge *eed; + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + /* draw selected edges, or edges next to selected verts while dragging */ + if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || + (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || + BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)))) { + float v1_clip[3], v2_clip[3]; + + copy_v3_v3(v1, eed->v1->co); + copy_v3_v3(v2, eed->v2->co); + + if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { + + mid_v3_v3v3(vmid, v1_clip, v2_clip); + mul_m4_v3(ob->obmat, vmid); + + if (do_global) { + mul_mat3_m4_v3(ob->obmat, v1); + mul_mat3_m4_v3(ob->obmat, v2); + } + + if (unit->system) { + numstr_len = bUnit_AsString2(numstr, + sizeof(numstr), + len_v3v3(v1, v2) * unit->scale_length, + 3, + B_UNIT_LENGTH, + unit, + false); + } + else { + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); + } + + DRW_text_cache_add(dt, + vmid, + numstr, + numstr_len, + 0, + (do_edge_textpair) ? edge_texpair_sep : 0, + txt_flag, + col); + } + } + } + } + + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_ANG) { + const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS); + BMEdge *eed; + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col); + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(eed, &l_a, &l_b)) { + /* draw selected edges, or edges next to selected verts while dragging */ + if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || + (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || + BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) || + /* special case, this is useful to show when verts connected to + * this edge via a face are being transformed */ + BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) || + BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) || + BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) || + BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT)))) { + float v1_clip[3], v2_clip[3]; + + copy_v3_v3(v1, eed->v1->co); + copy_v3_v3(v2, eed->v2->co); + + if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { + float no_a[3], no_b[3]; + float angle; + + mid_v3_v3v3(vmid, v1_clip, v2_clip); + mul_m4_v3(ob->obmat, vmid); + + copy_v3_v3(no_a, l_a->f->no); + copy_v3_v3(no_b, l_b->f->no); + + if (do_global) { + mul_mat3_m4_v3(ob->imat, no_a); + mul_mat3_m4_v3(ob->imat, no_b); + normalize_v3(no_a); + normalize_v3(no_b); + } + + angle = angle_normalized_v3v3(no_a, no_b); + + numstr_len = BLI_snprintf_rlen(numstr, + sizeof(numstr), + "%.3f%s", + (is_rad) ? angle : RAD2DEGF(angle), + (is_rad) ? "r" : "°"); + + DRW_text_cache_add(dt, + vmid, + numstr, + numstr_len, + 0, + (do_edge_textpair) ? -edge_texpair_sep : 0, + txt_flag, + col); + } + } + } + } + } + + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_AREA) { + /* would be nice to use BM_face_calc_area, but that is for 2d faces + * so instead add up tessellation triangle areas */ + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); + + int i, n, numtri; + BMFace *f = NULL; + BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + n = 0; + numtri = f->len - 2; + area = 0; + zero_v3(vmid); + BMLoop *(*l)[3] = &em->looptris[poly_to_tri_count(i, BM_elem_index_get(f->l_first))]; + for (int j = 0; j < numtri; j++) { + copy_v3_v3(v1, l[j][0]->v->co); + copy_v3_v3(v2, l[j][1]->v->co); + copy_v3_v3(v3, l[j][2]->v->co); + + add_v3_v3(vmid, v1); + add_v3_v3(vmid, v2); + add_v3_v3(vmid, v3); + n += 3; + + if (do_global) { + mul_mat3_m4_v3(ob->obmat, v1); + mul_mat3_m4_v3(ob->obmat, v2); + mul_mat3_m4_v3(ob->obmat, v3); + } + + area += area_tri_v3(v1, v2, v3); + } + + mul_v3_fl(vmid, 1.0f / (float)n); + mul_m4_v3(ob->obmat, vmid); + + if (unit->system) { + numstr_len = bUnit_AsString2(numstr, + sizeof(numstr), + (double)(area * unit->scale_length * unit->scale_length), + 3, + B_UNIT_AREA, + unit, + false); + } + else { + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); + } + + DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, 0, txt_flag, col); + } + } + } + + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_ANG) { + BMFace *efa; + const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS); + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT); + + if (is_face_sel || do_moving) { + BMIter liter; + BMLoop *loop; + bool is_first = true; + + BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) { + if (is_face_sel || (do_moving && (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) || + BM_elem_flag_test(loop->prev->v, BM_ELEM_SELECT) || + BM_elem_flag_test(loop->next->v, BM_ELEM_SELECT)))) { + float v2_local[3]; + + /* lazy init center calc */ + if (is_first) { + BM_face_calc_center_bounds(efa, vmid); + is_first = false; + } + copy_v3_v3(v1, loop->prev->v->co); + copy_v3_v3(v2, loop->v->co); + copy_v3_v3(v3, loop->next->v->co); + + copy_v3_v3(v2_local, v2); + + if (do_global) { + mul_mat3_m4_v3(ob->obmat, v1); + mul_mat3_m4_v3(ob->obmat, v2); + mul_mat3_m4_v3(ob->obmat, v3); + } + + float angle = angle_v3v3v3(v1, v2, v3); + + numstr_len = BLI_snprintf_rlen(numstr, + sizeof(numstr), + "%.3f%s", + (is_rad) ? angle : RAD2DEGF(angle), + (is_rad) ? "r" : "°"); + interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); + mul_m4_v3(ob->obmat, fvec); + DRW_text_cache_add(dt, fvec, numstr, numstr_len, 0, 0, txt_flag, col); + } + } + } + } + } + + /* This option is for mesh ops and addons debugging; only available in UI if Blender starts with --debug */ + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_INDICES) { + int i; + + /* For now, reuse an appropriate theme color */ + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); + + if (em->selectmode & SCE_SELECT_VERTEX) { + BMVert *v; + + BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + float vec[3]; + mul_v3_m4v3(vec, ob->obmat, v->co); + + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); + DRW_text_cache_add(dt, vec, numstr, numstr_len, 0, 0, txt_flag, col); + } + } + } + + if (em->selectmode & SCE_SELECT_EDGE) { + BMEdge *e; + + BM_ITER_MESH_INDEX (e, &iter, em->bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + float v1_clip[3], v2_clip[3]; + + copy_v3_v3(v1, e->v1->co); + copy_v3_v3(v2, e->v2->co); + + if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { + mid_v3_v3v3(vmid, v1_clip, v2_clip); + mul_m4_v3(ob->obmat, vmid); + + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); + DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, 0, txt_flag, col); + } + } + } + } + + if (em->selectmode & SCE_SELECT_FACE) { + BMFace *f; + + BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_face_calc_center_median(f, v1); + mul_m4_v3(ob->obmat, v1); + + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); + DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, 0, txt_flag, col); + } + } + } + } } diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index 600b77f46bf..90c5676727f 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -42,177 +42,175 @@ * for EDIT_METABALL_PassList */ typedef struct EDIT_METABALL_PassList { - /* Declare all passes here and init them in - * EDIT_METABALL_cache_init(). - * Only contains (DRWPass *) */ - struct DRWPass *pass; + /* Declare all passes here and init them in + * EDIT_METABALL_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *pass; } EDIT_METABALL_PassList; typedef struct EDIT_METABALL_FramebufferList { - /* Contains all framebuffer objects needed by this engine. - * Only contains (GPUFrameBuffer *) */ - struct GPUFrameBuffer *fb; + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; } EDIT_METABALL_FramebufferList; typedef struct EDIT_METABALL_TextureList { - /* Contains all framebuffer textures / utility textures - * needed by this engine. Only viewport specific textures - * (not per object). Only contains (GPUTexture *) */ - struct GPUTexture *texture; + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; } EDIT_METABALL_TextureList; typedef struct EDIT_METABALL_StorageList { - /* Contains any other memory block that the engine needs. - * Only directly MEM_(m/c)allocN'ed blocks because they are - * free with MEM_freeN() when viewport is freed. - * (not per object) */ - // struct CustomStruct *block; - struct EDIT_METABALL_PrivateData *g_data; + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + // struct CustomStruct *block; + struct EDIT_METABALL_PrivateData *g_data; } EDIT_METABALL_StorageList; typedef struct EDIT_METABALL_Data { - /* Struct returned by DRW_viewport_engine_data_ensure. - * If you don't use one of these, just make it a (void *) */ - // void *fbl; - void *engine_type; /* Required */ - EDIT_METABALL_FramebufferList *fbl; - EDIT_METABALL_TextureList *txl; - EDIT_METABALL_PassList *psl; - EDIT_METABALL_StorageList *stl; + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_METABALL_FramebufferList *fbl; + EDIT_METABALL_TextureList *txl; + EDIT_METABALL_PassList *psl; + EDIT_METABALL_StorageList *stl; } EDIT_METABALL_Data; /* *********** STATIC *********** */ typedef struct EDIT_METABALL_PrivateData { - /* This keeps the references of the shading groups for - * easy access in EDIT_METABALL_cache_populate() */ - DRWShadingGroup *group; + /* This keeps the references of the shading groups for + * easy access in EDIT_METABALL_cache_populate() */ + DRWShadingGroup *group; } EDIT_METABALL_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ static void EDIT_METABALL_engine_init(void *UNUSED(vedata)) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); + } } /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void EDIT_METABALL_cache_init(void *vedata) { - EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; - EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - { - /* Create a pass */ - DRWState state = ( - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_BLEND | DRW_STATE_WIRE); - psl->pass = DRW_pass_create("My Pass", state); - - /* Create a shadingGroup using a function in draw_common.c or custom one */ - stl->g_data->group = shgroup_instance_mball_handles(psl->pass, draw_ctx->sh_cfg); - } + EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; + EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create a pass */ + DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); + psl->pass = DRW_pass_create("My Pass", state); + + /* Create a shadingGroup using a function in draw_common.c or custom one */ + stl->g_data->group = shgroup_instance_mball_handles(psl->pass, draw_ctx->sh_cfg); + } } /* Add geometry to shadingGroups. Execute for each objects */ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) { - //EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; - EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; - - if (ob->type == OB_MBALL) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - DRWShadingGroup *group = stl->g_data->group; - - if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { - MetaBall *mb = ob->data; - - const float *color; - const float col_radius[3] = {0.63, 0.19, 0.19}; /* 0x3030A0 */ - const float col_radius_select[3] = {0.94, 0.63, 0.63}; /* 0xA0A0F0 */ - const float col_stiffness[3] = {0.19, 0.63, 0.19}; /* 0x30A030 */ - const float col_stiffness_select[3] = {0.63, 0.94, 0.63}; /* 0xA0F0A0 */ - - const bool is_select = DRW_state_is_select(); - - float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */ - { - float scamat[3][3]; - copy_m3_m4(scamat, ob->obmat); - /* Get the normalized inverse matrix to extract only - * the scale of Scamat */ - float iscamat[3][3]; - invert_m3_m3(iscamat, scamat); - normalize_m3(iscamat); - mul_m3_m3_post(scamat, iscamat); - - copy_v3_v3(draw_scale_xform[0], scamat[0]); - copy_v3_v3(draw_scale_xform[1], scamat[1]); - copy_v3_v3(draw_scale_xform[2], scamat[2]); - } - - int select_id = ob->select_id; - for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next, select_id += 0x10000) { - float world_pos[3]; - mul_v3_m4v3(world_pos, ob->obmat, &ml->x); - draw_scale_xform[0][3] = world_pos[0]; - draw_scale_xform[1][3] = world_pos[1]; - draw_scale_xform[2][3] = world_pos[2]; - - float draw_stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2; - - if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) { - color = col_radius_select; - } - else { - color = col_radius; - } - - if (is_select) { - DRW_select_load_id(select_id | MBALLSEL_RADIUS); - } - - DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &ml->rad, color); - - if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) { - color = col_stiffness_select; - } - else { - color = col_stiffness; - } - - if (is_select) { - DRW_select_load_id(select_id | MBALLSEL_STIFF); - } - - DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &draw_stiffness_radius, color); - } - } - } + //EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; + EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; + + if (ob->type == OB_MBALL) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + DRWShadingGroup *group = stl->g_data->group; + + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { + MetaBall *mb = ob->data; + + const float *color; + const float col_radius[3] = {0.63, 0.19, 0.19}; /* 0x3030A0 */ + const float col_radius_select[3] = {0.94, 0.63, 0.63}; /* 0xA0A0F0 */ + const float col_stiffness[3] = {0.19, 0.63, 0.19}; /* 0x30A030 */ + const float col_stiffness_select[3] = {0.63, 0.94, 0.63}; /* 0xA0F0A0 */ + + const bool is_select = DRW_state_is_select(); + + float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */ + { + float scamat[3][3]; + copy_m3_m4(scamat, ob->obmat); + /* Get the normalized inverse matrix to extract only + * the scale of Scamat */ + float iscamat[3][3]; + invert_m3_m3(iscamat, scamat); + normalize_m3(iscamat); + mul_m3_m3_post(scamat, iscamat); + + copy_v3_v3(draw_scale_xform[0], scamat[0]); + copy_v3_v3(draw_scale_xform[1], scamat[1]); + copy_v3_v3(draw_scale_xform[2], scamat[2]); + } + + int select_id = ob->select_id; + for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next, select_id += 0x10000) { + float world_pos[3]; + mul_v3_m4v3(world_pos, ob->obmat, &ml->x); + draw_scale_xform[0][3] = world_pos[0]; + draw_scale_xform[1][3] = world_pos[1]; + draw_scale_xform[2][3] = world_pos[2]; + + float draw_stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2; + + if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) { + color = col_radius_select; + } + else { + color = col_radius; + } + + if (is_select) { + DRW_select_load_id(select_id | MBALLSEL_RADIUS); + } + + DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &ml->rad, color); + + if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) { + color = col_stiffness_select; + } + else { + color = col_stiffness; + } + + if (is_select) { + DRW_select_load_id(select_id | MBALLSEL_STIFF); + } + + DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &draw_stiffness_radius, color); + } + } + } } /* Draw time ! Control rendering pipeline from here */ static void EDIT_METABALL_draw_scene(void *vedata) { - EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; - /* render passes on default framebuffer. */ - DRW_draw_pass(psl->pass); + EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; + /* render passes on default framebuffer. */ + DRW_draw_pass(psl->pass); - /* If you changed framebuffer, double check you rebind - * the default one with its textures attached before finishing */ + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ - DRW_state_clip_planes_reset(); + DRW_state_clip_planes_reset(); } /* Cleanup when destroying the engine. @@ -220,22 +218,24 @@ static void EDIT_METABALL_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void EDIT_METABALL_engine_free(void) { - // DRW_SHADER_FREE_SAFE(custom_shader); + // DRW_SHADER_FREE_SAFE(custom_shader); } -static const DrawEngineDataSize EDIT_METABALL_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_METABALL_Data); +static const DrawEngineDataSize EDIT_METABALL_data_size = DRW_VIEWPORT_DATA_SIZE( + EDIT_METABALL_Data); DrawEngineType draw_engine_edit_metaball_type = { - NULL, NULL, - N_("EditMetaballMode"), - &EDIT_METABALL_data_size, - &EDIT_METABALL_engine_init, - &EDIT_METABALL_engine_free, - &EDIT_METABALL_cache_init, - &EDIT_METABALL_cache_populate, - NULL, - NULL, /* draw_background but not needed by mode engines */ - &EDIT_METABALL_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("EditMetaballMode"), + &EDIT_METABALL_data_size, + &EDIT_METABALL_engine_init, + &EDIT_METABALL_engine_free, + &EDIT_METABALL_cache_init, + &EDIT_METABALL_cache_populate, + NULL, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_METABALL_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c index caebc94f3ce..5f44a74b24e 100644 --- a/source/blender/draw/modes/edit_text_mode.c +++ b/source/blender/draw/modes/edit_text_mode.c @@ -43,67 +43,67 @@ * for EDIT_TEXT_PassList */ typedef struct EDIT_TEXT_PassList { - /* Declare all passes here and init them in - * EDIT_TEXT_cache_init(). - * Only contains (DRWPass *) */ - struct DRWPass *wire_pass; - struct DRWPass *overlay_select_pass; - struct DRWPass *overlay_cursor_pass; - struct DRWPass *text_box_pass; + /* Declare all passes here and init them in + * EDIT_TEXT_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *wire_pass; + struct DRWPass *overlay_select_pass; + struct DRWPass *overlay_cursor_pass; + struct DRWPass *text_box_pass; } EDIT_TEXT_PassList; typedef struct EDIT_TEXT_FramebufferList { - /* Contains all framebuffer objects needed by this engine. - * Only contains (GPUFrameBuffer *) */ - struct GPUFrameBuffer *fb; + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; } EDIT_TEXT_FramebufferList; typedef struct EDIT_TEXT_TextureList { - /* Contains all framebuffer textures / utility textures - * needed by this engine. Only viewport specific textures - * (not per object). Only contains (GPUTexture *) */ - struct GPUTexture *texture; + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; } EDIT_TEXT_TextureList; typedef struct EDIT_TEXT_StorageList { - /* Contains any other memory block that the engine needs. - * Only directly MEM_(m/c)allocN'ed blocks because they are - * free with MEM_freeN() when viewport is freed. - * (not per object) */ - struct CustomStruct *block; - struct EDIT_TEXT_PrivateData *g_data; + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct EDIT_TEXT_PrivateData *g_data; } EDIT_TEXT_StorageList; typedef struct EDIT_TEXT_Data { - /* Struct returned by DRW_viewport_engine_data_ensure. - * If you don't use one of these, just make it a (void *) */ - // void *fbl; - void *engine_type; /* Required */ - EDIT_TEXT_FramebufferList *fbl; - EDIT_TEXT_TextureList *txl; - EDIT_TEXT_PassList *psl; - EDIT_TEXT_StorageList *stl; + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_TEXT_FramebufferList *fbl; + EDIT_TEXT_TextureList *txl; + EDIT_TEXT_PassList *psl; + EDIT_TEXT_StorageList *stl; } EDIT_TEXT_Data; /* *********** STATIC *********** */ static struct { - /* Custom shaders : - * Add sources to source/blender/draw/modes/shaders - * init in EDIT_TEXT_engine_init(); - * free in EDIT_TEXT_engine_free(); */ - GPUShader *wire_sh; - GPUShader *overlay_select_sh; - GPUShader *overlay_cursor_sh; + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in EDIT_TEXT_engine_init(); + * free in EDIT_TEXT_engine_free(); */ + GPUShader *wire_sh; + GPUShader *overlay_select_sh; + GPUShader *overlay_cursor_sh; } e_data = {NULL}; /* Engine data */ typedef struct EDIT_TEXT_PrivateData { - /* resulting curve as 'wire' for fast editmode drawing */ - DRWShadingGroup *wire_shgrp; - DRWShadingGroup *overlay_select_shgrp; - DRWShadingGroup *overlay_cursor_shgrp; - DRWShadingGroup *box_shgrp; - DRWShadingGroup *box_active_shgrp; + /* resulting curve as 'wire' for fast editmode drawing */ + DRWShadingGroup *wire_shgrp; + DRWShadingGroup *overlay_select_shgrp; + DRWShadingGroup *overlay_cursor_shgrp; + DRWShadingGroup *box_shgrp; + DRWShadingGroup *box_active_shgrp; } EDIT_TEXT_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -113,285 +113,285 @@ typedef struct EDIT_TEXT_PrivateData { * (Optional) */ static void EDIT_TEXT_engine_init(void *vedata) { - EDIT_TEXT_TextureList *txl = ((EDIT_TEXT_Data *)vedata)->txl; - EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - - UNUSED_VARS(txl, fbl, stl); - - /* Init Framebuffers like this: order is attachment order (for color texs) */ - /* - * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, - * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; - */ - - /* DRW_framebuffer_init takes care of checking if - * the framebuffer is valid and has the right size*/ - /* - * float *viewport_size = DRW_viewport_size_get(); - * DRW_framebuffer_init(&fbl->occlude_wire_fb, - * (int)viewport_size[0], (int)viewport_size[1], - * tex, 2); - */ - - if (!e_data.wire_sh) { - e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - } - - if (!e_data.overlay_select_sh) { - e_data.overlay_select_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - } - - if (!e_data.overlay_cursor_sh) { - e_data.overlay_cursor_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - } + EDIT_TEXT_TextureList *txl = ((EDIT_TEXT_Data *)vedata)->txl; + EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.wire_sh) { + e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (!e_data.overlay_select_sh) { + e_data.overlay_select_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (!e_data.overlay_cursor_sh) { + e_data.overlay_cursor_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } } /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void EDIT_TEXT_cache_init(void *vedata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - { - /* Text outline (fast drawing!) */ - psl->wire_pass = DRW_pass_create( - "Font Wire", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); - stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass); - - psl->overlay_select_pass = DRW_pass_create( - "Font Select", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); - stl->g_data->overlay_select_shgrp = DRW_shgroup_create(e_data.overlay_select_sh, psl->overlay_select_pass); - - psl->overlay_cursor_pass = DRW_pass_create( - "Font Cursor", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); - stl->g_data->overlay_cursor_shgrp = DRW_shgroup_create(e_data.overlay_cursor_sh, psl->overlay_cursor_pass); - - psl->text_box_pass = DRW_pass_create( - "Font Text Boxes", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); - stl->g_data->box_shgrp = shgroup_dynlines_dashed_uniform_color(psl->text_box_pass, G_draw.block.colorWire, draw_ctx->sh_cfg); - stl->g_data->box_active_shgrp = shgroup_dynlines_dashed_uniform_color(psl->text_box_pass, G_draw.block.colorActive, draw_ctx->sh_cfg); - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Text outline (fast drawing!) */ + psl->wire_pass = DRW_pass_create("Font Wire", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass); + + psl->overlay_select_pass = DRW_pass_create("Font Select", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); + stl->g_data->overlay_select_shgrp = DRW_shgroup_create(e_data.overlay_select_sh, + psl->overlay_select_pass); + + psl->overlay_cursor_pass = DRW_pass_create("Font Cursor", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); + stl->g_data->overlay_cursor_shgrp = DRW_shgroup_create(e_data.overlay_cursor_sh, + psl->overlay_cursor_pass); + + psl->text_box_pass = DRW_pass_create("Font Text Boxes", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); + stl->g_data->box_shgrp = shgroup_dynlines_dashed_uniform_color( + psl->text_box_pass, G_draw.block.colorWire, draw_ctx->sh_cfg); + stl->g_data->box_active_shgrp = shgroup_dynlines_dashed_uniform_color( + psl->text_box_pass, G_draw.block.colorActive, draw_ctx->sh_cfg); + } } /* Use 2D quad corners to create a matrix that set * a [-1..1] quad at the right position. */ static void v2_quad_corners_to_mat4(float corners[4][2], float r_mat[4][4]) { - unit_m4(r_mat); - sub_v2_v2v2(r_mat[0], corners[1], corners[0]); - sub_v2_v2v2(r_mat[1], corners[3], corners[0]); - mul_v2_fl(r_mat[0], 0.5f); - mul_v2_fl(r_mat[1], 0.5f); - copy_v2_v2(r_mat[3], corners[0]); - add_v2_v2(r_mat[3], r_mat[0]); - add_v2_v2(r_mat[3], r_mat[1]); + unit_m4(r_mat); + sub_v2_v2v2(r_mat[0], corners[1], corners[0]); + sub_v2_v2v2(r_mat[1], corners[3], corners[0]); + mul_v2_fl(r_mat[0], 0.5f); + mul_v2_fl(r_mat[1], 0.5f); + copy_v2_v2(r_mat[3], corners[0]); + add_v2_v2(r_mat[3], r_mat[0]); + add_v2_v2(r_mat[3], r_mat[1]); } static void edit_text_cache_populate_select(void *vedata, Object *ob) { - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - const Curve *cu = ob->data; - EditFont *ef = cu->editfont; - float final_mat[4][4], box[4][2]; - struct GPUBatch *geom = DRW_cache_quad_get(); - - for (int i = 0; i < ef->selboxes_len; i++) { - EditFontSelBox *sb = &ef->selboxes[i]; - - float selboxw; - if (i + 1 != ef->selboxes_len) { - if (ef->selboxes[i + 1].y == sb->y) { - selboxw = ef->selboxes[i + 1].x - sb->x; - } - else { - selboxw = sb->w; - } - } - else { - selboxw = sb->w; - } - /* NOTE: v2_quad_corners_to_mat4 don't need the 3rd corner. */ - if (sb->rot == 0.0f) { - copy_v2_fl2(box[0], sb->x, sb->y); - copy_v2_fl2(box[1], sb->x + selboxw, sb->y); - copy_v2_fl2(box[3], sb->x, sb->y + sb->h); - } - else { - float mat[2][2]; - angle_to_mat2(mat, sb->rot); - copy_v2_fl2(box[0], sb->x, sb->y); - mul_v2_v2fl(box[1], mat[0], selboxw); - add_v2_v2(box[1], &sb->x); - mul_v2_v2fl(box[3], mat[1], sb->h); - add_v2_v2(box[3], &sb->x); - } - v2_quad_corners_to_mat4(box, final_mat); - mul_m4_m4m4(final_mat, ob->obmat, final_mat); - - DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, final_mat); - } + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + const Curve *cu = ob->data; + EditFont *ef = cu->editfont; + float final_mat[4][4], box[4][2]; + struct GPUBatch *geom = DRW_cache_quad_get(); + + for (int i = 0; i < ef->selboxes_len; i++) { + EditFontSelBox *sb = &ef->selboxes[i]; + + float selboxw; + if (i + 1 != ef->selboxes_len) { + if (ef->selboxes[i + 1].y == sb->y) { + selboxw = ef->selboxes[i + 1].x - sb->x; + } + else { + selboxw = sb->w; + } + } + else { + selboxw = sb->w; + } + /* NOTE: v2_quad_corners_to_mat4 don't need the 3rd corner. */ + if (sb->rot == 0.0f) { + copy_v2_fl2(box[0], sb->x, sb->y); + copy_v2_fl2(box[1], sb->x + selboxw, sb->y); + copy_v2_fl2(box[3], sb->x, sb->y + sb->h); + } + else { + float mat[2][2]; + angle_to_mat2(mat, sb->rot); + copy_v2_fl2(box[0], sb->x, sb->y); + mul_v2_v2fl(box[1], mat[0], selboxw); + add_v2_v2(box[1], &sb->x); + mul_v2_v2fl(box[3], mat[1], sb->h); + add_v2_v2(box[3], &sb->x); + } + v2_quad_corners_to_mat4(box, final_mat); + mul_m4_m4m4(final_mat, ob->obmat, final_mat); + + DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, final_mat); + } } static void edit_text_cache_populate_cursor(void *vedata, Object *ob) { - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - const Curve *cu = ob->data; - EditFont *edit_font = cu->editfont; - float (*cursor)[2] = edit_font->textcurs; - float mat[4][4]; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + const Curve *cu = ob->data; + EditFont *edit_font = cu->editfont; + float(*cursor)[2] = edit_font->textcurs; + float mat[4][4]; - v2_quad_corners_to_mat4(cursor, mat); - mul_m4_m4m4(mat, ob->obmat, mat); + v2_quad_corners_to_mat4(cursor, mat); + mul_m4_m4m4(mat, ob->obmat, mat); - struct GPUBatch *geom = DRW_cache_quad_get(); - DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, mat); + struct GPUBatch *geom = DRW_cache_quad_get(); + DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, mat); } static void edit_text_cache_populate_boxes(void *vedata, Object *ob) { - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - const Curve *cu = ob->data; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + const Curve *cu = ob->data; - DRWShadingGroup *shading_groups[] = { - stl->g_data->box_active_shgrp, - stl->g_data->box_shgrp, - }; + DRWShadingGroup *shading_groups[] = { + stl->g_data->box_active_shgrp, + stl->g_data->box_shgrp, + }; - float vec[3], vec1[3], vec2[3]; - for (int i = 0; i < cu->totbox; i++) { - TextBox *tb = &cu->tb[i]; + float vec[3], vec1[3], vec2[3]; + for (int i = 0; i < cu->totbox; i++) { + TextBox *tb = &cu->tb[i]; - if ((tb->w == 0.0f) && (tb->h == 0.0f)) { - continue; - } + if ((tb->w == 0.0f) && (tb->h == 0.0f)) { + continue; + } - const bool is_active = i == (cu->actbox - 1); - DRWShadingGroup *shading_group = shading_groups[is_active ? 0 : 1]; + const bool is_active = i == (cu->actbox - 1); + DRWShadingGroup *shading_group = shading_groups[is_active ? 0 : 1]; - vec[0] = cu->xof + tb->x; - vec[1] = cu->yof + tb->y + cu->fsize_realtime; - vec[2] = 0.001; + vec[0] = cu->xof + tb->x; + vec[1] = cu->yof + tb->y + cu->fsize_realtime; + vec[2] = 0.001; - mul_v3_m4v3(vec1, ob->obmat, vec); - vec[0] += tb->w; - mul_v3_m4v3(vec2, ob->obmat, vec); + mul_v3_m4v3(vec1, ob->obmat, vec); + vec[0] += tb->w; + mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_shgroup_call_dynamic_add(shading_group, vec1); + DRW_shgroup_call_dynamic_add(shading_group, vec2); - vec[1] -= tb->h; - copy_v3_v3(vec1, vec2); - mul_v3_m4v3(vec2, ob->obmat, vec); + vec[1] -= tb->h; + copy_v3_v3(vec1, vec2); + mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_shgroup_call_dynamic_add(shading_group, vec1); + DRW_shgroup_call_dynamic_add(shading_group, vec2); - vec[0] -= tb->w; - copy_v3_v3(vec1, vec2); - mul_v3_m4v3(vec2, ob->obmat, vec); + vec[0] -= tb->w; + copy_v3_v3(vec1, vec2); + mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_shgroup_call_dynamic_add(shading_group, vec1); + DRW_shgroup_call_dynamic_add(shading_group, vec2); - vec[1] += tb->h; - copy_v3_v3(vec1, vec2); - mul_v3_m4v3(vec2, ob->obmat, vec); + vec[1] += tb->h; + copy_v3_v3(vec1, vec2); + mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); - } + DRW_shgroup_call_dynamic_add(shading_group, vec1); + DRW_shgroup_call_dynamic_add(shading_group, vec2); + } } /* Add geometry to shadingGroups. Execute for each objects */ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob) { - EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - UNUSED_VARS(psl, stl); - - if (ob->type == OB_FONT) { - if (ob == draw_ctx->object_edit) { - const Curve *cu = ob->data; - /* Get geometry cache */ - struct GPUBatch *geom; - - bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; - if ((cu->flag & CU_FAST) || !has_surface) { - geom = DRW_cache_text_edge_wire_get(ob); - if (geom) { - DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); - } - } - else { - /* object mode draws */ - } - - edit_text_cache_populate_select(vedata, ob); - edit_text_cache_populate_cursor(vedata, ob); - edit_text_cache_populate_boxes(vedata, ob); - } - } + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + UNUSED_VARS(psl, stl); + + if (ob->type == OB_FONT) { + if (ob == draw_ctx->object_edit) { + const Curve *cu = ob->data; + /* Get geometry cache */ + struct GPUBatch *geom; + + bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; + if ((cu->flag & CU_FAST) || !has_surface) { + geom = DRW_cache_text_edge_wire_get(ob); + if (geom) { + DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + } + } + else { + /* object mode draws */ + } + + edit_text_cache_populate_select(vedata, ob); + edit_text_cache_populate_cursor(vedata, ob); + edit_text_cache_populate_boxes(vedata, ob); + } + } } /* Optional: Post-cache_populate callback */ static void EDIT_TEXT_cache_finish(void *vedata) { - EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; - EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; - /* Do something here! dependent on the objects gathered */ - UNUSED_VARS(psl, stl); + /* Do something here! dependent on the objects gathered */ + UNUSED_VARS(psl, stl); } /* Draw time ! Control rendering pipeline from here */ static void EDIT_TEXT_draw_scene(void *vedata) { - EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; - EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; - /* Default framebuffer and texture */ - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - UNUSED_VARS(fbl, dfbl, dtxl); + UNUSED_VARS(fbl, dfbl, dtxl); - /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ - /* - * DRW_framebuffer_texture_detach(dtxl->depth); - * DRW_framebuffer_bind(fbl->custom_fb); - * DRW_draw_pass(psl->pass); - * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); - * DRW_framebuffer_bind(dfbl->default_fb); - */ + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ - DRW_draw_pass(psl->wire_pass); + DRW_draw_pass(psl->wire_pass); - if (!DRW_pass_is_empty(psl->text_box_pass)) { - DRW_draw_pass(psl->text_box_pass); - } + if (!DRW_pass_is_empty(psl->text_box_pass)) { + DRW_draw_pass(psl->text_box_pass); + } - set_inverted_drawing(1); - DRW_draw_pass(psl->overlay_select_pass); - DRW_draw_pass(psl->overlay_cursor_pass); - set_inverted_drawing(0); + set_inverted_drawing(1); + DRW_draw_pass(psl->overlay_select_pass); + DRW_draw_pass(psl->overlay_cursor_pass); + set_inverted_drawing(0); - /* If you changed framebuffer, double check you rebind - * the default one with its textures attached before finishing */ + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ } /* Cleanup when destroying the engine. @@ -399,22 +399,23 @@ static void EDIT_TEXT_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void EDIT_TEXT_engine_free(void) { - // DRW_SHADER_FREE_SAFE(custom_shader); + // DRW_SHADER_FREE_SAFE(custom_shader); } static const DrawEngineDataSize EDIT_TEXT_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_TEXT_Data); DrawEngineType draw_engine_edit_text_type = { - NULL, NULL, - N_("EditTextMode"), - &EDIT_TEXT_data_size, - &EDIT_TEXT_engine_init, - &EDIT_TEXT_engine_free, - &EDIT_TEXT_cache_init, - &EDIT_TEXT_cache_populate, - &EDIT_TEXT_cache_finish, - NULL, /* draw_background but not needed by mode engines */ - &EDIT_TEXT_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("EditTextMode"), + &EDIT_TEXT_data_size, + &EDIT_TEXT_engine_init, + &EDIT_TEXT_engine_free, + &EDIT_TEXT_cache_init, + &EDIT_TEXT_cache_populate, + &EDIT_TEXT_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_TEXT_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 7b6519a6863..ec49b4dbe51 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -95,3339 +95,3464 @@ extern char datatoc_gpu_shader_3D_vert_glsl[]; /* *********** LISTS *********** */ typedef struct OBJECT_PassList { - struct DRWPass *non_meshes[2]; - struct DRWPass *image_empties[2]; - struct DRWPass *transp_shapes[2]; - struct DRWPass *ob_center; - struct DRWPass *outlines; - struct DRWPass *outlines_search; - struct DRWPass *outlines_expand; - struct DRWPass *outlines_bleed; - struct DRWPass *outlines_resolve; - struct DRWPass *grid; - struct DRWPass *bone_solid[2]; - struct DRWPass *bone_outline[2]; - struct DRWPass *bone_wire[2]; - struct DRWPass *bone_envelope[2]; - struct DRWPass *bone_axes[2]; - struct DRWPass *particle; - struct DRWPass *lightprobes; + struct DRWPass *non_meshes[2]; + struct DRWPass *image_empties[2]; + struct DRWPass *transp_shapes[2]; + struct DRWPass *ob_center; + struct DRWPass *outlines; + struct DRWPass *outlines_search; + struct DRWPass *outlines_expand; + struct DRWPass *outlines_bleed; + struct DRWPass *outlines_resolve; + struct DRWPass *grid; + struct DRWPass *bone_solid[2]; + struct DRWPass *bone_outline[2]; + struct DRWPass *bone_wire[2]; + struct DRWPass *bone_envelope[2]; + struct DRWPass *bone_axes[2]; + struct DRWPass *particle; + struct DRWPass *lightprobes; } OBJECT_PassList; typedef struct OBJECT_FramebufferList { - struct GPUFrameBuffer *outlines_fb; - struct GPUFrameBuffer *blur_fb; - struct GPUFrameBuffer *expand_fb; - struct GPUFrameBuffer *ghost_fb; + struct GPUFrameBuffer *outlines_fb; + struct GPUFrameBuffer *blur_fb; + struct GPUFrameBuffer *expand_fb; + struct GPUFrameBuffer *ghost_fb; } OBJECT_FramebufferList; typedef struct OBJECT_StorageList { - struct OBJECT_PrivateData *g_data; + struct OBJECT_PrivateData *g_data; } OBJECT_StorageList; typedef struct OBJECT_Data { - void *engine_type; - OBJECT_FramebufferList *fbl; - DRWViewportEmptyList *txl; - OBJECT_PassList *psl; - OBJECT_StorageList *stl; + void *engine_type; + OBJECT_FramebufferList *fbl; + DRWViewportEmptyList *txl; + OBJECT_PassList *psl; + OBJECT_StorageList *stl; } OBJECT_Data; typedef struct OBJECT_Shaders { - /* fullscreen shaders */ - GPUShader *outline_prepass; - GPUShader *outline_prepass_wire; - GPUShader *outline_resolve; - GPUShader *outline_resolve_aa; - GPUShader *outline_detect; - GPUShader *outline_detect_wire; - GPUShader *outline_fade; - GPUShader *outline_fade_large; - - /* regular shaders */ - GPUShader *object_empty_image; - GPUShader *object_empty_image_wire; - GPUShader *grid; - GPUShader *part_dot; - GPUShader *part_prim; - GPUShader *part_axis; - GPUShader *lightprobe_grid; - GPUShader *loose_points; + /* fullscreen shaders */ + GPUShader *outline_prepass; + GPUShader *outline_prepass_wire; + GPUShader *outline_resolve; + GPUShader *outline_resolve_aa; + GPUShader *outline_detect; + GPUShader *outline_detect_wire; + GPUShader *outline_fade; + GPUShader *outline_fade_large; + + /* regular shaders */ + GPUShader *object_empty_image; + GPUShader *object_empty_image_wire; + GPUShader *grid; + GPUShader *part_dot; + GPUShader *part_prim; + GPUShader *part_axis; + GPUShader *lightprobe_grid; + GPUShader *loose_points; } OBJECT_Shaders; /* *********** STATIC *********** */ typedef struct OBJECT_ShadingGroupList { - /* Reference only */ - struct DRWPass *non_meshes; - struct DRWPass *image_empties; - struct DRWPass *transp_shapes; - struct DRWPass *bone_solid; - struct DRWPass *bone_outline; - struct DRWPass *bone_wire; - struct DRWPass *bone_envelope; - struct DRWPass *bone_axes; - - /* Empties */ - DRWShadingGroup *plain_axes; - DRWShadingGroup *cube; - DRWShadingGroup *circle; - DRWShadingGroup *sphere; - DRWShadingGroup *sphere_solid; - DRWShadingGroup *cylinder; - DRWShadingGroup *capsule_cap; - DRWShadingGroup *capsule_body; - DRWShadingGroup *cone; - DRWShadingGroup *single_arrow; - DRWShadingGroup *single_arrow_line; - DRWShadingGroup *empty_axes; - - /* Force Field */ - DRWShadingGroup *field_wind; - DRWShadingGroup *field_force; - DRWShadingGroup *field_vortex; - DRWShadingGroup *field_curve_sta; - DRWShadingGroup *field_curve_end; - DRWShadingGroup *field_tube_limit; - DRWShadingGroup *field_cone_limit; - - /* Grease Pencil */ - DRWShadingGroup *gpencil_axes; - - /* Speaker */ - DRWShadingGroup *speaker; - - /* Probe */ - DRWShadingGroup *probe_cube; - DRWShadingGroup *probe_planar; - DRWShadingGroup *probe_grid; - - /* MetaBalls */ - DRWShadingGroup *mball_handle; - - /* Lights */ - DRWShadingGroup *light_center; - DRWShadingGroup *light_groundpoint; - DRWShadingGroup *light_groundline; - DRWShadingGroup *light_circle; - DRWShadingGroup *light_circle_shadow; - DRWShadingGroup *light_sunrays; - DRWShadingGroup *light_distance; - DRWShadingGroup *light_buflimit; - DRWShadingGroup *light_buflimit_points; - DRWShadingGroup *light_area_sphere; - DRWShadingGroup *light_area_square; - DRWShadingGroup *light_area_disk; - DRWShadingGroup *light_hemi; - DRWShadingGroup *light_spot_cone; - DRWShadingGroup *light_spot_blend; - DRWShadingGroup *light_spot_pyramid; - DRWShadingGroup *light_spot_blend_rect; - DRWShadingGroup *light_spot_volume; - DRWShadingGroup *light_spot_volume_rect; - DRWShadingGroup *light_spot_volume_outside; - DRWShadingGroup *light_spot_volume_rect_outside; - - /* Helpers */ - DRWShadingGroup *relationship_lines; - DRWShadingGroup *constraint_lines; - - /* Camera */ - DRWShadingGroup *camera; - DRWShadingGroup *camera_frame; - DRWShadingGroup *camera_tria; - DRWShadingGroup *camera_focus; - DRWShadingGroup *camera_clip; - DRWShadingGroup *camera_clip_points; - DRWShadingGroup *camera_mist; - DRWShadingGroup *camera_mist_points; - DRWShadingGroup *camera_stereo_plane; - DRWShadingGroup *camera_stereo_plane_wires; - DRWShadingGroup *camera_stereo_volume; - DRWShadingGroup *camera_stereo_volume_wires; - ListBase camera_path; - - /* Wire */ - DRWShadingGroup *wire; - DRWShadingGroup *wire_active; - DRWShadingGroup *wire_select; - DRWShadingGroup *wire_transform; - /* Wire (duplicator) */ - DRWShadingGroup *wire_dupli; - DRWShadingGroup *wire_dupli_select; - - /* Points */ - DRWShadingGroup *points; - DRWShadingGroup *points_active; - DRWShadingGroup *points_select; - DRWShadingGroup *points_transform; - /* Points (duplicator) */ - DRWShadingGroup *points_dupli; - DRWShadingGroup *points_dupli_select; - - /* Texture Space */ - DRWShadingGroup *texspace; + /* Reference only */ + struct DRWPass *non_meshes; + struct DRWPass *image_empties; + struct DRWPass *transp_shapes; + struct DRWPass *bone_solid; + struct DRWPass *bone_outline; + struct DRWPass *bone_wire; + struct DRWPass *bone_envelope; + struct DRWPass *bone_axes; + + /* Empties */ + DRWShadingGroup *plain_axes; + DRWShadingGroup *cube; + DRWShadingGroup *circle; + DRWShadingGroup *sphere; + DRWShadingGroup *sphere_solid; + DRWShadingGroup *cylinder; + DRWShadingGroup *capsule_cap; + DRWShadingGroup *capsule_body; + DRWShadingGroup *cone; + DRWShadingGroup *single_arrow; + DRWShadingGroup *single_arrow_line; + DRWShadingGroup *empty_axes; + + /* Force Field */ + DRWShadingGroup *field_wind; + DRWShadingGroup *field_force; + DRWShadingGroup *field_vortex; + DRWShadingGroup *field_curve_sta; + DRWShadingGroup *field_curve_end; + DRWShadingGroup *field_tube_limit; + DRWShadingGroup *field_cone_limit; + + /* Grease Pencil */ + DRWShadingGroup *gpencil_axes; + + /* Speaker */ + DRWShadingGroup *speaker; + + /* Probe */ + DRWShadingGroup *probe_cube; + DRWShadingGroup *probe_planar; + DRWShadingGroup *probe_grid; + + /* MetaBalls */ + DRWShadingGroup *mball_handle; + + /* Lights */ + DRWShadingGroup *light_center; + DRWShadingGroup *light_groundpoint; + DRWShadingGroup *light_groundline; + DRWShadingGroup *light_circle; + DRWShadingGroup *light_circle_shadow; + DRWShadingGroup *light_sunrays; + DRWShadingGroup *light_distance; + DRWShadingGroup *light_buflimit; + DRWShadingGroup *light_buflimit_points; + DRWShadingGroup *light_area_sphere; + DRWShadingGroup *light_area_square; + DRWShadingGroup *light_area_disk; + DRWShadingGroup *light_hemi; + DRWShadingGroup *light_spot_cone; + DRWShadingGroup *light_spot_blend; + DRWShadingGroup *light_spot_pyramid; + DRWShadingGroup *light_spot_blend_rect; + DRWShadingGroup *light_spot_volume; + DRWShadingGroup *light_spot_volume_rect; + DRWShadingGroup *light_spot_volume_outside; + DRWShadingGroup *light_spot_volume_rect_outside; + + /* Helpers */ + DRWShadingGroup *relationship_lines; + DRWShadingGroup *constraint_lines; + + /* Camera */ + DRWShadingGroup *camera; + DRWShadingGroup *camera_frame; + DRWShadingGroup *camera_tria; + DRWShadingGroup *camera_focus; + DRWShadingGroup *camera_clip; + DRWShadingGroup *camera_clip_points; + DRWShadingGroup *camera_mist; + DRWShadingGroup *camera_mist_points; + DRWShadingGroup *camera_stereo_plane; + DRWShadingGroup *camera_stereo_plane_wires; + DRWShadingGroup *camera_stereo_volume; + DRWShadingGroup *camera_stereo_volume_wires; + ListBase camera_path; + + /* Wire */ + DRWShadingGroup *wire; + DRWShadingGroup *wire_active; + DRWShadingGroup *wire_select; + DRWShadingGroup *wire_transform; + /* Wire (duplicator) */ + DRWShadingGroup *wire_dupli; + DRWShadingGroup *wire_dupli_select; + + /* Points */ + DRWShadingGroup *points; + DRWShadingGroup *points_active; + DRWShadingGroup *points_select; + DRWShadingGroup *points_transform; + /* Points (duplicator) */ + DRWShadingGroup *points_dupli; + DRWShadingGroup *points_dupli_select; + + /* Texture Space */ + DRWShadingGroup *texspace; } OBJECT_ShadingGroupList; typedef struct OBJECT_PrivateData { - OBJECT_ShadingGroupList sgl; - OBJECT_ShadingGroupList sgl_ghost; - - /* Outlines */ - DRWShadingGroup *outlines_active; - DRWShadingGroup *outlines_select; - DRWShadingGroup *outlines_select_dupli; - DRWShadingGroup *outlines_transform; - - /* Lightprobes */ - DRWShadingGroup *lightprobes_cube_select; - DRWShadingGroup *lightprobes_cube_select_dupli; - DRWShadingGroup *lightprobes_cube_active; - DRWShadingGroup *lightprobes_cube_transform; - - DRWShadingGroup *lightprobes_planar_select; - DRWShadingGroup *lightprobes_planar_select_dupli; - DRWShadingGroup *lightprobes_planar_active; - DRWShadingGroup *lightprobes_planar_transform; - - /* Objects Centers */ - DRWShadingGroup *center_active; - DRWShadingGroup *center_selected; - DRWShadingGroup *center_deselected; - DRWShadingGroup *center_selected_lib; - DRWShadingGroup *center_deselected_lib; - - /* Outlines id offset (accessed as an array) */ - int id_ofs_active; - int id_ofs_select; - int id_ofs_select_dupli; - int id_ofs_transform; - - int id_ofs_prb_active; - int id_ofs_prb_select; - int id_ofs_prb_select_dupli; - int id_ofs_prb_transform; - - bool xray_enabled; - bool xray_enabled_and_not_wire; + OBJECT_ShadingGroupList sgl; + OBJECT_ShadingGroupList sgl_ghost; + + /* Outlines */ + DRWShadingGroup *outlines_active; + DRWShadingGroup *outlines_select; + DRWShadingGroup *outlines_select_dupli; + DRWShadingGroup *outlines_transform; + + /* Lightprobes */ + DRWShadingGroup *lightprobes_cube_select; + DRWShadingGroup *lightprobes_cube_select_dupli; + DRWShadingGroup *lightprobes_cube_active; + DRWShadingGroup *lightprobes_cube_transform; + + DRWShadingGroup *lightprobes_planar_select; + DRWShadingGroup *lightprobes_planar_select_dupli; + DRWShadingGroup *lightprobes_planar_active; + DRWShadingGroup *lightprobes_planar_transform; + + /* Objects Centers */ + DRWShadingGroup *center_active; + DRWShadingGroup *center_selected; + DRWShadingGroup *center_deselected; + DRWShadingGroup *center_selected_lib; + DRWShadingGroup *center_deselected_lib; + + /* Outlines id offset (accessed as an array) */ + int id_ofs_active; + int id_ofs_select; + int id_ofs_select_dupli; + int id_ofs_transform; + + int id_ofs_prb_active; + int id_ofs_prb_select; + int id_ofs_prb_select_dupli; + int id_ofs_prb_transform; + + bool xray_enabled; + bool xray_enabled_and_not_wire; } OBJECT_PrivateData; /* Transient data */ static struct { - /* Instance Data format */ - struct GPUVertFormat *particle_format; - struct GPUVertFormat *empty_image_format; - struct GPUVertFormat *empty_image_wire_format; - - OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN]; - - float camera_pos[3]; - float grid_settings[5]; - float grid_mesh_size; - int grid_flag; - float grid_axes[3]; - int zpos_flag; - int zneg_flag; - float zplane_axes[3]; - float inv_viewport_size[2]; - bool draw_grid; - /* Temp buffer textures */ - struct GPUTexture *outlines_depth_tx; - struct GPUTexture *outlines_id_tx; - struct GPUTexture *outlines_color_tx; - struct GPUTexture *outlines_blur_tx; - - ListBase smoke_domains; + /* Instance Data format */ + struct GPUVertFormat *particle_format; + struct GPUVertFormat *empty_image_format; + struct GPUVertFormat *empty_image_wire_format; + + OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN]; + + float camera_pos[3]; + float grid_settings[5]; + float grid_mesh_size; + int grid_flag; + float grid_axes[3]; + int zpos_flag; + int zneg_flag; + float zplane_axes[3]; + float inv_viewport_size[2]; + bool draw_grid; + /* Temp buffer textures */ + struct GPUTexture *outlines_depth_tx; + struct GPUTexture *outlines_id_tx; + struct GPUTexture *outlines_color_tx; + struct GPUTexture *outlines_blur_tx; + + ListBase smoke_domains; } e_data = {NULL}; /* Engine data */ - enum { - SHOW_AXIS_X = (1 << 0), - SHOW_AXIS_Y = (1 << 1), - SHOW_AXIS_Z = (1 << 2), - SHOW_GRID = (1 << 3), - PLANE_XY = (1 << 4), - PLANE_XZ = (1 << 5), - PLANE_YZ = (1 << 6), - CLIP_ZPOS = (1 << 7), - CLIP_ZNEG = (1 << 8), - GRID_BACK = (1 << 9), + SHOW_AXIS_X = (1 << 0), + SHOW_AXIS_Y = (1 << 1), + SHOW_AXIS_Z = (1 << 2), + SHOW_GRID = (1 << 3), + PLANE_XY = (1 << 4), + PLANE_XZ = (1 << 5), + PLANE_YZ = (1 << 6), + CLIP_ZPOS = (1 << 7), + CLIP_ZNEG = (1 << 8), + GRID_BACK = (1 << 9), }; /* Prototypes. */ -static void DRW_shgroup_empty_ex( - OBJECT_ShadingGroupList *sgl, const float mat[4][4], const float *draw_size, char draw_type, const float color[4]); +static void DRW_shgroup_empty_ex(OBJECT_ShadingGroupList *sgl, + const float mat[4][4], + const float *draw_size, + char draw_type, + const float color[4]); /* *********** FUNCTIONS *********** */ static void OBJECT_engine_init(void *vedata) { - OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; - - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - - if (DRW_state_is_fbo()) { - e_data.outlines_depth_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_object_type); - /* XXX TODO GPU_R16UI can overflow, it would cause no harm - * (only bad colored or missing outlines) but we should - * use 32bits only if the scene have that many objects */ - e_data.outlines_id_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_R16UI, - &draw_engine_object_type); - - GPU_framebuffer_ensure_config(&fbl->outlines_fb, { - GPU_ATTACHMENT_TEXTURE(e_data.outlines_depth_tx), - GPU_ATTACHMENT_TEXTURE(e_data.outlines_id_tx) - }); - - e_data.outlines_color_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_RGBA8, - &draw_engine_object_type); - - GPU_framebuffer_ensure_config(&fbl->expand_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx) - }); - - e_data.outlines_blur_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_RGBA8, - &draw_engine_object_type); - - GPU_framebuffer_ensure_config(&fbl->blur_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.outlines_blur_tx) - }); - } - - /* Shaders */ - const DRWContextState *draw_ctx = DRW_context_state_get(); - OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - - if (!sh_data->outline_resolve) { - /* Outline */ - sh_data->outline_prepass = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - sh_data->outline_prepass_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - - sh_data->outline_resolve = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL); - - sh_data->outline_resolve_aa = DRW_shader_create_with_lib( - datatoc_common_fullscreen_vert_glsl, NULL, - datatoc_object_outline_resolve_frag_glsl, - datatoc_common_fxaa_lib_glsl, - "#define FXAA_ALPHA\n" - "#define USE_FXAA\n"); - - sh_data->outline_detect = DRW_shader_create_with_lib( - datatoc_common_fullscreen_vert_glsl, NULL, - datatoc_object_outline_detect_frag_glsl, - datatoc_common_globals_lib_glsl, - NULL); - - sh_data->outline_detect_wire = DRW_shader_create_with_lib( - datatoc_common_fullscreen_vert_glsl, NULL, - datatoc_object_outline_detect_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define WIRE\n"); - - - sh_data->outline_fade = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL); - sh_data->outline_fade_large = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, "#define LARGE_OUTLINE\n"); - - /* Empty images */ - { - const char *empty_image_defs = ( - "#define DEPTH_UNCHANGED " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_DEFAULT) "\n" - "#define DEPTH_FRONT " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_FRONT) "\n" - "#define DEPTH_BACK " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_BACK) "\n"); - - sh_data->object_empty_image = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, empty_image_defs, NULL}, - }); - sh_data->object_empty_image_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define USE_WIRE\n", empty_image_defs, NULL}, - }); - } - - /* Grid */ - sh_data->grid = DRW_shader_create_with_lib( - datatoc_object_grid_vert_glsl, NULL, - datatoc_object_grid_frag_glsl, - datatoc_common_globals_lib_glsl, NULL); - - /* Particles */ - sh_data->part_prim = DRW_shader_create( - datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL); - - sh_data->part_axis = DRW_shader_create( - datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, - "#define USE_AXIS\n"); - - sh_data->part_dot = DRW_shader_create( - datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL); - - /* Lightprobes */ - sh_data->lightprobe_grid = DRW_shader_create( - datatoc_object_lightprobe_grid_vert_glsl, NULL, datatoc_gpu_shader_flat_id_frag_glsl, NULL); - - /* Loose Points */ - sh_data->loose_points = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_object_loose_points_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - } - - { - /* Grid precompute */ - float invviewmat[4][4], invwinmat[4][4]; - float viewmat[4][4], winmat[4][4]; - View3D *v3d = draw_ctx->v3d; - Scene *scene = draw_ctx->scene; - RegionView3D *rv3d = draw_ctx->rv3d; - float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL); - float grid_res; - - const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0; - const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0; - const bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0; - const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) != 0; - e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor; - - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV); - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); - - /* Setup camera pos */ - copy_v3_v3(e_data.camera_pos, invviewmat[3]); - - /* if perps */ - if (winmat[3][3] == 0.0f) { - float fov; - float viewvecs[2][4] = { - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f}, - }; - - /* convert the view vectors to view space */ - for (int i = 0; i < 2; i++) { - mul_m4_v4(invwinmat, viewvecs[i]); - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */ - } - - fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f; - grid_res = fabsf(tanf(fov)) / grid_scale; - - e_data.grid_flag = (1 << 4); /* XY plane */ - if (show_axis_x) { - e_data.grid_flag |= SHOW_AXIS_X; - } - if (show_axis_y) { - e_data.grid_flag |= SHOW_AXIS_Y; - } - if (show_floor) { - e_data.grid_flag |= SHOW_GRID; - } - - } - else { - if (rv3d->view != RV3D_VIEW_USER) { - /* Allow 3 more subdivisions. */ - grid_scale /= powf(v3d->gridsubdiv, 3); - } - - float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); - grid_res = viewdist / grid_scale; - - if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) { - e_data.draw_grid = true; - e_data.grid_flag = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK; - } - else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { - e_data.draw_grid = true; - e_data.grid_flag = PLANE_XY | SHOW_AXIS_X | SHOW_AXIS_Y | SHOW_GRID | GRID_BACK; - } - else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { - e_data.draw_grid = true; - e_data.grid_flag = PLANE_XZ | SHOW_AXIS_X | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK; - } - else { /* RV3D_VIEW_USER */ - e_data.grid_flag = PLANE_XY; - if (show_axis_x) { - e_data.grid_flag |= SHOW_AXIS_X; - } - if (show_axis_y) { - e_data.grid_flag |= SHOW_AXIS_Y; - } - if (show_floor) { - e_data.grid_flag |= SHOW_GRID; - } - } - } - - e_data.grid_axes[0] = (float)((e_data.grid_flag & (PLANE_XZ | PLANE_XY)) != 0); - e_data.grid_axes[1] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XY)) != 0); - e_data.grid_axes[2] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XZ)) != 0); - - /* Z axis if needed */ - if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) { - e_data.zpos_flag = SHOW_AXIS_Z; - - float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f}; - mul_m4_v4(invviewmat, zvec); - - /* z axis : chose the most facing plane */ - if (fabsf(zvec[0]) < fabsf(zvec[1])) { - e_data.zpos_flag |= PLANE_XZ; - } - else { - e_data.zpos_flag |= PLANE_YZ; - } - - e_data.zneg_flag = e_data.zpos_flag; - - /* Persp : If camera is below floor plane, we switch clipping - * Ortho : If eye vector is looking up, we switch clipping */ - if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) || - ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) - { - e_data.zpos_flag |= CLIP_ZPOS; - e_data.zneg_flag |= CLIP_ZNEG; - } - else { - e_data.zpos_flag |= CLIP_ZNEG; - e_data.zneg_flag |= CLIP_ZPOS; - } - - e_data.zplane_axes[0] = (float)((e_data.zpos_flag & (PLANE_XZ | PLANE_XY)) != 0); - e_data.zplane_axes[1] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XY)) != 0); - e_data.zplane_axes[2] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0); - - } - else { - e_data.zneg_flag = e_data.zpos_flag = CLIP_ZNEG | CLIP_ZPOS; - } - - float dist; - if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) { - Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); - dist = ((Camera *)(camera_object->data))->clip_end; - } - else { - dist = v3d->clip_end; - } - - e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */ - e_data.grid_settings[1] = grid_res; /* gridResolution */ - e_data.grid_settings[2] = grid_scale; /* gridScale */ - e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */ - e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) : 0.0f; /* 1/log(gridSubdiv) */ - - if (winmat[3][3] == 0.0f) { - e_data.grid_mesh_size = dist; - } - else { - float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); - e_data.grid_mesh_size = viewdist * dist; - } - } - - copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get()); - invert_v2(e_data.inv_viewport_size); + OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; + + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + if (DRW_state_is_fbo()) { + e_data.outlines_depth_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_object_type); + /* XXX TODO GPU_R16UI can overflow, it would cause no harm + * (only bad colored or missing outlines) but we should + * use 32bits only if the scene have that many objects */ + e_data.outlines_id_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_R16UI, &draw_engine_object_type); + + GPU_framebuffer_ensure_config(&fbl->outlines_fb, + {GPU_ATTACHMENT_TEXTURE(e_data.outlines_depth_tx), + GPU_ATTACHMENT_TEXTURE(e_data.outlines_id_tx)}); + + e_data.outlines_color_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA8, &draw_engine_object_type); + + GPU_framebuffer_ensure_config( + &fbl->expand_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx)}); + + e_data.outlines_blur_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA8, &draw_engine_object_type); + + GPU_framebuffer_ensure_config( + &fbl->blur_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.outlines_blur_tx)}); + } + + /* Shaders */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + if (!sh_data->outline_resolve) { + /* Outline */ + sh_data->outline_prepass = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + sh_data->outline_prepass_wire = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + + sh_data->outline_resolve = DRW_shader_create_fullscreen( + datatoc_object_outline_resolve_frag_glsl, NULL); + + sh_data->outline_resolve_aa = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, + NULL, + datatoc_object_outline_resolve_frag_glsl, + datatoc_common_fxaa_lib_glsl, + "#define FXAA_ALPHA\n" + "#define USE_FXAA\n"); + + sh_data->outline_detect = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl, + NULL, + datatoc_object_outline_detect_frag_glsl, + datatoc_common_globals_lib_glsl, + NULL); + + sh_data->outline_detect_wire = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, + NULL, + datatoc_object_outline_detect_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define WIRE\n"); + + sh_data->outline_fade = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, + NULL); + sh_data->outline_fade_large = DRW_shader_create_fullscreen( + datatoc_object_outline_expand_frag_glsl, "#define LARGE_OUTLINE\n"); + + /* Empty images */ + { + const char *empty_image_defs = ( + "#define DEPTH_UNCHANGED " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_DEFAULT) "\n" + "#define DEPTH_FRONT " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_FRONT) "\n" + "#define DEPTH_BACK " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_BACK) "\n"); + + sh_data->object_empty_image = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, empty_image_defs, NULL}, + }); + sh_data->object_empty_image_wire = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define USE_WIRE\n", empty_image_defs, NULL}, + }); + } + + /* Grid */ + sh_data->grid = DRW_shader_create_with_lib(datatoc_object_grid_vert_glsl, + NULL, + datatoc_object_grid_frag_glsl, + datatoc_common_globals_lib_glsl, + NULL); + + /* Particles */ + sh_data->part_prim = DRW_shader_create(datatoc_object_particle_prim_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + NULL); + + sh_data->part_axis = DRW_shader_create(datatoc_object_particle_prim_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + "#define USE_AXIS\n"); + + sh_data->part_dot = DRW_shader_create( + datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL); + + /* Lightprobes */ + sh_data->lightprobe_grid = DRW_shader_create(datatoc_object_lightprobe_grid_vert_glsl, + NULL, + datatoc_gpu_shader_flat_id_frag_glsl, + NULL); + + /* Loose Points */ + sh_data->loose_points = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_gpu_shader_3D_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_object_loose_points_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + + { + /* Grid precompute */ + float invviewmat[4][4], invwinmat[4][4]; + float viewmat[4][4], winmat[4][4]; + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + RegionView3D *rv3d = draw_ctx->rv3d; + float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL); + float grid_res; + + const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0; + const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0; + const bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0; + const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) != 0; + e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor; + + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV); + DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + + /* Setup camera pos */ + copy_v3_v3(e_data.camera_pos, invviewmat[3]); + + /* if perps */ + if (winmat[3][3] == 0.0f) { + float fov; + float viewvecs[2][4] = { + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f}, + }; + + /* convert the view vectors to view space */ + for (int i = 0; i < 2; i++) { + mul_m4_v4(invwinmat, viewvecs[i]); + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */ + } + + fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f; + grid_res = fabsf(tanf(fov)) / grid_scale; + + e_data.grid_flag = (1 << 4); /* XY plane */ + if (show_axis_x) { + e_data.grid_flag |= SHOW_AXIS_X; + } + if (show_axis_y) { + e_data.grid_flag |= SHOW_AXIS_Y; + } + if (show_floor) { + e_data.grid_flag |= SHOW_GRID; + } + } + else { + if (rv3d->view != RV3D_VIEW_USER) { + /* Allow 3 more subdivisions. */ + grid_scale /= powf(v3d->gridsubdiv, 3); + } + + float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); + grid_res = viewdist / grid_scale; + + if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) { + e_data.draw_grid = true; + e_data.grid_flag = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK; + } + else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { + e_data.draw_grid = true; + e_data.grid_flag = PLANE_XY | SHOW_AXIS_X | SHOW_AXIS_Y | SHOW_GRID | GRID_BACK; + } + else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { + e_data.draw_grid = true; + e_data.grid_flag = PLANE_XZ | SHOW_AXIS_X | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK; + } + else { /* RV3D_VIEW_USER */ + e_data.grid_flag = PLANE_XY; + if (show_axis_x) { + e_data.grid_flag |= SHOW_AXIS_X; + } + if (show_axis_y) { + e_data.grid_flag |= SHOW_AXIS_Y; + } + if (show_floor) { + e_data.grid_flag |= SHOW_GRID; + } + } + } + + e_data.grid_axes[0] = (float)((e_data.grid_flag & (PLANE_XZ | PLANE_XY)) != 0); + e_data.grid_axes[1] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XY)) != 0); + e_data.grid_axes[2] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XZ)) != 0); + + /* Z axis if needed */ + if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) { + e_data.zpos_flag = SHOW_AXIS_Z; + + float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f}; + mul_m4_v4(invviewmat, zvec); + + /* z axis : chose the most facing plane */ + if (fabsf(zvec[0]) < fabsf(zvec[1])) { + e_data.zpos_flag |= PLANE_XZ; + } + else { + e_data.zpos_flag |= PLANE_YZ; + } + + e_data.zneg_flag = e_data.zpos_flag; + + /* Persp : If camera is below floor plane, we switch clipping + * Ortho : If eye vector is looking up, we switch clipping */ + if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) || + ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) { + e_data.zpos_flag |= CLIP_ZPOS; + e_data.zneg_flag |= CLIP_ZNEG; + } + else { + e_data.zpos_flag |= CLIP_ZNEG; + e_data.zneg_flag |= CLIP_ZPOS; + } + + e_data.zplane_axes[0] = (float)((e_data.zpos_flag & (PLANE_XZ | PLANE_XY)) != 0); + e_data.zplane_axes[1] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XY)) != 0); + e_data.zplane_axes[2] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0); + } + else { + e_data.zneg_flag = e_data.zpos_flag = CLIP_ZNEG | CLIP_ZPOS; + } + + float dist; + if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) { + Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); + dist = ((Camera *)(camera_object->data))->clip_end; + } + else { + dist = v3d->clip_end; + } + + e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */ + e_data.grid_settings[1] = grid_res; /* gridResolution */ + e_data.grid_settings[2] = grid_scale; /* gridScale */ + e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */ + e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) : + 0.0f; /* 1/log(gridSubdiv) */ + + if (winmat[3][3] == 0.0f) { + e_data.grid_mesh_size = dist; + } + else { + float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); + e_data.grid_mesh_size = viewdist * dist; + } + } + + copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get()); + invert_v2(e_data.inv_viewport_size); } static void OBJECT_engine_free(void) { - MEM_SAFE_FREE(e_data.particle_format); - MEM_SAFE_FREE(e_data.empty_image_format); - MEM_SAFE_FREE(e_data.empty_image_wire_format); - - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - OBJECT_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - GPUShader **sh_data_as_array = (GPUShader **)sh_data; - for (int i = 0; i < (sizeof(OBJECT_Shaders) / sizeof(GPUShader *)); i++) { - DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); - } - } + MEM_SAFE_FREE(e_data.particle_format); + MEM_SAFE_FREE(e_data.empty_image_format); + MEM_SAFE_FREE(e_data.empty_image_wire_format); + + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + OBJECT_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(OBJECT_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } -static DRWShadingGroup *shgroup_outline(DRWPass *pass, const int *ofs, GPUShader *sh, eGPUShaderConfig sh_cfg) +static DRWShadingGroup *shgroup_outline(DRWPass *pass, + const int *ofs, + GPUShader *sh, + eGPUShaderConfig sh_cfg) { - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - return grp; + if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } + return grp; } /* currently same as 'shgroup_outline', new function to avoid confustion */ -static DRWShadingGroup *shgroup_wire(DRWPass *pass, const float col[4], GPUShader *sh, eGPUShaderConfig sh_cfg) +static DRWShadingGroup *shgroup_wire(DRWPass *pass, + const float col[4], + GPUShader *sh, + eGPUShaderConfig sh_cfg) { - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", col, 1); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", col, 1); - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - return grp; + if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } + return grp; } /* currently same as 'shgroup_outline', new function to avoid confustion */ -static DRWShadingGroup *shgroup_points(DRWPass *pass, const float col[4], GPUShader *sh, eGPUShaderConfig sh_cfg) +static DRWShadingGroup *shgroup_points(DRWPass *pass, + const float col[4], + GPUShader *sh, + eGPUShaderConfig sh_cfg) { - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", col, 1); - DRW_shgroup_uniform_vec4(grp, "innerColor", G_draw.block.colorEditMeshMiddle, 1); - - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - return grp; + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", col, 1); + DRW_shgroup_uniform_vec4(grp, "innerColor", G_draw.block.colorEditMeshMiddle, 1); + + if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } + return grp; } -static int *shgroup_theme_id_to_probe_outline_counter( - OBJECT_StorageList *stl, int theme_id, const int base_flag) +static int *shgroup_theme_id_to_probe_outline_counter(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { - if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return &stl->g_data->id_ofs_prb_select_dupli; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_prb_transform; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return &stl->g_data->id_ofs_prb_active; - case TH_SELECT: - return &stl->g_data->id_ofs_prb_select; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_prb_transform; - } + if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { + switch (theme_id) { + case TH_ACTIVE: + case TH_SELECT: + return &stl->g_data->id_ofs_prb_select_dupli; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_prb_transform; + } + } + + switch (theme_id) { + case TH_ACTIVE: + return &stl->g_data->id_ofs_prb_active; + case TH_SELECT: + return &stl->g_data->id_ofs_prb_select; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_prb_transform; + } } -static int *shgroup_theme_id_to_outline_counter( - OBJECT_StorageList *stl, int theme_id, const int base_flag) +static int *shgroup_theme_id_to_outline_counter(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { - if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return &stl->g_data->id_ofs_select_dupli; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_transform; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return &stl->g_data->id_ofs_active; - case TH_SELECT: - return &stl->g_data->id_ofs_select; - case TH_TRANSFORM: - default: - return &stl->g_data->id_ofs_transform; - } + if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { + switch (theme_id) { + case TH_ACTIVE: + case TH_SELECT: + return &stl->g_data->id_ofs_select_dupli; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_transform; + } + } + + switch (theme_id) { + case TH_ACTIVE: + return &stl->g_data->id_ofs_active; + case TH_SELECT: + return &stl->g_data->id_ofs_select; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_transform; + } } -static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp( - OBJECT_StorageList *stl, int theme_id) +static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl, + int theme_id) { - /* does not increment counter */ - switch (theme_id) { - case TH_ACTIVE: - return stl->g_data->lightprobes_planar_active; - case TH_SELECT: - return stl->g_data->lightprobes_planar_select; - case TH_TRANSFORM: - default: - return stl->g_data->lightprobes_planar_transform; - } + /* does not increment counter */ + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->lightprobes_planar_active; + case TH_SELECT: + return stl->g_data->lightprobes_planar_select; + case TH_TRANSFORM: + default: + return stl->g_data->lightprobes_planar_transform; + } } -static DRWShadingGroup *shgroup_theme_id_to_probe_cube_outline_shgrp( - OBJECT_StorageList *stl, int theme_id, const int base_flag) +static DRWShadingGroup *shgroup_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { - /* does not increment counter */ - if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return stl->g_data->lightprobes_cube_select_dupli; - case TH_TRANSFORM: - default: - return stl->g_data->lightprobes_cube_transform; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return stl->g_data->lightprobes_cube_active; - case TH_SELECT: - return stl->g_data->lightprobes_cube_select; - case TH_TRANSFORM: - default: - return stl->g_data->lightprobes_cube_transform; - } + /* does not increment counter */ + if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { + switch (theme_id) { + case TH_ACTIVE: + case TH_SELECT: + return stl->g_data->lightprobes_cube_select_dupli; + case TH_TRANSFORM: + default: + return stl->g_data->lightprobes_cube_transform; + } + } + + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->lightprobes_cube_active; + case TH_SELECT: + return stl->g_data->lightprobes_cube_select; + case TH_TRANSFORM: + default: + return stl->g_data->lightprobes_cube_transform; + } } -static DRWShadingGroup *shgroup_theme_id_to_outline_or_null( - OBJECT_StorageList *stl, int theme_id, const int base_flag) +static DRWShadingGroup *shgroup_theme_id_to_outline_or_null(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { - int *counter = shgroup_theme_id_to_outline_counter(stl, theme_id, base_flag); - *counter += 1; - - if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return stl->g_data->outlines_select_dupli; - case TH_TRANSFORM: - return stl->g_data->outlines_transform; - default: - return NULL; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return stl->g_data->outlines_active; - case TH_SELECT: - return stl->g_data->outlines_select; - case TH_TRANSFORM: - return stl->g_data->outlines_transform; - default: - return NULL; - } + int *counter = shgroup_theme_id_to_outline_counter(stl, theme_id, base_flag); + *counter += 1; + + if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { + switch (theme_id) { + case TH_ACTIVE: + case TH_SELECT: + return stl->g_data->outlines_select_dupli; + case TH_TRANSFORM: + return stl->g_data->outlines_transform; + default: + return NULL; + } + } + + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->outlines_active; + case TH_SELECT: + return stl->g_data->outlines_select; + case TH_TRANSFORM: + return stl->g_data->outlines_transform; + default: + return NULL; + } } -static DRWShadingGroup *shgroup_theme_id_to_wire( - OBJECT_ShadingGroupList *sgl, int theme_id, const short base_flag) +static DRWShadingGroup *shgroup_theme_id_to_wire(OBJECT_ShadingGroupList *sgl, + int theme_id, + const short base_flag) { - if (UNLIKELY(base_flag & BASE_FROM_SET)) { - return sgl->wire_dupli; - } - else if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return sgl->wire_dupli_select; - case TH_TRANSFORM: - return sgl->wire_transform; - default: - return sgl->wire_dupli; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return sgl->wire_active; - case TH_SELECT: - return sgl->wire_select; - case TH_TRANSFORM: - return sgl->wire_transform; - default: - return sgl->wire; - } + if (UNLIKELY(base_flag & BASE_FROM_SET)) { + return sgl->wire_dupli; + } + else if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { + switch (theme_id) { + case TH_ACTIVE: + case TH_SELECT: + return sgl->wire_dupli_select; + case TH_TRANSFORM: + return sgl->wire_transform; + default: + return sgl->wire_dupli; + } + } + + switch (theme_id) { + case TH_ACTIVE: + return sgl->wire_active; + case TH_SELECT: + return sgl->wire_select; + case TH_TRANSFORM: + return sgl->wire_transform; + default: + return sgl->wire; + } } -static DRWShadingGroup *shgroup_theme_id_to_point( - OBJECT_ShadingGroupList *sgl, int theme_id, const short base_flag) +static DRWShadingGroup *shgroup_theme_id_to_point(OBJECT_ShadingGroupList *sgl, + int theme_id, + const short base_flag) { - if (UNLIKELY(base_flag & BASE_FROM_SET)) { - return sgl->points_dupli; - } - else if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { - switch (theme_id) { - case TH_ACTIVE: - case TH_SELECT: - return sgl->points_dupli_select; - case TH_TRANSFORM: - return sgl->points_transform; - default: - return sgl->points_dupli; - } - } - - switch (theme_id) { - case TH_ACTIVE: - return sgl->points_active; - case TH_SELECT: - return sgl->points_select; - case TH_TRANSFORM: - return sgl->points_transform; - default: - return sgl->points; - } + if (UNLIKELY(base_flag & BASE_FROM_SET)) { + return sgl->points_dupli; + } + else if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { + switch (theme_id) { + case TH_ACTIVE: + case TH_SELECT: + return sgl->points_dupli_select; + case TH_TRANSFORM: + return sgl->points_transform; + default: + return sgl->points_dupli; + } + } + + switch (theme_id) { + case TH_ACTIVE: + return sgl->points_active; + case TH_SELECT: + return sgl->points_select; + case TH_TRANSFORM: + return sgl->points_transform; + default: + return sgl->points; + } } static void image_calc_aspect(Image *ima, const int size[2], float r_image_aspect[2]) { - float ima_x, ima_y; - if (ima) { - ima_x = size[0]; - ima_y = size[1]; - } - else { - /* if no image, make it a 1x1 empty square, honor scale & offset */ - ima_x = ima_y = 1.0f; - } - /* Get the image aspect even if the buffer is invalid */ - float sca_x = 1.0f, sca_y = 1.0f; - if (ima) { - if (ima->aspx > ima->aspy) { - sca_y = ima->aspy / ima->aspx; - } - else if (ima->aspx < ima->aspy) { - sca_x = ima->aspx / ima->aspy; - } - } - - const float scale_x_inv = ima_x * sca_x; - const float scale_y_inv = ima_y * sca_y; - if (scale_x_inv > scale_y_inv) { - r_image_aspect[0] = 1.0f; - r_image_aspect[1] = scale_y_inv / scale_x_inv; - } - else { - r_image_aspect[0] = scale_x_inv / scale_y_inv; - r_image_aspect[1] = 1.0f; - } + float ima_x, ima_y; + if (ima) { + ima_x = size[0]; + ima_y = size[1]; + } + else { + /* if no image, make it a 1x1 empty square, honor scale & offset */ + ima_x = ima_y = 1.0f; + } + /* Get the image aspect even if the buffer is invalid */ + float sca_x = 1.0f, sca_y = 1.0f; + if (ima) { + if (ima->aspx > ima->aspy) { + sca_y = ima->aspy / ima->aspx; + } + else if (ima->aspx < ima->aspy) { + sca_x = ima->aspx / ima->aspy; + } + } + + const float scale_x_inv = ima_x * sca_x; + const float scale_y_inv = ima_y * sca_y; + if (scale_x_inv > scale_y_inv) { + r_image_aspect[0] = 1.0f; + r_image_aspect[1] = scale_y_inv / scale_x_inv; + } + else { + r_image_aspect[0] = scale_x_inv / scale_y_inv; + r_image_aspect[1] = 1.0f; + } } -static void DRW_shgroup_empty_image( - OBJECT_Shaders *sh_data, OBJECT_ShadingGroupList *sgl, - Object *ob, const float color[3], RegionView3D *rv3d, eGPUShaderConfig sh_cfg) +static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, + OBJECT_ShadingGroupList *sgl, + Object *ob, + const float color[3], + RegionView3D *rv3d, + eGPUShaderConfig sh_cfg) { - /* TODO: 'StereoViews', see draw_empty_image. */ - - if (!BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) { - return; - } - - /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, see: T59347 */ - int size[2] = {0}; - - const bool use_alpha_blend = (ob->empty_image_flag & OB_EMPTY_IMAGE_USE_ALPHA_BLEND) != 0; - GPUTexture *tex = NULL; - - if (ob->data != NULL) { - tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false); - if (tex) { - size[0] = GPU_texture_width(tex); - size[1] = GPU_texture_height(tex); - } - } - - CLAMP_MIN(size[0], 1); - CLAMP_MIN(size[1], 1); - - float image_aspect[2]; - image_calc_aspect(ob->data, size, image_aspect); - - char depth_mode; - if (DRW_state_is_depth()) { - /* Use the actual depth if we are doing depth tests to determine the distance to the object */ - depth_mode = OB_EMPTY_IMAGE_DEPTH_DEFAULT; - } - else { - depth_mode = ob->empty_image_depth; - } - - { - DRWShadingGroup *grp = DRW_shgroup_create(sh_data->object_empty_image_wire, sgl->non_meshes); - /* TODO(fclem) implement DRW_shgroup_uniform_vec2_copy */ - DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]); - DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]); - DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode); - DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1); - DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); - DRW_shgroup_uniform_vec3(grp, "color", color, 1); - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - DRW_shgroup_call_add(grp, DRW_cache_image_plane_wire_get(), ob->obmat); - } - - if (!BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d)) { - return; - } - - if (tex && ((ob->color[3] > 0.0f) || !use_alpha_blend)) { - DRWShadingGroup *grp = DRW_shgroup_create(sh_data->object_empty_image, - (use_alpha_blend) ? sgl->image_empties : sgl->non_meshes); - DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]); - DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]); - DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode); - DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1); - DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); - DRW_shgroup_uniform_texture(grp, "image", tex); - DRW_shgroup_uniform_vec4(grp, "objectColor", ob->color, 1); - DRW_shgroup_uniform_bool_copy(grp, "useAlphaTest", !use_alpha_blend); - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - DRW_shgroup_call_add(grp, DRW_cache_image_plane_get(), ob->obmat); - } + /* TODO: 'StereoViews', see draw_empty_image. */ + + if (!BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) { + return; + } + + /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, see: T59347 */ + int size[2] = {0}; + + const bool use_alpha_blend = (ob->empty_image_flag & OB_EMPTY_IMAGE_USE_ALPHA_BLEND) != 0; + GPUTexture *tex = NULL; + + if (ob->data != NULL) { + tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false); + if (tex) { + size[0] = GPU_texture_width(tex); + size[1] = GPU_texture_height(tex); + } + } + + CLAMP_MIN(size[0], 1); + CLAMP_MIN(size[1], 1); + + float image_aspect[2]; + image_calc_aspect(ob->data, size, image_aspect); + + char depth_mode; + if (DRW_state_is_depth()) { + /* Use the actual depth if we are doing depth tests to determine the distance to the object */ + depth_mode = OB_EMPTY_IMAGE_DEPTH_DEFAULT; + } + else { + depth_mode = ob->empty_image_depth; + } + + { + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->object_empty_image_wire, sgl->non_meshes); + /* TODO(fclem) implement DRW_shgroup_uniform_vec2_copy */ + DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]); + DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]); + DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode); + DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1); + DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); + DRW_shgroup_uniform_vec3(grp, "color", color, 1); + if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } + DRW_shgroup_call_add(grp, DRW_cache_image_plane_wire_get(), ob->obmat); + } + + if (!BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d)) { + return; + } + + if (tex && ((ob->color[3] > 0.0f) || !use_alpha_blend)) { + DRWShadingGroup *grp = DRW_shgroup_create( + sh_data->object_empty_image, (use_alpha_blend) ? sgl->image_empties : sgl->non_meshes); + DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]); + DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]); + DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode); + DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1); + DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); + DRW_shgroup_uniform_texture(grp, "image", tex); + DRW_shgroup_uniform_vec4(grp, "objectColor", ob->color, 1); + DRW_shgroup_uniform_bool_copy(grp, "useAlphaTest", !use_alpha_blend); + if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } + DRW_shgroup_call_add(grp, DRW_cache_image_plane_get(), ob->obmat); + } } static void OBJECT_cache_init(void *vedata) { - const GlobalsUboStorage *gb = &G_draw.block; - OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; - OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - OBJECT_PrivateData *g_data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH); - const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f); - const bool do_large_expand = ((U.pixelsize > 1.0) && (outline_width > 2.0f)) || (outline_width > 4.0f); - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - g_data = stl->g_data; - g_data->xray_enabled = XRAY_ACTIVE(draw_ctx->v3d); - g_data->xray_enabled_and_not_wire = g_data->xray_enabled && draw_ctx->v3d->shading.type > OB_WIRE; - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; - psl->outlines = DRW_pass_create("Outlines Depth Pass", state); - - GPUShader *sh = sh_data->outline_prepass; - - if (g_data->xray_enabled_and_not_wire) { - sh = sh_data->outline_prepass_wire; - } - - g_data->outlines_select = shgroup_outline(psl->outlines, &g_data->id_ofs_select, sh, draw_ctx->sh_cfg); - g_data->outlines_select_dupli = shgroup_outline(psl->outlines, &g_data->id_ofs_select_dupli, sh, draw_ctx->sh_cfg); - g_data->outlines_transform = shgroup_outline(psl->outlines, &g_data->id_ofs_transform, sh, draw_ctx->sh_cfg); - g_data->outlines_active = shgroup_outline(psl->outlines, &g_data->id_ofs_active, sh, draw_ctx->sh_cfg); - - g_data->id_ofs_select = 0; - g_data->id_ofs_select_dupli = 0; - g_data->id_ofs_active = 0; - g_data->id_ofs_transform = 0; - } - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_POINT; - DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state); - struct GPUBatch *sphere = DRW_cache_sphere_get(); - struct GPUBatch *quad = DRW_cache_quad_get(); - - /* Cubemap */ - g_data->lightprobes_cube_select = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_select); - g_data->lightprobes_cube_select_dupli = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_select_dupli); - g_data->lightprobes_cube_active = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_active); - g_data->lightprobes_cube_transform = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_transform); - - /* Planar */ - g_data->lightprobes_planar_select = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_select); - g_data->lightprobes_planar_select_dupli = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_select_dupli); - g_data->lightprobes_planar_active = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_active); - g_data->lightprobes_planar_transform = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_transform); - - g_data->id_ofs_prb_select = 0; - g_data->id_ofs_prb_select_dupli = 0; - g_data->id_ofs_prb_active = 0; - g_data->id_ofs_prb_transform = 0; - } - - { - DRWState state = DRW_STATE_WRITE_COLOR; - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); - /* Don't occlude the "outline" detection pass if in xray mode (too much flickering). */ - float alphaOcclu = (g_data->xray_enabled) ? 1.0f : 0.35f; - - psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state); - - GPUShader *sh = (g_data->xray_enabled_and_not_wire) ? sh_data->outline_detect_wire : sh_data->outline_detect; - DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->outlines_search); - DRW_shgroup_uniform_texture_ref(grp, "outlineId", &e_data.outlines_id_tx); - DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx); - DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu); - DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 4); - DRW_shgroup_call_add(grp, quad, NULL); - - /* This is the bleed pass if do_outline_expand is false. */ - GPUShader *fade_sh = (do_large_expand) ? sh_data->outline_fade_large : sh_data->outline_fade; - psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state); - - grp = DRW_shgroup_create(fade_sh, psl->outlines_expand); - DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_blur_tx); - DRW_shgroup_uniform_bool_copy(grp, "doExpand", do_outline_expand); - DRW_shgroup_call_add(grp, quad, NULL); - - psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state); - - if (do_outline_expand) { - grp = DRW_shgroup_create(sh_data->outline_fade, psl->outlines_bleed); - DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx); - DRW_shgroup_uniform_bool_copy(grp, "doExpand", false); - DRW_shgroup_call_add(grp, quad, NULL); - } - } - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; - psl->outlines_resolve = DRW_pass_create("Outlines Resolve Pass", state); - - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); - GPUTexture **outline_tx = (do_outline_expand) ? &e_data.outlines_blur_tx : &e_data.outlines_color_tx; - - DRWShadingGroup *grp = DRW_shgroup_create(sh_data->outline_resolve_aa, psl->outlines_resolve); - DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx); - DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1); - DRW_shgroup_call_add(grp, quad, NULL); - } - - { - /* Grid pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; - psl->grid = DRW_pass_create("Infinite Grid Pass", state); - - struct GPUBatch *geom = DRW_cache_grid_get(); - float grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; - static float mat[4][4]; - unit_m4(mat); - - /* Create 3 quads to render ordered transparency Z axis */ - DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid); - DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1); - DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); - DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1); - DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1); - DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size); - DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size); - DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, geom, mat); - - grp = DRW_shgroup_create(sh_data->grid, psl->grid); - DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1); - DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, geom, mat); - - grp = DRW_shgroup_create(sh_data->grid, psl->grid); - DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1); - DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, geom, mat); - } - - for (int i = 0; i < 2; ++i) { - OBJECT_ShadingGroupList *sgl = (i == 1) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; - - /* Solid bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - sgl->bone_solid = psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state); - sgl->bone_outline = psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state); - - /* Wire bones */ - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; - sgl->bone_wire = psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state); - - /* distance outline around envelope bones */ - state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT; - sgl->bone_envelope = psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state); - - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; - sgl->bone_axes = psl->bone_axes[i] = DRW_pass_create("Bone Axes Pass", state); - } - - for (int i = 0; i < 2; ++i) { - OBJECT_ShadingGroupList *sgl = (i == 1) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; - - /* Non Meshes Pass (Camera, empties, lights ...) */ - struct GPUBatch *geom; - struct GPUShader *sh; - - DRWState state = - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_POINT | DRW_STATE_WIRE; - sgl->non_meshes = psl->non_meshes[i] = DRW_pass_create("Non Meshes Pass", state); - - state = DRW_STATE_WRITE_COLOR | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE; - sgl->image_empties = psl->image_empties[i] = DRW_pass_create("Image Empties", state); - - /* Empties */ - geom = DRW_cache_plain_axes_get(); - sgl->plain_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_empty_cube_get(); - sgl->cube = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_circle_get(); - sgl->circle = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_empty_sphere_get(); - sgl->sphere = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_sphere_get(); - sgl->sphere_solid = shgroup_instance_solid(sgl->non_meshes, geom); - - geom = DRW_cache_empty_cylinder_get(); - sgl->cylinder = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_empty_capsule_cap_get(); - sgl->capsule_cap = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_empty_capsule_body_get(); - sgl->capsule_body = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_empty_cone_get(); - sgl->cone = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_single_arrow_get(); - sgl->single_arrow = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_single_line_get(); - sgl->single_arrow_line = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_bone_arrows_get(); - sgl->empty_axes = shgroup_instance_empty_axes(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Force Field */ - geom = DRW_cache_field_wind_get(); - sgl->field_wind = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_field_force_get(); - sgl->field_force = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_field_vortex_get(); - sgl->field_vortex = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_screenspace_circle_get(); - sgl->field_curve_sta = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Grease Pencil */ - geom = DRW_cache_gpencil_axes_get(); - sgl->gpencil_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Speaker */ - geom = DRW_cache_speaker_get(); - sgl->speaker = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Probe */ - static float probeSize = 14.0f; - geom = DRW_cache_lightprobe_cube_get(); - sgl->probe_cube = shgroup_instance_screenspace(sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg); - - geom = DRW_cache_lightprobe_grid_get(); - sgl->probe_grid = shgroup_instance_screenspace(sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg); - - static float probePlanarSize = 20.0f; - geom = DRW_cache_lightprobe_planar_get(); - sgl->probe_planar = shgroup_instance_screenspace(sgl->non_meshes, geom, &probePlanarSize, draw_ctx->sh_cfg); - - /* Camera */ - geom = DRW_cache_camera_get(); - sgl->camera = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_camera_frame_get(); - sgl->camera_frame = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_camera_tria_get(); - sgl->camera_tria = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_plain_axes_get(); - sgl->camera_focus = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_single_line_get(); - sgl->camera_clip = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - sgl->camera_mist = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_single_line_endpoints_get(); - sgl->camera_clip_points = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - sgl->camera_mist_points = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_quad_wires_get(); - sgl->camera_stereo_plane_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_enable(sgl->camera_stereo_plane_wires, DRW_STATE_WIRE); - - geom = DRW_cache_empty_cube_get(); - sgl->camera_stereo_volume_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - BLI_listbase_clear(&sgl->camera_path); - - /* Texture Space */ - geom = DRW_cache_empty_cube_get(); - sgl->texspace = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Wires (for loose edges) */ - sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->sh_cfg); - sgl->wire = shgroup_wire(sgl->non_meshes, gb->colorWire, sh, draw_ctx->sh_cfg); - sgl->wire_select = shgroup_wire(sgl->non_meshes, gb->colorSelect, sh, draw_ctx->sh_cfg); - sgl->wire_transform = shgroup_wire(sgl->non_meshes, gb->colorTransform, sh, draw_ctx->sh_cfg); - sgl->wire_active = shgroup_wire(sgl->non_meshes, gb->colorActive, sh, draw_ctx->sh_cfg); - /* Wire (duplicator) */ - sgl->wire_dupli = shgroup_wire(sgl->non_meshes, gb->colorDupli, sh, draw_ctx->sh_cfg); - sgl->wire_dupli_select = shgroup_wire(sgl->non_meshes, gb->colorDupliSelect, sh, draw_ctx->sh_cfg); - - /* Points (loose points) */ - sh = sh_data->loose_points; - sgl->points = shgroup_points(sgl->non_meshes, gb->colorWire, sh, draw_ctx->sh_cfg); - sgl->points_select = shgroup_points(sgl->non_meshes, gb->colorSelect, sh, draw_ctx->sh_cfg); - sgl->points_transform = shgroup_points(sgl->non_meshes, gb->colorTransform, sh, draw_ctx->sh_cfg); - sgl->points_active = shgroup_points(sgl->non_meshes, gb->colorActive, sh, draw_ctx->sh_cfg); - /* Points (duplicator) */ - sgl->points_dupli = shgroup_points(sgl->non_meshes, gb->colorDupli, sh, draw_ctx->sh_cfg); - sgl->points_dupli_select = shgroup_points(sgl->non_meshes, gb->colorDupliSelect, sh, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->points, DRW_STATE_BLEND); - DRW_shgroup_state_disable(sgl->points_select, DRW_STATE_BLEND); - DRW_shgroup_state_disable(sgl->points_transform, DRW_STATE_BLEND); - DRW_shgroup_state_disable(sgl->points_active, DRW_STATE_BLEND); - DRW_shgroup_state_disable(sgl->points_dupli, DRW_STATE_BLEND); - DRW_shgroup_state_disable(sgl->points_dupli_select, DRW_STATE_BLEND); - - /* Metaballs Handles */ - sgl->mball_handle = shgroup_instance_mball_handles(sgl->non_meshes, draw_ctx->sh_cfg); - - /* Lights */ - /* TODO - * for now we create multiple times the same VBO with only light 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(); - sgl->light_buflimit = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + const GlobalsUboStorage *gb = &G_draw.block; + OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + OBJECT_PrivateData *g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH); + const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f); + const bool do_large_expand = ((U.pixelsize > 1.0) && (outline_width > 2.0f)) || + (outline_width > 4.0f); + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + g_data = stl->g_data; + g_data->xray_enabled = XRAY_ACTIVE(draw_ctx->v3d); + g_data->xray_enabled_and_not_wire = g_data->xray_enabled && + draw_ctx->v3d->shading.type > OB_WIRE; + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_WIRE; + psl->outlines = DRW_pass_create("Outlines Depth Pass", state); + + GPUShader *sh = sh_data->outline_prepass; + + if (g_data->xray_enabled_and_not_wire) { + sh = sh_data->outline_prepass_wire; + } + + g_data->outlines_select = shgroup_outline( + psl->outlines, &g_data->id_ofs_select, sh, draw_ctx->sh_cfg); + g_data->outlines_select_dupli = shgroup_outline( + psl->outlines, &g_data->id_ofs_select_dupli, sh, draw_ctx->sh_cfg); + g_data->outlines_transform = shgroup_outline( + psl->outlines, &g_data->id_ofs_transform, sh, draw_ctx->sh_cfg); + g_data->outlines_active = shgroup_outline( + psl->outlines, &g_data->id_ofs_active, sh, draw_ctx->sh_cfg); + + g_data->id_ofs_select = 0; + g_data->id_ofs_select_dupli = 0; + g_data->id_ofs_active = 0; + g_data->id_ofs_transform = 0; + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_POINT; + DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state); + struct GPUBatch *sphere = DRW_cache_sphere_get(); + struct GPUBatch *quad = DRW_cache_quad_get(); + + /* Cubemap */ + g_data->lightprobes_cube_select = shgroup_instance_outline( + pass, sphere, &g_data->id_ofs_prb_select); + g_data->lightprobes_cube_select_dupli = shgroup_instance_outline( + pass, sphere, &g_data->id_ofs_prb_select_dupli); + g_data->lightprobes_cube_active = shgroup_instance_outline( + pass, sphere, &g_data->id_ofs_prb_active); + g_data->lightprobes_cube_transform = shgroup_instance_outline( + pass, sphere, &g_data->id_ofs_prb_transform); + + /* Planar */ + g_data->lightprobes_planar_select = shgroup_instance_outline( + pass, quad, &g_data->id_ofs_prb_select); + g_data->lightprobes_planar_select_dupli = shgroup_instance_outline( + pass, quad, &g_data->id_ofs_prb_select_dupli); + g_data->lightprobes_planar_active = shgroup_instance_outline( + pass, quad, &g_data->id_ofs_prb_active); + g_data->lightprobes_planar_transform = shgroup_instance_outline( + pass, quad, &g_data->id_ofs_prb_transform); + + g_data->id_ofs_prb_select = 0; + g_data->id_ofs_prb_select_dupli = 0; + g_data->id_ofs_prb_active = 0; + g_data->id_ofs_prb_transform = 0; + } + + { + DRWState state = DRW_STATE_WRITE_COLOR; + struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + /* Don't occlude the "outline" detection pass if in xray mode (too much flickering). */ + float alphaOcclu = (g_data->xray_enabled) ? 1.0f : 0.35f; + + psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state); + + GPUShader *sh = (g_data->xray_enabled_and_not_wire) ? sh_data->outline_detect_wire : + sh_data->outline_detect; + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->outlines_search); + DRW_shgroup_uniform_texture_ref(grp, "outlineId", &e_data.outlines_id_tx); + DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx); + DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu); + DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 4); + DRW_shgroup_call_add(grp, quad, NULL); + + /* This is the bleed pass if do_outline_expand is false. */ + GPUShader *fade_sh = (do_large_expand) ? sh_data->outline_fade_large : sh_data->outline_fade; + psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state); + + grp = DRW_shgroup_create(fade_sh, psl->outlines_expand); + DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_blur_tx); + DRW_shgroup_uniform_bool_copy(grp, "doExpand", do_outline_expand); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state); + + if (do_outline_expand) { + grp = DRW_shgroup_create(sh_data->outline_fade, psl->outlines_bleed); + DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx); + DRW_shgroup_uniform_bool_copy(grp, "doExpand", false); + DRW_shgroup_call_add(grp, quad, NULL); + } + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; + psl->outlines_resolve = DRW_pass_create("Outlines Resolve Pass", state); + + struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + GPUTexture **outline_tx = (do_outline_expand) ? &e_data.outlines_blur_tx : + &e_data.outlines_color_tx; + + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->outline_resolve_aa, psl->outlines_resolve); + DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx); + DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } + + { + /* Grid pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; + psl->grid = DRW_pass_create("Infinite Grid Pass", state); + + struct GPUBatch *geom = DRW_cache_grid_get(); + float grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; + static float mat[4][4]; + unit_m4(mat); + + /* Create 3 quads to render ordered transparency Z axis */ + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1); + DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); + DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1); + DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1); + DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size); + DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size); + DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, geom, mat); + + grp = DRW_shgroup_create(sh_data->grid, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1); + DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, geom, mat); + + grp = DRW_shgroup_create(sh_data->grid, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1); + DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, geom, mat); + } + + for (int i = 0; i < 2; ++i) { + OBJECT_ShadingGroupList *sgl = (i == 1) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; + + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + sgl->bone_solid = psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state); + sgl->bone_outline = psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state); + + /* Wire bones */ + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND; + sgl->bone_wire = psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state); + + /* distance outline around envelope bones */ + state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_CULL_FRONT; + sgl->bone_envelope = psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", + state); + + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_WIRE; + sgl->bone_axes = psl->bone_axes[i] = DRW_pass_create("Bone Axes Pass", state); + } + + for (int i = 0; i < 2; ++i) { + OBJECT_ShadingGroupList *sgl = (i == 1) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; + + /* Non Meshes Pass (Camera, empties, lights ...) */ + struct GPUBatch *geom; + struct GPUShader *sh; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_POINT | DRW_STATE_WIRE; + sgl->non_meshes = psl->non_meshes[i] = DRW_pass_create("Non Meshes Pass", state); + + state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE; + sgl->image_empties = psl->image_empties[i] = DRW_pass_create("Image Empties", state); + + /* Empties */ + geom = DRW_cache_plain_axes_get(); + sgl->plain_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_empty_cube_get(); + sgl->cube = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_circle_get(); + sgl->circle = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_empty_sphere_get(); + sgl->sphere = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_sphere_get(); + sgl->sphere_solid = shgroup_instance_solid(sgl->non_meshes, geom); + + geom = DRW_cache_empty_cylinder_get(); + sgl->cylinder = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_empty_capsule_cap_get(); + sgl->capsule_cap = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_empty_capsule_body_get(); + sgl->capsule_body = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_empty_cone_get(); + sgl->cone = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_single_arrow_get(); + sgl->single_arrow = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_single_line_get(); + sgl->single_arrow_line = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_bone_arrows_get(); + sgl->empty_axes = shgroup_instance_empty_axes(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* Force Field */ + geom = DRW_cache_field_wind_get(); + sgl->field_wind = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_field_force_get(); + sgl->field_force = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_field_vortex_get(); + sgl->field_vortex = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_screenspace_circle_get(); + sgl->field_curve_sta = shgroup_instance_screen_aligned( + sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* Grease Pencil */ + geom = DRW_cache_gpencil_axes_get(); + sgl->gpencil_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* Speaker */ + geom = DRW_cache_speaker_get(); + sgl->speaker = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* Probe */ + static float probeSize = 14.0f; + geom = DRW_cache_lightprobe_cube_get(); + sgl->probe_cube = shgroup_instance_screenspace( + sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg); + + geom = DRW_cache_lightprobe_grid_get(); + sgl->probe_grid = shgroup_instance_screenspace( + sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg); + + static float probePlanarSize = 20.0f; + geom = DRW_cache_lightprobe_planar_get(); + sgl->probe_planar = shgroup_instance_screenspace( + sgl->non_meshes, geom, &probePlanarSize, draw_ctx->sh_cfg); + + /* Camera */ + geom = DRW_cache_camera_get(); + sgl->camera = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_camera_frame_get(); + sgl->camera_frame = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_camera_tria_get(); + sgl->camera_tria = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_plain_axes_get(); + sgl->camera_focus = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_single_line_get(); + sgl->camera_clip = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_mist = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_single_line_endpoints_get(); + sgl->camera_clip_points = shgroup_distance_lines_instance( + sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_mist_points = shgroup_distance_lines_instance( + sgl->non_meshes, geom, draw_ctx->sh_cfg); - sgl->light_center = shgroup_dynpoints_uniform_color(sgl->non_meshes, gb->colorLightNoAlpha, &gb->sizeLightCenter, draw_ctx->sh_cfg); + geom = DRW_cache_quad_wires_get(); + sgl->camera_stereo_plane_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + DRW_shgroup_state_enable(sgl->camera_stereo_plane_wires, DRW_STATE_WIRE); + + geom = DRW_cache_empty_cube_get(); + sgl->camera_stereo_volume_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - geom = DRW_cache_light_get(); - sgl->light_circle = shgroup_instance_screenspace(sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg); - geom = DRW_cache_light_shadows_get(); - sgl->light_circle_shadow = shgroup_instance_screenspace(sgl->non_meshes, geom, &gb->sizeLightCircleShadow, draw_ctx->sh_cfg); + BLI_listbase_clear(&sgl->camera_path); - geom = DRW_cache_light_sunrays_get(); - sgl->light_sunrays = shgroup_instance_screenspace(sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg); + /* Texture Space */ + geom = DRW_cache_empty_cube_get(); + sgl->texspace = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - sgl->light_groundline = shgroup_groundlines_uniform_color(sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg); - sgl->light_groundpoint = shgroup_groundpoints_uniform_color(sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg); - - geom = DRW_cache_screenspace_circle_get(); - sgl->light_area_sphere = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_area_square_get(); - sgl->light_area_square = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_area_disk_get(); - sgl->light_area_disk = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_hemi_get(); - sgl->light_hemi = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_single_line_get(); - sgl->light_distance = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_single_line_endpoints_get(); - sgl->light_buflimit_points = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_spot_get(); - sgl->light_spot_cone = shgroup_spot_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_circle_get(); - sgl->light_spot_blend = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_spot_square_get(); - sgl->light_spot_pyramid = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_square_get(); - sgl->light_spot_blend_rect = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* -------- STIPPLES ------- */ - - /* Relationship Lines */ - sgl->relationship_lines = shgroup_dynlines_dashed_uniform_color(sgl->non_meshes, gb->colorWire, draw_ctx->sh_cfg); - sgl->constraint_lines = shgroup_dynlines_dashed_uniform_color(sgl->non_meshes, gb->colorGridAxisZ, draw_ctx->sh_cfg); - - /* Force Field Curve Guide End (here because of stipple) */ - /* TODO port to shader stipple */ - geom = DRW_cache_screenspace_circle_get(); - sgl->field_curve_end = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Force Field Limits */ - /* TODO port to shader stipple */ - geom = DRW_cache_field_tube_limit_get(); - sgl->field_tube_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* TODO port to shader stipple */ - geom = DRW_cache_field_cone_limit_get(); - sgl->field_cone_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); - - /* Transparent Shapes */ - state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_CULL_FRONT; - sgl->transp_shapes = psl->transp_shapes[i] = DRW_pass_create("Transparent Shapes", state); - - /* Spot cones */ - geom = DRW_cache_light_spot_volume_get(); - sgl->light_spot_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_spot_square_volume_get(); - sgl->light_spot_volume_rect = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_light_spot_volume_get(); - sgl->light_spot_volume_outside = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->light_spot_volume_outside, DRW_STATE_CULL_FRONT); - DRW_shgroup_state_enable(sgl->light_spot_volume_outside, DRW_STATE_CULL_BACK); - - geom = DRW_cache_light_spot_square_volume_get(); - sgl->light_spot_volume_rect_outside = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_FRONT); - DRW_shgroup_state_enable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_BACK); - - /* Camera stereo volumes */ - geom = DRW_cache_cube_get(); - sgl->camera_stereo_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - - geom = DRW_cache_quad_get(); - sgl->camera_stereo_plane = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->camera_stereo_plane, DRW_STATE_CULL_FRONT); - } - - { - /* 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_with_config( - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, draw_ctx->sh_cfg); - - /* 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", gb->colorActive, 1); - DRW_shgroup_uniform_vec4(grp, "outlineColor", gb->colorOutline, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_active = grp; - - /* Select */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); - DRW_shgroup_uniform_vec4(grp, "color", gb->colorSelect, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_selected = grp; - - /* Deselect */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); - DRW_shgroup_uniform_vec4(grp, "color", gb->colorDeselect, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_deselected = grp; - - /* Select (library) */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); - DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrarySelect, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_selected_lib = grp; - - /* Deselect (library) */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); - DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrary, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_deselected_lib = grp; - } - - { - /* Particle Pass */ - psl->particle = DRW_pass_create( - "Particle Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_POINT | DRW_STATE_BLEND); - } + /* Wires (for loose edges) */ + sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->sh_cfg); + sgl->wire = shgroup_wire(sgl->non_meshes, gb->colorWire, sh, draw_ctx->sh_cfg); + sgl->wire_select = shgroup_wire(sgl->non_meshes, gb->colorSelect, sh, draw_ctx->sh_cfg); + sgl->wire_transform = shgroup_wire(sgl->non_meshes, gb->colorTransform, sh, draw_ctx->sh_cfg); + sgl->wire_active = shgroup_wire(sgl->non_meshes, gb->colorActive, sh, draw_ctx->sh_cfg); + /* Wire (duplicator) */ + sgl->wire_dupli = shgroup_wire(sgl->non_meshes, gb->colorDupli, sh, draw_ctx->sh_cfg); + sgl->wire_dupli_select = shgroup_wire( + sgl->non_meshes, gb->colorDupliSelect, sh, draw_ctx->sh_cfg); + + /* Points (loose points) */ + sh = sh_data->loose_points; + sgl->points = shgroup_points(sgl->non_meshes, gb->colorWire, sh, draw_ctx->sh_cfg); + sgl->points_select = shgroup_points(sgl->non_meshes, gb->colorSelect, sh, draw_ctx->sh_cfg); + sgl->points_transform = shgroup_points( + sgl->non_meshes, gb->colorTransform, sh, draw_ctx->sh_cfg); + sgl->points_active = shgroup_points(sgl->non_meshes, gb->colorActive, sh, draw_ctx->sh_cfg); + /* Points (duplicator) */ + sgl->points_dupli = shgroup_points(sgl->non_meshes, gb->colorDupli, sh, draw_ctx->sh_cfg); + sgl->points_dupli_select = shgroup_points( + sgl->non_meshes, gb->colorDupliSelect, sh, draw_ctx->sh_cfg); + DRW_shgroup_state_disable(sgl->points, DRW_STATE_BLEND); + DRW_shgroup_state_disable(sgl->points_select, DRW_STATE_BLEND); + DRW_shgroup_state_disable(sgl->points_transform, DRW_STATE_BLEND); + DRW_shgroup_state_disable(sgl->points_active, DRW_STATE_BLEND); + DRW_shgroup_state_disable(sgl->points_dupli, DRW_STATE_BLEND); + DRW_shgroup_state_disable(sgl->points_dupli_select, DRW_STATE_BLEND); + + /* Metaballs Handles */ + sgl->mball_handle = shgroup_instance_mball_handles(sgl->non_meshes, draw_ctx->sh_cfg); + + /* Lights */ + /* TODO + * for now we create multiple times the same VBO with only light 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(); + sgl->light_buflimit = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + sgl->light_center = shgroup_dynpoints_uniform_color( + sgl->non_meshes, gb->colorLightNoAlpha, &gb->sizeLightCenter, draw_ctx->sh_cfg); + + geom = DRW_cache_light_get(); + sgl->light_circle = shgroup_instance_screenspace( + sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg); + geom = DRW_cache_light_shadows_get(); + sgl->light_circle_shadow = shgroup_instance_screenspace( + sgl->non_meshes, geom, &gb->sizeLightCircleShadow, draw_ctx->sh_cfg); + + geom = DRW_cache_light_sunrays_get(); + sgl->light_sunrays = shgroup_instance_screenspace( + sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg); + + sgl->light_groundline = shgroup_groundlines_uniform_color( + sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg); + sgl->light_groundpoint = shgroup_groundpoints_uniform_color( + sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg); + + geom = DRW_cache_screenspace_circle_get(); + sgl->light_area_sphere = shgroup_instance_screen_aligned( + sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_area_square_get(); + sgl->light_area_square = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_area_disk_get(); + sgl->light_area_disk = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_hemi_get(); + sgl->light_hemi = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_single_line_get(); + sgl->light_distance = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_single_line_endpoints_get(); + sgl->light_buflimit_points = shgroup_distance_lines_instance( + sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_spot_get(); + sgl->light_spot_cone = shgroup_spot_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_circle_get(); + sgl->light_spot_blend = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_spot_square_get(); + sgl->light_spot_pyramid = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_square_get(); + sgl->light_spot_blend_rect = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* -------- STIPPLES ------- */ + + /* Relationship Lines */ + sgl->relationship_lines = shgroup_dynlines_dashed_uniform_color( + sgl->non_meshes, gb->colorWire, draw_ctx->sh_cfg); + sgl->constraint_lines = shgroup_dynlines_dashed_uniform_color( + sgl->non_meshes, gb->colorGridAxisZ, draw_ctx->sh_cfg); + + /* Force Field Curve Guide End (here because of stipple) */ + /* TODO port to shader stipple */ + geom = DRW_cache_screenspace_circle_get(); + sgl->field_curve_end = shgroup_instance_screen_aligned( + sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* Force Field Limits */ + /* TODO port to shader stipple */ + geom = DRW_cache_field_tube_limit_get(); + sgl->field_tube_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* TODO port to shader stipple */ + geom = DRW_cache_field_cone_limit_get(); + sgl->field_cone_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + + /* Transparent Shapes */ + state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | + DRW_STATE_CULL_FRONT; + sgl->transp_shapes = psl->transp_shapes[i] = DRW_pass_create("Transparent Shapes", state); + + /* Spot cones */ + geom = DRW_cache_light_spot_volume_get(); + sgl->light_spot_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_spot_square_volume_get(); + sgl->light_spot_volume_rect = shgroup_instance_alpha( + sgl->transp_shapes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_light_spot_volume_get(); + sgl->light_spot_volume_outside = shgroup_instance_alpha( + sgl->transp_shapes, geom, draw_ctx->sh_cfg); + DRW_shgroup_state_disable(sgl->light_spot_volume_outside, DRW_STATE_CULL_FRONT); + DRW_shgroup_state_enable(sgl->light_spot_volume_outside, DRW_STATE_CULL_BACK); + + geom = DRW_cache_light_spot_square_volume_get(); + sgl->light_spot_volume_rect_outside = shgroup_instance_alpha( + sgl->transp_shapes, geom, draw_ctx->sh_cfg); + DRW_shgroup_state_disable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_FRONT); + DRW_shgroup_state_enable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_BACK); + + /* Camera stereo volumes */ + geom = DRW_cache_cube_get(); + sgl->camera_stereo_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); + + geom = DRW_cache_quad_get(); + sgl->camera_stereo_plane = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); + DRW_shgroup_state_disable(sgl->camera_stereo_plane, DRW_STATE_CULL_FRONT); + } + + { + /* 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_with_config( + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, draw_ctx->sh_cfg); + + /* 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", gb->colorActive, 1); + DRW_shgroup_uniform_vec4(grp, "outlineColor", gb->colorOutline, 1); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); + } + stl->g_data->center_active = grp; + + /* Select */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", gb->colorSelect, 1); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); + } + stl->g_data->center_selected = grp; + + /* Deselect */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", gb->colorDeselect, 1); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); + } + stl->g_data->center_deselected = grp; + + /* Select (library) */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrarySelect, 1); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); + } + stl->g_data->center_selected_lib = grp; + + /* Deselect (library) */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrary, 1); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); + } + stl->g_data->center_deselected_lib = grp; + } + + { + /* Particle Pass */ + psl->particle = DRW_pass_create("Particle Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_POINT | + DRW_STATE_BLEND); + } } -static void DRW_shgroup_mball_handles(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLayer *view_layer) +static void DRW_shgroup_mball_handles(OBJECT_ShadingGroupList *sgl, + Object *ob, + ViewLayer *view_layer) { - MetaBall *mb = ob->data; - - float *color; - DRW_object_wire_theme_get(ob, view_layer, &color); - - float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */ - { - float scamat[3][3]; - copy_m3_m4(scamat, ob->obmat); - /* Get the normalized inverse matrix to extract only - * the scale of Scamat */ - float iscamat[3][3]; - invert_m3_m3(iscamat, scamat); - normalize_m3(iscamat); - mul_m3_m3_post(scamat, iscamat); - - copy_v3_v3(draw_scale_xform[0], scamat[0]); - copy_v3_v3(draw_scale_xform[1], scamat[1]); - copy_v3_v3(draw_scale_xform[2], scamat[2]); - } - - for (MetaElem *ml = mb->elems.first; ml != NULL; ml = ml->next) { - /* draw radius */ - float world_pos[3]; - mul_v3_m4v3(world_pos, ob->obmat, &ml->x); - draw_scale_xform[0][3] = world_pos[0]; - draw_scale_xform[1][3] = world_pos[1]; - draw_scale_xform[2][3] = world_pos[2]; - - DRW_shgroup_call_dynamic_add(sgl->mball_handle, draw_scale_xform, &ml->rad, color); - } + MetaBall *mb = ob->data; + + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */ + { + float scamat[3][3]; + copy_m3_m4(scamat, ob->obmat); + /* Get the normalized inverse matrix to extract only + * the scale of Scamat */ + float iscamat[3][3]; + invert_m3_m3(iscamat, scamat); + normalize_m3(iscamat); + mul_m3_m3_post(scamat, iscamat); + + copy_v3_v3(draw_scale_xform[0], scamat[0]); + copy_v3_v3(draw_scale_xform[1], scamat[1]); + copy_v3_v3(draw_scale_xform[2], scamat[2]); + } + + for (MetaElem *ml = mb->elems.first; ml != NULL; ml = ml->next) { + /* draw radius */ + float world_pos[3]; + mul_v3_m4v3(world_pos, ob->obmat, &ml->x); + draw_scale_xform[0][3] = world_pos[0]; + draw_scale_xform[1][3] = world_pos[1]; + draw_scale_xform[2][3] = world_pos[2]; + + DRW_shgroup_call_dynamic_add(sgl->mball_handle, draw_scale_xform, &ml->rad, color); + } } static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLayer *view_layer) { - Light *la = ob->data; - float *color; - int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color); - static float zero = 0.0f; - - typedef struct LightEngineData { - DrawData dd; - float shape_mat[4][4]; - float spot_blend_mat[4][4]; - } LightEngineData; - - LightEngineData *light_engine_data = - (LightEngineData *)DRW_drawdata_ensure( - &ob->id, - &draw_engine_object_type, - sizeof(LightEngineData), - NULL, - NULL); - - float (*shapemat)[4] = light_engine_data->shape_mat; - float (*spotblendmat)[4] = light_engine_data->spot_blend_mat; - - if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) { - /* Don't draw the center if it's selected or active */ - if (theme_id == TH_LIGHT) { - DRW_shgroup_call_dynamic_add(sgl->light_center, ob->obmat[3]); - } - } - - /* First circle */ - DRW_shgroup_call_dynamic_add(sgl->light_circle, ob->obmat[3], color); - - /* draw dashed outer circle for shadow */ - DRW_shgroup_call_dynamic_add(sgl->light_circle_shadow, ob->obmat[3], color); - - /* Distance */ - if (ELEM(la->type, LA_SUN, LA_AREA)) { - DRW_shgroup_call_dynamic_add(sgl->light_distance, color, &zero, &la->dist, ob->obmat); - } - - copy_m4_m4(shapemat, ob->obmat); - - if (la->type == LA_SUN) { - DRW_shgroup_call_dynamic_add(sgl->light_sunrays, ob->obmat[3], color); - } - else if (la->type == LA_SPOT) { - float size[3], sizemat[4][4]; - static float one = 1.0f; - float cone_inside[4] = {0.0f, 0.0f, 0.0f, 0.5f}; - float cone_outside[4] = {1.0f, 1.0f, 1.0f, 0.3f}; - 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(shapemat, 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', (float)(M_PI / 2)); - mul_m4_m4m4(spotblendmat, shapemat, sizemat); - - if (la->mode & LA_SQUARE) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_pyramid, color, &one, shapemat); - - /* 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_call_dynamic_add(sgl->light_spot_blend_rect, color, &one, spotblendmat); - } - - if (la->mode & LA_SHOW_CONE) { - - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_rect, cone_inside, &one, shapemat); - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_rect_outside, cone_outside, &one, shapemat); - } - } - else { - DRW_shgroup_call_dynamic_add(sgl->light_spot_cone, color, shapemat); - - /* 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_call_dynamic_add(sgl->light_spot_blend, color, &one, spotblendmat); - } - - if (la->mode & LA_SHOW_CONE) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume, cone_inside, &one, shapemat); - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_outside, cone_outside, &one, shapemat); - } - } - - DRW_shgroup_call_dynamic_add(sgl->light_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->light_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); - } - else if (la->type == LA_AREA) { - float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; - - if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { - size[1] = la->area_sizey / la->area_size; - size_to_mat4(sizemat, size); - mul_m4_m4m4(shapemat, shapemat, sizemat); - } - - if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { - DRW_shgroup_call_dynamic_add(sgl->light_area_disk, color, &la->area_size, shapemat); - } - else { - DRW_shgroup_call_dynamic_add(sgl->light_area_square, color, &la->area_size, shapemat); - } - } - - if (ELEM(la->type, LA_LOCAL, LA_SPOT)) { - /* We only want position not scale. */ - shapemat[0][0] = shapemat[1][1] = shapemat[2][2] = 1.0f; - shapemat[0][1] = shapemat[0][2] = 0.0f; - shapemat[1][0] = shapemat[1][2] = 0.0f; - shapemat[2][0] = shapemat[2][1] = 0.0f; - DRW_shgroup_call_dynamic_add(sgl->light_area_sphere, color, &la->area_size, shapemat); - } - - /* Line and point going to the ground */ - DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]); + Light *la = ob->data; + float *color; + int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color); + static float zero = 0.0f; + + typedef struct LightEngineData { + DrawData dd; + float shape_mat[4][4]; + float spot_blend_mat[4][4]; + } LightEngineData; + + LightEngineData *light_engine_data = (LightEngineData *)DRW_drawdata_ensure( + &ob->id, &draw_engine_object_type, sizeof(LightEngineData), NULL, NULL); + + float(*shapemat)[4] = light_engine_data->shape_mat; + float(*spotblendmat)[4] = light_engine_data->spot_blend_mat; + + if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) { + /* Don't draw the center if it's selected or active */ + if (theme_id == TH_LIGHT) { + DRW_shgroup_call_dynamic_add(sgl->light_center, ob->obmat[3]); + } + } + + /* First circle */ + DRW_shgroup_call_dynamic_add(sgl->light_circle, ob->obmat[3], color); + + /* draw dashed outer circle for shadow */ + DRW_shgroup_call_dynamic_add(sgl->light_circle_shadow, ob->obmat[3], color); + + /* Distance */ + if (ELEM(la->type, LA_SUN, LA_AREA)) { + DRW_shgroup_call_dynamic_add(sgl->light_distance, color, &zero, &la->dist, ob->obmat); + } + + copy_m4_m4(shapemat, ob->obmat); + + if (la->type == LA_SUN) { + DRW_shgroup_call_dynamic_add(sgl->light_sunrays, ob->obmat[3], color); + } + else if (la->type == LA_SPOT) { + float size[3], sizemat[4][4]; + static float one = 1.0f; + float cone_inside[4] = {0.0f, 0.0f, 0.0f, 0.5f}; + float cone_outside[4] = {1.0f, 1.0f, 1.0f, 0.3f}; + 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(shapemat, 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', (float)(M_PI / 2)); + mul_m4_m4m4(spotblendmat, shapemat, sizemat); + + if (la->mode & LA_SQUARE) { + DRW_shgroup_call_dynamic_add(sgl->light_spot_pyramid, color, &one, shapemat); + + /* 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_call_dynamic_add(sgl->light_spot_blend_rect, color, &one, spotblendmat); + } + + if (la->mode & LA_SHOW_CONE) { + + DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_rect, cone_inside, &one, shapemat); + DRW_shgroup_call_dynamic_add( + sgl->light_spot_volume_rect_outside, cone_outside, &one, shapemat); + } + } + else { + DRW_shgroup_call_dynamic_add(sgl->light_spot_cone, color, shapemat); + + /* 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_call_dynamic_add(sgl->light_spot_blend, color, &one, spotblendmat); + } + + if (la->mode & LA_SHOW_CONE) { + DRW_shgroup_call_dynamic_add(sgl->light_spot_volume, cone_inside, &one, shapemat); + DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_outside, cone_outside, &one, shapemat); + } + } + + DRW_shgroup_call_dynamic_add( + sgl->light_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); + DRW_shgroup_call_dynamic_add( + sgl->light_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); + } + else if (la->type == LA_AREA) { + float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; + + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { + size[1] = la->area_sizey / la->area_size; + size_to_mat4(sizemat, size); + mul_m4_m4m4(shapemat, shapemat, sizemat); + } + + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + DRW_shgroup_call_dynamic_add(sgl->light_area_disk, color, &la->area_size, shapemat); + } + else { + DRW_shgroup_call_dynamic_add(sgl->light_area_square, color, &la->area_size, shapemat); + } + } + + if (ELEM(la->type, LA_LOCAL, LA_SPOT)) { + /* We only want position not scale. */ + shapemat[0][0] = shapemat[1][1] = shapemat[2][2] = 1.0f; + shapemat[0][1] = shapemat[0][2] = 0.0f; + shapemat[1][0] = shapemat[1][2] = 0.0f; + shapemat[2][0] = shapemat[2][1] = 0.0f; + DRW_shgroup_call_dynamic_add(sgl->light_area_sphere, color, &la->area_size, shapemat); + } + + /* Line and point going to the ground */ + DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]); + DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]); } -static GPUBatch *batch_camera_path_get( - ListBase *camera_paths, const MovieTrackingReconstruction *reconstruction) +static GPUBatch *batch_camera_path_get(ListBase *camera_paths, + const MovieTrackingReconstruction *reconstruction) { - GPUBatch *geom; - static GPUVertFormat format = { 0 }; - static struct { uint pos; } attr_id; - if (format.attr_len == 0) { - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, reconstruction->camnr); - - MovieReconstructedCamera *camera = reconstruction->cameras; - for (int a = 0; a < reconstruction->camnr; a++, camera++) { - GPU_vertbuf_attr_set(vbo, attr_id.pos, a, camera->mat[3]); - } - - geom = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); - - /* Store the batch to do cleanup after drawing. */ - BLI_addtail(camera_paths, BLI_genericNodeN(geom)); - return geom; + GPUBatch *geom; + static GPUVertFormat format = {0}; + static struct { + uint pos; + } attr_id; + if (format.attr_len == 0) { + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + } + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, reconstruction->camnr); + + MovieReconstructedCamera *camera = reconstruction->cameras; + for (int a = 0; a < reconstruction->camnr; a++, camera++) { + GPU_vertbuf_attr_set(vbo, attr_id.pos, a, camera->mat[3]); + } + + geom = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); + + /* Store the batch to do cleanup after drawing. */ + BLI_addtail(camera_paths, BLI_genericNodeN(geom)); + return geom; } static void batch_camera_path_free(ListBase *camera_paths) { - LinkData *link; - while ((link = BLI_pophead(camera_paths))) { - GPUBatch *camera_path = link->data; - GPU_batch_discard(camera_path); - MEM_freeN(link); - } + LinkData *link; + while ((link = BLI_pophead(camera_paths))) { + GPUBatch *camera_path = link->data; + GPU_batch_discard(camera_path); + MEM_freeN(link); + } } /** * Draw the stereo 3d support elements (cameras, plane, volume). * They are only visible when not looking through the camera: */ -static void camera_view3d_stereoscopy_display_extra( - OBJECT_ShadingGroupList *sgl, - Scene *scene, ViewLayer *view_layer, View3D *v3d, - Object *ob, Camera *cam, - const float vec[4][3], float drawsize, const float scale[3]) +static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl, + Scene *scene, + ViewLayer *view_layer, + View3D *v3d, + Object *ob, + Camera *cam, + const float vec[4][3], + float drawsize, + const float scale[3]) { - const bool is_select = DRW_state_is_select(); - static float drw_tria_dummy[2][2][2] = {{{0}}}; - const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f; - float origin[2][3] = {{0}}; - const char *viewnames[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - - const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); - const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); - const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME); - - float *color; - DRW_object_wire_theme_get(ob, view_layer, &color); - - for (int eye = 0; eye < 2; eye++) { - float obmat[4][4]; - ob = BKE_camera_multiview_render(scene, ob, viewnames[eye]); - - BKE_camera_multiview_model_matrix_scaled(&scene->r, ob, viewnames[eye], obmat); - - copy_v2_v2(cam->runtime.drw_corners[eye][0], vec[0]); - copy_v2_v2(cam->runtime.drw_corners[eye][1], vec[1]); - copy_v2_v2(cam->runtime.drw_corners[eye][2], vec[2]); - copy_v2_v2(cam->runtime.drw_corners[eye][3], vec[3]); - - cam->runtime.drw_depth[eye] = vec[0][2]; - - if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) { - const float shift_x = - ((BKE_camera_multiview_shift_x(&scene->r, ob, viewnames[eye]) - cam->shiftx) * - (drawsize * scale[0] * fac)); - - for (int i = 0; i < 4; i++) { - cam->runtime.drw_corners[eye][i][0] += shift_x; - } - } - - /* Dummy triangle, draw on top of existent lines so it is invisible. */ - copy_v2_v2(drw_tria_dummy[eye][0], cam->runtime.drw_corners[eye][0]); - copy_v2_v2(drw_tria_dummy[eye][1], cam->runtime.drw_corners[eye][0]); - - if (is_stereo3d_cameras) { - DRW_shgroup_call_dynamic_add( - sgl->camera_frame, color, cam->runtime.drw_corners[eye], - &cam->runtime.drw_depth[eye], cam->runtime.drw_tria, obmat); - - DRW_shgroup_call_dynamic_add( - sgl->camera, color, cam->runtime.drw_corners[eye], - &cam->runtime.drw_depth[eye], drw_tria_dummy[eye], obmat); - } - - /* Connecting line. */ - mul_m4_v3(obmat, origin[eye]); - } - - /* Draw connecting lines. */ - if (is_stereo3d_cameras) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[0]); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[1]); - } - - /* Draw convergence plane. */ - if (is_stereo3d_plane && !is_select) { - float convergence_plane[4][2]; - const float offset = cam->stereo.convergence_distance / cam->runtime.drw_depth[0]; - - for (int i = 0; i < 4; i++) { - mid_v2_v2v2(convergence_plane[i], cam->runtime.drw_corners[0][i], cam->runtime.drw_corners[1][i]); - mul_v2_fl(convergence_plane[i], offset); - } - - /* We are using a -1,1 quad for this shading group, so we need to - * scale and transform it to match the convergence plane border. */ - static float one = 1.0f; - float plane_mat[4][4], scale_mat[4][4]; - float scale_factor[3] = {1.0f, 1.0f, 1.0f}; - float color_plane[2][4] = {{0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha}, - {0.0f, 0.0f, 0.0f, 1.0f}}; - - const float height = convergence_plane[1][1] - convergence_plane[0][1]; - const float width = convergence_plane[2][0] - convergence_plane[0][0]; - - scale_factor[0] = width * 0.5f; - scale_factor[1] = height * 0.5f; - - copy_m4_m4(plane_mat, cam->runtime.drw_normalmat); - translate_m4(plane_mat, 0.0f, 0.0f, -cam->stereo.convergence_distance); - size_to_mat4(scale_mat, scale_factor); - mul_m4_m4_post(plane_mat, scale_mat); - translate_m4(plane_mat, 2.0f * cam->shiftx, (width / height) * 2.0f * cam->shifty, 0.0f); - - if (v3d->stereo3d_convergence_alpha > 0.0f) { - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane, color_plane[0], &one, plane_mat); - } - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane_wires, color_plane[1], &one, plane_mat); - } - - /* Draw convergence volume. */ - if (is_stereo3d_volume && !is_select) { - static float one = 1.0f; - float color_volume[3][4] = {{0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha}, - {1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha}, - {0.0f, 0.0f, 0.0f, 1.0f}}; - - for (int eye = 0; eye < 2; eye++) { - float winmat[4][4], viewinv[4][4], viewmat[4][4], persmat[4][4], persinv[4][4]; - ob = BKE_camera_multiview_render(scene, ob, viewnames[eye]); - - BKE_camera_multiview_window_matrix(&scene->r, ob, viewnames[eye], winmat); - BKE_camera_multiview_model_matrix(&scene->r, ob, viewnames[eye], viewinv); - - invert_m4_m4(viewmat, viewinv); - mul_m4_m4m4(persmat, winmat, viewmat); - invert_m4_m4(persinv, persmat); - - if (v3d->stereo3d_volume_alpha > 0.0f) { - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_volume, color_volume[eye], &one, persinv); - } - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_volume_wires, color_volume[2], &one, persinv); - } - } + const bool is_select = DRW_state_is_select(); + static float drw_tria_dummy[2][2][2] = {{{0}}}; + const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f; + float origin[2][3] = {{0}}; + const char *viewnames[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + + const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && + (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && + (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME); + + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + for (int eye = 0; eye < 2; eye++) { + float obmat[4][4]; + ob = BKE_camera_multiview_render(scene, ob, viewnames[eye]); + + BKE_camera_multiview_model_matrix_scaled(&scene->r, ob, viewnames[eye], obmat); + + copy_v2_v2(cam->runtime.drw_corners[eye][0], vec[0]); + copy_v2_v2(cam->runtime.drw_corners[eye][1], vec[1]); + copy_v2_v2(cam->runtime.drw_corners[eye][2], vec[2]); + copy_v2_v2(cam->runtime.drw_corners[eye][3], vec[3]); + + cam->runtime.drw_depth[eye] = vec[0][2]; + + if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) { + const float shift_x = ((BKE_camera_multiview_shift_x(&scene->r, ob, viewnames[eye]) - + cam->shiftx) * + (drawsize * scale[0] * fac)); + + for (int i = 0; i < 4; i++) { + cam->runtime.drw_corners[eye][i][0] += shift_x; + } + } + + /* Dummy triangle, draw on top of existent lines so it is invisible. */ + copy_v2_v2(drw_tria_dummy[eye][0], cam->runtime.drw_corners[eye][0]); + copy_v2_v2(drw_tria_dummy[eye][1], cam->runtime.drw_corners[eye][0]); + + if (is_stereo3d_cameras) { + DRW_shgroup_call_dynamic_add(sgl->camera_frame, + color, + cam->runtime.drw_corners[eye], + &cam->runtime.drw_depth[eye], + cam->runtime.drw_tria, + obmat); + + DRW_shgroup_call_dynamic_add(sgl->camera, + color, + cam->runtime.drw_corners[eye], + &cam->runtime.drw_depth[eye], + drw_tria_dummy[eye], + obmat); + } + + /* Connecting line. */ + mul_m4_v3(obmat, origin[eye]); + } + + /* Draw connecting lines. */ + if (is_stereo3d_cameras) { + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[0]); + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[1]); + } + + /* Draw convergence plane. */ + if (is_stereo3d_plane && !is_select) { + float convergence_plane[4][2]; + const float offset = cam->stereo.convergence_distance / cam->runtime.drw_depth[0]; + + for (int i = 0; i < 4; i++) { + mid_v2_v2v2( + convergence_plane[i], cam->runtime.drw_corners[0][i], cam->runtime.drw_corners[1][i]); + mul_v2_fl(convergence_plane[i], offset); + } + + /* We are using a -1,1 quad for this shading group, so we need to + * scale and transform it to match the convergence plane border. */ + static float one = 1.0f; + float plane_mat[4][4], scale_mat[4][4]; + float scale_factor[3] = {1.0f, 1.0f, 1.0f}; + float color_plane[2][4] = {{0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha}, + {0.0f, 0.0f, 0.0f, 1.0f}}; + + const float height = convergence_plane[1][1] - convergence_plane[0][1]; + const float width = convergence_plane[2][0] - convergence_plane[0][0]; + + scale_factor[0] = width * 0.5f; + scale_factor[1] = height * 0.5f; + + copy_m4_m4(plane_mat, cam->runtime.drw_normalmat); + translate_m4(plane_mat, 0.0f, 0.0f, -cam->stereo.convergence_distance); + size_to_mat4(scale_mat, scale_factor); + mul_m4_m4_post(plane_mat, scale_mat); + translate_m4(plane_mat, 2.0f * cam->shiftx, (width / height) * 2.0f * cam->shifty, 0.0f); + + if (v3d->stereo3d_convergence_alpha > 0.0f) { + DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane, color_plane[0], &one, plane_mat); + } + DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane_wires, color_plane[1], &one, plane_mat); + } + + /* Draw convergence volume. */ + if (is_stereo3d_volume && !is_select) { + static float one = 1.0f; + float color_volume[3][4] = {{0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha}, + {1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha}, + {0.0f, 0.0f, 0.0f, 1.0f}}; + + for (int eye = 0; eye < 2; eye++) { + float winmat[4][4], viewinv[4][4], viewmat[4][4], persmat[4][4], persinv[4][4]; + ob = BKE_camera_multiview_render(scene, ob, viewnames[eye]); + + BKE_camera_multiview_window_matrix(&scene->r, ob, viewnames[eye], winmat); + BKE_camera_multiview_model_matrix(&scene->r, ob, viewnames[eye], viewinv); + + invert_m4_m4(viewmat, viewinv); + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persinv, persmat); + + if (v3d->stereo3d_volume_alpha > 0.0f) { + DRW_shgroup_call_dynamic_add(sgl->camera_stereo_volume, color_volume[eye], &one, persinv); + } + DRW_shgroup_call_dynamic_add( + sgl->camera_stereo_volume_wires, color_volume[2], &one, persinv); + } + } } -static void camera_view3d_reconstruction( - OBJECT_ShadingGroupList *sgl, - Scene *scene, - View3D *v3d, - const Object *camera_object, - Object *ob, - const float color[4], - const bool is_select) +static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl, + Scene *scene, + View3D *v3d, + const Object *camera_object, + Object *ob, + const float color[4], + const bool is_select) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Camera *cam = ob->data; - - if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0) { - return; - } - - MovieClip *clip = BKE_object_movieclip_get(scene, ob, false); - if (clip == NULL) { - return; - } - - BLI_assert(BLI_listbase_is_empty(&sgl->camera_path)); - const bool is_solid_bundle = (v3d->bundle_drawtype == OB_EMPTY_SPHERE) && - ((v3d->shading.type != OB_SOLID) || !XRAY_FLAG_ENABLED(v3d)); - - MovieTracking *tracking = &clip->tracking; - /* Index must start in 1, to mimic BKE_tracking_track_get_indexed. */ - int track_index = 1; - - uchar text_color_selected[4], text_color_unselected[4]; - float bundle_color_unselected[4], bundle_color_solid[4]; - - UI_GetThemeColor4ubv(TH_SELECT, text_color_selected); - UI_GetThemeColor4ubv(TH_TEXT, text_color_unselected); - UI_GetThemeColor4fv(TH_WIRE, bundle_color_unselected); - UI_GetThemeColor4fv(TH_BUNDLE_SOLID, bundle_color_solid); - - float camera_mat[4][4]; - BKE_tracking_get_camera_object_matrix(scene, ob, camera_mat); - - float bundle_scale_mat[4][4]; - if (is_solid_bundle) { - scale_m4_fl(bundle_scale_mat, v3d->bundle_size); - } - - for (MovieTrackingObject *tracking_object = tracking->objects.first; - tracking_object != NULL; - tracking_object = tracking_object->next) - { - float tracking_object_mat[4][4]; - - if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { - copy_m4_m4(tracking_object_mat, camera_mat); - } - else { - const int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, DEG_get_ctime(draw_ctx->depsgraph)); - float object_mat[4][4]; - BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, object_mat); - - invert_m4(object_mat); - mul_m4_m4m4(tracking_object_mat, cam->runtime.drw_normalmat, object_mat); - } - - ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); - for (MovieTrackingTrack *track = tracksbase->first; track; track = track->next) { - - if ((track->flag & TRACK_HAS_BUNDLE) == 0) { - continue; - } - - bool is_selected = TRACK_SELECTED(track); - - float bundle_mat[4][4]; - copy_m4_m4(bundle_mat, tracking_object_mat); - translate_m4(bundle_mat, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); - - const float *bundle_color; - if (track->flag & TRACK_CUSTOMCOLOR) { - bundle_color = track->color; - } - else if (is_solid_bundle) { - bundle_color = bundle_color_solid; - } - else if (is_selected) { - bundle_color = color; - } - else { - bundle_color = bundle_color_unselected; - } - - if (is_select) { - DRW_select_load_id(camera_object->select_id | (track_index << 16)); - track_index++; - } - - if (is_solid_bundle) { - - if (is_selected) { - DRW_shgroup_empty_ex(sgl, - bundle_mat, - &v3d->bundle_size, - v3d->bundle_drawtype, - color); - } - - float bundle_color_v4[4] = { - bundle_color[0], - bundle_color[1], - bundle_color[2], - 1.0f, - }; - - mul_m4_m4m4(bundle_mat, bundle_mat, bundle_scale_mat); - DRW_shgroup_call_dynamic_add(sgl->sphere_solid, - bundle_mat, - bundle_color_v4); - } - else { - DRW_shgroup_empty_ex(sgl, - bundle_mat, - &v3d->bundle_size, - v3d->bundle_drawtype, - bundle_color); - } - - if ((v3d->flag2 & V3D_SHOW_BUNDLENAME) && !is_select) { - struct DRWTextStore *dt = DRW_text_cache_ensure(); - - DRW_text_cache_add(dt, - bundle_mat[3], - track->name, - strlen(track->name), - 10, 0, - DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, - is_selected ? text_color_selected : text_color_unselected); - } - } - - if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA) && !is_select) { - MovieTrackingReconstruction *reconstruction; - reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object); - - if (reconstruction->camnr) { - static float camera_path_color[4]; - UI_GetThemeColor4fv(TH_CAMERA_PATH, camera_path_color); - - GPUBatch *geom = batch_camera_path_get(&sgl->camera_path, reconstruction); - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - DRWShadingGroup *shading_group = DRW_shgroup_create(shader, sgl->non_meshes); - DRW_shgroup_uniform_vec4(shading_group, "color", camera_path_color, 1); - DRW_shgroup_call_add(shading_group, geom, camera_mat); - } - } - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Camera *cam = ob->data; + + if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0) { + return; + } + + MovieClip *clip = BKE_object_movieclip_get(scene, ob, false); + if (clip == NULL) { + return; + } + + BLI_assert(BLI_listbase_is_empty(&sgl->camera_path)); + const bool is_solid_bundle = (v3d->bundle_drawtype == OB_EMPTY_SPHERE) && + ((v3d->shading.type != OB_SOLID) || !XRAY_FLAG_ENABLED(v3d)); + + MovieTracking *tracking = &clip->tracking; + /* Index must start in 1, to mimic BKE_tracking_track_get_indexed. */ + int track_index = 1; + + uchar text_color_selected[4], text_color_unselected[4]; + float bundle_color_unselected[4], bundle_color_solid[4]; + + UI_GetThemeColor4ubv(TH_SELECT, text_color_selected); + UI_GetThemeColor4ubv(TH_TEXT, text_color_unselected); + UI_GetThemeColor4fv(TH_WIRE, bundle_color_unselected); + UI_GetThemeColor4fv(TH_BUNDLE_SOLID, bundle_color_solid); + + float camera_mat[4][4]; + BKE_tracking_get_camera_object_matrix(scene, ob, camera_mat); + + float bundle_scale_mat[4][4]; + if (is_solid_bundle) { + scale_m4_fl(bundle_scale_mat, v3d->bundle_size); + } + + for (MovieTrackingObject *tracking_object = tracking->objects.first; tracking_object != NULL; + tracking_object = tracking_object->next) { + float tracking_object_mat[4][4]; + + if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { + copy_m4_m4(tracking_object_mat, camera_mat); + } + else { + const int framenr = BKE_movieclip_remap_scene_to_clip_frame( + clip, DEG_get_ctime(draw_ctx->depsgraph)); + float object_mat[4][4]; + BKE_tracking_camera_get_reconstructed_interpolate( + tracking, tracking_object, framenr, object_mat); + + invert_m4(object_mat); + mul_m4_m4m4(tracking_object_mat, cam->runtime.drw_normalmat, object_mat); + } + + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); + for (MovieTrackingTrack *track = tracksbase->first; track; track = track->next) { + + if ((track->flag & TRACK_HAS_BUNDLE) == 0) { + continue; + } + + bool is_selected = TRACK_SELECTED(track); + + float bundle_mat[4][4]; + copy_m4_m4(bundle_mat, tracking_object_mat); + translate_m4(bundle_mat, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); + + const float *bundle_color; + if (track->flag & TRACK_CUSTOMCOLOR) { + bundle_color = track->color; + } + else if (is_solid_bundle) { + bundle_color = bundle_color_solid; + } + else if (is_selected) { + bundle_color = color; + } + else { + bundle_color = bundle_color_unselected; + } + + if (is_select) { + DRW_select_load_id(camera_object->select_id | (track_index << 16)); + track_index++; + } + + if (is_solid_bundle) { + + if (is_selected) { + DRW_shgroup_empty_ex(sgl, bundle_mat, &v3d->bundle_size, v3d->bundle_drawtype, color); + } + + float bundle_color_v4[4] = { + bundle_color[0], + bundle_color[1], + bundle_color[2], + 1.0f, + }; + + mul_m4_m4m4(bundle_mat, bundle_mat, bundle_scale_mat); + DRW_shgroup_call_dynamic_add(sgl->sphere_solid, bundle_mat, bundle_color_v4); + } + else { + DRW_shgroup_empty_ex( + sgl, bundle_mat, &v3d->bundle_size, v3d->bundle_drawtype, bundle_color); + } + + if ((v3d->flag2 & V3D_SHOW_BUNDLENAME) && !is_select) { + struct DRWTextStore *dt = DRW_text_cache_ensure(); + + DRW_text_cache_add(dt, + bundle_mat[3], + track->name, + strlen(track->name), + 10, + 0, + DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, + is_selected ? text_color_selected : text_color_unselected); + } + } + + if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA) && + !is_select) { + MovieTrackingReconstruction *reconstruction; + reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object); + + if (reconstruction->camnr) { + static float camera_path_color[4]; + UI_GetThemeColor4fv(TH_CAMERA_PATH, camera_path_color); + + GPUBatch *geom = batch_camera_path_get(&sgl->camera_path, reconstruction); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + DRWShadingGroup *shading_group = DRW_shgroup_create(shader, sgl->non_meshes); + DRW_shgroup_uniform_vec4(shading_group, "color", camera_path_color, 1); + DRW_shgroup_call_add(shading_group, geom, camera_mat); + } + } + } } static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLayer *view_layer) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - Scene *scene = draw_ctx->scene; - RegionView3D *rv3d = draw_ctx->rv3d; - - Camera *cam = ob->data; - const Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); - const bool is_select = DRW_state_is_select(); - const bool is_active = (ob == camera_object); - const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB)); - - const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0; - const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); - const bool is_stereo3d_display_extra = is_active && is_multiview && (!look_through) && ((v3d->stereo3d_flag) != 0); - const bool is_stereo3d_cameras = (ob == scene->camera) && - is_multiview && - is_stereo3d_view && - (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS); - const bool is_selection_camera_stereo = is_select && - look_through && is_multiview && - is_stereo3d_view; - - float *color; - DRW_object_wire_theme_get(ob, view_layer, &color); - - float vec[4][3], asp[2], shift[2], scale[3], drawsize; - - /* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here. */ - if (is_selection_camera_stereo) { - scale[0] = 1.0f; - scale[1] = 1.0f; - scale[2] = 1.0f; - } - else { - 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, look_through, scale, - asp, shift, &drawsize, vec); - - /* Frame coords */ - copy_v2_v2(cam->runtime.drw_corners[0][0], vec[0]); - copy_v2_v2(cam->runtime.drw_corners[0][1], vec[1]); - copy_v2_v2(cam->runtime.drw_corners[0][2], vec[2]); - copy_v2_v2(cam->runtime.drw_corners[0][3], vec[3]); - - /* depth */ - cam->runtime.drw_depth[0] = vec[0][2]; - - /* tria */ - cam->runtime.drw_tria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]); - cam->runtime.drw_tria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); - cam->runtime.drw_tria[1][0] = shift[0]; - cam->runtime.drw_tria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); - - if (look_through) { - /* Only draw the frame. */ - float mat[4][4]; - if (is_multiview) { - const bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; - const char *view_name = is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME; - BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat); - const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, view_name); - const float delta_shiftx = shiftx - cam->shiftx; - const float width = cam->runtime.drw_corners[0][2][0] - cam->runtime.drw_corners[0][0][0]; - for (int i = 0; i < 4; i++) { - cam->runtime.drw_corners[0][i][0] -= delta_shiftx * width; - } - } - else { - copy_m4_m4(mat, ob->obmat); - } - - DRW_shgroup_call_dynamic_add( - sgl->camera_frame, color, cam->runtime.drw_corners[0], - &cam->runtime.drw_depth[0], cam->runtime.drw_tria, mat); - } - else { - if (!is_stereo3d_cameras) { - DRW_shgroup_call_dynamic_add( - sgl->camera, color, cam->runtime.drw_corners[0], - &cam->runtime.drw_depth[0], cam->runtime.drw_tria, ob->obmat); - } - - /* Active cam */ - if (is_active) { - DRW_shgroup_call_dynamic_add( - sgl->camera_tria, color, - cam->runtime.drw_corners[0], &cam->runtime.drw_depth[0], cam->runtime.drw_tria, ob->obmat); - } - } - - /* draw the rest in normalize object space */ - normalize_m4_m4(cam->runtime.drw_normalmat, ob->obmat); - - if (cam->flag & CAM_SHOWLIMITS) { - static float col[4] = {0.5f, 0.5f, 0.25f, 1.0f}, col_hi[4] = {1.0f, 1.0f, 0.5f, 1.0f}; - float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f}; - float focusdist = BKE_camera_object_dof_distance(ob); - - copy_m4_m4(cam->runtime.drw_focusmat, cam->runtime.drw_normalmat); - translate_m4(cam->runtime.drw_focusmat, 0.0f, 0.0f, -focusdist); - size_to_mat4(sizemat, size); - mul_m4_m4m4(cam->runtime.drw_focusmat, cam->runtime.drw_focusmat, sizemat); - - DRW_shgroup_call_dynamic_add( - sgl->camera_focus, (is_active ? col_hi : col), - &cam->drawsize, cam->runtime.drw_focusmat); - - DRW_shgroup_call_dynamic_add( - sgl->camera_clip, color, - &cam->clip_start, &cam->clip_end, cam->runtime.drw_normalmat); - DRW_shgroup_call_dynamic_add( - sgl->camera_clip_points, (is_active ? col_hi : col), - &cam->clip_start, &cam->clip_end, cam->runtime.drw_normalmat); - } - - if (cam->flag & CAM_SHOWMIST) { - World *world = scene->world; - - if (world) { - static float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}, col_hi[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - world->mistend = world->miststa + world->mistdist; - DRW_shgroup_call_dynamic_add( - sgl->camera_mist, color, - &world->miststa, &world->mistend, cam->runtime.drw_normalmat); - DRW_shgroup_call_dynamic_add( - sgl->camera_mist_points, (is_active ? col_hi : col), - &world->miststa, &world->mistend, cam->runtime.drw_normalmat); - } - } - - /* Stereo cameras, volumes, plane drawing. */ - if (is_stereo3d_display_extra) { - camera_view3d_stereoscopy_display_extra(sgl, scene, view_layer, v3d, ob, cam, vec, drawsize, scale); - } - - /* Motion Tracking. */ - camera_view3d_reconstruction(sgl, scene, v3d, camera_object, ob, color, is_select); + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + RegionView3D *rv3d = draw_ctx->rv3d; + + Camera *cam = ob->data; + const Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); + const bool is_select = DRW_state_is_select(); + const bool is_active = (ob == camera_object); + const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB)); + + const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0; + const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D); + const bool is_stereo3d_display_extra = is_active && is_multiview && (!look_through) && + ((v3d->stereo3d_flag) != 0); + const bool is_stereo3d_cameras = (ob == scene->camera) && is_multiview && is_stereo3d_view && + (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS); + const bool is_selection_camera_stereo = is_select && look_through && is_multiview && + is_stereo3d_view; + + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + float vec[4][3], asp[2], shift[2], scale[3], drawsize; + + /* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here. */ + if (is_selection_camera_stereo) { + scale[0] = 1.0f; + scale[1] = 1.0f; + scale[2] = 1.0f; + } + else { + 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, look_through, scale, asp, shift, &drawsize, vec); + + /* Frame coords */ + copy_v2_v2(cam->runtime.drw_corners[0][0], vec[0]); + copy_v2_v2(cam->runtime.drw_corners[0][1], vec[1]); + copy_v2_v2(cam->runtime.drw_corners[0][2], vec[2]); + copy_v2_v2(cam->runtime.drw_corners[0][3], vec[3]); + + /* depth */ + cam->runtime.drw_depth[0] = vec[0][2]; + + /* tria */ + cam->runtime.drw_tria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]); + cam->runtime.drw_tria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); + cam->runtime.drw_tria[1][0] = shift[0]; + cam->runtime.drw_tria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); + + if (look_through) { + /* Only draw the frame. */ + float mat[4][4]; + if (is_multiview) { + const bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; + const char *view_name = is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME; + BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat); + const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, view_name); + const float delta_shiftx = shiftx - cam->shiftx; + const float width = cam->runtime.drw_corners[0][2][0] - cam->runtime.drw_corners[0][0][0]; + for (int i = 0; i < 4; i++) { + cam->runtime.drw_corners[0][i][0] -= delta_shiftx * width; + } + } + else { + copy_m4_m4(mat, ob->obmat); + } + + DRW_shgroup_call_dynamic_add(sgl->camera_frame, + color, + cam->runtime.drw_corners[0], + &cam->runtime.drw_depth[0], + cam->runtime.drw_tria, + mat); + } + else { + if (!is_stereo3d_cameras) { + DRW_shgroup_call_dynamic_add(sgl->camera, + color, + cam->runtime.drw_corners[0], + &cam->runtime.drw_depth[0], + cam->runtime.drw_tria, + ob->obmat); + } + + /* Active cam */ + if (is_active) { + DRW_shgroup_call_dynamic_add(sgl->camera_tria, + color, + cam->runtime.drw_corners[0], + &cam->runtime.drw_depth[0], + cam->runtime.drw_tria, + ob->obmat); + } + } + + /* draw the rest in normalize object space */ + normalize_m4_m4(cam->runtime.drw_normalmat, ob->obmat); + + if (cam->flag & CAM_SHOWLIMITS) { + static float col[4] = {0.5f, 0.5f, 0.25f, 1.0f}, col_hi[4] = {1.0f, 1.0f, 0.5f, 1.0f}; + float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f}; + float focusdist = BKE_camera_object_dof_distance(ob); + + copy_m4_m4(cam->runtime.drw_focusmat, cam->runtime.drw_normalmat); + translate_m4(cam->runtime.drw_focusmat, 0.0f, 0.0f, -focusdist); + size_to_mat4(sizemat, size); + mul_m4_m4m4(cam->runtime.drw_focusmat, cam->runtime.drw_focusmat, sizemat); + + DRW_shgroup_call_dynamic_add( + sgl->camera_focus, (is_active ? col_hi : col), &cam->drawsize, cam->runtime.drw_focusmat); + + DRW_shgroup_call_dynamic_add( + sgl->camera_clip, color, &cam->clip_start, &cam->clip_end, cam->runtime.drw_normalmat); + DRW_shgroup_call_dynamic_add(sgl->camera_clip_points, + (is_active ? col_hi : col), + &cam->clip_start, + &cam->clip_end, + cam->runtime.drw_normalmat); + } + + if (cam->flag & CAM_SHOWMIST) { + World *world = scene->world; + + if (world) { + static float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}, col_hi[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + world->mistend = world->miststa + world->mistdist; + DRW_shgroup_call_dynamic_add( + sgl->camera_mist, color, &world->miststa, &world->mistend, cam->runtime.drw_normalmat); + DRW_shgroup_call_dynamic_add(sgl->camera_mist_points, + (is_active ? col_hi : col), + &world->miststa, + &world->mistend, + cam->runtime.drw_normalmat); + } + } + + /* Stereo cameras, volumes, plane drawing. */ + if (is_stereo3d_display_extra) { + camera_view3d_stereoscopy_display_extra( + sgl, scene, view_layer, v3d, ob, cam, vec, drawsize, scale); + } + + /* Motion Tracking. */ + camera_view3d_reconstruction(sgl, scene, v3d, camera_object, ob, color, is_select); } -static void DRW_shgroup_empty_ex( - OBJECT_ShadingGroupList *sgl, const float mat[4][4], const float *draw_size, char draw_type, const float color[4]) +static void DRW_shgroup_empty_ex(OBJECT_ShadingGroupList *sgl, + const float mat[4][4], + const float *draw_size, + char draw_type, + const float color[4]) { - switch (draw_type) { - case OB_PLAINAXES: - DRW_shgroup_call_dynamic_add(sgl->plain_axes, color, draw_size, mat); - break; - case OB_SINGLE_ARROW: - DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, draw_size, mat); - DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, draw_size, mat); - break; - case OB_CUBE: - DRW_shgroup_call_dynamic_add(sgl->cube, color, draw_size, mat); - break; - case OB_CIRCLE: - DRW_shgroup_call_dynamic_add(sgl->circle, color, draw_size, mat); - break; - case OB_EMPTY_SPHERE: - DRW_shgroup_call_dynamic_add(sgl->sphere, color, draw_size, mat); - break; - case OB_EMPTY_CONE: - DRW_shgroup_call_dynamic_add(sgl->cone, color, draw_size, mat); - break; - case OB_ARROWS: - DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, draw_size, mat); - break; - case OB_EMPTY_IMAGE: - BLI_assert(!"Should never happen, use DRW_shgroup_empty instead."); - break; - } + switch (draw_type) { + case OB_PLAINAXES: + DRW_shgroup_call_dynamic_add(sgl->plain_axes, color, draw_size, mat); + break; + case OB_SINGLE_ARROW: + DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, draw_size, mat); + DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, draw_size, mat); + break; + case OB_CUBE: + DRW_shgroup_call_dynamic_add(sgl->cube, color, draw_size, mat); + break; + case OB_CIRCLE: + DRW_shgroup_call_dynamic_add(sgl->circle, color, draw_size, mat); + break; + case OB_EMPTY_SPHERE: + DRW_shgroup_call_dynamic_add(sgl->sphere, color, draw_size, mat); + break; + case OB_EMPTY_CONE: + DRW_shgroup_call_dynamic_add(sgl->cone, color, draw_size, mat); + break; + case OB_ARROWS: + DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, draw_size, mat); + break; + case OB_EMPTY_IMAGE: + BLI_assert(!"Should never happen, use DRW_shgroup_empty instead."); + break; + } } -static void DRW_shgroup_empty( - OBJECT_Shaders *sh_data, OBJECT_ShadingGroupList *sgl, - Object *ob, ViewLayer *view_layer, RegionView3D *rv3d, eGPUShaderConfig sh_cfg) +static void DRW_shgroup_empty(OBJECT_Shaders *sh_data, + OBJECT_ShadingGroupList *sgl, + Object *ob, + ViewLayer *view_layer, + RegionView3D *rv3d, + eGPUShaderConfig sh_cfg) { - float *color; - DRW_object_wire_theme_get(ob, view_layer, &color); - - switch (ob->empty_drawtype) { - case OB_PLAINAXES: - case OB_SINGLE_ARROW: - case OB_CUBE: - case OB_CIRCLE: - case OB_EMPTY_SPHERE: - case OB_EMPTY_CONE: - case OB_ARROWS: - DRW_shgroup_empty_ex(sgl, ob->obmat, &ob->empty_drawsize, ob->empty_drawtype, color); - break; - case OB_EMPTY_IMAGE: - DRW_shgroup_empty_image(sh_data, sgl, ob, color, rv3d, sh_cfg); - break; - } + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + switch (ob->empty_drawtype) { + case OB_PLAINAXES: + case OB_SINGLE_ARROW: + case OB_CUBE: + case OB_CIRCLE: + case OB_EMPTY_SPHERE: + case OB_EMPTY_CONE: + case OB_ARROWS: + DRW_shgroup_empty_ex(sgl, ob->obmat, &ob->empty_drawsize, ob->empty_drawtype, color); + break; + case OB_EMPTY_IMAGE: + DRW_shgroup_empty_image(sh_data, sgl, ob, color, rv3d, sh_cfg); + break; + } } static void DRW_shgroup_forcefield(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLayer *view_layer) { - int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - float *color = DRW_color_background_blend_get(theme_id); - PartDeflect *pd = ob->pd; - Curve *cu = (ob->type == OB_CURVE) ? ob->data : NULL; - - /* TODO Move this to depsgraph */ - float tmp[3]; - copy_v3_fl(pd->drawvec1, ob->empty_drawsize); - - switch (pd->forcefield) { - case PFIELD_WIND: - pd->drawvec1[2] = pd->f_strength; - break; - case PFIELD_VORTEX: - if (pd->f_strength < 0.0f) { - pd->drawvec1[1] = -pd->drawvec1[1]; - } - break; - case PFIELD_GUIDE: - if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && ob->runtime.curve_cache->path->data) { - where_on_path(ob, 0.0f, pd->drawvec1, tmp, NULL, NULL, NULL); - where_on_path(ob, 1.0f, pd->drawvec2, tmp, NULL, NULL, NULL); - } - break; - } - - if (pd->falloff == PFIELD_FALL_TUBE) { - pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f; - pd->drawvec_falloff_max[2] = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; - - pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f; - pd->drawvec_falloff_min[2] = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; - } - else if (pd->falloff == PFIELD_FALL_CONE) { - float radius, distance; - - radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f); - distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; - pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = distance * sinf(radius); - pd->drawvec_falloff_max[2] = distance * cosf(radius); - - radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f); - distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; - - pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = distance * sinf(radius); - pd->drawvec_falloff_min[2] = distance * cosf(radius); - } - /* End of things that should go to depthgraph */ - - switch (pd->forcefield) { - case PFIELD_WIND: - DRW_shgroup_call_dynamic_add(sgl->field_wind, color, &pd->drawvec1, ob->obmat); - break; - case PFIELD_FORCE: - DRW_shgroup_call_dynamic_add(sgl->field_force, color, &pd->drawvec1, ob->obmat); - break; - case PFIELD_VORTEX: - DRW_shgroup_call_dynamic_add(sgl->field_vortex, color, &pd->drawvec1, ob->obmat); - break; - case PFIELD_GUIDE: - if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && ob->runtime.curve_cache->path->data) { - DRW_shgroup_call_dynamic_add(sgl->field_curve_sta, color, &pd->f_strength, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->f_strength, ob->obmat); - } - break; - } - - if (pd->falloff == PFIELD_FALL_SPHERE) { - /* as last, guide curve alters it */ - if ((pd->flag & PFIELD_USEMAX) != 0) { - DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->maxdist, ob->obmat); - } - - if ((pd->flag & PFIELD_USEMIN) != 0) { - DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->mindist, ob->obmat); - } - } - else if (pd->falloff == PFIELD_FALL_TUBE) { - if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - DRW_shgroup_call_dynamic_add(sgl->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat); - } - - if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - DRW_shgroup_call_dynamic_add(sgl->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat); - } - } - else if (pd->falloff == PFIELD_FALL_CONE) { - if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - DRW_shgroup_call_dynamic_add(sgl->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat); - } - - if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - DRW_shgroup_call_dynamic_add(sgl->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat); - } - } + int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + float *color = DRW_color_background_blend_get(theme_id); + PartDeflect *pd = ob->pd; + Curve *cu = (ob->type == OB_CURVE) ? ob->data : NULL; + + /* TODO Move this to depsgraph */ + float tmp[3]; + copy_v3_fl(pd->drawvec1, ob->empty_drawsize); + + switch (pd->forcefield) { + case PFIELD_WIND: + pd->drawvec1[2] = pd->f_strength; + break; + case PFIELD_VORTEX: + if (pd->f_strength < 0.0f) { + pd->drawvec1[1] = -pd->drawvec1[1]; + } + break; + case PFIELD_GUIDE: + if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && + ob->runtime.curve_cache->path->data) { + where_on_path(ob, 0.0f, pd->drawvec1, tmp, NULL, NULL, NULL); + where_on_path(ob, 1.0f, pd->drawvec2, tmp, NULL, NULL, NULL); + } + break; + } + + if (pd->falloff == PFIELD_FALL_TUBE) { + pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = (pd->flag & PFIELD_USEMAXR) ? + pd->maxrad : + 1.0f; + pd->drawvec_falloff_max[2] = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; + + pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = (pd->flag & PFIELD_USEMINR) ? + pd->minrad : + 1.0f; + pd->drawvec_falloff_min[2] = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; + } + else if (pd->falloff == PFIELD_FALL_CONE) { + float radius, distance; + + radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f); + distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; + pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = distance * sinf(radius); + pd->drawvec_falloff_max[2] = distance * cosf(radius); + + radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f); + distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; + + pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = distance * sinf(radius); + pd->drawvec_falloff_min[2] = distance * cosf(radius); + } + /* End of things that should go to depthgraph */ + + switch (pd->forcefield) { + case PFIELD_WIND: + DRW_shgroup_call_dynamic_add(sgl->field_wind, color, &pd->drawvec1, ob->obmat); + break; + case PFIELD_FORCE: + DRW_shgroup_call_dynamic_add(sgl->field_force, color, &pd->drawvec1, ob->obmat); + break; + case PFIELD_VORTEX: + DRW_shgroup_call_dynamic_add(sgl->field_vortex, color, &pd->drawvec1, ob->obmat); + break; + case PFIELD_GUIDE: + if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && + ob->runtime.curve_cache->path->data) { + DRW_shgroup_call_dynamic_add(sgl->field_curve_sta, color, &pd->f_strength, ob->obmat); + DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->f_strength, ob->obmat); + } + break; + } + + if (pd->falloff == PFIELD_FALL_SPHERE) { + /* as last, guide curve alters it */ + if ((pd->flag & PFIELD_USEMAX) != 0) { + DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->maxdist, ob->obmat); + } + + if ((pd->flag & PFIELD_USEMIN) != 0) { + DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->mindist, ob->obmat); + } + } + else if (pd->falloff == PFIELD_FALL_TUBE) { + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + DRW_shgroup_call_dynamic_add( + sgl->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat); + } + + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + DRW_shgroup_call_dynamic_add( + sgl->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat); + } + } + else if (pd->falloff == PFIELD_FALL_CONE) { + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + DRW_shgroup_call_dynamic_add( + sgl->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat); + } + + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + DRW_shgroup_call_dynamic_add( + sgl->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat); + } + } } -static void DRW_shgroup_volume_extra( - OBJECT_ShadingGroupList *sgl, - Object *ob, ViewLayer *view_layer, Scene *scene, ModifierData *md) +static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl, + Object *ob, + ViewLayer *view_layer, + Scene *scene, + ModifierData *md) { - SmokeModifierData *smd = (SmokeModifierData *)md; - SmokeDomainSettings *sds = smd->domain; - float *color; - float one = 1.0f; - - if (sds == NULL) { - return; - } - - DRW_object_wire_theme_get(ob, view_layer, &color); - - /* Small cube showing voxel size. */ - float voxel_cubemat[4][4] = {{0.0f}}; - voxel_cubemat[0][0] = 1.0f / (float)sds->res[0]; - voxel_cubemat[1][1] = 1.0f / (float)sds->res[1]; - voxel_cubemat[2][2] = 1.0f / (float)sds->res[2]; - voxel_cubemat[3][0] = voxel_cubemat[3][1] = voxel_cubemat[3][2] = -1.0f; - voxel_cubemat[3][3] = 1.0f; - translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f); - mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat); - - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, voxel_cubemat); - - /* Don't show smoke before simulation starts, this could be made an option in the future. */ - if (!sds->draw_velocity || !sds->fluid || CFRA < sds->point_cache[0]->startframe) { - return; - } - - const bool use_needle = (sds->vector_draw_type == VECTOR_DRAW_NEEDLE); - int line_count = (use_needle) ? 6 : 1; - int slice_axis = -1; - line_count *= sds->res[0] * sds->res[1] * sds->res[2]; - - if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && - sds->axis_slice_method == AXIS_SLICE_SINGLE) - { - float invviewmat[4][4]; - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); - - const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) - ? axis_dominant_v3_single(invviewmat[2]) - : sds->slice_axis - 1; - slice_axis = axis; - line_count /= sds->res[axis]; - } - - GPU_create_smoke_velocity(smd); - - DRWShadingGroup *grp = DRW_shgroup_create(volume_velocity_shader_get(use_needle), sgl->non_meshes); - DRW_shgroup_uniform_texture(grp, "velocityX", sds->tex_velocity_x); - DRW_shgroup_uniform_texture(grp, "velocityY", sds->tex_velocity_y); - DRW_shgroup_uniform_texture(grp, "velocityZ", sds->tex_velocity_z); - DRW_shgroup_uniform_float_copy(grp, "displaySize", sds->vector_scale); - DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); - DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis); - DRW_shgroup_call_procedural_lines_add(grp, line_count, ob->obmat); - - BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd)); + SmokeModifierData *smd = (SmokeModifierData *)md; + SmokeDomainSettings *sds = smd->domain; + float *color; + float one = 1.0f; + + if (sds == NULL) { + return; + } + + DRW_object_wire_theme_get(ob, view_layer, &color); + + /* Small cube showing voxel size. */ + float voxel_cubemat[4][4] = {{0.0f}}; + voxel_cubemat[0][0] = 1.0f / (float)sds->res[0]; + voxel_cubemat[1][1] = 1.0f / (float)sds->res[1]; + voxel_cubemat[2][2] = 1.0f / (float)sds->res[2]; + voxel_cubemat[3][0] = voxel_cubemat[3][1] = voxel_cubemat[3][2] = -1.0f; + voxel_cubemat[3][3] = 1.0f; + translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f); + mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat); + + DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, voxel_cubemat); + + /* Don't show smoke before simulation starts, this could be made an option in the future. */ + if (!sds->draw_velocity || !sds->fluid || CFRA < sds->point_cache[0]->startframe) { + return; + } + + const bool use_needle = (sds->vector_draw_type == VECTOR_DRAW_NEEDLE); + int line_count = (use_needle) ? 6 : 1; + int slice_axis = -1; + line_count *= sds->res[0] * sds->res[1] * sds->res[2]; + + if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && + sds->axis_slice_method == AXIS_SLICE_SINGLE) { + float invviewmat[4][4]; + DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + + const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? + axis_dominant_v3_single(invviewmat[2]) : + sds->slice_axis - 1; + slice_axis = axis; + line_count /= sds->res[axis]; + } + + GPU_create_smoke_velocity(smd); + + DRWShadingGroup *grp = DRW_shgroup_create(volume_velocity_shader_get(use_needle), + sgl->non_meshes); + DRW_shgroup_uniform_texture(grp, "velocityX", sds->tex_velocity_x); + DRW_shgroup_uniform_texture(grp, "velocityY", sds->tex_velocity_y); + DRW_shgroup_uniform_texture(grp, "velocityZ", sds->tex_velocity_z); + DRW_shgroup_uniform_float_copy(grp, "displaySize", sds->vector_scale); + DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); + DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis); + DRW_shgroup_call_procedural_lines_add(grp, line_count, ob->obmat); + + BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd)); } static void volumes_free_smoke_textures(void) { - /* Free Smoke Textures after rendering */ - /* XXX This is a waste of processing and GPU bandwidth if nothing - * is updated. But the problem is since Textures are stored in the - * modifier we don't want them to take precious VRAM if the - * modifier is not used for display. We should share them for - * all viewport in a redraw at least. */ - for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) { - SmokeModifierData *smd = (SmokeModifierData *)link->data; - GPU_free_smoke_velocity(smd); - } - BLI_freelistN(&e_data.smoke_domains); + /* Free Smoke Textures after rendering */ + /* XXX This is a waste of processing and GPU bandwidth if nothing + * is updated. But the problem is since Textures are stored in the + * modifier we don't want them to take precious VRAM if the + * modifier is not used for display. We should share them for + * all viewport in a redraw at least. */ + for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) { + SmokeModifierData *smd = (SmokeModifierData *)link->data; + GPU_free_smoke_velocity(smd); + } + BLI_freelistN(&e_data.smoke_domains); } static void DRW_shgroup_speaker(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLayer *view_layer) { - float *color; - static float one = 1.0f; - DRW_object_wire_theme_get(ob, view_layer, &color); + float *color; + static float one = 1.0f; + DRW_object_wire_theme_get(ob, view_layer, &color); - DRW_shgroup_call_dynamic_add(sgl->speaker, color, &one, ob->obmat); + DRW_shgroup_call_dynamic_add(sgl->speaker, color, &one, ob->obmat); } typedef struct OBJECT_LightProbeEngineData { - DrawData dd; + DrawData dd; - float increment_x[3]; - float increment_y[3]; - float increment_z[3]; - float corner[3]; + float increment_x[3]; + float increment_y[3]; + float increment_z[3]; + float corner[3]; } OBJECT_LightProbeEngineData; -static void DRW_shgroup_lightprobe( - OBJECT_Shaders *sh_data, OBJECT_StorageList *stl, OBJECT_PassList *psl, - Object *ob, ViewLayer *view_layer) +static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, + OBJECT_StorageList *stl, + OBJECT_PassList *psl, + Object *ob, + ViewLayer *view_layer) { - float *color; - static float one = 1.0f; - LightProbe *prb = (LightProbe *)ob->data; - bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); - int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color); - - OBJECT_ShadingGroupList *sgl = (ob->dtx & OB_DRAWXRAY) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; - - OBJECT_LightProbeEngineData *prb_data = (OBJECT_LightProbeEngineData *)DRW_drawdata_ensure( - &ob->id, - &draw_engine_object_type, - sizeof(OBJECT_LightProbeEngineData), - NULL, - NULL); - - if ((DRW_state_is_select() || do_outlines) && ((prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) != 0)) { - int *call_id = shgroup_theme_id_to_probe_outline_counter(stl, theme_id, ob->base_flag); - - if (prb->type == LIGHTPROBE_TYPE_GRID) { - /* Update transforms */ - float cell_dim[3], half_cell_dim[3]; - cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x); - cell_dim[1] = 2.0f / (float)(prb->grid_resolution_y); - cell_dim[2] = 2.0f / (float)(prb->grid_resolution_z); - - mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); - - /* First cell. */ - copy_v3_fl(prb_data->corner, -1.0f); - add_v3_v3(prb_data->corner, half_cell_dim); - mul_m4_v3(ob->obmat, prb_data->corner); - - /* Opposite neighbor cell. */ - copy_v3_fl3(prb_data->increment_x, cell_dim[0], 0.0f, 0.0f); - add_v3_v3(prb_data->increment_x, half_cell_dim); - add_v3_fl(prb_data->increment_x, -1.0f); - mul_m4_v3(ob->obmat, prb_data->increment_x); - sub_v3_v3(prb_data->increment_x, prb_data->corner); - - copy_v3_fl3(prb_data->increment_y, 0.0f, cell_dim[1], 0.0f); - add_v3_v3(prb_data->increment_y, half_cell_dim); - add_v3_fl(prb_data->increment_y, -1.0f); - mul_m4_v3(ob->obmat, prb_data->increment_y); - sub_v3_v3(prb_data->increment_y, prb_data->corner); - - copy_v3_fl3(prb_data->increment_z, 0.0f, 0.0f, cell_dim[2]); - add_v3_v3(prb_data->increment_z, half_cell_dim); - add_v3_fl(prb_data->increment_z, -1.0f); - mul_m4_v3(ob->obmat, prb_data->increment_z); - sub_v3_v3(prb_data->increment_z, prb_data->corner); - - uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z; - DRWShadingGroup *grp = DRW_shgroup_create(sh_data->lightprobe_grid, psl->lightprobes); - DRW_shgroup_uniform_int_copy(grp, "call_id", *call_id); - DRW_shgroup_uniform_int(grp, "baseId", call_id, 1); /* that's correct */ - DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1); - DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1); - DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1); - DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1); - DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1); - DRW_shgroup_call_procedural_points_add(grp, cell_count, NULL); - } - else if (prb->type == LIGHTPROBE_TYPE_CUBE) { - float draw_size = 1.0f; - float probe_cube_mat[4][4]; - // prb_data->draw_size = prb->data_draw_size * 0.1f; - // unit_m4(prb_data->probe_cube_mat); - // copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]); - - DRWShadingGroup *grp = shgroup_theme_id_to_probe_cube_outline_shgrp(stl, theme_id, ob->base_flag); - /* TODO remove or change the drawing of the cube probes. Theses line draws nothing on purpose - * to keep the call ids correct. */ - zero_m4(probe_cube_mat); - DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, probe_cube_mat); - } - else { - float draw_size = 1.0f; - DRWShadingGroup *grp = shgroup_theme_id_to_probe_planar_outline_shgrp(stl, theme_id); - DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, ob->obmat); - } - - *call_id += 1; - } - - switch (prb->type) { - case LIGHTPROBE_TYPE_PLANAR: - DRW_shgroup_call_dynamic_add(sgl->probe_planar, ob->obmat[3], color); - break; - case LIGHTPROBE_TYPE_GRID: - DRW_shgroup_call_dynamic_add(sgl->probe_grid, ob->obmat[3], color); - break; - case LIGHTPROBE_TYPE_CUBE: - default: - DRW_shgroup_call_dynamic_add(sgl->probe_cube, ob->obmat[3], color); - break; - } - - - - if (prb->type == LIGHTPROBE_TYPE_PLANAR) { - float mat[4][4]; - copy_m4_m4(mat, ob->obmat); - normalize_m4(mat); - - DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, &ob->empty_drawsize, mat); - DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, &ob->empty_drawsize, mat); - - copy_m4_m4(mat, ob->obmat); - zero_v3(mat[2]); - - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, mat); - } - - if ((prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0) { - - prb->distfalloff = (1.0f - prb->falloff) * prb->distinf; - prb->distgridinf = prb->distinf; - - if (prb->type == LIGHTPROBE_TYPE_GRID) { - prb->distfalloff += 1.0f; - prb->distgridinf += 1.0f; - } - - if (prb->type == LIGHTPROBE_TYPE_GRID || - prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) - { - DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distgridinf, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distfalloff, ob->obmat); - } - else if (prb->type == LIGHTPROBE_TYPE_PLANAR) { - float rangemat[4][4]; - copy_m4_m4(rangemat, ob->obmat); - normalize_v3(rangemat[2]); - mul_v3_fl(rangemat[2], prb->distinf); - - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat); - - copy_m4_m4(rangemat, ob->obmat); - normalize_v3(rangemat[2]); - mul_v3_fl(rangemat[2], prb->distfalloff); - - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat); - } - else { - DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distgridinf, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distfalloff, ob->obmat); - } - } - - if ((prb->flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0) { - if (prb->type != LIGHTPROBE_TYPE_PLANAR) { - float (*obmat)[4], *dist; - - if ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) { - dist = &prb->distpar; - /* TODO object parallax */ - obmat = ob->obmat; - } - else { - dist = &prb->distinf; - obmat = ob->obmat; - } - - if (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) { - DRW_shgroup_call_dynamic_add(sgl->cube, color, dist, obmat); - } - else { - DRW_shgroup_call_dynamic_add(sgl->sphere, color, dist, obmat); - } - } - } - - if ((prb->flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0) { - if (prb->type != LIGHTPROBE_TYPE_PLANAR) { - static const float cubefacemat[6][4][4] = { - {{0.0, 0.0, -1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, - {{0.0, 0.0, 1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, - {{1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, -1.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, - {{1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, - {{1.0, 0.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, -1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, - {{-1.0, 0.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, - }; - - for (int i = 0; i < 6; ++i) { - float clipmat[4][4]; - normalize_m4_m4(clipmat, ob->obmat); - mul_m4_m4m4(clipmat, clipmat, cubefacemat[i]); - - DRW_shgroup_call_dynamic_add(sgl->light_buflimit, color, &prb->clipsta, &prb->clipend, clipmat); - DRW_shgroup_call_dynamic_add(sgl->light_buflimit_points, color, &prb->clipsta, &prb->clipend, clipmat); - } - } - } - - /* Line and point going to the ground */ - if (prb->type == LIGHTPROBE_TYPE_CUBE) { - DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]); - } + float *color; + static float one = 1.0f; + LightProbe *prb = (LightProbe *)ob->data; + bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); + int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color); + + OBJECT_ShadingGroupList *sgl = (ob->dtx & OB_DRAWXRAY) ? &stl->g_data->sgl_ghost : + &stl->g_data->sgl; + + OBJECT_LightProbeEngineData *prb_data = (OBJECT_LightProbeEngineData *)DRW_drawdata_ensure( + &ob->id, &draw_engine_object_type, sizeof(OBJECT_LightProbeEngineData), NULL, NULL); + + if ((DRW_state_is_select() || do_outlines) && ((prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) != 0)) { + int *call_id = shgroup_theme_id_to_probe_outline_counter(stl, theme_id, ob->base_flag); + + if (prb->type == LIGHTPROBE_TYPE_GRID) { + /* Update transforms */ + float cell_dim[3], half_cell_dim[3]; + cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x); + cell_dim[1] = 2.0f / (float)(prb->grid_resolution_y); + cell_dim[2] = 2.0f / (float)(prb->grid_resolution_z); + + mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); + + /* First cell. */ + copy_v3_fl(prb_data->corner, -1.0f); + add_v3_v3(prb_data->corner, half_cell_dim); + mul_m4_v3(ob->obmat, prb_data->corner); + + /* Opposite neighbor cell. */ + copy_v3_fl3(prb_data->increment_x, cell_dim[0], 0.0f, 0.0f); + add_v3_v3(prb_data->increment_x, half_cell_dim); + add_v3_fl(prb_data->increment_x, -1.0f); + mul_m4_v3(ob->obmat, prb_data->increment_x); + sub_v3_v3(prb_data->increment_x, prb_data->corner); + + copy_v3_fl3(prb_data->increment_y, 0.0f, cell_dim[1], 0.0f); + add_v3_v3(prb_data->increment_y, half_cell_dim); + add_v3_fl(prb_data->increment_y, -1.0f); + mul_m4_v3(ob->obmat, prb_data->increment_y); + sub_v3_v3(prb_data->increment_y, prb_data->corner); + + copy_v3_fl3(prb_data->increment_z, 0.0f, 0.0f, cell_dim[2]); + add_v3_v3(prb_data->increment_z, half_cell_dim); + add_v3_fl(prb_data->increment_z, -1.0f); + mul_m4_v3(ob->obmat, prb_data->increment_z); + sub_v3_v3(prb_data->increment_z, prb_data->corner); + + uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z; + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->lightprobe_grid, psl->lightprobes); + DRW_shgroup_uniform_int_copy(grp, "call_id", *call_id); + DRW_shgroup_uniform_int(grp, "baseId", call_id, 1); /* that's correct */ + DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1); + DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1); + DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1); + DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1); + DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1); + DRW_shgroup_call_procedural_points_add(grp, cell_count, NULL); + } + else if (prb->type == LIGHTPROBE_TYPE_CUBE) { + float draw_size = 1.0f; + float probe_cube_mat[4][4]; + // prb_data->draw_size = prb->data_draw_size * 0.1f; + // unit_m4(prb_data->probe_cube_mat); + // copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]); + + DRWShadingGroup *grp = shgroup_theme_id_to_probe_cube_outline_shgrp( + stl, theme_id, ob->base_flag); + /* TODO remove or change the drawing of the cube probes. Theses line draws nothing on purpose + * to keep the call ids correct. */ + zero_m4(probe_cube_mat); + DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, probe_cube_mat); + } + else { + float draw_size = 1.0f; + DRWShadingGroup *grp = shgroup_theme_id_to_probe_planar_outline_shgrp(stl, theme_id); + DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, ob->obmat); + } + + *call_id += 1; + } + + switch (prb->type) { + case LIGHTPROBE_TYPE_PLANAR: + DRW_shgroup_call_dynamic_add(sgl->probe_planar, ob->obmat[3], color); + break; + case LIGHTPROBE_TYPE_GRID: + DRW_shgroup_call_dynamic_add(sgl->probe_grid, ob->obmat[3], color); + break; + case LIGHTPROBE_TYPE_CUBE: + default: + DRW_shgroup_call_dynamic_add(sgl->probe_cube, ob->obmat[3], color); + break; + } + + if (prb->type == LIGHTPROBE_TYPE_PLANAR) { + float mat[4][4]; + copy_m4_m4(mat, ob->obmat); + normalize_m4(mat); + + DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, &ob->empty_drawsize, mat); + DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, &ob->empty_drawsize, mat); + + copy_m4_m4(mat, ob->obmat); + zero_v3(mat[2]); + + DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, mat); + } + + if ((prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0) { + + prb->distfalloff = (1.0f - prb->falloff) * prb->distinf; + prb->distgridinf = prb->distinf; + + if (prb->type == LIGHTPROBE_TYPE_GRID) { + prb->distfalloff += 1.0f; + prb->distgridinf += 1.0f; + } + + if (prb->type == LIGHTPROBE_TYPE_GRID || prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) { + DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distgridinf, ob->obmat); + DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distfalloff, ob->obmat); + } + else if (prb->type == LIGHTPROBE_TYPE_PLANAR) { + float rangemat[4][4]; + copy_m4_m4(rangemat, ob->obmat); + normalize_v3(rangemat[2]); + mul_v3_fl(rangemat[2], prb->distinf); + + DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat); + + copy_m4_m4(rangemat, ob->obmat); + normalize_v3(rangemat[2]); + mul_v3_fl(rangemat[2], prb->distfalloff); + + DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat); + } + else { + DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distgridinf, ob->obmat); + DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distfalloff, ob->obmat); + } + } + + if ((prb->flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0) { + if (prb->type != LIGHTPROBE_TYPE_PLANAR) { + float(*obmat)[4], *dist; + + if ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) { + dist = &prb->distpar; + /* TODO object parallax */ + obmat = ob->obmat; + } + else { + dist = &prb->distinf; + obmat = ob->obmat; + } + + if (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) { + DRW_shgroup_call_dynamic_add(sgl->cube, color, dist, obmat); + } + else { + DRW_shgroup_call_dynamic_add(sgl->sphere, color, dist, obmat); + } + } + } + + if ((prb->flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0) { + if (prb->type != LIGHTPROBE_TYPE_PLANAR) { + static const float cubefacemat[6][4][4] = { + {{0.0, 0.0, -1.0, 0.0}, + {0.0, -1.0, 0.0, 0.0}, + {-1.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}, + {{0.0, 0.0, 1.0, 0.0}, + {0.0, -1.0, 0.0, 0.0}, + {1.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}, + {{1.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, -1.0, 0.0}, + {0.0, 1.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}, + {{1.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 1.0, 0.0}, + {0.0, -1.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}, + {{1.0, 0.0, 0.0, 0.0}, + {0.0, -1.0, 0.0, 0.0}, + {0.0, 0.0, -1.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}, + {{-1.0, 0.0, 0.0, 0.0}, + {0.0, -1.0, 0.0, 0.0}, + {0.0, 0.0, 1.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}, + }; + + for (int i = 0; i < 6; ++i) { + float clipmat[4][4]; + normalize_m4_m4(clipmat, ob->obmat); + mul_m4_m4m4(clipmat, clipmat, cubefacemat[i]); + + DRW_shgroup_call_dynamic_add( + sgl->light_buflimit, color, &prb->clipsta, &prb->clipend, clipmat); + DRW_shgroup_call_dynamic_add( + sgl->light_buflimit_points, color, &prb->clipsta, &prb->clipend, clipmat); + } + } + } + + /* Line and point going to the ground */ + if (prb->type == LIGHTPROBE_TYPE_CUBE) { + DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]); + DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]); + } } -static void DRW_shgroup_relationship_lines( - OBJECT_ShadingGroupList *sgl, - Depsgraph *depsgraph, - Scene *scene, - Object *ob) +static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl, + Depsgraph *depsgraph, + Scene *scene, + Object *ob) { - if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->runtime.parent_display_origin); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); - } - - if (ob->rigidbody_constraint) { - Object *rbc_ob1 = ob->rigidbody_constraint->ob1; - Object *rbc_ob2 = ob->rigidbody_constraint->ob2; - if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob1->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); - } - if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob2->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); - } - } - - /* Drawing the constraint lines */ - if (!BLI_listbase_is_empty(&ob->constraints)) { - bConstraint *curcon; - bConstraintOb *cob; - ListBase *list = &ob->constraints; - - cob = BKE_constraints_make_evalob(depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - - for (curcon = list->first; curcon; curcon = curcon->next) { - if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) { - /* special case for object solver and follow track constraints because they don't fill - * constraint targets properly (design limitation -- scene is needed for their target - * but it can't be accessed from get_targets callback) */ - - Object *camob = NULL; - - if (curcon->type == CONSTRAINT_TYPE_FOLLOWTRACK) { - bFollowTrackConstraint *data = (bFollowTrackConstraint *)curcon->data; - - camob = data->camera ? data->camera : scene->camera; - } - else if (curcon->type == CONSTRAINT_TYPE_OBJECTSOLVER) { - bObjectSolverConstraint *data = (bObjectSolverConstraint *)curcon->data; - - camob = data->camera ? data->camera : scene->camera; - } - - if (camob) { - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, camob->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]); - } - } - else { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); - - if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) { - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - cti->get_constraint_targets(curcon, &targets); - - for (ct = targets.first; ct; ct = ct->next) { - /* calculate target's matrix */ - if (cti->get_target_matrix) { - cti->get_target_matrix(depsgraph, - curcon, - cob, - ct, - DEG_get_ctime(depsgraph)); - } - else { - unit_m4(ct->matrix); - } - - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ct->matrix[3]); - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]); - } - - if (cti->flush_constraint_targets) { - cti->flush_constraint_targets(curcon, &targets, 1); - } - } - } - } - - BKE_constraints_clear_evalob(cob); - } + if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) { + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->runtime.parent_display_origin); + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); + } + + if (ob->rigidbody_constraint) { + Object *rbc_ob1 = ob->rigidbody_constraint->ob1; + Object *rbc_ob2 = ob->rigidbody_constraint->ob2; + if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) { + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob1->obmat[3]); + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); + } + if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) { + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob2->obmat[3]); + DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); + } + } + + /* Drawing the constraint lines */ + if (!BLI_listbase_is_empty(&ob->constraints)) { + bConstraint *curcon; + bConstraintOb *cob; + ListBase *list = &ob->constraints; + + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + + for (curcon = list->first; curcon; curcon = curcon->next) { + if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) { + /* special case for object solver and follow track constraints because they don't fill + * constraint targets properly (design limitation -- scene is needed for their target + * but it can't be accessed from get_targets callback) */ + + Object *camob = NULL; + + if (curcon->type == CONSTRAINT_TYPE_FOLLOWTRACK) { + bFollowTrackConstraint *data = (bFollowTrackConstraint *)curcon->data; + + camob = data->camera ? data->camera : scene->camera; + } + else if (curcon->type == CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data = (bObjectSolverConstraint *)curcon->data; + + camob = data->camera ? data->camera : scene->camera; + } + + if (camob) { + DRW_shgroup_call_dynamic_add(sgl->constraint_lines, camob->obmat[3]); + DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]); + } + } + else { + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); + + if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) { + ListBase targets = {NULL, NULL}; + bConstraintTarget *ct; + + cti->get_constraint_targets(curcon, &targets); + + for (ct = targets.first; ct; ct = ct->next) { + /* calculate target's matrix */ + if (cti->get_target_matrix) { + cti->get_target_matrix(depsgraph, curcon, cob, ct, DEG_get_ctime(depsgraph)); + } + else { + unit_m4(ct->matrix); + } + + DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ct->matrix[3]); + DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]); + } + + if (cti->flush_constraint_targets) { + cti->flush_constraint_targets(curcon, &targets, 1); + } + } + } + } + + BKE_constraints_clear_evalob(cob); + } } -static void DRW_shgroup_object_center(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer, View3D *v3d) +static void DRW_shgroup_object_center(OBJECT_StorageList *stl, + Object *ob, + ViewLayer *view_layer, + View3D *v3d) { - if (v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_ORIGINS) { - return; - } - const bool is_library = ob->id.us > 1 || ID_IS_LINKED(ob); - DRWShadingGroup *shgroup; - - if (ob == OBACT(view_layer)) { - shgroup = stl->g_data->center_active; - } - else if (ob->base_flag & BASE_SELECTED) { - if (is_library) { - shgroup = stl->g_data->center_selected_lib; - } - else { - shgroup = stl->g_data->center_selected; - } - } - else if (v3d->flag & V3D_DRAW_CENTERS) { - if (is_library) { - shgroup = stl->g_data->center_deselected_lib; - } - else { - shgroup = stl->g_data->center_deselected; - } - } - else { - return; - } - - DRW_shgroup_call_dynamic_add(shgroup, ob->obmat[3]); + if (v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_ORIGINS) { + return; + } + const bool is_library = ob->id.us > 1 || ID_IS_LINKED(ob); + DRWShadingGroup *shgroup; + + if (ob == OBACT(view_layer)) { + shgroup = stl->g_data->center_active; + } + else if (ob->base_flag & BASE_SELECTED) { + if (is_library) { + shgroup = stl->g_data->center_selected_lib; + } + else { + shgroup = stl->g_data->center_selected; + } + } + else if (v3d->flag & V3D_DRAW_CENTERS) { + if (is_library) { + shgroup = stl->g_data->center_deselected_lib; + } + else { + shgroup = stl->g_data->center_deselected; + } + } + else { + return; + } + + DRW_shgroup_call_dynamic_add(shgroup, ob->obmat[3]); } static void DRW_shgroup_texture_space(OBJECT_ShadingGroupList *sgl, Object *ob, int theme_id) { - if (ob->data == NULL) { - return; - } - - ID *ob_data = ob->data; - float *texcoloc = NULL; - float *texcosize = NULL; - - switch (GS(ob_data->name)) { - case ID_ME: - BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize); - break; - case ID_CU: - { - Curve *cu = (Curve *)ob_data; - if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) { - BKE_curve_texspace_calc(cu); - } - texcoloc = cu->loc; - texcosize = cu->size; - break; - } - case ID_MB: - { - MetaBall *mb = (MetaBall *)ob_data; - texcoloc = mb->loc; - texcosize = mb->size; - break; - } - default: - BLI_assert(0); - } - - float tmp[4][4] = {{0.0f}}, one = 1.0f; - tmp[0][0] = texcosize[0]; - tmp[1][1] = texcosize[1]; - tmp[2][2] = texcosize[2]; - tmp[3][0] = texcoloc[0]; - tmp[3][1] = texcoloc[1]; - tmp[3][2] = texcoloc[2]; - tmp[3][3] = 1.0f; - - mul_m4_m4m4(tmp, ob->obmat, tmp); - - float color[4]; - UI_GetThemeColor4fv(theme_id, color); - - DRW_shgroup_call_dynamic_add(sgl->texspace, color, &one, tmp); + if (ob->data == NULL) { + return; + } + + ID *ob_data = ob->data; + float *texcoloc = NULL; + float *texcosize = NULL; + + switch (GS(ob_data->name)) { + case ID_ME: + BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize); + break; + case ID_CU: { + Curve *cu = (Curve *)ob_data; + if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) { + BKE_curve_texspace_calc(cu); + } + texcoloc = cu->loc; + texcosize = cu->size; + break; + } + case ID_MB: { + MetaBall *mb = (MetaBall *)ob_data; + texcoloc = mb->loc; + texcosize = mb->size; + break; + } + default: + BLI_assert(0); + } + + float tmp[4][4] = {{0.0f}}, one = 1.0f; + tmp[0][0] = texcosize[0]; + tmp[1][1] = texcosize[1]; + tmp[2][2] = texcosize[2]; + tmp[3][0] = texcoloc[0]; + tmp[3][1] = texcoloc[1]; + tmp[3][2] = texcoloc[2]; + tmp[3][3] = 1.0f; + + mul_m4_m4m4(tmp, ob->obmat, tmp); + + float color[4]; + UI_GetThemeColor4fv(theme_id, color); + + DRW_shgroup_call_dynamic_add(sgl->texspace, color, &one, tmp); } static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int theme_id) { - float color[4], center[3], size[3], tmp[4][4], final_mat[4][4], one = 1.0f; - BoundBox bb_local; - - if (ob->type == OB_MBALL && !BKE_mball_is_basis(ob)) { - return; - } - - BoundBox *bb = BKE_object_boundbox_get(ob); - - if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, - OB_MBALL, OB_ARMATURE, OB_LATTICE, OB_GPENCIL)) - { - const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; - bb = &bb_local; - BKE_boundbox_init_from_minmax(bb, min, max); - } - - UI_GetThemeColor4fv(theme_id, color); - BKE_boundbox_calc_center_aabb(bb, center); - BKE_boundbox_calc_size_aabb(bb, size); - - switch (ob->boundtype) { - case OB_BOUND_BOX: - size_to_mat4(tmp, size); - copy_v3_v3(tmp[3], center); - mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, tmp); - break; - case OB_BOUND_SPHERE: - size[0] = max_fff(size[0], size[1], size[2]); - size[1] = size[2] = size[0]; - size_to_mat4(tmp, size); - copy_v3_v3(tmp[3], center); - mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->sphere, color, &one, tmp); - break; - case OB_BOUND_CYLINDER: - size[0] = max_ff(size[0], size[1]); - size[1] = size[0]; - size_to_mat4(tmp, size); - copy_v3_v3(tmp[3], center); - mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->cylinder, color, &one, tmp); - break; - case OB_BOUND_CONE: - size[0] = max_ff(size[0], size[1]); - size[1] = size[0]; - size_to_mat4(tmp, size); - copy_v3_v3(tmp[3], center); - /* Cone batch has base at 0 and is pointing towards +Y. */ - swap_v3_v3(tmp[1], tmp[2]); - tmp[3][2] -= size[2]; - mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->cone, color, &one, tmp); - break; - case OB_BOUND_CAPSULE: - size[0] = max_ff(size[0], size[1]); - size[1] = size[0]; - scale_m4_fl(tmp, size[0]); - copy_v2_v2(tmp[3], center); - tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]); - mul_m4_m4m4(final_mat, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat); - negate_v3(tmp[2]); - tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]); - mul_m4_m4m4(final_mat, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat); - tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f); - mul_m4_m4m4(final_mat, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->capsule_body, color, &one, final_mat); - break; - } + float color[4], center[3], size[3], tmp[4][4], final_mat[4][4], one = 1.0f; + BoundBox bb_local; + + if (ob->type == OB_MBALL && !BKE_mball_is_basis(ob)) { + return; + } + + BoundBox *bb = BKE_object_boundbox_get(ob); + + if (!ELEM(ob->type, + OB_MESH, + OB_CURVE, + OB_SURF, + OB_FONT, + OB_MBALL, + OB_ARMATURE, + OB_LATTICE, + OB_GPENCIL)) { + const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; + bb = &bb_local; + BKE_boundbox_init_from_minmax(bb, min, max); + } + + UI_GetThemeColor4fv(theme_id, color); + BKE_boundbox_calc_center_aabb(bb, center); + BKE_boundbox_calc_size_aabb(bb, size); + + switch (ob->boundtype) { + case OB_BOUND_BOX: + size_to_mat4(tmp, size); + copy_v3_v3(tmp[3], center); + mul_m4_m4m4(tmp, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, tmp); + break; + case OB_BOUND_SPHERE: + size[0] = max_fff(size[0], size[1], size[2]); + size[1] = size[2] = size[0]; + size_to_mat4(tmp, size); + copy_v3_v3(tmp[3], center); + mul_m4_m4m4(tmp, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->sphere, color, &one, tmp); + break; + case OB_BOUND_CYLINDER: + size[0] = max_ff(size[0], size[1]); + size[1] = size[0]; + size_to_mat4(tmp, size); + copy_v3_v3(tmp[3], center); + mul_m4_m4m4(tmp, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->cylinder, color, &one, tmp); + break; + case OB_BOUND_CONE: + size[0] = max_ff(size[0], size[1]); + size[1] = size[0]; + size_to_mat4(tmp, size); + copy_v3_v3(tmp[3], center); + /* Cone batch has base at 0 and is pointing towards +Y. */ + swap_v3_v3(tmp[1], tmp[2]); + tmp[3][2] -= size[2]; + mul_m4_m4m4(tmp, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->cone, color, &one, tmp); + break; + case OB_BOUND_CAPSULE: + size[0] = max_ff(size[0], size[1]); + size[1] = size[0]; + scale_m4_fl(tmp, size[0]); + copy_v2_v2(tmp[3], center); + tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]); + mul_m4_m4m4(final_mat, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat); + negate_v3(tmp[2]); + tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]); + mul_m4_m4m4(final_mat, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat); + tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f); + mul_m4_m4m4(final_mat, ob->obmat, tmp); + DRW_shgroup_call_dynamic_add(sgl->capsule_body, color, &one, final_mat); + break; + } } -static void OBJECT_cache_populate_particles( - OBJECT_Shaders *sh_data, - Object *ob, - OBJECT_PassList *psl) +static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data, + Object *ob, + OBJECT_PassList *psl) { - for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { - if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { - continue; - } - - ParticleSettings *part = psys->part; - int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; - - static float mat[4][4]; - unit_m4(mat); - - if (draw_as != PART_DRAW_PATH) { - struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys); - DRWShadingGroup *shgrp = NULL; - static int screen_space[2] = {0, 1}; - static float def_prim_col[3] = {0.5f, 0.5f, 0.5f}; - static float def_sec_col[3] = {1.0f, 1.0f, 1.0f}; - - /* Dummy particle format for instancing to work. */ - DRW_shgroup_instance_format(e_data.particle_format, {{"dummy", DRW_ATTR_FLOAT, 1}}); - - Material *ma = give_current_material(ob, part->omat); - - switch (draw_as) { - case PART_DRAW_DOT: - shgrp = DRW_shgroup_create(sh_data->part_dot, psl->particle); - DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); - DRW_shgroup_uniform_vec3(shgrp, "outlineColor", ma ? &ma->specr : def_sec_col, 1); - DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1); - DRW_shgroup_uniform_float(shgrp, "size", &part->draw_size, 1); - DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); - DRW_shgroup_call_add(shgrp, geom, mat); - break; - case PART_DRAW_CROSS: - shgrp = DRW_shgroup_instance_create( - sh_data->part_prim, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS), - e_data.particle_format); - DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); - DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); - DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); - break; - case PART_DRAW_CIRC: - shgrp = DRW_shgroup_instance_create( - sh_data->part_prim, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC), - e_data.particle_format); - DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); - DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); - DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1); - break; - case PART_DRAW_AXIS: - shgrp = DRW_shgroup_instance_create( - sh_data->part_axis, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS), - e_data.particle_format); - DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); - break; - default: - break; - } - - if (shgrp) { - if (draw_as != PART_DRAW_DOT) { - DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); - DRW_shgroup_instance_batch(shgrp, geom); - } - } - } - } + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { + continue; + } + + ParticleSettings *part = psys->part; + int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + static float mat[4][4]; + unit_m4(mat); + + if (draw_as != PART_DRAW_PATH) { + struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys); + DRWShadingGroup *shgrp = NULL; + static int screen_space[2] = {0, 1}; + static float def_prim_col[3] = {0.5f, 0.5f, 0.5f}; + static float def_sec_col[3] = {1.0f, 1.0f, 1.0f}; + + /* Dummy particle format for instancing to work. */ + DRW_shgroup_instance_format(e_data.particle_format, {{"dummy", DRW_ATTR_FLOAT, 1}}); + + Material *ma = give_current_material(ob, part->omat); + + switch (draw_as) { + case PART_DRAW_DOT: + shgrp = DRW_shgroup_create(sh_data->part_dot, psl->particle); + DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); + DRW_shgroup_uniform_vec3(shgrp, "outlineColor", ma ? &ma->specr : def_sec_col, 1); + DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1); + DRW_shgroup_uniform_float(shgrp, "size", &part->draw_size, 1); + DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); + DRW_shgroup_call_add(shgrp, geom, mat); + break; + case PART_DRAW_CROSS: + shgrp = DRW_shgroup_instance_create(sh_data->part_prim, + psl->particle, + DRW_cache_particles_get_prim(PART_DRAW_CROSS), + e_data.particle_format); + DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); + DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); + DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); + break; + case PART_DRAW_CIRC: + shgrp = DRW_shgroup_instance_create(sh_data->part_prim, + psl->particle, + DRW_cache_particles_get_prim(PART_DRAW_CIRC), + e_data.particle_format); + DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); + DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); + DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1); + break; + case PART_DRAW_AXIS: + shgrp = DRW_shgroup_instance_create(sh_data->part_axis, + psl->particle, + DRW_cache_particles_get_prim(PART_DRAW_AXIS), + e_data.particle_format); + DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); + break; + default: + break; + } + + if (shgrp) { + if (draw_as != PART_DRAW_DOT) { + DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); + DRW_shgroup_instance_batch(shgrp, geom); + } + } + } + } } static void OBJECT_gpencil_color_names(Object *ob, struct DRWTextStore *dt, uchar color[4]) { - if (ob->mode != OB_MODE_EDIT_GPENCIL) { - return; - } - - bGPdata *gpd = (bGPdata *)ob->data; - if (gpd == NULL) { - return; - } - - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - bGPDframe *gpf = gpl->actframe; - if (gpf == NULL) { - continue; - } - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - Material *ma = give_current_material(ob, gps->mat_nr + 1); - if (ma == NULL) { - continue; - } - - MaterialGPencilStyle *gp_style = ma->gp_style; - /* skip stroke if it doesn't have any valid data */ - if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) { - continue; - } - /* check if the color is visible */ - if (gp_style->flag & GP_STYLE_COLOR_HIDE) { - continue; - } - - /* only if selected */ - if (gps->flag & GP_STROKE_SELECT) { - float fpt[3]; - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - if (pt->flag & GP_SPOINT_SELECT) { - mul_v3_m4v3(fpt, ob->obmat, &pt->x); - DRW_text_cache_add( - dt, fpt, - ma->id.name + 2, strlen(ma->id.name + 2), - 10, 0, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color); - break; - } - } - } - } - } + if (ob->mode != OB_MODE_EDIT_GPENCIL) { + return; + } + + bGPdata *gpd = (bGPdata *)ob->data; + if (gpd == NULL) { + return; + } + + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + bGPDframe *gpf = gpl->actframe; + if (gpf == NULL) { + continue; + } + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + Material *ma = give_current_material(ob, gps->mat_nr + 1); + if (ma == NULL) { + continue; + } + + MaterialGPencilStyle *gp_style = ma->gp_style; + /* skip stroke if it doesn't have any valid data */ + if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) { + continue; + } + /* check if the color is visible */ + if (gp_style->flag & GP_STYLE_COLOR_HIDE) { + continue; + } + + /* only if selected */ + if (gps->flag & GP_STROKE_SELECT) { + float fpt[3]; + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (pt->flag & GP_SPOINT_SELECT) { + mul_v3_m4v3(fpt, ob->obmat, &pt->x); + DRW_text_cache_add(dt, + fpt, + ma->id.name + 2, + strlen(ma->id.name + 2), + 10, + 0, + DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, + color); + break; + } + } + } + } + } } static void OBJECT_cache_populate(void *vedata, Object *ob) { - OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; - OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; - OBJECT_ShadingGroupList *sgl = (ob->dtx & OB_DRAWXRAY) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool is_edit_mode = (ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob); - ViewLayer *view_layer = draw_ctx->view_layer; - Scene *scene = draw_ctx->scene; - View3D *v3d = draw_ctx->v3d; - RegionView3D *rv3d = draw_ctx->rv3d; - ModifierData *md = NULL; - int theme_id = TH_UNDEFINED; - const int ob_visibility = DRW_object_visibility_in_active_context(ob); - OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - /* Handle particles first in case the emitter itself shouldn't be rendered. */ - if (ob_visibility & OB_VISIBLE_PARTICLES) { - OBJECT_cache_populate_particles(sh_data, ob, psl); - } - - if ((ob_visibility & OB_VISIBLE_SELF) == 0) { - return; - } - - const bool do_outlines = ( - (draw_ctx->v3d->flag & V3D_SELECT_OUTLINE) && ((ob->base_flag & BASE_SELECTED) != 0) && - ((DRW_object_is_renderable(ob) && (ob->dt > OB_WIRE)) || (ob->dt == OB_WIRE))); - const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); - const bool hide_object_extra = ( - (v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) != 0 && - /* Show if this is the camera we're looking through - * since it's useful for moving the camera. */ - (((rv3d->persp == RV3D_CAMOB) && ((ID *)v3d->camera == ob->id.orig_id)) == 0)); - - if (do_outlines) { - if (!BKE_object_is_in_editmode(ob) && - !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) - { - struct GPUBatch *geom; - - /* This fixes only the biggest case which is a plane in ortho view. */ - int flat_axis = 0; - bool is_flat_object_viewed_from_side = ( - (rv3d->persp == RV3D_ORTHO) && - DRW_object_is_flat(ob, &flat_axis) && - DRW_object_axis_orthogonal_to_view(ob, flat_axis)); - - if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) { - geom = DRW_cache_object_edge_detection_get(ob, NULL); - } - else { - geom = DRW_cache_object_surface_get(ob); - } - - if (geom) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or_null(stl, theme_id, ob->base_flag); - if (shgroup != NULL) { - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - } - } - } - - switch (ob->type) { - case OB_MESH: - { - if (hide_object_extra) { - break; - } - Mesh *me = ob->data; - if (!is_edit_mode && me->totedge == 0) { - struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob); - if (geom) { - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_point(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - } - else { - bool has_edit_mesh_cage = false; - /* TODO: Should be its own function. */ - if (is_edit_mode) { - BMEditMesh *embm = me->edit_mesh; - has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); - } - if ((!is_edit_mode && me->totedge > 0) || has_edit_mesh_cage) { - struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob); - if (geom) { - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - } - } - break; - } - case OB_SURF: - { - if (hide_object_extra) { - break; - } - struct GPUBatch *geom = DRW_cache_surf_edge_wire_get(ob); - if (geom == NULL) { - break; - } - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - break; - } - case OB_LATTICE: - { - if (!is_edit_mode) { - if (hide_object_extra) { - break; - } - struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false); - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - break; - } - case OB_CURVE: - { - if (!is_edit_mode) { - if (hide_object_extra) { - break; - } - struct GPUBatch *geom = DRW_cache_curve_edge_wire_get(ob); - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - break; - } - case OB_MBALL: - { - if (!is_edit_mode) { - DRW_shgroup_mball_handles(sgl, ob, view_layer); - } - break; - } - case OB_LAMP: - if (hide_object_extra) { - break; - } - DRW_shgroup_light(sgl, ob, view_layer); - break; - case OB_CAMERA: - if (hide_object_extra) { - break; - } - DRW_shgroup_camera(sgl, ob, view_layer); - break; - case OB_EMPTY: - if (hide_object_extra) { - break; - } - DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg); - break; - case OB_SPEAKER: - if (hide_object_extra) { - break; - } - DRW_shgroup_speaker(sgl, ob, view_layer); - break; - case OB_LIGHTPROBE: - if (hide_object_extra) { - break; - } - DRW_shgroup_lightprobe(sh_data, stl, psl, ob, view_layer); - break; - case OB_ARMATURE: - { - if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || - (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) || - ((ob->dt < OB_WIRE) && !DRW_state_is_select())) - { - break; - } - bArmature *arm = ob->data; - if (arm->edbo == NULL) { - if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) { - bool is_wire = (v3d->shading.type == OB_WIRE) || (ob->dt <= OB_WIRE) || XRAY_FLAG_ENABLED(v3d); - DRWArmaturePasses passes = { - .bone_solid = (is_wire) ? NULL : sgl->bone_solid, - .bone_outline = sgl->bone_outline, - .bone_wire = sgl->bone_wire, - .bone_envelope = sgl->bone_envelope, - .bone_axes = sgl->bone_axes, - .relationship_lines = NULL, /* Don't draw relationship lines */ - }; - DRW_shgroup_armature_object(ob, view_layer, passes, is_wire); - } - } - break; - } - case OB_FONT: - { - if (hide_object_extra) { - break; - } - Curve *cu = (Curve *)ob->data; - bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; - if (!has_surface) { - struct GPUBatch *geom = DRW_cache_text_edge_wire_get(ob); - if (geom) { - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - } - break; - } - default: - break; - } - - if (ob->pd && ob->pd->forcefield) { - DRW_shgroup_forcefield(sgl, ob, view_layer); - } - - if ((ob->dt == OB_BOUNDBOX) && - !ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE)) - { - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRW_shgroup_bounds(sgl, ob, theme_id); - } - - /* don't show object extras in set's */ - if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) { - if ((draw_ctx->object_mode & (OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL)) == 0) { - DRW_shgroup_object_center(stl, ob, view_layer, v3d); - } - - if (show_relations && !DRW_state_is_select()) { - DRW_shgroup_relationship_lines(sgl, draw_ctx->depsgraph, scene, ob); - } - - const bool draw_extra = (ob->dtx != 0); - if (draw_extra && (theme_id == TH_UNDEFINED)) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - - if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) { - struct DRWTextStore *dt = DRW_text_cache_ensure(); - - uchar color[4]; - UI_GetThemeColor4ubv(theme_id, color); - - DRW_text_cache_add( - dt, ob->obmat[3], - ob->id.name + 2, strlen(ob->id.name + 2), - 10, 0, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color); - - /* draw grease pencil stroke names */ - if (ob->type == OB_GPENCIL) { - OBJECT_gpencil_color_names(ob, dt, color); - } - } - - if ((ob->dtx & OB_TEXSPACE) && ELEM(ob->type, OB_MESH, OB_CURVE, OB_MBALL)) { - DRW_shgroup_texture_space(sgl, ob, theme_id); - } - - /* Don't draw bounding box again if draw type is bound box. */ - if ((ob->dtx & OB_DRAWBOUNDOX) && - (ob->dt != OB_BOUNDBOX) && - !ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE)) - { - DRW_shgroup_bounds(sgl, ob, theme_id); - } - - if (ob->dtx & OB_AXIS) { - float *color, axes_size = 1.0f; - DRW_object_wire_theme_get(ob, view_layer, &color); - - DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, &axes_size, ob->obmat); - } - - if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && - (((SmokeModifierData *)md)->domain != NULL)) - { - DRW_shgroup_volume_extra(sgl, ob, view_layer, scene, md); - } - } + OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + OBJECT_ShadingGroupList *sgl = (ob->dtx & OB_DRAWXRAY) ? &stl->g_data->sgl_ghost : + &stl->g_data->sgl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool is_edit_mode = (ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob); + ViewLayer *view_layer = draw_ctx->view_layer; + Scene *scene = draw_ctx->scene; + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + ModifierData *md = NULL; + int theme_id = TH_UNDEFINED; + const int ob_visibility = DRW_object_visibility_in_active_context(ob); + OBJECT_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + /* Handle particles first in case the emitter itself shouldn't be rendered. */ + if (ob_visibility & OB_VISIBLE_PARTICLES) { + OBJECT_cache_populate_particles(sh_data, ob, psl); + } + + if ((ob_visibility & OB_VISIBLE_SELF) == 0) { + return; + } + + const bool do_outlines = ((draw_ctx->v3d->flag & V3D_SELECT_OUTLINE) && + ((ob->base_flag & BASE_SELECTED) != 0) && + ((DRW_object_is_renderable(ob) && (ob->dt > OB_WIRE)) || + (ob->dt == OB_WIRE))); + const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); + const bool hide_object_extra = ((v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) != 0 && + /* Show if this is the camera we're looking through + * since it's useful for moving the camera. */ + (((rv3d->persp == RV3D_CAMOB) && + ((ID *)v3d->camera == ob->id.orig_id)) == 0)); + + if (do_outlines) { + if (!BKE_object_is_in_editmode(ob) && + !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) { + struct GPUBatch *geom; + + /* This fixes only the biggest case which is a plane in ortho view. */ + int flat_axis = 0; + bool is_flat_object_viewed_from_side = ((rv3d->persp == RV3D_ORTHO) && + DRW_object_is_flat(ob, &flat_axis) && + DRW_object_axis_orthogonal_to_view(ob, flat_axis)); + + if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) { + geom = DRW_cache_object_edge_detection_get(ob, NULL); + } + else { + geom = DRW_cache_object_surface_get(ob); + } + + if (geom) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or_null( + stl, theme_id, ob->base_flag); + if (shgroup != NULL) { + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + } + } + + switch (ob->type) { + case OB_MESH: { + if (hide_object_extra) { + break; + } + Mesh *me = ob->data; + if (!is_edit_mode && me->totedge == 0) { + struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRWShadingGroup *shgroup = shgroup_theme_id_to_point(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + else { + bool has_edit_mesh_cage = false; + /* TODO: Should be its own function. */ + if (is_edit_mode) { + BMEditMesh *embm = me->edit_mesh; + has_edit_mesh_cage = embm->mesh_eval_cage && + (embm->mesh_eval_cage != embm->mesh_eval_final); + } + if ((!is_edit_mode && me->totedge > 0) || has_edit_mesh_cage) { + struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + } + break; + } + case OB_SURF: { + if (hide_object_extra) { + break; + } + struct GPUBatch *geom = DRW_cache_surf_edge_wire_get(ob); + if (geom == NULL) { + break; + } + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object_add(shgroup, geom, ob); + break; + } + case OB_LATTICE: { + if (!is_edit_mode) { + if (hide_object_extra) { + break; + } + struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false); + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + break; + } + case OB_CURVE: { + if (!is_edit_mode) { + if (hide_object_extra) { + break; + } + struct GPUBatch *geom = DRW_cache_curve_edge_wire_get(ob); + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + break; + } + case OB_MBALL: { + if (!is_edit_mode) { + DRW_shgroup_mball_handles(sgl, ob, view_layer); + } + break; + } + case OB_LAMP: + if (hide_object_extra) { + break; + } + DRW_shgroup_light(sgl, ob, view_layer); + break; + case OB_CAMERA: + if (hide_object_extra) { + break; + } + DRW_shgroup_camera(sgl, ob, view_layer); + break; + case OB_EMPTY: + if (hide_object_extra) { + break; + } + DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg); + break; + case OB_SPEAKER: + if (hide_object_extra) { + break; + } + DRW_shgroup_speaker(sgl, ob, view_layer); + break; + case OB_LIGHTPROBE: + if (hide_object_extra) { + break; + } + DRW_shgroup_lightprobe(sh_data, stl, psl, ob, view_layer); + break; + case OB_ARMATURE: { + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) || + ((ob->dt < OB_WIRE) && !DRW_state_is_select())) { + break; + } + bArmature *arm = ob->data; + if (arm->edbo == NULL) { + if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) { + bool is_wire = (v3d->shading.type == OB_WIRE) || (ob->dt <= OB_WIRE) || + XRAY_FLAG_ENABLED(v3d); + DRWArmaturePasses passes = { + .bone_solid = (is_wire) ? NULL : sgl->bone_solid, + .bone_outline = sgl->bone_outline, + .bone_wire = sgl->bone_wire, + .bone_envelope = sgl->bone_envelope, + .bone_axes = sgl->bone_axes, + .relationship_lines = NULL, /* Don't draw relationship lines */ + }; + DRW_shgroup_armature_object(ob, view_layer, passes, is_wire); + } + } + break; + } + case OB_FONT: { + if (hide_object_extra) { + break; + } + Curve *cu = (Curve *)ob->data; + bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; + if (!has_surface) { + struct GPUBatch *geom = DRW_cache_text_edge_wire_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + break; + } + default: + break; + } + + if (ob->pd && ob->pd->forcefield) { + DRW_shgroup_forcefield(sgl, ob, view_layer); + } + + if ((ob->dt == OB_BOUNDBOX) && + !ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE)) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRW_shgroup_bounds(sgl, ob, theme_id); + } + + /* don't show object extras in set's */ + if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) { + if ((draw_ctx->object_mode & (OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL)) == 0) { + DRW_shgroup_object_center(stl, ob, view_layer, v3d); + } + + if (show_relations && !DRW_state_is_select()) { + DRW_shgroup_relationship_lines(sgl, draw_ctx->depsgraph, scene, ob); + } + + const bool draw_extra = (ob->dtx != 0); + if (draw_extra && (theme_id == TH_UNDEFINED)) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) { + struct DRWTextStore *dt = DRW_text_cache_ensure(); + + uchar color[4]; + UI_GetThemeColor4ubv(theme_id, color); + + DRW_text_cache_add(dt, + ob->obmat[3], + ob->id.name + 2, + strlen(ob->id.name + 2), + 10, + 0, + DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, + color); + + /* draw grease pencil stroke names */ + if (ob->type == OB_GPENCIL) { + OBJECT_gpencil_color_names(ob, dt, color); + } + } + + if ((ob->dtx & OB_TEXSPACE) && ELEM(ob->type, OB_MESH, OB_CURVE, OB_MBALL)) { + DRW_shgroup_texture_space(sgl, ob, theme_id); + } + + /* Don't draw bounding box again if draw type is bound box. */ + if ((ob->dtx & OB_DRAWBOUNDOX) && (ob->dt != OB_BOUNDBOX) && + !ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE)) { + DRW_shgroup_bounds(sgl, ob, theme_id); + } + + if (ob->dtx & OB_AXIS) { + float *color, axes_size = 1.0f; + DRW_object_wire_theme_get(ob, view_layer, &color); + + DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, &axes_size, ob->obmat); + } + + if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && + (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + (((SmokeModifierData *)md)->domain != NULL)) { + DRW_shgroup_volume_extra(sgl, ob, view_layer, scene, md); + } + } } static void OBJECT_cache_finish(void *vedata) { - OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; - DRW_pass_sort_shgroup_z(stl->g_data->sgl.image_empties); - DRW_pass_sort_shgroup_z(stl->g_data->sgl_ghost.image_empties); + DRW_pass_sort_shgroup_z(stl->g_data->sgl.image_empties); + DRW_pass_sort_shgroup_z(stl->g_data->sgl_ghost.image_empties); } static void OBJECT_draw_scene(void *vedata) { - OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; - OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; - OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; - OBJECT_PrivateData *g_data = stl->g_data; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - - int id_len_select = g_data->id_ofs_select; - int id_len_select_dupli = g_data->id_ofs_select_dupli; - int id_len_active = g_data->id_ofs_active; - int id_len_transform = g_data->id_ofs_transform; - - int id_len_prb_select = g_data->id_ofs_prb_select; - int id_len_prb_select_dupli = g_data->id_ofs_prb_select_dupli; - int id_len_prb_active = g_data->id_ofs_prb_active; - int id_len_prb_transform = g_data->id_ofs_prb_transform; - - int outline_calls = id_len_select + id_len_select_dupli + id_len_active + id_len_transform; - outline_calls += id_len_prb_select + id_len_prb_select_dupli + id_len_prb_active + id_len_prb_transform; - - float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - /* Don't draw Transparent passes in MSAA buffer. */ -// DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */ - DRW_draw_pass(stl->g_data->sgl.transp_shapes); - - MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - - DRW_draw_pass(stl->g_data->sgl.bone_solid); - DRW_draw_pass(stl->g_data->sgl.bone_wire); - DRW_draw_pass(stl->g_data->sgl.bone_outline); - DRW_draw_pass(stl->g_data->sgl.non_meshes); - DRW_draw_pass(psl->particle); - DRW_draw_pass(stl->g_data->sgl.bone_axes); - - MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - - DRW_draw_pass(stl->g_data->sgl.image_empties); - - if (DRW_state_is_fbo() && outline_calls > 0) { - DRW_stats_group_start("Outlines"); - - g_data->id_ofs_active = 1; - g_data->id_ofs_select = g_data->id_ofs_active + id_len_active + id_len_prb_active + 1; - g_data->id_ofs_select_dupli = g_data->id_ofs_select + id_len_select + id_len_prb_select + 1; - g_data->id_ofs_transform = g_data->id_ofs_select_dupli + id_len_select_dupli + id_len_prb_select_dupli + 1; - - g_data->id_ofs_prb_active = g_data->id_ofs_active + id_len_active; - g_data->id_ofs_prb_select = g_data->id_ofs_select + id_len_select; - g_data->id_ofs_prb_select_dupli = g_data->id_ofs_select_dupli + id_len_select_dupli; - g_data->id_ofs_prb_transform = g_data->id_ofs_transform + id_len_transform; - - /* Render filled polygon on a separate framebuffer */ - GPU_framebuffer_bind(fbl->outlines_fb); - GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f); - DRW_draw_pass(psl->outlines); - DRW_draw_pass(psl->lightprobes); - - /* Search outline pixels */ - GPU_framebuffer_bind(fbl->blur_fb); - DRW_draw_pass(psl->outlines_search); - - /* Expand outline to form a 3px wide line */ - GPU_framebuffer_bind(fbl->expand_fb); - DRW_draw_pass(psl->outlines_expand); - - /* Bleed color so the AA can do it's stuff */ - GPU_framebuffer_bind(fbl->blur_fb); - DRW_draw_pass(psl->outlines_bleed); - - /* restore main framebuffer */ - GPU_framebuffer_bind(dfbl->default_fb); - DRW_stats_group_end(); - } - else if (DRW_state_is_select()) { - /* Render probes spheres/planes so we can select them. */ - DRW_draw_pass(psl->lightprobes); - } - - if (DRW_state_is_fbo()) { - if (e_data.draw_grid) { - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->grid); - } - - /* Combine with scene buffer last */ - if (outline_calls > 0) { - DRW_draw_pass(psl->outlines_resolve); - } - } - - volumes_free_smoke_textures(); - batch_camera_path_free(&stl->g_data->sgl.camera_path); - - if (!DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_solid) || - !DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_wire) || - !DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_outline) || - !DRW_pass_is_empty(stl->g_data->sgl_ghost.non_meshes) || - !DRW_pass_is_empty(stl->g_data->sgl_ghost.image_empties) || - !DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_axes)) - { - if (DRW_state_is_fbo()) { - /* meh, late init to not request a depth buffer we won't use. */ - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - - GPUTexture *ghost_depth_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_object_type); - GPU_framebuffer_ensure_config(&fbl->ghost_fb, { - GPU_ATTACHMENT_TEXTURE(ghost_depth_tx), - GPU_ATTACHMENT_TEXTURE(dtxl->color), - }); - - GPU_framebuffer_bind(fbl->ghost_fb); - GPU_framebuffer_clear_depth(fbl->ghost_fb, 1.0f); - } - else if (DRW_state_is_select()) { - /* XXX `GPU_depth_range` is not a perfect solution - * since very distant geometries can still be occluded. - * Also the depth test precision of these geometries is impaired. - * However solves the selection for the vast majority of cases. */ - GPU_depth_range(0.0f, 0.01f); - } - - DRW_draw_pass(stl->g_data->sgl_ghost.transp_shapes); - DRW_draw_pass(stl->g_data->sgl_ghost.bone_solid); - DRW_draw_pass(stl->g_data->sgl_ghost.bone_wire); - DRW_draw_pass(stl->g_data->sgl_ghost.bone_outline); - DRW_draw_pass(stl->g_data->sgl_ghost.non_meshes); - DRW_draw_pass(stl->g_data->sgl_ghost.image_empties); - DRW_draw_pass(stl->g_data->sgl_ghost.bone_axes); - - if (DRW_state_is_select()) { - GPU_depth_range(0.0f, 1.0f); - } - } - - batch_camera_path_free(&stl->g_data->sgl_ghost.camera_path); - - DRW_draw_pass(psl->ob_center); + OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; + OBJECT_PrivateData *g_data = stl->g_data; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + int id_len_select = g_data->id_ofs_select; + int id_len_select_dupli = g_data->id_ofs_select_dupli; + int id_len_active = g_data->id_ofs_active; + int id_len_transform = g_data->id_ofs_transform; + + int id_len_prb_select = g_data->id_ofs_prb_select; + int id_len_prb_select_dupli = g_data->id_ofs_prb_select_dupli; + int id_len_prb_active = g_data->id_ofs_prb_active; + int id_len_prb_transform = g_data->id_ofs_prb_transform; + + int outline_calls = id_len_select + id_len_select_dupli + id_len_active + id_len_transform; + outline_calls += id_len_prb_select + id_len_prb_select_dupli + id_len_prb_active + + id_len_prb_transform; + + float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Don't draw Transparent passes in MSAA buffer. */ + // DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */ + DRW_draw_pass(stl->g_data->sgl.transp_shapes); + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + + DRW_draw_pass(stl->g_data->sgl.bone_solid); + DRW_draw_pass(stl->g_data->sgl.bone_wire); + DRW_draw_pass(stl->g_data->sgl.bone_outline); + DRW_draw_pass(stl->g_data->sgl.non_meshes); + DRW_draw_pass(psl->particle); + DRW_draw_pass(stl->g_data->sgl.bone_axes); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); + + DRW_draw_pass(stl->g_data->sgl.image_empties); + + if (DRW_state_is_fbo() && outline_calls > 0) { + DRW_stats_group_start("Outlines"); + + g_data->id_ofs_active = 1; + g_data->id_ofs_select = g_data->id_ofs_active + id_len_active + id_len_prb_active + 1; + g_data->id_ofs_select_dupli = g_data->id_ofs_select + id_len_select + id_len_prb_select + 1; + g_data->id_ofs_transform = g_data->id_ofs_select_dupli + id_len_select_dupli + + id_len_prb_select_dupli + 1; + + g_data->id_ofs_prb_active = g_data->id_ofs_active + id_len_active; + g_data->id_ofs_prb_select = g_data->id_ofs_select + id_len_select; + g_data->id_ofs_prb_select_dupli = g_data->id_ofs_select_dupli + id_len_select_dupli; + g_data->id_ofs_prb_transform = g_data->id_ofs_transform + id_len_transform; + + /* Render filled polygon on a separate framebuffer */ + GPU_framebuffer_bind(fbl->outlines_fb); + GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f); + DRW_draw_pass(psl->outlines); + DRW_draw_pass(psl->lightprobes); + + /* Search outline pixels */ + GPU_framebuffer_bind(fbl->blur_fb); + DRW_draw_pass(psl->outlines_search); + + /* Expand outline to form a 3px wide line */ + GPU_framebuffer_bind(fbl->expand_fb); + DRW_draw_pass(psl->outlines_expand); + + /* Bleed color so the AA can do it's stuff */ + GPU_framebuffer_bind(fbl->blur_fb); + DRW_draw_pass(psl->outlines_bleed); + + /* restore main framebuffer */ + GPU_framebuffer_bind(dfbl->default_fb); + DRW_stats_group_end(); + } + else if (DRW_state_is_select()) { + /* Render probes spheres/planes so we can select them. */ + DRW_draw_pass(psl->lightprobes); + } + + if (DRW_state_is_fbo()) { + if (e_data.draw_grid) { + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->grid); + } + + /* Combine with scene buffer last */ + if (outline_calls > 0) { + DRW_draw_pass(psl->outlines_resolve); + } + } + + volumes_free_smoke_textures(); + batch_camera_path_free(&stl->g_data->sgl.camera_path); + + if (!DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_solid) || + !DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_wire) || + !DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_outline) || + !DRW_pass_is_empty(stl->g_data->sgl_ghost.non_meshes) || + !DRW_pass_is_empty(stl->g_data->sgl_ghost.image_empties) || + !DRW_pass_is_empty(stl->g_data->sgl_ghost.bone_axes)) { + if (DRW_state_is_fbo()) { + /* meh, late init to not request a depth buffer we won't use. */ + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + GPUTexture *ghost_depth_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_object_type); + GPU_framebuffer_ensure_config(&fbl->ghost_fb, + { + GPU_ATTACHMENT_TEXTURE(ghost_depth_tx), + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); + + GPU_framebuffer_bind(fbl->ghost_fb); + GPU_framebuffer_clear_depth(fbl->ghost_fb, 1.0f); + } + else if (DRW_state_is_select()) { + /* XXX `GPU_depth_range` is not a perfect solution + * since very distant geometries can still be occluded. + * Also the depth test precision of these geometries is impaired. + * However solves the selection for the vast majority of cases. */ + GPU_depth_range(0.0f, 0.01f); + } + + DRW_draw_pass(stl->g_data->sgl_ghost.transp_shapes); + DRW_draw_pass(stl->g_data->sgl_ghost.bone_solid); + DRW_draw_pass(stl->g_data->sgl_ghost.bone_wire); + DRW_draw_pass(stl->g_data->sgl_ghost.bone_outline); + DRW_draw_pass(stl->g_data->sgl_ghost.non_meshes); + DRW_draw_pass(stl->g_data->sgl_ghost.image_empties); + DRW_draw_pass(stl->g_data->sgl_ghost.bone_axes); + + if (DRW_state_is_select()) { + GPU_depth_range(0.0f, 1.0f); + } + } + + batch_camera_path_free(&stl->g_data->sgl_ghost.camera_path); + + DRW_draw_pass(psl->ob_center); } static const DrawEngineDataSize OBJECT_data_size = DRW_VIEWPORT_DATA_SIZE(OBJECT_Data); DrawEngineType draw_engine_object_type = { - NULL, NULL, - N_("ObjectMode"), - &OBJECT_data_size, - &OBJECT_engine_init, - &OBJECT_engine_free, - &OBJECT_cache_init, - &OBJECT_cache_populate, - &OBJECT_cache_finish, - NULL, - &OBJECT_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("ObjectMode"), + &OBJECT_data_size, + &OBJECT_engine_init, + &OBJECT_engine_free, + &OBJECT_cache_init, + &OBJECT_cache_populate, + &OBJECT_cache_finish, + NULL, + &OBJECT_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index f2cafd51666..4d583066f44 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -39,51 +39,51 @@ #include "draw_mode_engines.h" #ifdef __APPLE__ -#define USE_GEOM_SHADER_WORKAROUND 1 +# define USE_GEOM_SHADER_WORKAROUND 1 #else -#define USE_GEOM_SHADER_WORKAROUND 0 +# define USE_GEOM_SHADER_WORKAROUND 0 #endif /* Structures */ typedef struct OVERLAY_StorageList { - struct OVERLAY_PrivateData *g_data; + struct OVERLAY_PrivateData *g_data; } OVERLAY_StorageList; typedef struct OVERLAY_PassList { - struct DRWPass *face_orientation_pass; - struct DRWPass *face_wireframe_pass; + struct DRWPass *face_orientation_pass; + struct DRWPass *face_wireframe_pass; } OVERLAY_PassList; typedef struct OVERLAY_Data { - void *engine_type; - DRWViewportEmptyList *fbl; - DRWViewportEmptyList *txl; - OVERLAY_PassList *psl; - OVERLAY_StorageList *stl; + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + OVERLAY_PassList *psl; + OVERLAY_StorageList *stl; } OVERLAY_Data; typedef struct OVERLAY_PrivateData { - DRWShadingGroup *face_orientation_shgrp; - DRWShadingGroup *face_wires_shgrp; - BLI_mempool *wire_color_mempool; - View3DOverlay overlay; - float wire_step_param; - bool ghost_stencil_test; - bool show_overlays; + DRWShadingGroup *face_orientation_shgrp; + DRWShadingGroup *face_wires_shgrp; + BLI_mempool *wire_color_mempool; + View3DOverlay overlay; + float wire_step_param; + bool ghost_stencil_test; + bool show_overlays; } OVERLAY_PrivateData; /* Transient data */ typedef struct OVERLAY_Shaders { - /* Face orientation shader */ - struct GPUShader *face_orientation; - /* Wireframe shader */ - struct GPUShader *select_wireframe; - struct GPUShader *face_wireframe; + /* Face orientation shader */ + struct GPUShader *face_orientation; + /* Wireframe shader */ + struct GPUShader *select_wireframe; + struct GPUShader *face_wireframe; } OVERLAY_Shaders; /* *********** STATIC *********** */ static struct { - OVERLAY_Shaders sh_data[GPU_SHADER_CFG_LEN]; + OVERLAY_Shaders sh_data[GPU_SHADER_CFG_LEN]; } e_data = {{{NULL}}}; /* Shaders */ @@ -98,404 +98,402 @@ extern char datatoc_gpu_shader_depth_only_frag_glsl[]; /* Functions */ static void overlay_engine_init(void *vedata) { - OVERLAY_Data *data = vedata; - OVERLAY_StorageList *stl = data->stl; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - stl->g_data->ghost_stencil_test = false; - - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - - if (!sh_data->face_orientation) { - /* Face orientation */ - sh_data->face_orientation = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_orientation_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_overlay_face_orientation_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - } - - if (!sh_data->face_wireframe) { - sh_data->select_wireframe = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_depth_only_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define SELECT_EDGES\n", NULL}, - }); + OVERLAY_Data *data = vedata; + OVERLAY_StorageList *stl = data->stl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); + } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + stl->g_data->ghost_stencil_test = false; + + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + if (!sh_data->face_orientation) { + /* Face orientation */ + sh_data->face_orientation = GPU_shader_create_from_arrays({ + .vert = + (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_orientation_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_overlay_face_orientation_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + + if (!sh_data->face_wireframe) { + sh_data->select_wireframe = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_depth_only_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define SELECT_EDGES\n", NULL}, + }); #if USE_GEOM_SHADER_WORKAROUND - /* Apple drivers does not support wide wires. Use geometry shader as a workaround. */ - sh_data->face_wireframe = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL}, - }); + /* Apple drivers does not support wide wires. Use geometry shader as a workaround. */ + sh_data->face_wireframe = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL}, + }); #else - sh_data->face_wireframe = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); + sh_data->face_wireframe = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); #endif - } + } } static void overlay_cache_init(void *vedata) { - OVERLAY_Data *data = vedata; - OVERLAY_PassList *psl = data->psl; - OVERLAY_StorageList *stl = data->stl; - OVERLAY_PrivateData *g_data = stl->g_data; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - RegionView3D *rv3d = draw_ctx->rv3d; - OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - const DRWContextState *DCS = DRW_context_state_get(); - - View3D *v3d = DCS->v3d; - if (v3d) { - g_data->overlay = v3d->overlay; - g_data->show_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; - } - else { - memset(&g_data->overlay, 0, sizeof(g_data->overlay)); - g_data->show_overlays = false; - } - - if (g_data->show_overlays == false) { - g_data->overlay.flag = 0; - } - - if (v3d->shading.type == OB_WIRE) { - g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES; - - if (ELEM(v3d->shading.wire_color_type, - V3D_SHADING_OBJECT_COLOR, - V3D_SHADING_RANDOM_COLOR)) - { - g_data->wire_color_mempool = BLI_mempool_create(sizeof(float[3]), 0, 512, 0); - } - } - - { - /* Face Orientation Pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; - psl->face_orientation_pass = DRW_pass_create("Face Orientation", state); - g_data->face_orientation_shgrp = DRW_shgroup_create( - sh_data->face_orientation, psl->face_orientation_pass); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_orientation_shgrp, rv3d); - } - } - - { - /* Wireframe */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | - DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE; - float wire_size = U.pixelsize * 0.5f; - - float winmat[4][4]; - float viewdist = rv3d->dist; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ - if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { - viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); - } - const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f); - - const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); - GPUShader *face_wires_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe; - - psl->face_wireframe_pass = DRW_pass_create("Face Wires", state); - - g_data->face_wires_shgrp = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass); - DRW_shgroup_uniform_float(g_data->face_wires_shgrp, "wireStepParam", &g_data->wire_step_param, 1); - DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "ofs", depth_ofs); - if (use_select || USE_GEOM_SHADER_WORKAROUND) { - DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size); - DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); - } - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d); - } - - g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f; - } + OVERLAY_Data *data = vedata; + OVERLAY_PassList *psl = data->psl; + OVERLAY_StorageList *stl = data->stl; + OVERLAY_PrivateData *g_data = stl->g_data; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + const DRWContextState *DCS = DRW_context_state_get(); + + View3D *v3d = DCS->v3d; + if (v3d) { + g_data->overlay = v3d->overlay; + g_data->show_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + } + else { + memset(&g_data->overlay, 0, sizeof(g_data->overlay)); + g_data->show_overlays = false; + } + + if (g_data->show_overlays == false) { + g_data->overlay.flag = 0; + } + + if (v3d->shading.type == OB_WIRE) { + g_data->overlay.flag |= V3D_OVERLAY_WIREFRAMES; + + if (ELEM(v3d->shading.wire_color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) { + g_data->wire_color_mempool = BLI_mempool_create(sizeof(float[3]), 0, 512, 0); + } + } + + { + /* Face Orientation Pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; + psl->face_orientation_pass = DRW_pass_create("Face Orientation", state); + g_data->face_orientation_shgrp = DRW_shgroup_create(sh_data->face_orientation, + psl->face_orientation_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_orientation_shgrp, rv3d); + } + } + + { + /* Wireframe */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | + DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE; + float wire_size = U.pixelsize * 0.5f; + + float winmat[4][4]; + float viewdist = rv3d->dist; + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ + if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { + viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); + } + const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f); + + const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); + GPUShader *face_wires_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe; + + psl->face_wireframe_pass = DRW_pass_create("Face Wires", state); + + g_data->face_wires_shgrp = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass); + DRW_shgroup_uniform_float( + g_data->face_wires_shgrp, "wireStepParam", &g_data->wire_step_param, 1); + DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "ofs", depth_ofs); + if (use_select || USE_GEOM_SHADER_WORKAROUND) { + DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size); + DRW_shgroup_uniform_vec2( + g_data->face_wires_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_vec2( + g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); + } + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d); + } + + g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f; + } } -static void overlay_wire_color_get( - const View3D *v3d, const OVERLAY_PrivateData *pd, const Object *ob, const bool use_coloring, - float **rim_col, float **wire_col) +static void overlay_wire_color_get(const View3D *v3d, + const OVERLAY_PrivateData *pd, + const Object *ob, + const bool use_coloring, + float **rim_col, + float **wire_col) { #ifndef NDEBUG - *rim_col = NULL; - *wire_col = NULL; + *rim_col = NULL; + *wire_col = NULL; #endif - const DRWContextState *draw_ctx = DRW_context_state_get(); - - if (UNLIKELY(ob->base_flag & BASE_FROM_SET)) { - *rim_col = G_draw.block.colorDupli; - *wire_col = G_draw.block.colorDupli; - } - else if (UNLIKELY(ob->base_flag & BASE_FROM_DUPLI)) { - if (ob->base_flag & BASE_SELECTED) { - if (G.moving & G_TRANSFORM_OBJ) { - *rim_col = G_draw.block.colorTransform; - } - else { - *rim_col = G_draw.block.colorDupliSelect; - } - } - else { - *rim_col = G_draw.block.colorDupli; - } - *wire_col = G_draw.block.colorDupli; - } - else if ((ob->base_flag & BASE_SELECTED) && use_coloring) { - if (G.moving & G_TRANSFORM_OBJ) { - *rim_col = G_draw.block.colorTransform; - } - else if (ob == draw_ctx->obact) { - *rim_col = G_draw.block.colorActive; - } - else { - *rim_col = G_draw.block.colorSelect; - } - *wire_col = G_draw.block.colorWire; - } - else { - *rim_col = G_draw.block.colorWire; - *wire_col = G_draw.block.colorBackground; - } - - if (v3d->shading.type == OB_WIRE) { - if (ELEM(v3d->shading.wire_color_type, - V3D_SHADING_OBJECT_COLOR, - V3D_SHADING_RANDOM_COLOR)) - { - *wire_col = BLI_mempool_alloc(pd->wire_color_mempool); - *rim_col = BLI_mempool_alloc(pd->wire_color_mempool); - - if (v3d->shading.wire_color_type == V3D_SHADING_OBJECT_COLOR) { - linearrgb_to_srgb_v3_v3(*wire_col, ob->color); - mul_v3_fl(*wire_col, 0.5f); - copy_v3_v3(*rim_col, *wire_col); - } - else { - uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); - if (ob->id.lib) { - hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name); - } - - float hue = BLI_hash_int_01(hash); - float hsv[3] = {hue, 0.75f, 0.8f}; - hsv_to_rgb_v(hsv, *wire_col); - copy_v3_v3(*rim_col, *wire_col); - } - - if ((ob->base_flag & BASE_SELECTED) && use_coloring) { - /* "Normalize" color. */ - add_v3_fl(*wire_col, 1e-4f); - float brightness = max_fff((*wire_col)[0], (*wire_col)[1], (*wire_col)[2]); - mul_v3_fl(*wire_col, (0.5f / brightness)); - add_v3_fl(*rim_col, 0.75f); - } - else { - mul_v3_fl(*rim_col, 0.5f); - add_v3_fl(*wire_col, 0.5f); - } - } - } - BLI_assert(*rim_col && *wire_col); + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (UNLIKELY(ob->base_flag & BASE_FROM_SET)) { + *rim_col = G_draw.block.colorDupli; + *wire_col = G_draw.block.colorDupli; + } + else if (UNLIKELY(ob->base_flag & BASE_FROM_DUPLI)) { + if (ob->base_flag & BASE_SELECTED) { + if (G.moving & G_TRANSFORM_OBJ) { + *rim_col = G_draw.block.colorTransform; + } + else { + *rim_col = G_draw.block.colorDupliSelect; + } + } + else { + *rim_col = G_draw.block.colorDupli; + } + *wire_col = G_draw.block.colorDupli; + } + else if ((ob->base_flag & BASE_SELECTED) && use_coloring) { + if (G.moving & G_TRANSFORM_OBJ) { + *rim_col = G_draw.block.colorTransform; + } + else if (ob == draw_ctx->obact) { + *rim_col = G_draw.block.colorActive; + } + else { + *rim_col = G_draw.block.colorSelect; + } + *wire_col = G_draw.block.colorWire; + } + else { + *rim_col = G_draw.block.colorWire; + *wire_col = G_draw.block.colorBackground; + } + + if (v3d->shading.type == OB_WIRE) { + if (ELEM(v3d->shading.wire_color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) { + *wire_col = BLI_mempool_alloc(pd->wire_color_mempool); + *rim_col = BLI_mempool_alloc(pd->wire_color_mempool); + + if (v3d->shading.wire_color_type == V3D_SHADING_OBJECT_COLOR) { + linearrgb_to_srgb_v3_v3(*wire_col, ob->color); + mul_v3_fl(*wire_col, 0.5f); + copy_v3_v3(*rim_col, *wire_col); + } + else { + uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); + if (ob->id.lib) { + hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name); + } + + float hue = BLI_hash_int_01(hash); + float hsv[3] = {hue, 0.75f, 0.8f}; + hsv_to_rgb_v(hsv, *wire_col); + copy_v3_v3(*rim_col, *wire_col); + } + + if ((ob->base_flag & BASE_SELECTED) && use_coloring) { + /* "Normalize" color. */ + add_v3_fl(*wire_col, 1e-4f); + float brightness = max_fff((*wire_col)[0], (*wire_col)[1], (*wire_col)[2]); + mul_v3_fl(*wire_col, (0.5f / brightness)); + add_v3_fl(*rim_col, 0.75f); + } + else { + mul_v3_fl(*rim_col, 0.5f); + add_v3_fl(*wire_col, 0.5f); + } + } + } + BLI_assert(*rim_col && *wire_col); } static void overlay_cache_populate(void *vedata, Object *ob) { - OVERLAY_Data *data = vedata; - OVERLAY_StorageList *stl = data->stl; - OVERLAY_PrivateData *pd = stl->g_data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - if ((ob->dt < OB_WIRE) || - (!DRW_object_is_renderable(ob) && (ob->dt != OB_WIRE))) - { - return; - } - - if (DRW_object_is_renderable(ob) && pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat); - } - } - - if ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || - (v3d->shading.type == OB_WIRE) || - (ob->dtx & OB_DRAWWIRE) || - (ob->dt == OB_WIRE)) - { - const bool is_edit_mode = BKE_object_is_in_editmode(ob); - bool has_edit_mesh_cage = false; - if (ob->type == OB_MESH) { - /* TODO: Should be its own function. */ - Mesh *me = (Mesh *)ob->data; - BMEditMesh *embm = me->edit_mesh; - if (embm) { - has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); - } - } - - /* Don't do that in edit Mesh mode, unless there is a modifier preview. */ - if ((!pd->show_overlays) || (((ob != draw_ctx->object_edit) && !is_edit_mode) || has_edit_mesh_cage) || - ob->type != OB_MESH) - { - const bool is_active = (ob == draw_ctx->obact); - const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; - const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES); - const bool is_wire = (ob->dt < OB_SOLID); - const bool use_coloring = (pd->show_overlays && !is_edit_mode && !is_sculpt_mode && !has_edit_mesh_cage); - const int stencil_mask = (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF; - float *rim_col, *wire_col; - DRWShadingGroup *shgrp = NULL; - - overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col); - - struct GPUBatch *geom; - geom = DRW_cache_object_face_wireframe_get(ob); - - if (geom || is_sculpt_mode) { - shgrp = DRW_shgroup_create_sub(pd->face_wires_shgrp); - - float wire_step_param = 10.0f; - if (!is_sculpt_mode) { - wire_step_param = (all_wires) ? 1.0f : pd->wire_step_param; - } - DRW_shgroup_uniform_float_copy(shgrp, "wireStepParam", wire_step_param); - - if (!(DRW_state_is_select() || DRW_state_is_depth())) { - DRW_shgroup_stencil_mask(shgrp, stencil_mask); - DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1); - DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1); - } - - if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_wires_add(shgrp, ob, ob->obmat); - } - else { - DRW_shgroup_call_add(shgrp, geom, ob->obmat); - } - } - if (is_wire && shgrp != NULL) { - /* If object is wireframe, don't try to use stencil test. */ - DRW_shgroup_state_disable(shgrp, DRW_STATE_STENCIL_EQUAL); - - if (ob->dtx & OB_DRAWXRAY) { - DRW_shgroup_state_disable(shgrp, DRW_STATE_DEPTH_LESS_EQUAL); - } - } - else if ((ob->dtx & OB_DRAWXRAY) && shgrp != NULL) { - pd->ghost_stencil_test = true; - } - } - } + OVERLAY_Data *data = vedata; + OVERLAY_StorageList *stl = data->stl; + OVERLAY_PrivateData *pd = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + if ((ob->dt < OB_WIRE) || (!DRW_object_is_renderable(ob) && (ob->dt != OB_WIRE))) { + return; + } + + if (DRW_object_is_renderable(ob) && pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat); + } + } + + if ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || (v3d->shading.type == OB_WIRE) || + (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE)) { + const bool is_edit_mode = BKE_object_is_in_editmode(ob); + bool has_edit_mesh_cage = false; + if (ob->type == OB_MESH) { + /* TODO: Should be its own function. */ + Mesh *me = (Mesh *)ob->data; + BMEditMesh *embm = me->edit_mesh; + if (embm) { + has_edit_mesh_cage = embm->mesh_eval_cage && + (embm->mesh_eval_cage != embm->mesh_eval_final); + } + } + + /* Don't do that in edit Mesh mode, unless there is a modifier preview. */ + if ((!pd->show_overlays) || + (((ob != draw_ctx->object_edit) && !is_edit_mode) || has_edit_mesh_cage) || + ob->type != OB_MESH) { + const bool is_active = (ob == draw_ctx->obact); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; + const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES); + const bool is_wire = (ob->dt < OB_SOLID); + const bool use_coloring = (pd->show_overlays && !is_edit_mode && !is_sculpt_mode && + !has_edit_mesh_cage); + const int stencil_mask = (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF; + float *rim_col, *wire_col; + DRWShadingGroup *shgrp = NULL; + + overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col); + + struct GPUBatch *geom; + geom = DRW_cache_object_face_wireframe_get(ob); + + if (geom || is_sculpt_mode) { + shgrp = DRW_shgroup_create_sub(pd->face_wires_shgrp); + + float wire_step_param = 10.0f; + if (!is_sculpt_mode) { + wire_step_param = (all_wires) ? 1.0f : pd->wire_step_param; + } + DRW_shgroup_uniform_float_copy(shgrp, "wireStepParam", wire_step_param); + + if (!(DRW_state_is_select() || DRW_state_is_depth())) { + DRW_shgroup_stencil_mask(shgrp, stencil_mask); + DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1); + DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1); + } + + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_wires_add(shgrp, ob, ob->obmat); + } + else { + DRW_shgroup_call_add(shgrp, geom, ob->obmat); + } + } + if (is_wire && shgrp != NULL) { + /* If object is wireframe, don't try to use stencil test. */ + DRW_shgroup_state_disable(shgrp, DRW_STATE_STENCIL_EQUAL); + + if (ob->dtx & OB_DRAWXRAY) { + DRW_shgroup_state_disable(shgrp, DRW_STATE_DEPTH_LESS_EQUAL); + } + } + else if ((ob->dtx & OB_DRAWXRAY) && shgrp != NULL) { + pd->ghost_stencil_test = true; + } + } + } } static void overlay_cache_finish(void *vedata) { - OVERLAY_Data *data = vedata; - OVERLAY_PassList *psl = data->psl; - OVERLAY_StorageList *stl = data->stl; - - const DRWContextState *ctx = DRW_context_state_get(); - View3D *v3d = ctx->v3d; - - /* only in solid mode */ - if (v3d->shading.type == OB_SOLID && !XRAY_FLAG_ENABLED(v3d)) { - if (stl->g_data->ghost_stencil_test) { - DRW_pass_state_add(psl->face_wireframe_pass, DRW_STATE_STENCIL_EQUAL); - } - } + OVERLAY_Data *data = vedata; + OVERLAY_PassList *psl = data->psl; + OVERLAY_StorageList *stl = data->stl; + + const DRWContextState *ctx = DRW_context_state_get(); + View3D *v3d = ctx->v3d; + + /* only in solid mode */ + if (v3d->shading.type == OB_SOLID && !XRAY_FLAG_ENABLED(v3d)) { + if (stl->g_data->ghost_stencil_test) { + DRW_pass_state_add(psl->face_wireframe_pass, DRW_STATE_STENCIL_EQUAL); + } + } } static void overlay_draw_scene(void *vedata) { - OVERLAY_Data *data = vedata; - OVERLAY_PassList *psl = data->psl; - OVERLAY_StorageList *stl = data->stl; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - - if (DRW_state_is_fbo()) { - GPU_framebuffer_bind(dfbl->default_fb); - } - DRW_draw_pass(psl->face_orientation_pass); - - /* This is replaced by the next code block */ - // MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - - if (dfbl->multisample_fb != NULL) { - DRW_stats_query_start("Multisample Blit"); - GPU_framebuffer_bind(dfbl->multisample_fb); - GPU_framebuffer_clear_color(dfbl->multisample_fb, (const float[4]){0.0f}); - /* Special blit: we need the original depth and stencil - * in the Multisample buffer. */ - GPU_framebuffer_blit(dfbl->default_fb, 0, - dfbl->multisample_fb, 0, - GPU_DEPTH_BIT | GPU_STENCIL_BIT); - DRW_stats_query_end(); - } - - DRW_draw_pass(psl->face_wireframe_pass); - - /* TODO(fclem): find a way to unify the multisample pass together - * (non meshes + armature + wireframe) */ - MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - - /* XXX TODO(fclem) do not discard data after drawing! Store them per viewport. */ - if (stl->g_data->wire_color_mempool) { - BLI_mempool_destroy(stl->g_data->wire_color_mempool); - stl->g_data->wire_color_mempool = NULL; - } + OVERLAY_Data *data = vedata; + OVERLAY_PassList *psl = data->psl; + OVERLAY_StorageList *stl = data->stl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->default_fb); + } + DRW_draw_pass(psl->face_orientation_pass); + + /* This is replaced by the next code block */ + // MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + + if (dfbl->multisample_fb != NULL) { + DRW_stats_query_start("Multisample Blit"); + GPU_framebuffer_bind(dfbl->multisample_fb); + GPU_framebuffer_clear_color(dfbl->multisample_fb, (const float[4]){0.0f}); + /* Special blit: we need the original depth and stencil + * in the Multisample buffer. */ + GPU_framebuffer_blit( + dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_DEPTH_BIT | GPU_STENCIL_BIT); + DRW_stats_query_end(); + } + + DRW_draw_pass(psl->face_wireframe_pass); + + /* TODO(fclem): find a way to unify the multisample pass together + * (non meshes + armature + wireframe) */ + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); + + /* XXX TODO(fclem) do not discard data after drawing! Store them per viewport. */ + if (stl->g_data->wire_color_mempool) { + BLI_mempool_destroy(stl->g_data->wire_color_mempool); + stl->g_data->wire_color_mempool = NULL; + } } static void overlay_engine_free(void) { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - OVERLAY_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - GPUShader **sh_data_as_array = (GPUShader **)sh_data; - for (int i = 0; i < (sizeof(OVERLAY_Shaders) / sizeof(GPUShader *)); i++) { - DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); - } - } + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + OVERLAY_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(OVERLAY_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data); DrawEngineType draw_engine_overlay_type = { - NULL, NULL, - N_("OverlayEngine"), - &overlay_data_size, - &overlay_engine_init, - &overlay_engine_free, - &overlay_cache_init, - &overlay_cache_populate, - &overlay_cache_finish, - NULL, - &overlay_draw_scene, - NULL, - NULL, - NULL, + NULL, + NULL, + N_("OverlayEngine"), + &overlay_data_size, + &overlay_engine_init, + &overlay_engine_free, + &overlay_cache_init, + &overlay_cache_populate, + &overlay_cache_finish, + NULL, + &overlay_draw_scene, + NULL, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index 83dfdd3284f..84852ff7ab3 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -55,72 +55,72 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; * for PAINT_TEXTURE_PassList */ typedef struct PAINT_TEXTURE_PassList { - /* Declare all passes here and init them in - * PAINT_TEXTURE_cache_init(). - * Only contains (DRWPass *) */ - struct DRWPass *image_faces; + /* Declare all passes here and init them in + * PAINT_TEXTURE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *image_faces; - struct DRWPass *wire_overlay; - struct DRWPass *face_overlay; + struct DRWPass *wire_overlay; + struct DRWPass *face_overlay; } PAINT_TEXTURE_PassList; typedef struct PAINT_TEXTURE_FramebufferList { - /* Contains all framebuffer objects needed by this engine. - * Only contains (GPUFrameBuffer *) */ - struct GPUFrameBuffer *fb; + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; } PAINT_TEXTURE_FramebufferList; typedef struct PAINT_TEXTURE_TextureList { - /* Contains all framebuffer textures / utility textures - * needed by this engine. Only viewport specific textures - * (not per object). Only contains (GPUTexture *) */ - struct GPUTexture *texture; + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; } PAINT_TEXTURE_TextureList; typedef struct PAINT_TEXTURE_StorageList { - /* Contains any other memory block that the engine needs. - * Only directly MEM_(m/c)allocN'ed blocks because they are - * free with MEM_freeN() when viewport is freed. - * (not per object) */ - struct CustomStruct *block; - struct PAINT_TEXTURE_PrivateData *g_data; + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct PAINT_TEXTURE_PrivateData *g_data; } PAINT_TEXTURE_StorageList; typedef struct PAINT_TEXTURE_Data { - /* Struct returned by DRW_viewport_engine_data_ensure. - * If you don't use one of these, just make it a (void *) */ - // void *fbl; - void *engine_type; /* Required */ - PAINT_TEXTURE_FramebufferList *fbl; - PAINT_TEXTURE_TextureList *txl; - PAINT_TEXTURE_PassList *psl; - PAINT_TEXTURE_StorageList *stl; + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + PAINT_TEXTURE_FramebufferList *fbl; + PAINT_TEXTURE_TextureList *txl; + PAINT_TEXTURE_PassList *psl; + PAINT_TEXTURE_StorageList *stl; } PAINT_TEXTURE_Data; /* *********** STATIC *********** */ static struct { - /* Custom shaders : - * Add sources to source/blender/draw/modes/shaders - * init in PAINT_TEXTURE_engine_init(); - * free in PAINT_TEXTURE_engine_free(); */ - struct GPUShader *fallback_sh; - struct GPUShader *image_sh; - struct GPUShader *image_masking_sh; - - struct GPUShader *wire_overlay_shader; - struct GPUShader *face_overlay_shader; + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in PAINT_TEXTURE_engine_init(); + * free in PAINT_TEXTURE_engine_free(); */ + struct GPUShader *fallback_sh; + struct GPUShader *image_sh; + struct GPUShader *image_masking_sh; + + struct GPUShader *wire_overlay_shader; + struct GPUShader *face_overlay_shader; } e_data = {NULL}; /* Engine data */ typedef struct PAINT_TEXTURE_PrivateData { - /* This keeps the references of the shading groups for - * easy access in PAINT_TEXTURE_cache_populate() */ - DRWShadingGroup *shgroup_fallback; - DRWShadingGroup **shgroup_image_array; - - /* face-mask */ - DRWShadingGroup *lwire_shgrp; - DRWShadingGroup *face_shgrp; + /* This keeps the references of the shading groups for + * easy access in PAINT_TEXTURE_cache_populate() */ + DRWShadingGroup *shgroup_fallback; + DRWShadingGroup **shgroup_image_array; + + /* face-mask */ + DRWShadingGroup *lwire_shgrp; + DRWShadingGroup *face_shgrp; } PAINT_TEXTURE_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -129,235 +129,246 @@ typedef struct PAINT_TEXTURE_PrivateData { * It is called for every frames. */ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata)) { - if (!e_data.fallback_sh) { - e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - - e_data.image_sh = DRW_shader_create_with_lib( - datatoc_paint_texture_vert_glsl, NULL, - datatoc_paint_texture_frag_glsl, - datatoc_common_globals_lib_glsl, NULL); - - e_data.image_masking_sh = DRW_shader_create_with_lib( - datatoc_paint_texture_vert_glsl, NULL, - datatoc_paint_texture_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define TEXTURE_PAINT_MASK\n"); - - e_data.wire_overlay_shader = DRW_shader_create_with_lib( - datatoc_paint_wire_vert_glsl, NULL, - datatoc_paint_wire_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define VERTEX_MODE\n"); - - e_data.face_overlay_shader = DRW_shader_create( - datatoc_paint_face_vert_glsl, NULL, - datatoc_gpu_shader_uniform_color_frag_glsl, NULL); - } + if (!e_data.fallback_sh) { + e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + e_data.image_sh = DRW_shader_create_with_lib(datatoc_paint_texture_vert_glsl, + NULL, + datatoc_paint_texture_frag_glsl, + datatoc_common_globals_lib_glsl, + NULL); + + e_data.image_masking_sh = DRW_shader_create_with_lib(datatoc_paint_texture_vert_glsl, + NULL, + datatoc_paint_texture_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define TEXTURE_PAINT_MASK\n"); + + e_data.wire_overlay_shader = DRW_shader_create_with_lib(datatoc_paint_wire_vert_glsl, + NULL, + datatoc_paint_wire_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define VERTEX_MODE\n"); + + e_data.face_overlay_shader = DRW_shader_create( + datatoc_paint_face_vert_glsl, NULL, datatoc_gpu_shader_uniform_color_frag_glsl, NULL); + } } -static DRWShadingGroup *create_texture_paint_shading_group( - PAINT_TEXTURE_PassList *psl, const struct GPUTexture *texture, const DRWContextState *draw_ctx, const bool nearest_interp) +static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassList *psl, + const struct GPUTexture *texture, + const DRWContextState *draw_ctx, + const bool nearest_interp) { - Scene *scene = draw_ctx->scene; - const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; - const bool masking_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL && imapaint->stencil != NULL; - - DRWShadingGroup *grp = DRW_shgroup_create( - masking_enabled ? e_data.image_masking_sh : e_data.image_sh, psl->image_faces); - DRW_shgroup_uniform_texture(grp, "image", texture); - DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_bool_copy(grp, "nearestInterp", nearest_interp); - - if (masking_enabled) { - const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0; - GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D, false); - DRW_shgroup_uniform_texture(grp, "maskingImage", stencil); - DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1); - DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted); - } - return grp; + Scene *scene = draw_ctx->scene; + const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; + const bool masking_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL && + imapaint->stencil != NULL; + + DRWShadingGroup *grp = DRW_shgroup_create( + masking_enabled ? e_data.image_masking_sh : e_data.image_sh, psl->image_faces); + DRW_shgroup_uniform_texture(grp, "image", texture); + DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_bool_copy(grp, "nearestInterp", nearest_interp); + + if (masking_enabled) { + const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0; + GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D, false); + DRW_shgroup_uniform_texture(grp, "maskingImage", stencil); + DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1); + DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted); + } + return grp; } /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void PAINT_TEXTURE_cache_init(void *vedata) { - PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; - PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - stl->g_data->shgroup_image_array = NULL; - } - - { - /* Create a pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; - psl->image_faces = DRW_pass_create("Image Color Pass", state); - - stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces); - - /* Uniforms need a pointer to it's value so be sure it's accessible at - * any given time (i.e. use static vars) */ - static float color[4] = {1.0f, 0.0f, 1.0f, 1.0}; - DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1); - - MEM_SAFE_FREE(stl->g_data->shgroup_image_array); - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Object *ob = draw_ctx->obact; - if (ob && ob->type == OB_MESH) { - Scene *scene = draw_ctx->scene; - const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; - const bool use_material_slots = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); - const Mesh *me = ob->data; - const int mat_nr = max_ii(1, me->totcol); - - stl->g_data->shgroup_image_array = MEM_mallocN( - sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? mat_nr : 1), __func__); - - if (use_material_slots) { - for (int i = 0; i < mat_nr; i++) { - Material *ma = give_current_material(ob, i + 1); - Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; - int interp = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].interp : 0; - GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false); - - if (tex) { - DRWShadingGroup *grp = create_texture_paint_shading_group(psl, tex, draw_ctx, interp == SHD_INTERP_CLOSEST); - stl->g_data->shgroup_image_array[i] = grp; - } - else { - stl->g_data->shgroup_image_array[i] = NULL; - } - } - } - else { - Image *ima = imapaint->canvas; - GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false); - - if (tex) { - DRWShadingGroup *grp = create_texture_paint_shading_group(psl, tex, draw_ctx, imapaint->interp == IMAGEPAINT_INTERP_CLOSEST); - stl->g_data->shgroup_image_array[0] = grp; - } - else { - stl->g_data->shgroup_image_array[0] = NULL; - } - } - } - } - - /* Face Mask */ - { - psl->wire_overlay = DRW_pass_create( - "Wire Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); - - stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay); - DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", G_draw.block_ubo); - } - - { - psl->face_overlay = DRW_pass_create( - "Face Mask Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); - - stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay); - - static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; - DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1); - } + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + stl->g_data->shgroup_image_array = NULL; + } + + { + /* Create a pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; + psl->image_faces = DRW_pass_create("Image Color Pass", state); + + stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces); + + /* Uniforms need a pointer to it's value so be sure it's accessible at + * any given time (i.e. use static vars) */ + static float color[4] = {1.0f, 0.0f, 1.0f, 1.0}; + DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1); + + MEM_SAFE_FREE(stl->g_data->shgroup_image_array); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Object *ob = draw_ctx->obact; + if (ob && ob->type == OB_MESH) { + Scene *scene = draw_ctx->scene; + const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; + const bool use_material_slots = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); + const Mesh *me = ob->data; + const int mat_nr = max_ii(1, me->totcol); + + stl->g_data->shgroup_image_array = MEM_mallocN( + sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? mat_nr : 1), __func__); + + if (use_material_slots) { + for (int i = 0; i < mat_nr; i++) { + Material *ma = give_current_material(ob, i + 1); + Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : + NULL; + int interp = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].interp : + 0; + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false); + + if (tex) { + DRWShadingGroup *grp = create_texture_paint_shading_group( + psl, tex, draw_ctx, interp == SHD_INTERP_CLOSEST); + stl->g_data->shgroup_image_array[i] = grp; + } + else { + stl->g_data->shgroup_image_array[i] = NULL; + } + } + } + else { + Image *ima = imapaint->canvas; + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false); + + if (tex) { + DRWShadingGroup *grp = create_texture_paint_shading_group( + psl, tex, draw_ctx, imapaint->interp == IMAGEPAINT_INTERP_CLOSEST); + stl->g_data->shgroup_image_array[0] = grp; + } + else { + stl->g_data->shgroup_image_array[0] = NULL; + } + } + } + } + + /* Face Mask */ + { + psl->wire_overlay = DRW_pass_create("Wire Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_OFFSET_NEGATIVE); + + stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay); + DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", G_draw.block_ubo); + } + + { + psl->face_overlay = DRW_pass_create("Face Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + + stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay); + + static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; + DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1); + } } /* Add geometry to shadingGroups. Execute for each objects */ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob) { - PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; - PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - UNUSED_VARS(psl, stl); - - if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) { - /* Get geometry cache */ - const Mesh *me = ob->data; - const Mesh *me_orig = DEG_get_original_object(ob)->data; - Scene *scene = draw_ctx->scene; - const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity != 0.0; //DRW_object_is_mode_shade(ob) == true; - const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL); - const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - - if (use_surface) { - if (me->mloopuv != NULL) { - if (use_material_slots) { - int mat_nr = max_ii(1, me->totcol); - struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); - - for (int i = 0; i < mat_nr; i++) { - const int index = use_material_slots ? i : 0; - if ((i < me->totcol) && stl->g_data->shgroup_image_array[index]) { - DRW_shgroup_call_add(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat); - } - else { - DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); - } - } - } - else { - if (stl->g_data->shgroup_image_array[0]) { - struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob); - DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat); - } - } - } - else { - struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); - } - } - - /* Face Mask */ - if (use_face_sel) { - struct GPUBatch *geom; - geom = DRW_cache_mesh_surface_edges_get(ob); - DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat); - - geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat); - } - } + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + UNUSED_VARS(psl, stl); + + if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) { + /* Get geometry cache */ + const Mesh *me = ob->data; + const Mesh *me_orig = DEG_get_original_object(ob)->data; + Scene *scene = draw_ctx->scene; + const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity != + 0.0; //DRW_object_is_mode_shade(ob) == true; + const bool use_material_slots = (scene->toolsettings->imapaint.mode == + IMAGEPAINT_MODE_MATERIAL); + const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + + if (use_surface) { + if (me->mloopuv != NULL) { + if (use_material_slots) { + int mat_nr = max_ii(1, me->totcol); + struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); + + for (int i = 0; i < mat_nr; i++) { + const int index = use_material_slots ? i : 0; + if ((i < me->totcol) && stl->g_data->shgroup_image_array[index]) { + DRW_shgroup_call_add( + stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat); + } + else { + DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); + } + } + } + else { + if (stl->g_data->shgroup_image_array[0]) { + struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob); + DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat); + } + } + } + else { + struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); + } + } + + /* Face Mask */ + if (use_face_sel) { + struct GPUBatch *geom; + geom = DRW_cache_mesh_surface_edges_get(ob); + DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat); + + geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat); + } + } } /* Optional: Post-cache_populate callback */ static void PAINT_TEXTURE_cache_finish(void *vedata) { - PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; - PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; - /* Do something here! dependent on the objects gathered */ - UNUSED_VARS(psl); + /* Do something here! dependent on the objects gathered */ + UNUSED_VARS(psl); - MEM_SAFE_FREE(stl->g_data->shgroup_image_array); + MEM_SAFE_FREE(stl->g_data->shgroup_image_array); } /* Draw time ! Control rendering pipeline from here */ static void PAINT_TEXTURE_draw_scene(void *vedata) { - PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; - PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl; + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl; - /* Default framebuffer and texture */ - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - UNUSED_VARS(fbl, dfbl, dtxl); + UNUSED_VARS(fbl, dfbl, dtxl); - DRW_draw_pass(psl->image_faces); + DRW_draw_pass(psl->image_faces); - DRW_draw_pass(psl->face_overlay); - DRW_draw_pass(psl->wire_overlay); + DRW_draw_pass(psl->face_overlay); + DRW_draw_pass(psl->wire_overlay); } /* Cleanup when destroying the engine. @@ -365,25 +376,27 @@ static void PAINT_TEXTURE_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void PAINT_TEXTURE_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.image_sh); - DRW_SHADER_FREE_SAFE(e_data.image_masking_sh); - DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader); - DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader); + DRW_SHADER_FREE_SAFE(e_data.image_sh); + DRW_SHADER_FREE_SAFE(e_data.image_masking_sh); + DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader); + DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader); } -static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data); +static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE( + PAINT_TEXTURE_Data); DrawEngineType draw_engine_paint_texture_type = { - NULL, NULL, - N_("PaintTextureMode"), - &PAINT_TEXTURE_data_size, - &PAINT_TEXTURE_engine_init, - &PAINT_TEXTURE_engine_free, - &PAINT_TEXTURE_cache_init, - &PAINT_TEXTURE_cache_populate, - &PAINT_TEXTURE_cache_finish, - NULL, /* draw_background but not needed by mode engines */ - &PAINT_TEXTURE_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("PaintTextureMode"), + &PAINT_TEXTURE_data_size, + &PAINT_TEXTURE_engine_init, + &PAINT_TEXTURE_engine_free, + &PAINT_TEXTURE_cache_init, + &PAINT_TEXTURE_cache_populate, + &PAINT_TEXTURE_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &PAINT_TEXTURE_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c index 95ee3729c77..ef3af1255eb 100644 --- a/source/blender/draw/modes/paint_vertex_mode.c +++ b/source/blender/draw/modes/paint_vertex_mode.c @@ -48,305 +48,318 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; /* *********** LISTS *********** */ enum { - VERTEX_MODE = 0, - WEIGHT_MODE = 1, + VERTEX_MODE = 0, + WEIGHT_MODE = 1, }; #define MODE_LEN (WEIGHT_MODE + 1) typedef struct PAINT_VERTEX_PassList { - struct { - struct DRWPass *color_faces; - } by_mode[MODE_LEN]; - struct DRWPass *wire_overlay; - struct DRWPass *wire_select_overlay; - struct DRWPass *face_select_overlay; - struct DRWPass *vert_select_overlay; + struct { + struct DRWPass *color_faces; + } by_mode[MODE_LEN]; + struct DRWPass *wire_overlay; + struct DRWPass *wire_select_overlay; + struct DRWPass *face_select_overlay; + struct DRWPass *vert_select_overlay; } PAINT_VERTEX_PassList; typedef struct PAINT_VERTEX_StorageList { - struct PAINT_VERTEX_PrivateData *g_data; + struct PAINT_VERTEX_PrivateData *g_data; } PAINT_VERTEX_StorageList; typedef struct PAINT_VERTEX_Data { - void *engine_type; /* Required */ - DRWViewportEmptyList *fbl; - DRWViewportEmptyList *txl; - PAINT_VERTEX_PassList *psl; - PAINT_VERTEX_StorageList *stl; + void *engine_type; /* Required */ + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + PAINT_VERTEX_PassList *psl; + PAINT_VERTEX_StorageList *stl; } PAINT_VERTEX_Data; typedef struct PAINT_VERTEX_Shaders { - struct { - struct GPUShader *color_face; - struct GPUShader *wire_overlay; - struct GPUShader *wire_select_overlay; - } by_mode[MODE_LEN]; - struct GPUShader *face_select_overlay; - struct GPUShader *vert_select_overlay; + struct { + struct GPUShader *color_face; + struct GPUShader *wire_overlay; + struct GPUShader *wire_select_overlay; + } by_mode[MODE_LEN]; + struct GPUShader *face_select_overlay; + struct GPUShader *vert_select_overlay; } PAINT_VERTEX_Shaders; /* *********** STATIC *********** */ static struct { - PAINT_VERTEX_Shaders sh_data[GPU_SHADER_CFG_LEN]; + PAINT_VERTEX_Shaders sh_data[GPU_SHADER_CFG_LEN]; } e_data = {{{{{NULL}}}}}; /* Engine data */ typedef struct PAINT_VERTEX_PrivateData { - struct { - DRWShadingGroup *color_shgrp; - DRWShadingGroup *lwire_shgrp; - DRWShadingGroup *lwire_select_shgrp; - } by_mode[MODE_LEN]; - DRWShadingGroup *face_select_shgrp; - DRWShadingGroup *vert_select_shgrp; + struct { + DRWShadingGroup *color_shgrp; + DRWShadingGroup *lwire_shgrp; + DRWShadingGroup *lwire_select_shgrp; + } by_mode[MODE_LEN]; + DRWShadingGroup *face_select_shgrp; + DRWShadingGroup *vert_select_shgrp; } PAINT_VERTEX_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - - if (!sh_data->face_select_overlay) { - sh_data->by_mode[VERTEX_MODE].color_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_vertex_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_paint_vertex_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - sh_data->by_mode[WEIGHT_MODE].color_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_paint_weight_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_common_globals_lib_glsl, datatoc_paint_weight_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - - sh_data->face_select_overlay = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_face_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, - }); - sh_data->vert_select_overlay = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_paint_wire_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_paint_vert_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, "#define USE_SELECT\n", NULL}, - }); - - const char *mode_defs[MODE_LEN] = { - "#define VERTEX_MODE\n", - "#define WEIGHT_MODE\n", - }; - for (int i = 0; i < MODE_LEN; i++) { - sh_data->by_mode[i].wire_overlay = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_paint_wire_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, mode_defs[i], NULL}, - }); - sh_data->by_mode[i].wire_select_overlay = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_paint_wire_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, mode_defs[i], "#define USE_SELECT\n", NULL}, - }); - } - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); + } + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + if (!sh_data->face_select_overlay) { + sh_data->by_mode[VERTEX_MODE].color_face = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_vertex_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_paint_vertex_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + sh_data->by_mode[WEIGHT_MODE].color_face = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_paint_weight_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_common_globals_lib_glsl, + datatoc_paint_weight_frag_glsl, + NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + + sh_data->face_select_overlay = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_face_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + sh_data->vert_select_overlay = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_paint_wire_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_paint_vert_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define USE_SELECT\n", NULL}, + }); + + const char *mode_defs[MODE_LEN] = { + "#define VERTEX_MODE\n", + "#define WEIGHT_MODE\n", + }; + for (int i = 0; i < MODE_LEN; i++) { + sh_data->by_mode[i].wire_overlay = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_paint_wire_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, mode_defs[i], NULL}, + }); + sh_data->by_mode[i].wire_select_overlay = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_paint_wire_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, mode_defs[i], "#define USE_SELECT\n", NULL}, + }); + } + } } static void PAINT_VERTEX_cache_init(void *vedata) { - PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; - PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - const View3D *v3d = draw_ctx->v3d; - const RegionView3D *rv3d = draw_ctx->rv3d; - PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - /* Vertex color pass */ - { - DRWPass *pass = DRW_pass_create( - "Vert Color Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY); - DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[VERTEX_MODE].color_face, pass); - DRW_shgroup_uniform_float_copy(shgrp, "white_factor", 1.0f - v3d->overlay.vertex_paint_mode_opacity); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); - } - psl->by_mode[VERTEX_MODE].color_faces = pass; - stl->g_data->by_mode[VERTEX_MODE].color_shgrp = shgrp; - } - - /* Weight color pass */ - { - DRWPass *pass = DRW_pass_create( - "Weight Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY); - DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[WEIGHT_MODE].color_face, pass); - DRW_shgroup_uniform_bool_copy(shgrp, "drawContours", (v3d->overlay.wpaint_flag & V3D_OVERLAY_WPAINT_CONTOURS) != 0); - DRW_shgroup_uniform_float(shgrp, "opacity", &v3d->overlay.weight_paint_mode_opacity, 1); - DRW_shgroup_uniform_texture(shgrp, "colorramp", G_draw.weight_ramp); - DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); - } - psl->by_mode[WEIGHT_MODE].color_faces = pass; - stl->g_data->by_mode[WEIGHT_MODE].color_shgrp = shgrp; - } - - { - DRWPass *pass = DRW_pass_create( - "Wire Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); - for (int i = 0; i < MODE_LEN; i++) { - DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_overlay, pass); - DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); - } - stl->g_data->by_mode[i].lwire_shgrp = shgrp; - } - psl->wire_overlay = pass; - } - - - { - DRWPass *pass = DRW_pass_create( - "Wire Mask Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); - for (int i = 0; i < MODE_LEN; i++) { - DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_select_overlay, pass); - DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); - } - stl->g_data->by_mode[i].lwire_select_shgrp = shgrp; - } - psl->wire_select_overlay = pass; - } - - { - static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; - DRWPass *pass = DRW_pass_create( - "Face Mask Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); - DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->face_select_overlay, pass); - DRW_shgroup_uniform_vec4(shgrp, "color", col, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); - } - psl->face_select_overlay = pass; - stl->g_data->face_select_shgrp = shgrp; - } - - { - DRWPass *pass = DRW_pass_create( - "Vert Mask Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); - DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->vert_select_overlay, pass); - DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); - } - psl->vert_select_overlay = pass; - stl->g_data->vert_select_shgrp = shgrp; - } + PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; + PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + const RegionView3D *rv3d = draw_ctx->rv3d; + PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + /* Vertex color pass */ + { + DRWPass *pass = DRW_pass_create( + "Vert Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY); + DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[VERTEX_MODE].color_face, pass); + DRW_shgroup_uniform_float_copy( + shgrp, "white_factor", 1.0f - v3d->overlay.vertex_paint_mode_opacity); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + } + psl->by_mode[VERTEX_MODE].color_faces = pass; + stl->g_data->by_mode[VERTEX_MODE].color_shgrp = shgrp; + } + + /* Weight color pass */ + { + DRWPass *pass = DRW_pass_create( + "Weight Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY); + DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[WEIGHT_MODE].color_face, pass); + DRW_shgroup_uniform_bool_copy( + shgrp, "drawContours", (v3d->overlay.wpaint_flag & V3D_OVERLAY_WPAINT_CONTOURS) != 0); + DRW_shgroup_uniform_float(shgrp, "opacity", &v3d->overlay.weight_paint_mode_opacity, 1); + DRW_shgroup_uniform_texture(shgrp, "colorramp", G_draw.weight_ramp); + DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + } + psl->by_mode[WEIGHT_MODE].color_faces = pass; + stl->g_data->by_mode[WEIGHT_MODE].color_shgrp = shgrp; + } + + { + DRWPass *pass = DRW_pass_create("Wire Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); + for (int i = 0; i < MODE_LEN; i++) { + DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_overlay, pass); + DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + } + stl->g_data->by_mode[i].lwire_shgrp = shgrp; + } + psl->wire_overlay = pass; + } + + { + DRWPass *pass = DRW_pass_create("Wire Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); + for (int i = 0; i < MODE_LEN; i++) { + DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_select_overlay, pass); + DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + } + stl->g_data->by_mode[i].lwire_select_shgrp = shgrp; + } + psl->wire_select_overlay = pass; + } + + { + static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; + DRWPass *pass = DRW_pass_create("Face Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->face_select_overlay, pass); + DRW_shgroup_uniform_vec4(shgrp, "color", col, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + } + psl->face_select_overlay = pass; + stl->g_data->face_select_shgrp = shgrp; + } + + { + DRWPass *pass = DRW_pass_create("Vert Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); + DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->vert_select_overlay, pass); + DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + } + psl->vert_select_overlay = pass; + stl->g_data->vert_select_shgrp = shgrp; + } } static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob) { - PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - const View3D *v3d = draw_ctx->v3d; - - if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) { - const int draw_mode = (ob->mode == OB_MODE_VERTEX_PAINT) ? VERTEX_MODE : WEIGHT_MODE; - const Mesh *me = ob->data; - const Mesh *me_orig = DEG_get_original_object(ob)->data; - const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0; - const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - const bool use_vert_sel = (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - - struct GPUBatch *geom = NULL; - if (draw_mode == VERTEX_MODE) { - if (me->mloopcol == NULL) { - return; - } - if (v3d->overlay.vertex_paint_mode_opacity != 0.0f) { - geom = DRW_cache_mesh_surface_vertpaint_get(ob); - } - } - else { - if (v3d->overlay.weight_paint_mode_opacity != 0.0f) { - geom = DRW_cache_mesh_surface_weights_get(ob); - } - } - if (geom != NULL) { - DRW_shgroup_call_add(stl->g_data->by_mode[draw_mode].color_shgrp, geom, ob->obmat); - } - - if (use_face_sel || use_wire) { - DRWShadingGroup *shgrp = use_face_sel ? - stl->g_data->by_mode[draw_mode].lwire_select_shgrp : - stl->g_data->by_mode[draw_mode].lwire_shgrp; - geom = DRW_cache_mesh_surface_edges_get(ob); - DRW_shgroup_call_add(shgrp, geom, ob->obmat); - } - - if (use_face_sel) { - geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->face_select_shgrp, geom, ob->obmat); - } - - if (use_vert_sel) { - geom = DRW_cache_mesh_all_verts_get(ob); - DRW_shgroup_call_add(stl->g_data->vert_select_shgrp, geom, ob->obmat); - } - } + PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + + if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) { + const int draw_mode = (ob->mode == OB_MODE_VERTEX_PAINT) ? VERTEX_MODE : WEIGHT_MODE; + const Mesh *me = ob->data; + const Mesh *me_orig = DEG_get_original_object(ob)->data; + const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0; + const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + const bool use_vert_sel = (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + + struct GPUBatch *geom = NULL; + if (draw_mode == VERTEX_MODE) { + if (me->mloopcol == NULL) { + return; + } + if (v3d->overlay.vertex_paint_mode_opacity != 0.0f) { + geom = DRW_cache_mesh_surface_vertpaint_get(ob); + } + } + else { + if (v3d->overlay.weight_paint_mode_opacity != 0.0f) { + geom = DRW_cache_mesh_surface_weights_get(ob); + } + } + if (geom != NULL) { + DRW_shgroup_call_add(stl->g_data->by_mode[draw_mode].color_shgrp, geom, ob->obmat); + } + + if (use_face_sel || use_wire) { + DRWShadingGroup *shgrp = use_face_sel ? stl->g_data->by_mode[draw_mode].lwire_select_shgrp : + stl->g_data->by_mode[draw_mode].lwire_shgrp; + geom = DRW_cache_mesh_surface_edges_get(ob); + DRW_shgroup_call_add(shgrp, geom, ob->obmat); + } + + if (use_face_sel) { + geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(stl->g_data->face_select_shgrp, geom, ob->obmat); + } + + if (use_vert_sel) { + geom = DRW_cache_mesh_all_verts_get(ob); + DRW_shgroup_call_add(stl->g_data->vert_select_shgrp, geom, ob->obmat); + } + } } static void PAINT_VERTEX_draw_scene(void *vedata) { - PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; - for (int i = 0; i < MODE_LEN; i++) { - DRW_draw_pass(psl->by_mode[i].color_faces); - } - DRW_draw_pass(psl->wire_overlay); - DRW_draw_pass(psl->wire_select_overlay); - DRW_draw_pass(psl->vert_select_overlay); - DRW_draw_pass(psl->face_select_overlay); + PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; + for (int i = 0; i < MODE_LEN; i++) { + DRW_draw_pass(psl->by_mode[i].color_faces); + } + DRW_draw_pass(psl->wire_overlay); + DRW_draw_pass(psl->wire_select_overlay); + DRW_draw_pass(psl->vert_select_overlay); + DRW_draw_pass(psl->face_select_overlay); } static void PAINT_VERTEX_engine_free(void) { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - GPUShader **sh_data_as_array = (GPUShader **)sh_data; - for (int i = 0; i < (sizeof(PAINT_VERTEX_Shaders) / sizeof(GPUShader *)); i++) { - DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); - } - } + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(PAINT_VERTEX_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize PAINT_VERTEX_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_VERTEX_Data); DrawEngineType draw_engine_paint_vertex_type = { - NULL, NULL, - N_("PaintVertexMode"), - &PAINT_VERTEX_data_size, - &PAINT_VERTEX_engine_init, - &PAINT_VERTEX_engine_free, - &PAINT_VERTEX_cache_init, - &PAINT_VERTEX_cache_populate, - NULL, - NULL, - &PAINT_VERTEX_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("PaintVertexMode"), + &PAINT_VERTEX_data_size, + &PAINT_VERTEX_engine_init, + &PAINT_VERTEX_engine_free, + &PAINT_VERTEX_cache_init, + &PAINT_VERTEX_cache_populate, + NULL, + NULL, + &PAINT_VERTEX_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c index 3090322fc80..600a29fecb4 100644 --- a/source/blender/draw/modes/particle_mode.c +++ b/source/blender/draw/modes/particle_mode.c @@ -43,101 +43,96 @@ extern char datatoc_common_globals_lib_glsl[]; /* *********** LISTS *********** */ typedef struct PARTICLE_PassList { - struct DRWPass *psys_edit_pass; + struct DRWPass *psys_edit_pass; } PARTICLE_PassList; typedef struct PARTICLE_FramebufferList { - struct GPUFrameBuffer *fb; + struct GPUFrameBuffer *fb; } PARTICLE_FramebufferList; typedef struct PARTICLE_TextureList { - struct GPUTexture *texture; + struct GPUTexture *texture; } PARTICLE_TextureList; typedef struct PARTICLE_StorageList { - struct CustomStruct *block; - struct PARTICLE_PrivateData *g_data; + struct CustomStruct *block; + struct PARTICLE_PrivateData *g_data; } PARTICLE_StorageList; typedef struct PARTICLE_Data { - void *engine_type; /* Required */ - PARTICLE_FramebufferList *fbl; - PARTICLE_TextureList *txl; - PARTICLE_PassList *psl; - PARTICLE_StorageList *stl; + void *engine_type; /* Required */ + PARTICLE_FramebufferList *fbl; + PARTICLE_TextureList *txl; + PARTICLE_PassList *psl; + PARTICLE_StorageList *stl; } PARTICLE_Data; /* *********** STATIC *********** */ static struct { - struct GPUShader *strands_shader; - struct GPUShader *strands_weight_shader; - struct GPUShader *points_shader; + struct GPUShader *strands_shader; + struct GPUShader *strands_weight_shader; + struct GPUShader *points_shader; } e_data = {NULL}; /* Engine data */ typedef struct PARTICLE_PrivateData { - DRWShadingGroup *strands_group; - DRWShadingGroup *inner_points_group; - DRWShadingGroup *tip_points_group; + DRWShadingGroup *strands_group; + DRWShadingGroup *inner_points_group; + DRWShadingGroup *tip_points_group; } PARTICLE_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ static void particle_engine_init(void *UNUSED(vedata)) { - if (!e_data.strands_shader) { - e_data.strands_shader = DRW_shader_create_with_lib( - datatoc_particle_strand_vert_glsl, - NULL, - datatoc_particle_strand_frag_glsl, - datatoc_common_globals_lib_glsl, - ""); - - e_data.strands_weight_shader = DRW_shader_create_with_lib( - datatoc_particle_strand_vert_glsl, - NULL, - datatoc_particle_strand_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define USE_WEIGHT"); - - e_data.points_shader = DRW_shader_create_with_lib( - datatoc_particle_strand_vert_glsl, - NULL, - datatoc_particle_strand_frag_glsl, - datatoc_common_globals_lib_glsl, - "#define USE_POINTS"); - } + if (!e_data.strands_shader) { + e_data.strands_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl, + NULL, + datatoc_particle_strand_frag_glsl, + datatoc_common_globals_lib_glsl, + ""); + + e_data.strands_weight_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl, + NULL, + datatoc_particle_strand_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define USE_WEIGHT"); + + e_data.points_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl, + NULL, + datatoc_particle_strand_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define USE_POINTS"); + } } static void particle_cache_init(void *vedata) { - PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl; - PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - ParticleEditSettings *pset = PE_settings(draw_ctx->scene); - const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT); - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - /* Create a pass */ - psl->psys_edit_pass = DRW_pass_create("PSys Edit Pass", - (DRW_STATE_WRITE_COLOR | - DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_WIRE | - DRW_STATE_POINT)); - - GPUShader *strand_shader = (use_weight) ? e_data.strands_weight_shader : e_data.strands_shader; - stl->g_data->strands_group = DRW_shgroup_create(strand_shader, psl->psys_edit_pass); - stl->g_data->inner_points_group = DRW_shgroup_create(e_data.points_shader, psl->psys_edit_pass); - stl->g_data->tip_points_group = DRW_shgroup_create(e_data.points_shader, psl->psys_edit_pass); - - DRW_shgroup_uniform_block(stl->g_data->strands_group, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_block(stl->g_data->inner_points_group, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_block(stl->g_data->tip_points_group, "globalsBlock", G_draw.block_ubo); + PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl; + PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + ParticleEditSettings *pset = PE_settings(draw_ctx->scene); + const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT); + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + /* Create a pass */ + psl->psys_edit_pass = DRW_pass_create("PSys Edit Pass", + (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE | + DRW_STATE_POINT)); + + GPUShader *strand_shader = (use_weight) ? e_data.strands_weight_shader : e_data.strands_shader; + stl->g_data->strands_group = DRW_shgroup_create(strand_shader, psl->psys_edit_pass); + stl->g_data->inner_points_group = DRW_shgroup_create(e_data.points_shader, psl->psys_edit_pass); + stl->g_data->tip_points_group = DRW_shgroup_create(e_data.points_shader, psl->psys_edit_pass); + + DRW_shgroup_uniform_block(stl->g_data->strands_group, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(stl->g_data->inner_points_group, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(stl->g_data->tip_points_group, "globalsBlock", G_draw.block_ubo); } static void particle_edit_cache_populate(void *vedata, @@ -145,69 +140,66 @@ static void particle_edit_cache_populate(void *vedata, ParticleSystem *psys, PTCacheEdit *edit) { - PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - ParticleEditSettings *pset = PE_settings(draw_ctx->scene); - const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT); - { - struct GPUBatch *strands = - DRW_cache_particles_get_edit_strands(object, psys, edit, use_weight); - DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL); - } - if (pset->selectmode == SCE_SELECT_POINT) { - struct GPUBatch *points = - DRW_cache_particles_get_edit_inner_points(object, psys, edit); - DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL); - } - if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) { - struct GPUBatch *points = - DRW_cache_particles_get_edit_tip_points(object, psys, edit); - DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL); - } + PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + ParticleEditSettings *pset = PE_settings(draw_ctx->scene); + const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT); + { + struct GPUBatch *strands = DRW_cache_particles_get_edit_strands( + object, psys, edit, use_weight); + DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL); + } + if (pset->selectmode == SCE_SELECT_POINT) { + struct GPUBatch *points = DRW_cache_particles_get_edit_inner_points(object, psys, edit); + DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL); + } + if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) { + struct GPUBatch *points = DRW_cache_particles_get_edit_tip_points(object, psys, edit); + DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL); + } } static void particle_cache_populate(void *vedata, Object *object) { - if (object->mode != OB_MODE_PARTICLE_EDIT) { - return; - } - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); - /* Usually the edit structure is created by Particle Edit Mode Toggle - * operator, but sometimes it's invoked after tagging hair as outdated - * (for example, when toggling edit mode). That makes it impossible to - * create edit structure for until after next dependency graph evaluation. - * - * Ideally, the edit structure will be created here already via some - * dependency graph callback or so, but currently trying to make it nicer - * only causes bad level calls and breaks design from the past. - */ - Object *object_orig = DEG_get_original_object(object); - PTCacheEdit *edit = PE_create_current( - draw_ctx->depsgraph, scene_orig, object_orig); - if (edit == NULL) { - /* Happens when trying to edit particles in EMITTER mode without - * having them cached. - */ - return; - } - /* NOTE: We need to pass evaluated particle system, which we need - * to find first. - */ - ParticleSystem *psys = object->particlesystem.first; - ParticleSystem *psys_orig = object_orig->particlesystem.first; - while (psys_orig != NULL) { - if (PE_get_current_from_psys(psys_orig) == edit) { - break; - } - psys = psys->next; - psys_orig = psys_orig->next; - } - if (psys == NULL) { - printf("Error getting evaluated particle system for edit.\n"); - return; - } - particle_edit_cache_populate(vedata, object, psys, edit); + if (object->mode != OB_MODE_PARTICLE_EDIT) { + return; + } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); + /* Usually the edit structure is created by Particle Edit Mode Toggle + * operator, but sometimes it's invoked after tagging hair as outdated + * (for example, when toggling edit mode). That makes it impossible to + * create edit structure for until after next dependency graph evaluation. + * + * Ideally, the edit structure will be created here already via some + * dependency graph callback or so, but currently trying to make it nicer + * only causes bad level calls and breaks design from the past. + */ + Object *object_orig = DEG_get_original_object(object); + PTCacheEdit *edit = PE_create_current(draw_ctx->depsgraph, scene_orig, object_orig); + if (edit == NULL) { + /* Happens when trying to edit particles in EMITTER mode without + * having them cached. + */ + return; + } + /* NOTE: We need to pass evaluated particle system, which we need + * to find first. + */ + ParticleSystem *psys = object->particlesystem.first; + ParticleSystem *psys_orig = object_orig->particlesystem.first; + while (psys_orig != NULL) { + if (PE_get_current_from_psys(psys_orig) == edit) { + break; + } + psys = psys->next; + psys_orig = psys_orig->next; + } + if (psys == NULL) { + printf("Error getting evaluated particle system for edit.\n"); + return; + } + particle_edit_cache_populate(vedata, object, psys, edit); } /* Optional: Post-cache_populate callback */ @@ -219,32 +211,32 @@ static void particle_cache_finish(void *UNUSED(vedata)) static void particle_draw_scene(void *vedata) { - PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl; + PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl; - DRW_draw_pass(psl->psys_edit_pass); + DRW_draw_pass(psl->psys_edit_pass); } static void particle_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.strands_shader); - DRW_SHADER_FREE_SAFE(e_data.strands_weight_shader); - DRW_SHADER_FREE_SAFE(e_data.points_shader); + DRW_SHADER_FREE_SAFE(e_data.strands_shader); + DRW_SHADER_FREE_SAFE(e_data.strands_weight_shader); + DRW_SHADER_FREE_SAFE(e_data.points_shader); } -static const DrawEngineDataSize particle_data_size = - DRW_VIEWPORT_DATA_SIZE(PARTICLE_Data); +static const DrawEngineDataSize particle_data_size = DRW_VIEWPORT_DATA_SIZE(PARTICLE_Data); DrawEngineType draw_engine_particle_type = { - NULL, NULL, - N_("Particle Mode"), - &particle_data_size, - &particle_engine_init, - &particle_engine_free, - &particle_cache_init, - &particle_cache_populate, - &particle_cache_finish, - NULL, /* draw_background but not needed by mode engines */ - &particle_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("Particle Mode"), + &particle_data_size, + &particle_engine_init, + &particle_engine_free, + &particle_cache_init, + &particle_cache_populate, + &particle_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &particle_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c index c445335b587..5e3353414f5 100644 --- a/source/blender/draw/modes/pose_mode.c +++ b/source/blender/draw/modes/pose_mode.c @@ -45,56 +45,55 @@ */ typedef struct POSE_PassList { - struct DRWPass *bone_solid[2]; - struct DRWPass *bone_transp[2]; - struct DRWPass *bone_outline[2]; - struct DRWPass *bone_wire[2]; - struct DRWPass *bone_envelope[2]; - struct DRWPass *bone_axes; - struct DRWPass *relationship[2]; - struct DRWPass *bone_selection; + struct DRWPass *bone_solid[2]; + struct DRWPass *bone_transp[2]; + struct DRWPass *bone_outline[2]; + struct DRWPass *bone_wire[2]; + struct DRWPass *bone_envelope[2]; + struct DRWPass *bone_axes; + struct DRWPass *relationship[2]; + struct DRWPass *bone_selection; } POSE_PassList; typedef struct POSE_StorageList { - struct POSE_PrivateData *g_data; + struct POSE_PrivateData *g_data; } POSE_StorageList; typedef struct POSE_Data { - void *engine_type; - DRWViewportEmptyList *fbl; - DRWViewportEmptyList *txl; - POSE_PassList *psl; - POSE_StorageList *stl; + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + POSE_PassList *psl; + POSE_StorageList *stl; } POSE_Data; /* *********** STATIC *********** */ typedef struct POSE_PrivateData { - DRWShadingGroup *bone_selection_shgrp; - DRWShadingGroup *bone_selection_invert_shgrp; - float blend_color[4]; - float blend_color_invert[4]; - bool transparent_bones; + DRWShadingGroup *bone_selection_shgrp; + DRWShadingGroup *bone_selection_invert_shgrp; + float blend_color[4]; + float blend_color_invert[4]; + bool transparent_bones; } POSE_PrivateData; /* Transient data */ static struct { - struct GPUShader *bone_selection_sh; + struct GPUShader *bone_selection_sh; } e_data = {NULL}; - /* *********** FUNCTIONS *********** */ static bool POSE_is_bone_selection_overlay_active(void) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - const View3D *v3d = draw_ctx->v3d; - return v3d && (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) && draw_ctx->object_pose; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + return v3d && (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) && draw_ctx->object_pose; } static void POSE_engine_init(void *UNUSED(vedata)) { - if (!e_data.bone_selection_sh) { - e_data.bone_selection_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - } + if (!e_data.bone_selection_sh) { + e_data.bone_selection_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } } static void POSE_engine_free(void) @@ -105,130 +104,131 @@ static void POSE_engine_free(void) * Assume that all Passes are NULL */ static void POSE_cache_init(void *vedata) { - POSE_PassList *psl = ((POSE_Data *)vedata)->psl; - POSE_StorageList *stl = ((POSE_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - POSE_PrivateData *ppd = stl->g_data; - ppd->transparent_bones = (draw_ctx->v3d->shading.type == OB_WIRE); - - for (int i = 0; i < 2; ++i) { - /* Solid bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; - psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state | DRW_STATE_WRITE_DEPTH); - psl->bone_transp[i] = DRW_pass_create("Bone Transp Pass", state | DRW_STATE_BLEND); - - /* Bones Outline */ - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state); - - /* Wire bones */ - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; - psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state); - - /* distance outline around envelope bones */ - state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT; - psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state); - - state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_BLEND | DRW_STATE_WIRE; - psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state); - } - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND; - psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); - } - - { - if (POSE_is_bone_selection_overlay_active()) { - const float alpha = (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) ? 0.0f : v3d->overlay.xray_alpha_bone; - copy_v4_fl4(ppd->blend_color, 0.0f, 0.0f, 0.0f, alpha); - copy_v4_fl4(ppd->blend_color_invert, 0.0f, 0.0f, 0.0f, pow(alpha, 4)); - DRWShadingGroup *grp; - psl->bone_selection = DRW_pass_create( - "Bone Selection", - DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND); - grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection); - DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color, 1); - stl->g_data->bone_selection_shgrp = grp; - grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection); - DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color_invert, 1); - stl->g_data->bone_selection_invert_shgrp = grp; - } - } + POSE_PassList *psl = ((POSE_Data *)vedata)->psl; + POSE_StorageList *stl = ((POSE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + POSE_PrivateData *ppd = stl->g_data; + ppd->transparent_bones = (draw_ctx->v3d->shading.type == OB_WIRE); + + for (int i = 0; i < 2; ++i) { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state | DRW_STATE_WRITE_DEPTH); + psl->bone_transp[i] = DRW_pass_create("Bone Transp Pass", state | DRW_STATE_BLEND); + + /* Bones Outline */ + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state); + + /* Wire bones */ + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND; + psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state); + + /* distance outline around envelope bones */ + state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_CULL_FRONT; + psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state); + + state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE; + psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND; + psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); + } + + { + if (POSE_is_bone_selection_overlay_active()) { + const float alpha = (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) ? + 0.0f : + v3d->overlay.xray_alpha_bone; + copy_v4_fl4(ppd->blend_color, 0.0f, 0.0f, 0.0f, alpha); + copy_v4_fl4(ppd->blend_color_invert, 0.0f, 0.0f, 0.0f, pow(alpha, 4)); + DRWShadingGroup *grp; + psl->bone_selection = DRW_pass_create( + "Bone Selection", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND); + grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection); + DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color, 1); + stl->g_data->bone_selection_shgrp = grp; + grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection); + DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color_invert, 1); + stl->g_data->bone_selection_invert_shgrp = grp; + } + } } static bool POSE_is_driven_by_active_armature(Object *ob) { - Object *ob_arm = modifiers_isDeformedByArmature(ob); - if (ob_arm) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - bool is_active = DRW_pose_mode_armature(ob_arm, draw_ctx->obact); - if (!is_active && ob_arm->proxy_from) { - is_active = DRW_pose_mode_armature(ob_arm->proxy_from, draw_ctx->obact); - } - return is_active; - } - else { - Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob); - if (ob_mesh_deform) { - return POSE_is_driven_by_active_armature(ob_mesh_deform); - } - } - return false; + Object *ob_arm = modifiers_isDeformedByArmature(ob); + if (ob_arm) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + bool is_active = DRW_pose_mode_armature(ob_arm, draw_ctx->obact); + if (!is_active && ob_arm->proxy_from) { + is_active = DRW_pose_mode_armature(ob_arm->proxy_from, draw_ctx->obact); + } + return is_active; + } + else { + Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob); + if (ob_mesh_deform) { + return POSE_is_driven_by_active_armature(ob_mesh_deform); + } + } + return false; } /* Add geometry to shading groups. Execute for each objects */ static void POSE_cache_populate(void *vedata, Object *ob) { - POSE_PassList *psl = ((POSE_Data *)vedata)->psl; - POSE_PrivateData *ppd = ((POSE_Data *)vedata)->stl->g_data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - /* In the future this will allow us to implement face gizmos, - * and similar functionalities. For now we handle only pose bones. */ - - if (ob->type == OB_ARMATURE) { - if ((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) || - (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES)) - { - return; - } - if (DRW_pose_mode_armature(ob, draw_ctx->obact)) { - int ghost = (ob->dtx & OB_DRAWXRAY) ? 1 : 0; - bool transp = (ppd->transparent_bones || (ob->dt <= OB_WIRE)) || XRAY_FLAG_ENABLED(draw_ctx->v3d); - - DRWArmaturePasses passes = { - .bone_solid = (transp) ? psl->bone_transp[ghost] : psl->bone_solid[ghost], - .bone_outline = psl->bone_outline[ghost], - .bone_wire = psl->bone_wire[ghost], - .bone_envelope = psl->bone_envelope[ghost], - .bone_axes = psl->bone_axes, - .relationship_lines = psl->relationship[ghost], - }; - DRW_shgroup_armature_pose(ob, passes, transp); - } - } - else if (ob->type == OB_MESH && - !DRW_state_is_select() && - POSE_is_bone_selection_overlay_active()) - { - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - if (POSE_is_driven_by_active_armature(ob)) { - DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob); - } - else { - DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob); - } - } - } + POSE_PassList *psl = ((POSE_Data *)vedata)->psl; + POSE_PrivateData *ppd = ((POSE_Data *)vedata)->stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + /* In the future this will allow us to implement face gizmos, + * and similar functionalities. For now we handle only pose bones. */ + + if (ob->type == OB_ARMATURE) { + if ((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) || + (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES)) { + return; + } + if (DRW_pose_mode_armature(ob, draw_ctx->obact)) { + int ghost = (ob->dtx & OB_DRAWXRAY) ? 1 : 0; + bool transp = (ppd->transparent_bones || (ob->dt <= OB_WIRE)) || + XRAY_FLAG_ENABLED(draw_ctx->v3d); + + DRWArmaturePasses passes = { + .bone_solid = (transp) ? psl->bone_transp[ghost] : psl->bone_solid[ghost], + .bone_outline = psl->bone_outline[ghost], + .bone_wire = psl->bone_wire[ghost], + .bone_envelope = psl->bone_envelope[ghost], + .bone_axes = psl->bone_axes, + .relationship_lines = psl->relationship[ghost], + }; + DRW_shgroup_armature_pose(ob, passes, transp); + } + } + else if (ob->type == OB_MESH && !DRW_state_is_select() && + POSE_is_bone_selection_overlay_active()) { + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + if (POSE_is_driven_by_active_armature(ob)) { + DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob); + } + else { + DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob); + } + } + } } /** @@ -236,100 +236,96 @@ static void POSE_cache_populate(void *vedata, Object *ob) */ bool DRW_pose_mode_armature(Object *ob, Object *active_ob) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - - /* Pose armature is handled by pose mode engine. */ - if (((ob == active_ob) || (ob->mode & OB_MODE_POSE)) && - ((draw_ctx->object_mode & OB_MODE_POSE) != 0)) - { - return true; - } - - /* Armature parent is also handled by pose mode engine. */ - if ((active_ob != NULL) && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) != 0)) { - if (ob == draw_ctx->object_pose) { - return true; - } - } - - return false; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + /* Pose armature is handled by pose mode engine. */ + if (((ob == active_ob) || (ob->mode & OB_MODE_POSE)) && + ((draw_ctx->object_mode & OB_MODE_POSE) != 0)) { + return true; + } + + /* Armature parent is also handled by pose mode engine. */ + if ((active_ob != NULL) && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) != 0)) { + if (ob == draw_ctx->object_pose) { + return true; + } + } + + return false; } /* Draw time ! Control rendering pipeline from here */ static void POSE_draw_scene(void *vedata) { - POSE_PassList *psl = ((POSE_Data *)vedata)->psl; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const bool bone_selection_overlay = POSE_is_bone_selection_overlay_active(); - - if (DRW_state_is_select()) { - DRW_draw_pass(psl->bone_outline[0]); - DRW_draw_pass(psl->bone_solid[0]); - DRW_draw_pass(psl->bone_wire[0]); - DRW_draw_pass(psl->bone_outline[1]); - DRW_draw_pass(psl->bone_solid[1]); - DRW_draw_pass(psl->bone_wire[1]); - return; - } - - if (bone_selection_overlay) { - GPU_framebuffer_bind(dfbl->default_fb); - DRW_draw_pass(psl->bone_selection); - GPU_framebuffer_bind(dfbl->depth_only_fb); - GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0); - GPU_framebuffer_bind(dfbl->default_fb); - } - - DRW_draw_pass(psl->bone_envelope[0]); - DRW_draw_pass(psl->bone_transp[0]); - - MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); - - DRW_draw_pass(psl->bone_solid[0]); - DRW_draw_pass(psl->bone_outline[0]); - DRW_draw_pass(psl->bone_wire[0]); - DRW_draw_pass(psl->relationship[0]); - - MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); - - if (!DRW_pass_is_empty(psl->bone_envelope[1]) || - !DRW_pass_is_empty(psl->bone_transp[1]) || - !DRW_pass_is_empty(psl->bone_solid[1]) || - !DRW_pass_is_empty(psl->bone_outline[1]) || - !DRW_pass_is_empty(psl->bone_wire[1]) || - !DRW_pass_is_empty(psl->relationship[1])) - { - if (DRW_state_is_fbo()) { - GPU_framebuffer_bind(dfbl->default_fb); - GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); - } - - DRW_draw_pass(psl->bone_envelope[1]); - DRW_draw_pass(psl->bone_solid[1]); - DRW_draw_pass(psl->bone_transp[1]); - DRW_draw_pass(psl->bone_outline[1]); - DRW_draw_pass(psl->bone_wire[1]); - DRW_draw_pass(psl->relationship[1]); - } - - /* Draw axes with linesmooth and outside of multisample buffer. */ - DRW_draw_pass(psl->bone_axes); + POSE_PassList *psl = ((POSE_Data *)vedata)->psl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const bool bone_selection_overlay = POSE_is_bone_selection_overlay_active(); + + if (DRW_state_is_select()) { + DRW_draw_pass(psl->bone_outline[0]); + DRW_draw_pass(psl->bone_solid[0]); + DRW_draw_pass(psl->bone_wire[0]); + DRW_draw_pass(psl->bone_outline[1]); + DRW_draw_pass(psl->bone_solid[1]); + DRW_draw_pass(psl->bone_wire[1]); + return; + } + + if (bone_selection_overlay) { + GPU_framebuffer_bind(dfbl->default_fb); + DRW_draw_pass(psl->bone_selection); + GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0); + GPU_framebuffer_bind(dfbl->default_fb); + } + + DRW_draw_pass(psl->bone_envelope[0]); + DRW_draw_pass(psl->bone_transp[0]); + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); + + DRW_draw_pass(psl->bone_solid[0]); + DRW_draw_pass(psl->bone_outline[0]); + DRW_draw_pass(psl->bone_wire[0]); + DRW_draw_pass(psl->relationship[0]); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); + + if (!DRW_pass_is_empty(psl->bone_envelope[1]) || !DRW_pass_is_empty(psl->bone_transp[1]) || + !DRW_pass_is_empty(psl->bone_solid[1]) || !DRW_pass_is_empty(psl->bone_outline[1]) || + !DRW_pass_is_empty(psl->bone_wire[1]) || !DRW_pass_is_empty(psl->relationship[1])) { + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); + } + + DRW_draw_pass(psl->bone_envelope[1]); + DRW_draw_pass(psl->bone_solid[1]); + DRW_draw_pass(psl->bone_transp[1]); + DRW_draw_pass(psl->bone_outline[1]); + DRW_draw_pass(psl->bone_wire[1]); + DRW_draw_pass(psl->relationship[1]); + } + + /* Draw axes with linesmooth and outside of multisample buffer. */ + DRW_draw_pass(psl->bone_axes); } static const DrawEngineDataSize POSE_data_size = DRW_VIEWPORT_DATA_SIZE(POSE_Data); DrawEngineType draw_engine_pose_type = { - NULL, NULL, - N_("PoseMode"), - &POSE_data_size, - &POSE_engine_init, - &POSE_engine_free, - &POSE_cache_init, - &POSE_cache_populate, - NULL, - NULL, - &POSE_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("PoseMode"), + &POSE_data_size, + &POSE_engine_init, + &POSE_engine_free, + &POSE_cache_init, + &POSE_cache_populate, + NULL, + NULL, + &POSE_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c index ead539bc30f..b25a8af795b 100644 --- a/source/blender/draw/modes/sculpt_mode.c +++ b/source/blender/draw/modes/sculpt_mode.c @@ -48,60 +48,60 @@ extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; * for SCULPT_PassList */ typedef struct SCULPT_PassList { - /* Declare all passes here and init them in - * SCULPT_cache_init(). - * Only contains (DRWPass *) */ - struct DRWPass *pass; + /* Declare all passes here and init them in + * SCULPT_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *pass; } SCULPT_PassList; typedef struct SCULPT_FramebufferList { - /* Contains all framebuffer objects needed by this engine. - * Only contains (GPUFrameBuffer *) */ - struct GPUFrameBuffer *fb; + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; } SCULPT_FramebufferList; typedef struct SCULPT_TextureList { - /* Contains all framebuffer textures / utility textures - * needed by this engine. Only viewport specific textures - * (not per object). Only contains (GPUTexture *) */ - struct GPUTexture *texture; + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; } SCULPT_TextureList; typedef struct SCULPT_StorageList { - /* Contains any other memory block that the engine needs. - * Only directly MEM_(m/c)allocN'ed blocks because they are - * free with MEM_freeN() when viewport is freed. - * (not per object) */ - struct CustomStruct *block; - struct SCULPT_PrivateData *g_data; + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct SCULPT_PrivateData *g_data; } SCULPT_StorageList; typedef struct SCULPT_Data { - /* Struct returned by DRW_viewport_engine_data_ensure. - * If you don't use one of these, just make it a (void *) */ - // void *fbl; - void *engine_type; /* Required */ - SCULPT_FramebufferList *fbl; - SCULPT_TextureList *txl; - SCULPT_PassList *psl; - SCULPT_StorageList *stl; + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + SCULPT_FramebufferList *fbl; + SCULPT_TextureList *txl; + SCULPT_PassList *psl; + SCULPT_StorageList *stl; } SCULPT_Data; /* *********** STATIC *********** */ static struct { - /* Custom shaders : - * Add sources to source/blender/draw/modes/shaders - * init in SCULPT_engine_init(); - * free in SCULPT_engine_free(); */ - struct GPUShader *shader_smooth; + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in SCULPT_engine_init(); + * free in SCULPT_engine_free(); */ + struct GPUShader *shader_smooth; } e_data = {NULL}; /* Engine data */ typedef struct SCULPT_PrivateData { - /* This keeps the references of the shading groups for - * easy access in SCULPT_cache_populate() */ - DRWShadingGroup *group_flat; - DRWShadingGroup *group_smooth; + /* This keeps the references of the shading groups for + * easy access in SCULPT_cache_populate() */ + DRWShadingGroup *group_flat; + DRWShadingGroup *group_smooth; } SCULPT_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -111,137 +111,143 @@ typedef struct SCULPT_PrivateData { * (Optional) */ static void SCULPT_engine_init(void *vedata) { - SCULPT_TextureList *txl = ((SCULPT_Data *)vedata)->txl; - SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl; - SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + SCULPT_TextureList *txl = ((SCULPT_Data *)vedata)->txl; + SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; - UNUSED_VARS(txl, fbl, stl); + UNUSED_VARS(txl, fbl, stl); - if (!e_data.shader_smooth) { - e_data.shader_smooth = DRW_shader_create(datatoc_sculpt_mask_vert_glsl, NULL, - datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL); - } + if (!e_data.shader_smooth) { + e_data.shader_smooth = DRW_shader_create( + datatoc_sculpt_mask_vert_glsl, NULL, datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL); + } } /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void SCULPT_cache_init(void *vedata) { - SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; - SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; - - if (!stl->g_data) { - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY; - psl->pass = DRW_pass_create("Sculpt Pass", state); - stl->g_data->group_smooth = DRW_shgroup_create(e_data.shader_smooth, psl->pass); - } + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + + if (!stl->g_data) { + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY; + psl->pass = DRW_pass_create("Sculpt Pass", state); + stl->g_data->group_smooth = DRW_shgroup_create(e_data.shader_smooth, psl->pass); + } } -static void sculpt_draw_mask_cb( - DRWShadingGroup *shgroup, - void (*draw_fn)(DRWShadingGroup *shgroup, struct GPUBatch *geom), - void *user_data) +static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup, + void (*draw_fn)(DRWShadingGroup *shgroup, struct GPUBatch *geom), + void *user_data) { - Object *ob = user_data; - PBVH *pbvh = ob->sculpt->pbvh; - - if (pbvh) { - BKE_pbvh_draw_cb( - pbvh, NULL, NULL, false, false, true, - (void (*)(void *, struct GPUBatch *))draw_fn, shgroup); - } + Object *ob = user_data; + PBVH *pbvh = ob->sculpt->pbvh; + + if (pbvh) { + BKE_pbvh_draw_cb(pbvh, + NULL, + NULL, + false, + false, + true, + (void (*)(void *, struct GPUBatch *))draw_fn, + shgroup); + } } static void sculpt_update_pbvh_normals(Object *object) { - Mesh *mesh = object->data; - PBVH *pbvh = object->sculpt->pbvh; - SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg; - if (pbvh == NULL || subdiv_ccg == NULL) { - return; - } - BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg); - struct CCGFace **faces; - int num_faces; - BKE_pbvh_get_grid_updates(pbvh, 1, (void ***)&faces, &num_faces); - if (num_faces > 0) { - BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces); - MEM_freeN(faces); - } + Mesh *mesh = object->data; + PBVH *pbvh = object->sculpt->pbvh; + SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg; + if (pbvh == NULL || subdiv_ccg == NULL) { + return; + } + BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg); + struct CCGFace **faces; + int num_faces; + BKE_pbvh_get_grid_updates(pbvh, 1, (void ***)&faces, &num_faces); + if (num_faces > 0) { + BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces); + MEM_freeN(faces); + } } /* Add geometry to shadingGroups. Execute for each objects */ static void SCULPT_cache_populate(void *vedata, Object *ob) { - SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; - SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; - - UNUSED_VARS(psl, stl); - - if (ob->type == OB_MESH) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - - if (ob->sculpt && (ob == draw_ctx->obact)) { - sculpt_update_pbvh_normals(ob); - - /* XXX, needed for dyntopo-undo (which clears). - * probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */ - if (ob->sculpt->pbvh == NULL) { - /* create PBVH immediately (would be created on the fly too, - * but this avoids waiting on first stroke) */ - Scene *scene = draw_ctx->scene; - - BKE_sculpt_update_mesh_elements(draw_ctx->depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); - } - - PBVH *pbvh = ob->sculpt->pbvh; - if (pbvh && pbvh_has_mask(pbvh)) { - DRW_shgroup_call_generate_add(stl->g_data->group_smooth, sculpt_draw_mask_cb, ob, ob->obmat); - } - } - } + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + + UNUSED_VARS(psl, stl); + + if (ob->type == OB_MESH) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (ob->sculpt && (ob == draw_ctx->obact)) { + sculpt_update_pbvh_normals(ob); + + /* XXX, needed for dyntopo-undo (which clears). + * probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */ + if (ob->sculpt->pbvh == NULL) { + /* create PBVH immediately (would be created on the fly too, + * but this avoids waiting on first stroke) */ + Scene *scene = draw_ctx->scene; + + BKE_sculpt_update_mesh_elements( + draw_ctx->depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); + } + + PBVH *pbvh = ob->sculpt->pbvh; + if (pbvh && pbvh_has_mask(pbvh)) { + DRW_shgroup_call_generate_add( + stl->g_data->group_smooth, sculpt_draw_mask_cb, ob, ob->obmat); + } + } + } } /* Optional: Post-cache_populate callback */ static void SCULPT_cache_finish(void *vedata) { - SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; - SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; - /* Do something here! dependent on the objects gathered */ - UNUSED_VARS(psl, stl); + /* Do something here! dependent on the objects gathered */ + UNUSED_VARS(psl, stl); } /* Draw time ! Control rendering pipeline from here */ static void SCULPT_draw_scene(void *vedata) { - SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; - SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl; + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl; - /* Default framebuffer and texture */ - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - UNUSED_VARS(fbl, dfbl, dtxl); + UNUSED_VARS(fbl, dfbl, dtxl); - /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ - /* - * DRW_framebuffer_texture_detach(dtxl->depth); - * DRW_framebuffer_bind(fbl->custom_fb); - * DRW_draw_pass(psl->pass); - * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); - * DRW_framebuffer_bind(dfbl->default_fb); - */ + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ - /* ... or just render passes on default framebuffer. */ - DRW_draw_pass(psl->pass); + /* ... or just render passes on default framebuffer. */ + DRW_draw_pass(psl->pass); - /* If you changed framebuffer, double check you rebind - * the default one with its textures attached before finishing */ + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ } /* Cleanup when destroying the engine. @@ -249,22 +255,23 @@ static void SCULPT_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void SCULPT_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.shader_smooth); + DRW_SHADER_FREE_SAFE(e_data.shader_smooth); } static const DrawEngineDataSize SCULPT_data_size = DRW_VIEWPORT_DATA_SIZE(SCULPT_Data); DrawEngineType draw_engine_sculpt_type = { - NULL, NULL, - N_("SculptMode"), - &SCULPT_data_size, - &SCULPT_engine_init, - &SCULPT_engine_free, - &SCULPT_cache_init, - &SCULPT_cache_populate, - &SCULPT_cache_finish, - NULL, /* draw_background but not needed by mode engines */ - &SCULPT_draw_scene, - NULL, - NULL, + NULL, + NULL, + N_("SculptMode"), + &SCULPT_data_size, + &SCULPT_engine_init, + &SCULPT_engine_free, + &SCULPT_cache_init, + &SCULPT_cache_populate, + &SCULPT_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &SCULPT_draw_scene, + NULL, + NULL, }; diff --git a/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl b/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl index d9d59880e99..b81f9f639ca 100644 --- a/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl +++ b/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl @@ -13,26 +13,30 @@ out vec4 finalColor; vec2 compute_dir(vec2 v0, vec2 v1) { - vec2 dir = normalize(v1 - v0 + 1e-8); - dir = vec2(-dir.y, dir.x); - return dir; + vec2 dir = normalize(v1 - v0 + 1e-8); + dir = vec2(-dir.y, dir.x); + return dir; } void main(void) { - vec2 t; - vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) / viewportSize; - - bool is_persp = (ProjectionMatrix[3][3] == 0.0); - - finalColor = finalColor_geom[0]; - t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[0].gl_Position.w : 1.0)); - gl_Position = gl_in[0].gl_Position + vec4(t, 0.0, 0.0); EmitVertex(); - gl_Position = gl_in[0].gl_Position - vec4(t, 0.0, 0.0); EmitVertex(); - - finalColor = finalColor_geom[1]; - t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[1].gl_Position.w : 1.0)); - gl_Position = gl_in[1].gl_Position + vec4(t, 0.0, 0.0); EmitVertex(); - gl_Position = gl_in[1].gl_Position - vec4(t, 0.0, 0.0); EmitVertex(); - EndPrimitive(); + vec2 t; + vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) / viewportSize; + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + finalColor = finalColor_geom[0]; + t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[0].gl_Position.w : 1.0)); + gl_Position = gl_in[0].gl_Position + vec4(t, 0.0, 0.0); + EmitVertex(); + gl_Position = gl_in[0].gl_Position - vec4(t, 0.0, 0.0); + EmitVertex(); + + finalColor = finalColor_geom[1]; + t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[1].gl_Position.w : 1.0)); + gl_Position = gl_in[1].gl_Position + vec4(t, 0.0, 0.0); + EmitVertex(); + gl_Position = gl_in[1].gl_Position - vec4(t, 0.0, 0.0); + EmitVertex(); + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl b/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl index 276f4004fb6..b4d8abfe180 100644 --- a/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl +++ b/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl @@ -19,73 +19,77 @@ out vec4 finalColor_geom; /* project to screen space */ vec2 proj(vec4 pos) { - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } -#define SET_INTENSITY(A, B, C, min, max) (((1.0 - (float(C - B) / float(C - A))) * (max - min)) + min) +#define SET_INTENSITY(A, B, C, min, max) \ + (((1.0 - (float(C - B) / float(C - A))) * (max - min)) + min) void main() { - gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); - ssPos = proj(gl_Position); + ssPos = proj(gl_Position); - int frame = gl_VertexID + cacheStart; + int frame = gl_VertexID + cacheStart; - float intensity; /* how faint */ + float intensity; /* how faint */ - vec3 blend_base = (abs(frame - frameCurrent) == 1) ? colorCurrentFrame.rgb : colorBackground.rgb; /* "bleed" cframe color to ease color blending */ + vec3 blend_base = (abs(frame - frameCurrent) == 1) ? + colorCurrentFrame.rgb : + colorBackground.rgb; /* "bleed" cframe color to ease color blending */ - /* TODO: We might want something more consistent with custom color and standard colors. */ - if (frame < frameCurrent) { - if (useCustomColor) { - /* Custom color: previous frames color is darker than current frame */ - finalColor_geom.rgb = customColor * 0.25; - } - else { - /* black - before frameCurrent */ - if (selected) { - intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75); - } - else { - intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.68, 0.92); - } - finalColor_geom.rgb = mix(colorWire.rgb, blend_base, intensity); - } - } - else if (frame > frameCurrent) { - if (useCustomColor) { - /* Custom color: next frames color is equal to user selected color */ - finalColor_geom.rgb = customColor; - } - else { - /* blue - after frameCurrent */ - if (selected) { - intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75); - } - else { - intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.68, 0.92); - } + /* TODO: We might want something more consistent with custom color and standard colors. */ + if (frame < frameCurrent) { + if (useCustomColor) { + /* Custom color: previous frames color is darker than current frame */ + finalColor_geom.rgb = customColor * 0.25; + } + else { + /* black - before frameCurrent */ + if (selected) { + intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75); + } + else { + intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.68, 0.92); + } + finalColor_geom.rgb = mix(colorWire.rgb, blend_base, intensity); + } + } + else if (frame > frameCurrent) { + if (useCustomColor) { + /* Custom color: next frames color is equal to user selected color */ + finalColor_geom.rgb = customColor; + } + else { + /* blue - after frameCurrent */ + if (selected) { + intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75); + } + else { + intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.68, 0.92); + } - finalColor_geom.rgb = mix(colorBonePose.rgb, blend_base, intensity); - } - } - else { - if (useCustomColor) { - /* Custom color: current frame color is slightly darker than user selected color */ - finalColor_geom.rgb = customColor * 0.5; - } - else { - /* green - on frameCurrent */ - if (selected) { - intensity = 0.5f; - } - else { - intensity = 0.99f; - } - finalColor_geom.rgb = clamp(mix(colorCurrentFrame.rgb, colorBackground.rgb, intensity) - 0.1, 0.0, 0.1); - } - } + finalColor_geom.rgb = mix(colorBonePose.rgb, blend_base, intensity); + } + } + else { + if (useCustomColor) { + /* Custom color: current frame color is slightly darker than user selected color */ + finalColor_geom.rgb = customColor * 0.5; + } + else { + /* green - on frameCurrent */ + if (selected) { + intensity = 0.5f; + } + else { + intensity = 0.99f; + } + finalColor_geom.rgb = clamp( + mix(colorCurrentFrame.rgb, colorBackground.rgb, intensity) - 0.1, 0.0, 0.1); + } + } - finalColor_geom.a = 1.0; + finalColor_geom.a = 1.0; } diff --git a/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl b/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl index f662cf5afde..70267e78d9e 100644 --- a/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl +++ b/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl @@ -19,34 +19,34 @@ out vec4 finalColor; void main() { - gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); - gl_PointSize = float(pointSize + 2); - - int frame = gl_VertexID + cacheStart; - finalColor = (useCustomColor) ? vec4(customColor, 1.0) : vec4(1.0); - - /* Bias to reduce z fighting with the path */ - gl_Position.z -= 1e-4; - - if (gl_VertexID % stepSize == 0) { - gl_PointSize = float(pointSize) + 4; - } - - if (showKeyFrames) { - if ((flag & MOTIONPATH_VERT_KEY) != 0) { - gl_PointSize = float(pointSize + 5); - finalColor = colorVertexSelect; - /* Bias more to get these on top of regular points */ - gl_Position.z -= 1e-4; - } - /* Draw big green dot where the current frame is. - * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter - */ - if (frame == frameCurrent) { - gl_PointSize = float(pointSize + 8); - finalColor = colorCurrentFrame; - /* Bias more to get these on top of keyframes */ - gl_Position.z -= 1e-4; - } - } + gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); + gl_PointSize = float(pointSize + 2); + + int frame = gl_VertexID + cacheStart; + finalColor = (useCustomColor) ? vec4(customColor, 1.0) : vec4(1.0); + + /* Bias to reduce z fighting with the path */ + gl_Position.z -= 1e-4; + + if (gl_VertexID % stepSize == 0) { + gl_PointSize = float(pointSize) + 4; + } + + if (showKeyFrames) { + if ((flag & MOTIONPATH_VERT_KEY) != 0) { + gl_PointSize = float(pointSize + 5); + finalColor = colorVertexSelect; + /* Bias more to get these on top of regular points */ + gl_Position.z -= 1e-4; + } + /* Draw big green dot where the current frame is. + * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter + */ + if (frame == frameCurrent) { + gl_PointSize = float(pointSize + 8); + finalColor = colorCurrentFrame; + /* Bias more to get these on top of keyframes */ + gl_Position.z -= 1e-4; + } + } } diff --git a/source/blender/draw/modes/shaders/armature_axes_vert.glsl b/source/blender/draw/modes/shaders/armature_axes_vert.glsl index ac640f0c303..a689dce4d70 100644 --- a/source/blender/draw/modes/shaders/armature_axes_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_axes_vert.glsl @@ -17,21 +17,21 @@ flat out vec4 finalColor; void main() { - vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz; - vec3 y_axis = InstanceModelMatrix[1].xyz; - vec3 bone_loc = InstanceModelMatrix[3].xyz; - vec3 wpos = bone_loc + y_axis + chosen_axis * fract(axis); - vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y; - /* Scale uniformly by axis length */ - spos *= length(chosen_axis); + vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz; + vec3 y_axis = InstanceModelMatrix[1].xyz; + vec3 bone_loc = InstanceModelMatrix[3].xyz; + vec3 wpos = bone_loc + y_axis + chosen_axis * fract(axis); + vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y; + /* Scale uniformly by axis length */ + spos *= length(chosen_axis); - vec4 pos_4d = vec4(wpos + spos, 1.0); - gl_Position = ViewProjectionMatrix * pos_4d; + vec4 pos_4d = vec4(wpos + spos, 1.0); + gl_Position = ViewProjectionMatrix * pos_4d; - finalColor.rgb = mix(colorAxis, color.rgb, color.a); - finalColor.a = 1.0; + finalColor.rgb = mix(colorAxis, color.rgb, color.a); + finalColor.a = 1.0; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_dof_vert.glsl b/source/blender/draw/modes/shaders/armature_dof_vert.glsl index d9d56862140..321614835a1 100644 --- a/source/blender/draw/modes/shaders/armature_dof_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_dof_vert.glsl @@ -15,16 +15,16 @@ flat out vec4 finalColor; vec3 sphere_project(float ax, float az) { - float sine = 1.0 - ax * ax - az * az; - float q3 = sqrt(max(0.0, sine)); + float sine = 1.0 - ax * ax - az * az; + float q3 = sqrt(max(0.0, sine)); - return vec3(-az * q3, 0.5 - sine, ax * q3) * 2.0; + return vec3(-az * q3, 0.5 - sine, ax * q3) * 2.0; } void main() { - vec3 final_pos = sphere_project(pos.x * abs((pos.x > 0.0) ? amax.x : amin.x), - pos.y * abs((pos.y > 0.0) ? amax.y : amin.y)); - gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(final_pos, 1.0)); - finalColor = color; + vec3 final_pos = sphere_project(pos.x * abs((pos.x > 0.0) ? amax.x : amin.x), + pos.y * abs((pos.y > 0.0) ? amax.y : amin.y)); + gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(final_pos, 1.0)); + finalColor = color; } diff --git a/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl index cecc5447c7c..61aaf153e83 100644 --- a/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl @@ -1,6 +1,6 @@ flat in vec3 finalStateColor; /* UNUSED */ -flat in vec3 finalBoneColor; /* UNUSED */ +flat in vec3 finalBoneColor; /* UNUSED */ in vec3 normalView; out vec4 fragColor; @@ -9,7 +9,7 @@ uniform vec4 color = vec4(1.0, 1.0, 1.0, 0.2); void main() { - float n = normalize(normalView).z; - n = 1.0 - clamp(-n, 0.0, 1.0); - fragColor = color * n; + float n = normalize(normalView).z; + n = 1.0 - clamp(-n, 0.0, 1.0); + fragColor = color * n; } diff --git a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl index 7e78f600518..1e7fc4d11b8 100644 --- a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl @@ -27,139 +27,148 @@ flat out vec4 finalColor; /* project to screen space */ vec2 proj(vec4 pos) { - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } vec2 compute_dir(vec2 v0, vec2 v1, vec2 v2) { - vec2 dir = normalize(v2 - v0); - dir = vec2(dir.y, -dir.x); - return dir; + vec2 dir = normalize(v2 - v0); + dir = vec2(dir.y, -dir.x); + return dir; } mat3 compute_mat(vec4 sphere, vec3 bone_vec, out float z_ofs) { - bool is_persp = (ProjectionMatrix[3][3] == 0.0); - vec3 cam_ray = (is_persp) ? sphere.xyz - ViewMatrixInverse[3].xyz - : -ViewMatrixInverse[2].xyz; - - /* Sphere center distance from the camera (persp) in world space. */ - float cam_dist = length(cam_ray); - - /* Compute view aligned orthonormal space. */ - vec3 z_axis = cam_ray / cam_dist; - vec3 x_axis = normalize(cross(bone_vec, z_axis)); - vec3 y_axis = cross(z_axis, x_axis); - z_ofs = 0.0; - - if (is_persp) { - /* For perspective, the projected sphere radius - * can be bigger than the center disc. Compute the - * max angular size and compensate by sliding the disc - * towards the camera and scale it accordingly. */ - const float half_pi = 3.1415926 * 0.5; - float rad = sphere.w; - /* Let be : - * V the view vector origin. - * O the sphere origin. - * T the point on the target circle. - * We compute the angle between (OV) and (OT). */ - float a = half_pi - asin(rad / cam_dist); - float cos_b = cos(a); - float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); - - x_axis *= sin_b; - y_axis *= sin_b; - z_ofs = -rad * cos_b; - } - - return mat3(x_axis, y_axis, z_axis); + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + vec3 cam_ray = (is_persp) ? sphere.xyz - ViewMatrixInverse[3].xyz : -ViewMatrixInverse[2].xyz; + + /* Sphere center distance from the camera (persp) in world space. */ + float cam_dist = length(cam_ray); + + /* Compute view aligned orthonormal space. */ + vec3 z_axis = cam_ray / cam_dist; + vec3 x_axis = normalize(cross(bone_vec, z_axis)); + vec3 y_axis = cross(z_axis, x_axis); + z_ofs = 0.0; + + if (is_persp) { + /* For perspective, the projected sphere radius + * can be bigger than the center disc. Compute the + * max angular size and compensate by sliding the disc + * towards the camera and scale it accordingly. */ + const float half_pi = 3.1415926 * 0.5; + float rad = sphere.w; + /* Let be : + * V the view vector origin. + * O the sphere origin. + * T the point on the target circle. + * We compute the angle between (OV) and (OT). */ + float a = half_pi - asin(rad / cam_dist); + float cos_b = cos(a); + float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); + + x_axis *= sin_b; + y_axis *= sin_b; + z_ofs = -rad * cos_b; + } + + return mat3(x_axis, y_axis, z_axis); } -struct Bone { vec3 vec; float sinb; }; +struct Bone { + vec3 vec; + float sinb; +}; bool bone_blend_starts(vec3 p, Bone b) { - /* we just want to know when the head sphere starts interpolating. */ - return dot(p, b.vec) > -b.sinb; + /* we just want to know when the head sphere starts interpolating. */ + return dot(p, b.vec) > -b.sinb; } -vec3 get_outline_point( - vec2 pos, vec4 sph_near, vec4 sph_far, - mat3 mat_near, mat3 mat_far, float z_ofs_near, float z_ofs_far, Bone b) +vec3 get_outline_point(vec2 pos, + vec4 sph_near, + vec4 sph_far, + mat3 mat_near, + mat3 mat_far, + float z_ofs_near, + float z_ofs_far, + Bone b) { - /* Compute outline position on the nearest sphere and check - * if it penetrates the capsule body. If it does, put this - * vertex on the farthest sphere. */ - vec3 wpos = mat_near * vec3(pos * sph_near.w, z_ofs_near); - if (bone_blend_starts(wpos, b)) { - wpos = sph_far.xyz + mat_far * vec3(pos * sph_far.w, z_ofs_far); - } - else { - wpos += sph_near.xyz; - } - return wpos; + /* Compute outline position on the nearest sphere and check + * if it penetrates the capsule body. If it does, put this + * vertex on the farthest sphere. */ + vec3 wpos = mat_near * vec3(pos * sph_near.w, z_ofs_near); + if (bone_blend_starts(wpos, b)) { + wpos = sph_far.xyz + mat_far * vec3(pos * sph_far.w, z_ofs_far); + } + else { + wpos += sph_near.xyz; + } + return wpos; } void main() { - float dst_head = distance(headSphere.xyz, ViewMatrixInverse[3].xyz); - float dst_tail = distance(tailSphere.xyz, ViewMatrixInverse[3].xyz); - // float dst_head = -dot(headSphere.xyz, ViewMatrix[2].xyz); - // float dst_tail = -dot(tailSphere.xyz, ViewMatrix[2].xyz); - - vec4 sph_near, sph_far; - if ((dst_head > dst_tail) && (ProjectionMatrix[3][3] == 0.0)) { - sph_near = tailSphere; - sph_far = headSphere; - } - else { - sph_near = headSphere; - sph_far = tailSphere; - } - - vec3 bone_vec = (sph_far.xyz - sph_near.xyz) + 1e-8; - - Bone b; - float bone_lenrcp = 1.0 / max(1e-8, sqrt(dot(bone_vec, bone_vec))); - b.sinb = (sph_far.w - sph_near.w) * bone_lenrcp * sph_near.w; - b.vec = bone_vec * bone_lenrcp; - - float z_ofs_near, z_ofs_far; - mat3 mat_near = compute_mat(sph_near, bone_vec, z_ofs_near); - mat3 mat_far = compute_mat(sph_far, bone_vec, z_ofs_far); - - vec3 wpos0 = get_outline_point(pos0, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); - vec3 wpos1 = get_outline_point(pos1, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); - vec3 wpos2 = get_outline_point(pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); - - - vec4 pos_4d = vec4(wpos1, 1.0); + float dst_head = distance(headSphere.xyz, ViewMatrixInverse[3].xyz); + float dst_tail = distance(tailSphere.xyz, ViewMatrixInverse[3].xyz); + // float dst_head = -dot(headSphere.xyz, ViewMatrix[2].xyz); + // float dst_tail = -dot(tailSphere.xyz, ViewMatrix[2].xyz); + + vec4 sph_near, sph_far; + if ((dst_head > dst_tail) && (ProjectionMatrix[3][3] == 0.0)) { + sph_near = tailSphere; + sph_far = headSphere; + } + else { + sph_near = headSphere; + sph_far = tailSphere; + } + + vec3 bone_vec = (sph_far.xyz - sph_near.xyz) + 1e-8; + + Bone b; + float bone_lenrcp = 1.0 / max(1e-8, sqrt(dot(bone_vec, bone_vec))); + b.sinb = (sph_far.w - sph_near.w) * bone_lenrcp * sph_near.w; + b.vec = bone_vec * bone_lenrcp; + + float z_ofs_near, z_ofs_far; + mat3 mat_near = compute_mat(sph_near, bone_vec, z_ofs_near); + mat3 mat_far = compute_mat(sph_far, bone_vec, z_ofs_far); + + vec3 wpos0 = get_outline_point( + pos0, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); + vec3 wpos1 = get_outline_point( + pos1, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); + vec3 wpos2 = get_outline_point( + pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); + + vec4 pos_4d = vec4(wpos1, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif - vec4 V = ViewMatrix * pos_4d; - float pres_fac = (ProjectionMatrix[3][3] == 0.0) ? abs(V.z) : 1.0; + vec4 V = ViewMatrix * pos_4d; + float pres_fac = (ProjectionMatrix[3][3] == 0.0) ? abs(V.z) : 1.0; - vec4 p0 = ViewProjectionMatrix * vec4(wpos0, 1.0); - vec4 p1 = ProjectionMatrix * V; - vec4 p2 = ViewProjectionMatrix * vec4(wpos2, 1.0); + vec4 p0 = ViewProjectionMatrix * vec4(wpos0, 1.0); + vec4 p1 = ProjectionMatrix * V; + vec4 p2 = ViewProjectionMatrix * vec4(wpos2, 1.0); - /* compute position from 3 vertex because the change in direction - * can happen very quicky and lead to very thin edges. */ - vec2 ss0 = proj(p0); - vec2 ss1 = proj(p1); - vec2 ss2 = proj(p2); - vec2 edge_dir = compute_dir(ss0, ss1, ss2); + /* compute position from 3 vertex because the change in direction + * can happen very quicky and lead to very thin edges. */ + vec2 ss0 = proj(p0); + vec2 ss1 = proj(p1); + vec2 ss2 = proj(p2); + vec2 edge_dir = compute_dir(ss0, ss1, ss2); - bool outer = ((gl_VertexID & 1) == 1); - vec2 t = outlineColorSize.w * (lineThickness / viewportSize); - t *= pres_fac; - t = (outer) ? t : vec2(0.0); + bool outer = ((gl_VertexID & 1) == 1); + vec2 t = outlineColorSize.w * (lineThickness / viewportSize); + t *= pres_fac; + t = (outer) ? t : vec2(0.0); - gl_Position = p1; - gl_Position.xy += t * edge_dir; + gl_Position = p1; + gl_Position.xy += t * edge_dir; - finalColor = vec4(outlineColorSize.rgb, 1.0); + finalColor = vec4(outlineColorSize.rgb, 1.0); } diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl index 78b29296601..424cc92b930 100644 --- a/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl @@ -9,10 +9,10 @@ out vec4 fragColor; void main() { - /* Smooth lighting factor. */ - const float s = 0.2; /* [0.0-0.5] range */ - float n = normalize(normalView).z; - float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0); - fragColor.rgb = mix(finalStateColor, finalBoneColor, fac); - fragColor.a = alpha; + /* Smooth lighting factor. */ + const float s = 0.2; /* [0.0-0.5] range */ + float n = normalize(normalView).z; + float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0); + fragColor.rgb = mix(finalStateColor, finalBoneColor, fac); + fragColor.a = alpha; } diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl index 880c8c6262c..7f8ccc0c95a 100644 --- a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl @@ -6,7 +6,6 @@ uniform mat4 ViewProjectionMatrix; uniform mat4 ModelMatrix; #endif - /* ---- Instantiated Attrs ---- */ in vec3 pos; @@ -24,40 +23,40 @@ out vec3 normalView; void main() { - vec3 bone_vec = tailSphere.xyz - headSphere.xyz; - float bone_len = max(1e-8, sqrt(dot(bone_vec, bone_vec))); - float bone_lenrcp = 1.0 / bone_len; + vec3 bone_vec = tailSphere.xyz - headSphere.xyz; + float bone_len = max(1e-8, sqrt(dot(bone_vec, bone_vec))); + float bone_lenrcp = 1.0 / bone_len; #ifdef SMOOTH_ENVELOPE - float sinb = (tailSphere.w - headSphere.w) * bone_lenrcp; + float sinb = (tailSphere.w - headSphere.w) * bone_lenrcp; #else - const float sinb = 0.0; + const float sinb = 0.0; #endif - vec3 y_axis = bone_vec * bone_lenrcp; - vec3 z_axis = normalize(cross(xAxis, -y_axis)); - vec3 x_axis = cross(y_axis, z_axis); /* cannot trust xAxis to be orthogonal. */ + vec3 y_axis = bone_vec * bone_lenrcp; + vec3 z_axis = normalize(cross(xAxis, -y_axis)); + vec3 x_axis = cross(y_axis, z_axis); /* cannot trust xAxis to be orthogonal. */ - vec3 sp, nor; - nor = sp = pos.xyz; + vec3 sp, nor; + nor = sp = pos.xyz; - /* In bone space */ - bool is_head = (pos.z < -sinb); - sp *= (is_head) ? headSphere.w : tailSphere.w; - sp.z += (is_head) ? 0.0 : bone_len; + /* In bone space */ + bool is_head = (pos.z < -sinb); + sp *= (is_head) ? headSphere.w : tailSphere.w; + sp.z += (is_head) ? 0.0 : bone_len; - /* Convert to world space */ - mat3 bone_mat = mat3(x_axis, y_axis, z_axis); - sp = bone_mat * sp.xzy + headSphere.xyz; - nor = bone_mat * nor.xzy; + /* Convert to world space */ + mat3 bone_mat = mat3(x_axis, y_axis, z_axis); + sp = bone_mat * sp.xzy + headSphere.xyz; + nor = bone_mat * nor.xzy; - normalView = mat3(ViewMatrix) * nor; + normalView = mat3(ViewMatrix) * nor; - finalStateColor = stateColor; - finalBoneColor = boneColor; + finalStateColor = stateColor; + finalBoneColor = boneColor; - vec4 pos_4d = vec4(sp, 1.0); - gl_Position = ViewProjectionMatrix * pos_4d; + vec4 pos_4d = vec4(sp, 1.0); + gl_Position = ViewProjectionMatrix * pos_4d; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl index 0fdd874f1fd..54315863a2e 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl @@ -15,104 +15,104 @@ uniform float lineThickness = 2.0; vec2 compute_dir(vec2 v0, vec2 v1) { - vec2 dir = normalize(v1 - v0); - dir = vec2(-dir.y, dir.x); - return dir; + vec2 dir = normalize(v1 - v0); + dir = vec2(-dir.y, dir.x); + return dir; } void emit_edge(vec2 edge_dir, vec2 hidden_dir, vec2 thick, bool is_persp) { - float fac = dot(-hidden_dir, edge_dir); - edge_dir *= (fac < 0.0) ? -1.0 : 1.0; + float fac = dot(-hidden_dir, edge_dir); + edge_dir *= (fac < 0.0) ? -1.0 : 1.0; - vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0); - gl_Position = pPos[1]; + vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0); + gl_Position = pPos[1]; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); #endif - EmitVertex(); - gl_Position.xy += t * edge_dir; + EmitVertex(); + gl_Position.xy += t * edge_dir; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); - t = thick * (is_persp ? abs(vPos[2].z) : 1.0); - gl_Position = pPos[2]; + t = thick * (is_persp ? abs(vPos[2].z) : 1.0); + gl_Position = pPos[2]; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); #endif - EmitVertex(); - gl_Position.xy += t * edge_dir; + EmitVertex(); + gl_Position.xy += t * edge_dir; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); } void emit_corner(const int e, vec2 thick, bool is_persp) { - vec2 corner_dir = ssNor[e]; - vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0); + vec2 corner_dir = ssNor[e]; + vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0); - gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); + gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[e].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[e].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); } void main(void) { - finalColor = vec4(vColSize[0].rgb, 1.0); - - bool is_persp = (ProjectionMatrix[3][3] == 0.0); - - vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); - vec3 v10 = vPos[0] - vPos[1]; - vec3 v12 = vPos[2] - vPos[1]; - vec3 v13 = vPos[3] - vPos[1]; - - vec3 n0 = cross(v12, v10); - vec3 n3 = cross(v13, v12); - - float fac0 = dot(view_vec, n0); - float fac3 = dot(view_vec, n3); - - /* If one of the face is perpendicular to the view, - * consider it and outline edge. */ - if (abs(fac0) > 1e-5 && abs(fac3) > 1e-5) { - /* If both adjacent verts are facing the camera the same way, - * then it isn't an outline edge. */ - if (sign(fac0) == sign(fac3)) { - return; - } - } - - /* Don't outline if concave edge. */ - if (dot(n0, v13) > 0.0001) { - return; - } - - vec2 thick = vColSize[0].w * (lineThickness / viewportSize); - vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]); - - vec2 hidden_point; - /* Take the farthest point to compute edge direction - * (avoid problems with point behind near plane). - * If the chosen point is parallel to the edge in screen space, - * choose the other point anyway. - * This fixes some issue with cubes in orthographic views.*/ - if (vPos[0].z < vPos[3].z) { - hidden_point = (abs(fac0) > 1e-5) ? ssPos[0] : ssPos[3]; - } - else { - hidden_point = (abs(fac3) > 1e-5) ? ssPos[3] : ssPos[0]; - } - vec2 hidden_dir = normalize(hidden_point - ssPos[1]); - - emit_corner(1, thick, is_persp); - emit_edge(edge_dir, hidden_dir, thick, is_persp); - emit_corner(2, thick, is_persp); - EndPrimitive(); + finalColor = vec4(vColSize[0].rgb, 1.0); + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); + vec3 v10 = vPos[0] - vPos[1]; + vec3 v12 = vPos[2] - vPos[1]; + vec3 v13 = vPos[3] - vPos[1]; + + vec3 n0 = cross(v12, v10); + vec3 n3 = cross(v13, v12); + + float fac0 = dot(view_vec, n0); + float fac3 = dot(view_vec, n3); + + /* If one of the face is perpendicular to the view, + * consider it and outline edge. */ + if (abs(fac0) > 1e-5 && abs(fac3) > 1e-5) { + /* If both adjacent verts are facing the camera the same way, + * then it isn't an outline edge. */ + if (sign(fac0) == sign(fac3)) { + return; + } + } + + /* Don't outline if concave edge. */ + if (dot(n0, v13) > 0.0001) { + return; + } + + vec2 thick = vColSize[0].w * (lineThickness / viewportSize); + vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]); + + vec2 hidden_point; + /* Take the farthest point to compute edge direction + * (avoid problems with point behind near plane). + * If the chosen point is parallel to the edge in screen space, + * choose the other point anyway. + * This fixes some issue with cubes in orthographic views.*/ + if (vPos[0].z < vPos[3].z) { + hidden_point = (abs(fac0) > 1e-5) ? ssPos[0] : ssPos[3]; + } + else { + hidden_point = (abs(fac3) > 1e-5) ? ssPos[3] : ssPos[0]; + } + vec2 hidden_dir = normalize(hidden_point - ssPos[1]); + + emit_corner(1, thick, is_persp); + emit_edge(edge_dir, hidden_dir, thick, is_persp); + emit_corner(2, thick, is_persp); + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl index b190d834a61..82a483d91a5 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl @@ -22,31 +22,31 @@ out vec4 vColSize; /* project to screen space */ vec2 proj(vec4 pos) { - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } void main() { - /* This is slow and run per vertex, but it's still faster than - * doing it per instance on CPU and sending it on via instance attribute. */ - mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); + /* This is slow and run per vertex, but it's still faster than + * doing it per instance on CPU and sending it on via instance attribute. */ + mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); - vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0); - vec4 viewpos = ViewMatrix * worldPosition; + vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0); + vec4 viewpos = ViewMatrix * worldPosition; - vPos = viewpos.xyz; - pPos = ProjectionMatrix * viewpos; + vPos = viewpos.xyz; + pPos = ProjectionMatrix * viewpos; - /* TODO FIX: there is still a problem with this vector - * when the bone is scaled or in persp mode. But it's - * barelly visible at the outline corners. */ - ssNor = normalize((NormalMatrix * snor).xy); + /* TODO FIX: there is still a problem with this vector + * when the bone is scaled or in persp mode. But it's + * barelly visible at the outline corners. */ + ssNor = normalize((NormalMatrix * snor).xy); - ssPos = proj(pPos); + ssPos = proj(pPos); - vColSize = outlineColorSize; + vColSize = outlineColorSize; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(worldPosition.xyz); + world_clip_planes_calc_clip_distance(worldPosition.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl index 45748bf5644..39963344dd8 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl @@ -7,5 +7,5 @@ out vec4 fragColor; void main() { - fragColor = vec4(finalColor.rgb, alpha); + fragColor = vec4(finalColor.rgb, alpha); } diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl index 8463ffab447..2df25bf0e03 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl @@ -19,24 +19,23 @@ out vec4 finalColor; void main() { - mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); - vec3 normal = normalize(NormalMatrix * nor); + mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); + vec3 normal = normalize(NormalMatrix * nor); - /* Do lighting at an angle to avoid flat shading on front facing bone. */ - const vec3 light = vec3(0.1, 0.1, 0.8); - float n = dot(normal, light); + /* Do lighting at an angle to avoid flat shading on front facing bone. */ + const vec3 light = vec3(0.1, 0.1, 0.8); + float n = dot(normal, light); - /* Smooth lighting factor. */ - const float s = 0.2; /* [0.0-0.5] range */ - float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0); - finalColor.rgb = mix(stateColor, boneColor, fac); - finalColor.a = 1.0; + /* Smooth lighting factor. */ + const float s = 0.2; /* [0.0-0.5] range */ + float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0); + finalColor.rgb = mix(stateColor, boneColor, fac); + finalColor.a = 1.0; - - vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0); - gl_Position = ViewProjectionMatrix * worldPosition; + vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0); + gl_Position = ViewProjectionMatrix * worldPosition; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(worldPosition.xyz); + world_clip_planes_calc_clip_distance(worldPosition.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl index a48148a9a50..70a7f495af9 100644 --- a/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl @@ -17,91 +17,91 @@ flat out vec4 finalColor; /* project to screen space */ vec2 proj(vec4 pos) { - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } vec2 compute_dir(vec2 v0, vec2 v1, vec2 c) { - vec2 dir = normalize(v1 - v0); - dir = vec2(dir.y, -dir.x); - /* The model matrix can be scaled negativly. - * Use projected sphere center to determine - * the outline direction. */ - vec2 cv = c - v0; - dir = (dot(dir, cv) > 0.0) ? -dir : dir; - return dir; + vec2 dir = normalize(v1 - v0); + dir = vec2(dir.y, -dir.x); + /* The model matrix can be scaled negativly. + * Use projected sphere center to determine + * the outline direction. */ + vec2 cv = c - v0; + dir = (dot(dir, cv) > 0.0) ? -dir : dir; + return dir; } void main() { - mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; - mat4 sphereMatrix = inverse(model_view_matrix); - - bool is_persp = (ProjectionMatrix[3][3] == 0.0); - - /* This is the local space camera ray (not normalize). - * In perspective mode it's also the viewspace position - * of the sphere center. */ - vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0); - cam_ray = mat3(sphereMatrix) * cam_ray; - - /* Sphere center distance from the camera (persp) in local space. */ - float cam_dist = length(cam_ray); - - /* Compute view aligned orthonormal space. */ - vec3 z_axis = cam_ray / cam_dist; - vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis)); - vec3 y_axis = cross(z_axis, x_axis); - float z_ofs = 0.0; - - if (is_persp) { - /* For perspective, the projected sphere radius - * can be bigger than the center disc. Compute the - * max angular size and compensate by sliding the disc - * towards the camera and scale it accordingly. */ - const float half_pi = 3.1415926 * 0.5; - const float rad = 0.05; - /* Let be (in local space): - * V the view vector origin. - * O the sphere origin. - * T the point on the target circle. - * We compute the angle between (OV) and (OT). */ - float a = half_pi - asin(rad / cam_dist); - float cos_b = cos(a); - float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); - - x_axis *= sin_b; - y_axis *= sin_b; - z_ofs = -rad * cos_b; - } - - /* Camera oriented position (but still in local space) */ - vec3 cam_pos0 = x_axis * pos0.x + y_axis * pos0.y + z_axis * z_ofs; - vec3 cam_pos1 = x_axis * pos1.x + y_axis * pos1.y + z_axis * z_ofs; - - vec4 V = model_view_matrix * vec4(cam_pos0, 1.0); - vec4 p0 = ProjectionMatrix * V; - vec4 p1 = ProjectionMatrix * (model_view_matrix * vec4(cam_pos1, 1.0)); - vec4 c = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0); - - vec2 ssc = proj(c); - vec2 ss0 = proj(p0); - vec2 ss1 = proj(p1); - vec2 edge_dir = compute_dir(ss0, ss1, ssc); - - bool outer = ((gl_VertexID & 1) == 1); - - vec2 t = outlineColorSize.w * (lineThickness / viewportSize); - t *= (is_persp) ? abs(V.z) : 1.0; - t = (outer) ? t : vec2(0.0); - - gl_Position = p0; - gl_Position.xy += t * edge_dir; - - finalColor = vec4(outlineColorSize.rgb, 1.0); + mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; + mat4 sphereMatrix = inverse(model_view_matrix); + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + /* This is the local space camera ray (not normalize). + * In perspective mode it's also the viewspace position + * of the sphere center. */ + vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0); + cam_ray = mat3(sphereMatrix) * cam_ray; + + /* Sphere center distance from the camera (persp) in local space. */ + float cam_dist = length(cam_ray); + + /* Compute view aligned orthonormal space. */ + vec3 z_axis = cam_ray / cam_dist; + vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis)); + vec3 y_axis = cross(z_axis, x_axis); + float z_ofs = 0.0; + + if (is_persp) { + /* For perspective, the projected sphere radius + * can be bigger than the center disc. Compute the + * max angular size and compensate by sliding the disc + * towards the camera and scale it accordingly. */ + const float half_pi = 3.1415926 * 0.5; + const float rad = 0.05; + /* Let be (in local space): + * V the view vector origin. + * O the sphere origin. + * T the point on the target circle. + * We compute the angle between (OV) and (OT). */ + float a = half_pi - asin(rad / cam_dist); + float cos_b = cos(a); + float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); + + x_axis *= sin_b; + y_axis *= sin_b; + z_ofs = -rad * cos_b; + } + + /* Camera oriented position (but still in local space) */ + vec3 cam_pos0 = x_axis * pos0.x + y_axis * pos0.y + z_axis * z_ofs; + vec3 cam_pos1 = x_axis * pos1.x + y_axis * pos1.y + z_axis * z_ofs; + + vec4 V = model_view_matrix * vec4(cam_pos0, 1.0); + vec4 p0 = ProjectionMatrix * V; + vec4 p1 = ProjectionMatrix * (model_view_matrix * vec4(cam_pos1, 1.0)); + vec4 c = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0); + + vec2 ssc = proj(c); + vec2 ss0 = proj(p0); + vec2 ss1 = proj(p1); + vec2 edge_dir = compute_dir(ss0, ss1, ssc); + + bool outer = ((gl_VertexID & 1) == 1); + + vec2 t = outlineColorSize.w * (lineThickness / viewportSize); + t *= (is_persp) ? abs(V.z) : 1.0; + t = (outer) ? t : vec2(0.0); + + gl_Position = p0; + gl_Position.xy += t * edge_dir; + + finalColor = vec4(outlineColorSize.rgb, 1.0); #ifdef USE_WORLD_CLIP_PLANES - vec4 worldPosition = InstanceModelMatrix * vec4(cam_pos0, 1.0); - world_clip_planes_calc_clip_distance(worldPosition.xyz); + vec4 worldPosition = InstanceModelMatrix * vec4(cam_pos0, 1.0); + world_clip_planes_calc_clip_distance(worldPosition.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl index a0fdd55931f..93edbe940fd 100644 --- a/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl @@ -21,61 +21,60 @@ out vec4 fragColor; float get_depth_from_view_z(float z) { - if (ProjectionMatrix[3][3] == 0.0) { - z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; - } - else { - z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]); - } - return z * 0.5 + 0.5; + if (ProjectionMatrix[3][3] == 0.0) { + z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; + } + else { + z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]); + } + return z * 0.5 + 0.5; } void main() { - const float sphere_radius = 0.05; - - bool is_perp = (ProjectionMatrix[3][3] == 0.0); - vec3 ray_ori_view = (is_perp) ? vec3(0.0) : viewPosition.xyz; - vec3 ray_dir_view = (is_perp) ? viewPosition : vec3(0.0, 0.0, -1.0); - - /* Single matrix mul without branch. */ - vec4 mul_vec = (is_perp) ? vec4(ray_dir_view, 0.0) : vec4(ray_ori_view, 1.0); - vec3 mul_res = (sphereMatrix * mul_vec).xyz; - - /* Reminder : - * sphereMatrix[3] is the view space origin in sphere space (sph_ori -> view_ori). - * sphereMatrix[2] is the view space Z axis in sphere space. */ - - /* convert to sphere local space */ - vec3 ray_ori = (is_perp) ? sphereMatrix[3].xyz : mul_res; - vec3 ray_dir = (is_perp) ? mul_res : -sphereMatrix[2].xyz; - float ray_len = length(ray_dir); - ray_dir /= ray_len; - - /* Line to sphere intersect */ - const float sphere_radius_sqr = sphere_radius * sphere_radius; - float b = dot(ray_ori, ray_dir); - float c = dot(ray_ori, ray_ori) - sphere_radius_sqr; - float h = b * b - c; - float t = -sqrt(max(0.0, h)) - b; - - /* Compute dot product for lighting */ - vec3 p = ray_dir * t + ray_ori; /* Point on sphere */ - vec3 n = normalize(p); /* Normal is just the point in sphere space, normalized. */ - vec3 l = normalize(sphereMatrix[2].xyz); /* Just the view Z axis in the sphere space. */ - - - /* Smooth lighting factor. */ - const float s = 0.2; /* [0.0-0.5] range */ - float fac = clamp((dot(n, l) * (1.0 - s)) + s, 0.0, 1.0); - fragColor.rgb = mix(finalStateColor, finalBoneColor, fac); - - /* 2x2 dither pattern to smooth the lighting. */ - float dither = (0.5 + dot(vec2(ivec2(gl_FragCoord.xy) & ivec2(1)), vec2(1.0, 2.0))) * 0.25; - dither *= (1.0 / 255.0); /* Assume 8bit per color buffer. */ - - fragColor = vec4(fragColor.rgb + dither, alpha); - - t /= ray_len; - gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z); + const float sphere_radius = 0.05; + + bool is_perp = (ProjectionMatrix[3][3] == 0.0); + vec3 ray_ori_view = (is_perp) ? vec3(0.0) : viewPosition.xyz; + vec3 ray_dir_view = (is_perp) ? viewPosition : vec3(0.0, 0.0, -1.0); + + /* Single matrix mul without branch. */ + vec4 mul_vec = (is_perp) ? vec4(ray_dir_view, 0.0) : vec4(ray_ori_view, 1.0); + vec3 mul_res = (sphereMatrix * mul_vec).xyz; + + /* Reminder : + * sphereMatrix[3] is the view space origin in sphere space (sph_ori -> view_ori). + * sphereMatrix[2] is the view space Z axis in sphere space. */ + + /* convert to sphere local space */ + vec3 ray_ori = (is_perp) ? sphereMatrix[3].xyz : mul_res; + vec3 ray_dir = (is_perp) ? mul_res : -sphereMatrix[2].xyz; + float ray_len = length(ray_dir); + ray_dir /= ray_len; + + /* Line to sphere intersect */ + const float sphere_radius_sqr = sphere_radius * sphere_radius; + float b = dot(ray_ori, ray_dir); + float c = dot(ray_ori, ray_ori) - sphere_radius_sqr; + float h = b * b - c; + float t = -sqrt(max(0.0, h)) - b; + + /* Compute dot product for lighting */ + vec3 p = ray_dir * t + ray_ori; /* Point on sphere */ + vec3 n = normalize(p); /* Normal is just the point in sphere space, normalized. */ + vec3 l = normalize(sphereMatrix[2].xyz); /* Just the view Z axis in the sphere space. */ + + /* Smooth lighting factor. */ + const float s = 0.2; /* [0.0-0.5] range */ + float fac = clamp((dot(n, l) * (1.0 - s)) + s, 0.0, 1.0); + fragColor.rgb = mix(finalStateColor, finalBoneColor, fac); + + /* 2x2 dither pattern to smooth the lighting. */ + float dither = (0.5 + dot(vec2(ivec2(gl_FragCoord.xy) & ivec2(1)), vec2(1.0, 2.0))) * 0.25; + dither *= (1.0 / 255.0); /* Assume 8bit per color buffer. */ + + fragColor = vec4(fragColor.rgb + dither, alpha); + + t /= ray_len; + gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z); } diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl index 0a2a2959120..38a721616a0 100644 --- a/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl @@ -20,69 +20,69 @@ const float rad = 0.05; void main() { - mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; - sphereMatrix = inverse(model_view_matrix); + mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; + sphereMatrix = inverse(model_view_matrix); - bool is_persp = (ProjectionMatrix[3][3] == 0.0); + bool is_persp = (ProjectionMatrix[3][3] == 0.0); - /* This is the local space camera ray (not normalize). - * In perspective mode it's also the viewspace position - * of the sphere center. */ - vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0); - cam_ray = mat3(sphereMatrix) * cam_ray; + /* This is the local space camera ray (not normalize). + * In perspective mode it's also the viewspace position + * of the sphere center. */ + vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0); + cam_ray = mat3(sphereMatrix) * cam_ray; - /* Sphere center distance from the camera (persp) in local space. */ - float cam_dist = length(cam_ray); + /* Sphere center distance from the camera (persp) in local space. */ + float cam_dist = length(cam_ray); - /* Compute view aligned orthonormal space. */ - vec3 z_axis = cam_ray / cam_dist; - vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis)); - vec3 y_axis = cross(z_axis, x_axis); + /* Compute view aligned orthonormal space. */ + vec3 z_axis = cam_ray / cam_dist; + vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis)); + vec3 y_axis = cross(z_axis, x_axis); - float z_ofs = -rad - 1e-8; /* offset to the front of the sphere */ - if (is_persp) { - /* For perspective, the projected sphere radius - * can be bigger than the center disc. Compute the - * max angular size and compensate by sliding the disc - * towards the camera and scale it accordingly. */ - const float half_pi = 3.1415926 * 0.5; - /* Let be (in local space): - * V the view vector origin. - * O the sphere origin. - * T the point on the target circle. - * We compute the angle between (OV) and (OT). */ - float a = half_pi - asin(rad / cam_dist); - float cos_b = cos(a); - float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); + float z_ofs = -rad - 1e-8; /* offset to the front of the sphere */ + if (is_persp) { + /* For perspective, the projected sphere radius + * can be bigger than the center disc. Compute the + * max angular size and compensate by sliding the disc + * towards the camera and scale it accordingly. */ + const float half_pi = 3.1415926 * 0.5; + /* Let be (in local space): + * V the view vector origin. + * O the sphere origin. + * T the point on the target circle. + * We compute the angle between (OV) and (OT). */ + float a = half_pi - asin(rad / cam_dist); + float cos_b = cos(a); + float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); #if 1 - /* Instead of choosing the biggest circle in screenspace, - * we choose the nearest with the same angular size. This - * permit us to leverage GL_ARB_conservative_depth in the - * fragment shader. */ - float minor = cam_dist - rad; - float major = cam_dist - cos_b * rad; - float fac = minor / major; - sin_b *= fac; + /* Instead of choosing the biggest circle in screenspace, + * we choose the nearest with the same angular size. This + * permit us to leverage GL_ARB_conservative_depth in the + * fragment shader. */ + float minor = cam_dist - rad; + float major = cam_dist - cos_b * rad; + float fac = minor / major; + sin_b *= fac; #else - z_ofs = -rad * cos_b; + z_ofs = -rad * cos_b; #endif - x_axis *= sin_b; - y_axis *= sin_b; - } + x_axis *= sin_b; + y_axis *= sin_b; + } - /* Camera oriented position (but still in local space) */ - vec3 cam_pos = x_axis * pos.x + y_axis * pos.y + z_axis * z_ofs; + /* Camera oriented position (but still in local space) */ + vec3 cam_pos = x_axis * pos.x + y_axis * pos.y + z_axis * z_ofs; - vec4 pos_4d = vec4(cam_pos, 1.0); - vec4 V = model_view_matrix * pos_4d; - gl_Position = ProjectionMatrix * V; - viewPosition = V.xyz; + vec4 pos_4d = vec4(cam_pos, 1.0); + vec4 V = model_view_matrix * pos_4d; + gl_Position = ProjectionMatrix * V; + viewPosition = V.xyz; - finalStateColor = stateColor; - finalBoneColor = boneColor; + finalStateColor = stateColor; + finalBoneColor = boneColor; #ifdef USE_WORLD_CLIP_PLANES - vec4 worldPosition = InstanceModelMatrix * pos_4d; - world_clip_planes_calc_clip_distance(worldPosition.xyz); + vec4 worldPosition = InstanceModelMatrix * pos_4d; + world_clip_planes_calc_clip_distance(worldPosition.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_stick_frag.glsl b/source/blender/draw/modes/shaders/armature_stick_frag.glsl index d03cf4c0366..ba89619e051 100644 --- a/source/blender/draw/modes/shaders/armature_stick_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_stick_frag.glsl @@ -7,7 +7,7 @@ out vec4 fragColor; void main() { - float fac = smoothstep(1.0, 0.2, colorFac); - fragColor.rgb = mix(finalInnerColor.rgb, finalWireColor.rgb, fac); - fragColor.a = 1.0; + float fac = smoothstep(1.0, 0.2, colorFac); + fragColor.rgb = mix(finalInnerColor.rgb, finalWireColor.rgb, fac); + fragColor.a = 1.0; } diff --git a/source/blender/draw/modes/shaders/armature_stick_vert.glsl b/source/blender/draw/modes/shaders/armature_stick_vert.glsl index 3f1aef47dce..9e5a3d76c0d 100644 --- a/source/blender/draw/modes/shaders/armature_stick_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_stick_vert.glsl @@ -14,9 +14,9 @@ in uint flag; #define COL_TAIL 4u /* (1 << 2) */ #define COL_BONE 8u /* (1 << 3) */ -#define POS_HEAD 16u /* (1 << 4) */ +#define POS_HEAD 16u /* (1 << 4) */ #define POS_TAIL 32u /* (1 << 5) */ /* UNUSED */ -#define POS_BONE 64u /* (1 << 6) */ +#define POS_BONE 64u /* (1 << 6) */ /* ---- Per instance Attrs ---- */ in vec3 boneStart; @@ -39,57 +39,60 @@ uniform float stickSize = 5.0; /* might be dependent on DPI setting in the futur /* project to screen space */ vec2 proj(vec4 pos) { - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } void main() { - finalInnerColor = ((flag & COL_HEAD) != 0u) ? headColor : tailColor; - finalInnerColor = ((flag & COL_BONE) != 0u) ? boneColor : finalInnerColor; - finalWireColor = (do_wire) ? wireColor : finalInnerColor; - /* Make the color */ - colorFac = ((flag & COL_WIRE) == 0u) ? ((flag & COL_BONE) != 0u) ? 1.0 : 2.0 : 0.0; - - vec4 boneStart_4d = vec4(boneStart, 1.0); - vec4 boneEnd_4d = vec4(boneEnd, 1.0); - vec4 v0 = ViewMatrix * boneStart_4d; - vec4 v1 = ViewMatrix * boneEnd_4d; - - /* Clip the bone to the camera origin plane (not the clip plane) - * to avoid glitches if one end is behind the camera origin (in persp). */ - float clip_dist = (ProjectionMatrix[3][3] == 0.0) ? -1e-7 : 1e20; /* hardcoded, -1e-8 is giving gliches. */ - vec3 bvec = v1.xyz - v0.xyz; - vec3 clip_pt = v0.xyz + bvec * ((v0.z - clip_dist) / -bvec.z); - if (v0.z > clip_dist) { - v0.xyz = clip_pt; - } - else if (v1.z > clip_dist) { - v1.xyz = clip_pt; - } - - vec4 p0 = ProjectionMatrix * v0; - vec4 p1 = ProjectionMatrix * v1; - - float h = (is_head) ? p0.w : p1.w; - - vec2 x_screen_vec = normalize(proj(p1) - proj(p0) + 1e-8); - vec2 y_screen_vec = vec2(x_screen_vec.y, -x_screen_vec.x); - - /* 2D screen aligned pos at the point */ - vec2 vpos = pos.x * x_screen_vec + pos.y * y_screen_vec; - vpos *= (ProjectionMatrix[3][3] == 0.0) ? h : 1.0; - vpos *= (do_wire) ? 1.0 : 0.5; - - if (finalInnerColor.a > 0.0) { - gl_Position = (is_head) ? p0 : p1; - gl_Position.xy += stickSize * (vpos / viewportSize); - gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */ + finalInnerColor = ((flag & COL_HEAD) != 0u) ? headColor : tailColor; + finalInnerColor = ((flag & COL_BONE) != 0u) ? boneColor : finalInnerColor; + finalWireColor = (do_wire) ? wireColor : finalInnerColor; + /* Make the color */ + colorFac = ((flag & COL_WIRE) == 0u) ? ((flag & COL_BONE) != 0u) ? 1.0 : 2.0 : 0.0; + + vec4 boneStart_4d = vec4(boneStart, 1.0); + vec4 boneEnd_4d = vec4(boneEnd, 1.0); + vec4 v0 = ViewMatrix * boneStart_4d; + vec4 v1 = ViewMatrix * boneEnd_4d; + + /* Clip the bone to the camera origin plane (not the clip plane) + * to avoid glitches if one end is behind the camera origin (in persp). */ + float clip_dist = (ProjectionMatrix[3][3] == 0.0) ? + -1e-7 : + 1e20; /* hardcoded, -1e-8 is giving gliches. */ + vec3 bvec = v1.xyz - v0.xyz; + vec3 clip_pt = v0.xyz + bvec * ((v0.z - clip_dist) / -bvec.z); + if (v0.z > clip_dist) { + v0.xyz = clip_pt; + } + else if (v1.z > clip_dist) { + v1.xyz = clip_pt; + } + + vec4 p0 = ProjectionMatrix * v0; + vec4 p1 = ProjectionMatrix * v1; + + float h = (is_head) ? p0.w : p1.w; + + vec2 x_screen_vec = normalize(proj(p1) - proj(p0) + 1e-8); + vec2 y_screen_vec = vec2(x_screen_vec.y, -x_screen_vec.x); + + /* 2D screen aligned pos at the point */ + vec2 vpos = pos.x * x_screen_vec + pos.y * y_screen_vec; + vpos *= (ProjectionMatrix[3][3] == 0.0) ? h : 1.0; + vpos *= (do_wire) ? 1.0 : 0.5; + + if (finalInnerColor.a > 0.0) { + gl_Position = (is_head) ? p0 : p1; + gl_Position.xy += stickSize * (vpos / viewportSize); + gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */ #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * (is_head ? boneStart_4d : boneEnd_4d)).xyz); + world_clip_planes_calc_clip_distance( + (ModelMatrix * (is_head ? boneStart_4d : boneEnd_4d)).xyz); #endif - } - else { - gl_Position = vec4(0.0); - } + } + else { + gl_Position = vec4(0.0); + } } diff --git a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl index e5c5ccc97bf..a1e6bb0f43d 100644 --- a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl +++ b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl @@ -5,6 +5,6 @@ out vec4 uvcoordsvar; void main() { - uvcoordsvar = vec4(uvs, 0.0, 0.0); - gl_Position = vec4(pos, 1.0, 1.0); + uvcoordsvar = vec4(uvs, 0.0, 0.0); + gl_Position = vec4(pos, 1.0, 1.0); } diff --git a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl index 236ac5c67f0..dcb7c0ba7f2 100644 --- a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl +++ b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl @@ -54,27 +54,27 @@ NOTE the other tuning knobs are now in the shader function inputs! ============================================================================*/ #ifndef FXAA_QUALITY__PRESET - // - // Choose the quality preset. - // This needs to be compiled into the shader as it effects code. - // Best option to include multiple presets is to - // in each shader define the preset, then include this file. - // - // OPTIONS - // ----------------------------------------------------------------------- - // 10 to 15 - default medium dither (10=fastest, 15=highest quality) - // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) - // 39 - no dither, very expensive - // - // NOTES - // ----------------------------------------------------------------------- - // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) - // 13 = about same speed as FXAA 3.9 and better than 12 - // 23 = closest to FXAA 3.9 visually and performance wise - // _ = the lowest digit is directly related to performance - // _ = the highest digit is directly related to style - // - #define FXAA_QUALITY__PRESET 12 +// +// Choose the quality preset. +// This needs to be compiled into the shader as it effects code. +// Best option to include multiple presets is to +// in each shader define the preset, then include this file. +// +// OPTIONS +// ----------------------------------------------------------------------- +// 10 to 15 - default medium dither (10=fastest, 15=highest quality) +// 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) +// 39 - no dither, very expensive +// +// NOTES +// ----------------------------------------------------------------------- +// 12 = slightly faster then FXAA 3.9 and higher edge quality (default) +// 13 = about same speed as FXAA 3.9 and better than 12 +// 23 = closest to FXAA 3.9 visually and performance wise +// _ = the lowest digit is directly related to performance +// _ = the highest digit is directly related to style +// +# define FXAA_QUALITY__PRESET 12 #endif /*============================================================================ @@ -87,218 +87,219 @@ NOTE the other tuning knobs are now in the shader function inputs! FXAA QUALITY - MEDIUM DITHER PRESETS ============================================================================*/ #if (FXAA_QUALITY__PRESET == 10) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 3.0 - #define FXAA_QUALITY__P2 12.0 +# define FXAA_QUALITY__PS 3 +# define FXAA_QUALITY__P0 1.5 +# define FXAA_QUALITY__P1 3.0 +# define FXAA_QUALITY__P2 12.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 11) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 3.0 - #define FXAA_QUALITY__P3 12.0 +# define FXAA_QUALITY__PS 4 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 3.0 +# define FXAA_QUALITY__P3 12.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 12) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 4.0 - #define FXAA_QUALITY__P4 12.0 +# define FXAA_QUALITY__PS 5 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 4.0 +# define FXAA_QUALITY__P4 12.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 13) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 4.0 - #define FXAA_QUALITY__P5 12.0 +# define FXAA_QUALITY__PS 6 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 4.0 +# define FXAA_QUALITY__P5 12.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 14) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 4.0 - #define FXAA_QUALITY__P6 12.0 +# define FXAA_QUALITY__PS 7 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 4.0 +# define FXAA_QUALITY__P6 12.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 15) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 12.0 +# define FXAA_QUALITY__PS 8 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 2.0 +# define FXAA_QUALITY__P6 4.0 +# define FXAA_QUALITY__P7 12.0 #endif /*============================================================================ FXAA QUALITY - LOW DITHER PRESETS ============================================================================*/ #if (FXAA_QUALITY__PRESET == 20) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 2.0 - #define FXAA_QUALITY__P2 8.0 +# define FXAA_QUALITY__PS 3 +# define FXAA_QUALITY__P0 1.5 +# define FXAA_QUALITY__P1 2.0 +# define FXAA_QUALITY__P2 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 21) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 8.0 +# define FXAA_QUALITY__PS 4 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 22) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 8.0 +# define FXAA_QUALITY__PS 5 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 23) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 8.0 +# define FXAA_QUALITY__PS 6 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 24) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 3.0 - #define FXAA_QUALITY__P6 8.0 +# define FXAA_QUALITY__PS 7 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 3.0 +# define FXAA_QUALITY__P6 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 25) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 8.0 +# define FXAA_QUALITY__PS 8 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 2.0 +# define FXAA_QUALITY__P6 4.0 +# define FXAA_QUALITY__P7 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 26) - #define FXAA_QUALITY__PS 9 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 4.0 - #define FXAA_QUALITY__P8 8.0 +# define FXAA_QUALITY__PS 9 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 2.0 +# define FXAA_QUALITY__P6 2.0 +# define FXAA_QUALITY__P7 4.0 +# define FXAA_QUALITY__P8 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 27) - #define FXAA_QUALITY__PS 10 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 4.0 - #define FXAA_QUALITY__P9 8.0 +# define FXAA_QUALITY__PS 10 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 2.0 +# define FXAA_QUALITY__P6 2.0 +# define FXAA_QUALITY__P7 2.0 +# define FXAA_QUALITY__P8 4.0 +# define FXAA_QUALITY__P9 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 28) - #define FXAA_QUALITY__PS 11 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 4.0 - #define FXAA_QUALITY__P10 8.0 +# define FXAA_QUALITY__PS 11 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 2.0 +# define FXAA_QUALITY__P6 2.0 +# define FXAA_QUALITY__P7 2.0 +# define FXAA_QUALITY__P8 2.0 +# define FXAA_QUALITY__P9 4.0 +# define FXAA_QUALITY__P10 8.0 #endif /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY__PRESET == 29) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 +# define FXAA_QUALITY__PS 12 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.5 +# define FXAA_QUALITY__P2 2.0 +# define FXAA_QUALITY__P3 2.0 +# define FXAA_QUALITY__P4 2.0 +# define FXAA_QUALITY__P5 2.0 +# define FXAA_QUALITY__P6 2.0 +# define FXAA_QUALITY__P7 2.0 +# define FXAA_QUALITY__P8 2.0 +# define FXAA_QUALITY__P9 2.0 +# define FXAA_QUALITY__P10 4.0 +# define FXAA_QUALITY__P11 8.0 #endif /*============================================================================ FXAA QUALITY - EXTREME QUALITY ============================================================================*/ #if (FXAA_QUALITY__PRESET == 39) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.0 - #define FXAA_QUALITY__P2 1.0 - #define FXAA_QUALITY__P3 1.0 - #define FXAA_QUALITY__P4 1.0 - #define FXAA_QUALITY__P5 1.5 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 +# define FXAA_QUALITY__PS 12 +# define FXAA_QUALITY__P0 1.0 +# define FXAA_QUALITY__P1 1.0 +# define FXAA_QUALITY__P2 1.0 +# define FXAA_QUALITY__P3 1.0 +# define FXAA_QUALITY__P4 1.0 +# define FXAA_QUALITY__P5 1.5 +# define FXAA_QUALITY__P6 2.0 +# define FXAA_QUALITY__P7 2.0 +# define FXAA_QUALITY__P8 2.0 +# define FXAA_QUALITY__P9 2.0 +# define FXAA_QUALITY__P10 4.0 +# define FXAA_QUALITY__P11 8.0 #endif #define FxaaSat(x) clamp(x, 0.0, 1.0) #ifdef FXAA_ALPHA -#define FxaaTexTop(t, p) textureLod(t, p, 0.0).aaaa -#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o).aaaa -#define FxaaLuma(rgba) rgba.a +# define FxaaTexTop(t, p) textureLod(t, p, 0.0).aaaa +# define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o).aaaa +# define FxaaLuma(rgba) rgba.a #else -#define FxaaTexTop(t, p) textureLod(t, p, 0.0) -#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) +# define FxaaTexTop(t, p) textureLod(t, p, 0.0) +# define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) /* (#B1#) */ -float FxaaLuma(vec4 rgba) { - // note: sqrt because the sampled colors are in a linear colorspace! - // this approximates a perceptual conversion, which is good enough for the - // algorithm - return sqrt(dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722))); +float FxaaLuma(vec4 rgba) +{ + // note: sqrt because the sampled colors are in a linear colorspace! + // this approximates a perceptual conversion, which is good enough for the + // algorithm + return sqrt(dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722))); } #endif @@ -355,323 +356,426 @@ vec4 FxaaPixelShader( // 0.0833 - upper limit (default, the start of visible unfiltered edges) // 0.0625 - high quality (faster) // 0.0312 - visible limit (slower) - float fxaaQualityEdgeThresholdMin -) { -/*--------------------------------------------------------------------------*/ - vec2 posM; - posM.x = pos.x; - posM.y = pos.y; - vec4 rgbyM = FxaaTexTop(tex, posM); - float lumaM = FxaaLuma(rgbyM); // (#B4#) - float lumaS = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0, 1), fxaaQualityRcpFrame.xy)); - float lumaE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 0), fxaaQualityRcpFrame.xy)); - float lumaN = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0,-1), fxaaQualityRcpFrame.xy)); - float lumaW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 0), fxaaQualityRcpFrame.xy)); -/*--------------------------------------------------------------------------*/ - float maxSM = max(lumaS, lumaM); - float minSM = min(lumaS, lumaM); - float maxESM = max(lumaE, maxSM); - float minESM = min(lumaE, minSM); - float maxWN = max(lumaN, lumaW); - float minWN = min(lumaN, lumaW); - float rangeMax = max(maxWN, maxESM); - float rangeMin = min(minWN, minESM); - float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; - float range = rangeMax - rangeMin; - float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); - bool earlyExit = range < rangeMaxClamped; -/*--------------------------------------------------------------------------*/ - if(earlyExit) { - return rgbyM; - } -/*--------------------------------------------------------------------------*/ - float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1,-1), fxaaQualityRcpFrame.xy)); - float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 1), fxaaQualityRcpFrame.xy)); - float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1,-1), fxaaQualityRcpFrame.xy)); - float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 1), fxaaQualityRcpFrame.xy)); -/*--------------------------------------------------------------------------*/ - float lumaNS = lumaN + lumaS; - float lumaWE = lumaW + lumaE; - float subpixRcpRange = 1.0/range; - float subpixNSWE = lumaNS + lumaWE; - float edgeHorz1 = (-2.0 * lumaM) + lumaNS; - float edgeVert1 = (-2.0 * lumaM) + lumaWE; -/*--------------------------------------------------------------------------*/ - float lumaNESE = lumaNE + lumaSE; - float lumaNWNE = lumaNW + lumaNE; - float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; - float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; -/*--------------------------------------------------------------------------*/ - float lumaNWSW = lumaNW + lumaSW; - float lumaSWSE = lumaSW + lumaSE; - float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); - float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); - float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; - float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; - float edgeHorz = abs(edgeHorz3) + edgeHorz4; - float edgeVert = abs(edgeVert3) + edgeVert4; -/*--------------------------------------------------------------------------*/ - float subpixNWSWNESE = lumaNWSW + lumaNESE; - float lengthSign = fxaaQualityRcpFrame.x; - bool horzSpan = edgeHorz >= edgeVert; - float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; -/*--------------------------------------------------------------------------*/ - if(!horzSpan) lumaN = lumaW; - if(!horzSpan) lumaS = lumaE; - if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; - float subpixB = (subpixA * (1.0/12.0)) - lumaM; -/*--------------------------------------------------------------------------*/ - float gradientN = lumaN - lumaM; - float gradientS = lumaS - lumaM; - float lumaNN = lumaN + lumaM; - float lumaSS = lumaS + lumaM; - bool pairN = abs(gradientN) >= abs(gradientS); - float gradient = max(abs(gradientN), abs(gradientS)); - if(pairN) lengthSign = -lengthSign; - float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); -/*--------------------------------------------------------------------------*/ - vec2 posB; - posB.x = posM.x; - posB.y = posM.y; - vec2 offNP; - offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; - offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; - if(!horzSpan) posB.x += lengthSign * 0.5; - if( horzSpan) posB.y += lengthSign * 0.5; -/*--------------------------------------------------------------------------*/ - vec2 posN; - posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; - posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; - vec2 posP; - posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; - posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; - float subpixD = ((-2.0)*subpixC) + 3.0; - float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); - float subpixE = subpixC * subpixC; - float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); -/*--------------------------------------------------------------------------*/ - if(!pairN) lumaNN = lumaSS; - float gradientScaled = gradient * 1.0/4.0; - float lumaMM = lumaM - lumaNN * 0.5; - float subpixF = subpixD * subpixE; - bool lumaMLTZero = lumaMM < 0.0; -/*--------------------------------------------------------------------------*/ - lumaEndN -= lumaNN * 0.5; - lumaEndP -= lumaNN * 0.5; - bool doneN = abs(lumaEndN) >= gradientScaled; - bool doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; - bool doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; -/*--------------------------------------------------------------------------*/ - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 3) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 4) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 5) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 6) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 7) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 8) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + float fxaaQualityEdgeThresholdMin) +{ + /*--------------------------------------------------------------------------*/ + vec2 posM; + posM.x = pos.x; + posM.y = pos.y; + vec4 rgbyM = FxaaTexTop(tex, posM); + float lumaM = FxaaLuma(rgbyM); // (#B4#) + float lumaS = FxaaLuma(FxaaTexOff(tex, posM, ivec2(0, 1), fxaaQualityRcpFrame.xy)); + float lumaE = FxaaLuma(FxaaTexOff(tex, posM, ivec2(1, 0), fxaaQualityRcpFrame.xy)); + float lumaN = FxaaLuma(FxaaTexOff(tex, posM, ivec2(0, -1), fxaaQualityRcpFrame.xy)); + float lumaW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 0), fxaaQualityRcpFrame.xy)); + /*--------------------------------------------------------------------------*/ + float maxSM = max(lumaS, lumaM); + float minSM = min(lumaS, lumaM); + float maxESM = max(lumaE, maxSM); + float minESM = min(lumaE, minSM); + float maxWN = max(lumaN, lumaW); + float minWN = min(lumaN, lumaW); + float rangeMax = max(maxWN, maxESM); + float rangeMin = min(minWN, minESM); + float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + float range = rangeMax - rangeMin; + float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + bool earlyExit = range < rangeMaxClamped; + /*--------------------------------------------------------------------------*/ + if (earlyExit) { + return rgbyM; + } + /*--------------------------------------------------------------------------*/ + float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, -1), fxaaQualityRcpFrame.xy)); + float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, ivec2(1, 1), fxaaQualityRcpFrame.xy)); + float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, ivec2(1, -1), fxaaQualityRcpFrame.xy)); + float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 1), fxaaQualityRcpFrame.xy)); + /*--------------------------------------------------------------------------*/ + float lumaNS = lumaN + lumaS; + float lumaWE = lumaW + lumaE; + float subpixRcpRange = 1.0 / range; + float subpixNSWE = lumaNS + lumaWE; + float edgeHorz1 = (-2.0 * lumaM) + lumaNS; + float edgeVert1 = (-2.0 * lumaM) + lumaWE; + /*--------------------------------------------------------------------------*/ + float lumaNESE = lumaNE + lumaSE; + float lumaNWNE = lumaNW + lumaNE; + float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; + /*--------------------------------------------------------------------------*/ + float lumaNWSW = lumaNW + lumaSW; + float lumaSWSE = lumaSW + lumaSE; + float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + float edgeHorz = abs(edgeHorz3) + edgeHorz4; + float edgeVert = abs(edgeVert3) + edgeVert4; + /*--------------------------------------------------------------------------*/ + float subpixNWSWNESE = lumaNWSW + lumaNESE; + float lengthSign = fxaaQualityRcpFrame.x; + bool horzSpan = edgeHorz >= edgeVert; + float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; + /*--------------------------------------------------------------------------*/ + if (!horzSpan) + lumaN = lumaW; + if (!horzSpan) + lumaS = lumaE; + if (horzSpan) + lengthSign = fxaaQualityRcpFrame.y; + float subpixB = (subpixA * (1.0 / 12.0)) - lumaM; + /*--------------------------------------------------------------------------*/ + float gradientN = lumaN - lumaM; + float gradientS = lumaS - lumaM; + float lumaNN = lumaN + lumaM; + float lumaSS = lumaS + lumaM; + bool pairN = abs(gradientN) >= abs(gradientS); + float gradient = max(abs(gradientN), abs(gradientS)); + if (pairN) + lengthSign = -lengthSign; + float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); + /*--------------------------------------------------------------------------*/ + vec2 posB; + posB.x = posM.x; + posB.y = posM.y; + vec2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = (horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if (!horzSpan) + posB.x += lengthSign * 0.5; + if (horzSpan) + posB.y += lengthSign * 0.5; + /*--------------------------------------------------------------------------*/ + vec2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + vec2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + float subpixD = ((-2.0) * subpixC) + 3.0; + float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + float subpixE = subpixC * subpixC; + float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); + /*--------------------------------------------------------------------------*/ + if (!pairN) + lumaNN = lumaSS; + float gradientScaled = gradient * 1.0 / 4.0; + float lumaMM = lumaM - lumaNN * 0.5; + float subpixF = subpixD * subpixE; + bool lumaMLTZero = lumaMM < 0.0; + /*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + bool doneN = abs(lumaEndN) >= gradientScaled; + bool doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P1; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P1; + bool doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P1; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P1; + /*--------------------------------------------------------------------------*/ + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P2; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P2; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P2; + /*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 3) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P3; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P3; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P3; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 4) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P4; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P4; doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 9) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P4; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P4; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 5) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P5; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P5; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P5; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 6) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P6; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P6; doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 10) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P6; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P6; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 7) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P7; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P7; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P7; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 8) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P8; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P8; doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 11) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P8; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P8; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 9) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P9; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P9; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P9; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 10) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P10; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P10; doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 12) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P10; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P10; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 11) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P11; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P11; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P11; + /*--------------------------------------------------------------------------*/ +# if (FXAA_QUALITY__PS > 12) + if (doneNP) { + if (!doneN) + lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if (!doneP) + lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P12; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P12; doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; -/*--------------------------------------------------------------------------*/ + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P12; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P12; + /*--------------------------------------------------------------------------*/ + } +# endif + /*--------------------------------------------------------------------------*/ } - #endif -/*--------------------------------------------------------------------------*/ +# endif + /*--------------------------------------------------------------------------*/ + } +# endif + /*--------------------------------------------------------------------------*/ } - #endif -/*--------------------------------------------------------------------------*/ +# endif + /*--------------------------------------------------------------------------*/ + } +# endif + /*--------------------------------------------------------------------------*/ } - #endif -/*--------------------------------------------------------------------------*/ +# endif + /*--------------------------------------------------------------------------*/ + } +# endif + /*--------------------------------------------------------------------------*/ } - #endif -/*--------------------------------------------------------------------------*/ +# endif + /*--------------------------------------------------------------------------*/ + } +# endif + /*--------------------------------------------------------------------------*/ } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } -/*--------------------------------------------------------------------------*/ - float dstN = posM.x - posN.x; - float dstP = posP.x - posM.x; - if(!horzSpan) dstN = posM.y - posN.y; - if(!horzSpan) dstP = posP.y - posM.y; -/*--------------------------------------------------------------------------*/ - bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; - float spanLength = (dstP + dstN); - bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; - float spanLengthRcp = 1.0/spanLength; -/*--------------------------------------------------------------------------*/ - bool directionN = dstN < dstP; - float dst = min(dstN, dstP); - bool goodSpan = directionN ? goodSpanN : goodSpanP; - float subpixG = subpixF * subpixF; - float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; - float subpixH = subpixG * fxaaQualitySubpix; -/*--------------------------------------------------------------------------*/ - float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; - float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); - if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; - if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; - return vec4(FxaaTexTop(tex, posM).xyz, lumaM); +#endif + /*--------------------------------------------------------------------------*/ + } + /*--------------------------------------------------------------------------*/ + float dstN = posM.x - posN.x; + float dstP = posP.x - posM.x; + if (!horzSpan) + dstN = posM.y - posN.y; + if (!horzSpan) + dstP = posP.y - posM.y; + /*--------------------------------------------------------------------------*/ + bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + float spanLength = (dstP + dstN); + bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + float spanLengthRcp = 1.0 / spanLength; + /*--------------------------------------------------------------------------*/ + bool directionN = dstN < dstP; + float dst = min(dstN, dstP); + bool goodSpan = directionN ? goodSpanN : goodSpanP; + float subpixG = subpixF * subpixF; + float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + float subpixH = subpixG * fxaaQualitySubpix; + /*--------------------------------------------------------------------------*/ + float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if (!horzSpan) + posM.x += pixelOffsetSubpix * lengthSign; + if (horzSpan) + posM.y += pixelOffsetSubpix * lengthSign; + return vec4(FxaaTexTop(tex, posM).xyz, lumaM); } /*==========================================================================*/ diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl index 88540b13941..3cc6ac9a5a4 100644 --- a/source/blender/draw/modes/shaders/common_globals_lib.glsl +++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl @@ -1,101 +1,102 @@ /* keep in sync with GlobalsUboStorage */ -layout(std140) uniform globalsBlock { - vec4 colorWire; - vec4 colorWireEdit; - vec4 colorActive; - vec4 colorSelect; - vec4 colorDupliSelect; - vec4 colorDupli; - vec4 colorLibrarySelect; - vec4 colorLibrary; - vec4 colorTransform; - vec4 colorLight; - vec4 colorSpeaker; - vec4 colorCamera; - vec4 colorEmpty; - vec4 colorVertex; - vec4 colorVertexSelect; - vec4 colorVertexUnreferenced; - vec4 colorVertexMissingData; - vec4 colorEditMeshActive; - vec4 colorEdgeSelect; - vec4 colorEdgeSeam; - vec4 colorEdgeSharp; - vec4 colorEdgeCrease; - vec4 colorEdgeBWeight; - vec4 colorEdgeFaceSelect; - vec4 colorEdgeFreestyle; - vec4 colorFace; - vec4 colorFaceSelect; - vec4 colorFaceFreestyle; - vec4 colorNormal; - vec4 colorVNormal; - vec4 colorLNormal; - vec4 colorFaceDot; - vec4 colorDeselect; - vec4 colorOutline; - vec4 colorLightNoAlpha; +layout(std140) uniform globalsBlock +{ + vec4 colorWire; + vec4 colorWireEdit; + vec4 colorActive; + vec4 colorSelect; + vec4 colorDupliSelect; + vec4 colorDupli; + vec4 colorLibrarySelect; + vec4 colorLibrary; + vec4 colorTransform; + vec4 colorLight; + vec4 colorSpeaker; + vec4 colorCamera; + vec4 colorEmpty; + vec4 colorVertex; + vec4 colorVertexSelect; + vec4 colorVertexUnreferenced; + vec4 colorVertexMissingData; + vec4 colorEditMeshActive; + vec4 colorEdgeSelect; + vec4 colorEdgeSeam; + vec4 colorEdgeSharp; + vec4 colorEdgeCrease; + vec4 colorEdgeBWeight; + vec4 colorEdgeFaceSelect; + vec4 colorEdgeFreestyle; + vec4 colorFace; + vec4 colorFaceSelect; + vec4 colorFaceFreestyle; + vec4 colorNormal; + vec4 colorVNormal; + vec4 colorLNormal; + vec4 colorFaceDot; + vec4 colorDeselect; + vec4 colorOutline; + vec4 colorLightNoAlpha; - vec4 colorBackground; - vec4 colorEditMeshMiddle; + vec4 colorBackground; + vec4 colorEditMeshMiddle; - vec4 colorHandleFree; - vec4 colorHandleAuto; - vec4 colorHandleVect; - vec4 colorHandleAlign; - vec4 colorHandleAutoclamp; - vec4 colorHandleSelFree; - vec4 colorHandleSelAuto; - vec4 colorHandleSelVect; - vec4 colorHandleSelAlign; - vec4 colorHandleSelAutoclamp; - vec4 colorNurbUline; - vec4 colorNurbVline; - vec4 colorNurbSelUline; - vec4 colorNurbSelVline; - vec4 colorActiveSpline; + vec4 colorHandleFree; + vec4 colorHandleAuto; + vec4 colorHandleVect; + vec4 colorHandleAlign; + vec4 colorHandleAutoclamp; + vec4 colorHandleSelFree; + vec4 colorHandleSelAuto; + vec4 colorHandleSelVect; + vec4 colorHandleSelAlign; + vec4 colorHandleSelAutoclamp; + vec4 colorNurbUline; + vec4 colorNurbVline; + vec4 colorNurbSelUline; + vec4 colorNurbSelVline; + vec4 colorActiveSpline; - vec4 colorBonePose; + vec4 colorBonePose; - vec4 colorCurrentFrame; + vec4 colorCurrentFrame; - vec4 colorGrid; - vec4 colorGridEmphasise; - vec4 colorGridAxisX; - vec4 colorGridAxisY; - vec4 colorGridAxisZ; + vec4 colorGrid; + vec4 colorGridEmphasise; + vec4 colorGridAxisX; + vec4 colorGridAxisY; + vec4 colorGridAxisZ; - float sizeLightCenter; - float sizeLightCircle; - float sizeLightCircleShadow; - float sizeVertex; - float sizeEdge; - float sizeEdgeFix; - float sizeFaceDot; + float sizeLightCenter; + float sizeLightCircle; + float sizeLightCircleShadow; + float sizeVertex; + float sizeEdge; + float sizeEdgeFix; + float sizeFaceDot; - float gridDistance; - float gridResolution; - float gridSubdivisions; - float gridScale; + float gridDistance; + float gridResolution; + float gridSubdivisions; + float gridScale; - float pad_globalsBlock; + float pad_globalsBlock; }; /* data[0] (1nd byte flags) */ -#define FACE_ACTIVE (1 << 0) -#define FACE_SELECTED (1 << 1) -#define FACE_FREESTYLE (1 << 2) -#define VERT_UV_SELECT (1 << 3) -#define VERT_UV_PINNED (1 << 4) -#define EDGE_UV_SELECT (1 << 5) -#define FACE_UV_ACTIVE (1 << 6) -#define FACE_UV_SELECT (1 << 7) +#define FACE_ACTIVE (1 << 0) +#define FACE_SELECTED (1 << 1) +#define FACE_FREESTYLE (1 << 2) +#define VERT_UV_SELECT (1 << 3) +#define VERT_UV_PINNED (1 << 4) +#define EDGE_UV_SELECT (1 << 5) +#define FACE_UV_ACTIVE (1 << 6) +#define FACE_UV_SELECT (1 << 7) /* data[1] (2st byte flags) */ -#define VERT_ACTIVE (1 << 0) -#define VERT_SELECTED (1 << 1) -#define EDGE_ACTIVE (1 << 2) -#define EDGE_SELECTED (1 << 3) -#define EDGE_SEAM (1 << 4) -#define EDGE_SHARP (1 << 5) -#define EDGE_FREESTYLE (1 << 6) +#define VERT_ACTIVE (1 << 0) +#define VERT_SELECTED (1 << 1) +#define EDGE_ACTIVE (1 << 2) +#define EDGE_SELECTED (1 << 3) +#define EDGE_SEAM (1 << 4) +#define EDGE_SHARP (1 << 5) +#define EDGE_FREESTYLE (1 << 6) diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl index 14df29f2e94..02254908232 100644 --- a/source/blender/draw/modes/shaders/common_hair_lib.glsl +++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl @@ -30,11 +30,11 @@ uniform mat4 hairDupliMatrix; /* -- Per control points -- */ uniform samplerBuffer hairPointBuffer; /* RGBA32F */ -#define point_position xyz -#define point_time w /* Position along the hair length */ +#define point_position xyz +#define point_time w /* Position along the hair length */ /* -- Per strands data -- */ -uniform usamplerBuffer hairStrandBuffer; /* R32UI */ +uniform usamplerBuffer hairStrandBuffer; /* R32UI */ uniform usamplerBuffer hairStrandSegBuffer; /* R16UI */ /* Not used, use one buffer per uv layer */ @@ -53,39 +53,40 @@ uniform usamplerBuffer hairStrandSegBuffer; /* R16UI */ #ifdef HAIR_PHASE_SUBDIV int hair_get_base_id(float local_time, int strand_segments, out float interp_time) { - float time_per_strand_seg = 1.0 / float(strand_segments); + float time_per_strand_seg = 1.0 / float(strand_segments); - float ratio = local_time / time_per_strand_seg; - interp_time = fract(ratio); + float ratio = local_time / time_per_strand_seg; + interp_time = fract(ratio); - return int(ratio); + return int(ratio); } -void hair_get_interp_attrs(out vec4 data0, out vec4 data1, out vec4 data2, out vec4 data3, out float interp_time) +void hair_get_interp_attrs( + out vec4 data0, out vec4 data1, out vec4 data2, out vec4 data3, out float interp_time) { - float local_time = float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1); + float local_time = float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1); - int hair_id = gl_VertexID / hairStrandsRes; - int strand_offset = int(texelFetch(hairStrandBuffer, hair_id).x); - int strand_segments = int(texelFetch(hairStrandSegBuffer, hair_id).x); + int hair_id = gl_VertexID / hairStrandsRes; + int strand_offset = int(texelFetch(hairStrandBuffer, hair_id).x); + int strand_segments = int(texelFetch(hairStrandSegBuffer, hair_id).x); - int id = hair_get_base_id(local_time, strand_segments, interp_time); + int id = hair_get_base_id(local_time, strand_segments, interp_time); - int ofs_id = id + strand_offset; + int ofs_id = id + strand_offset; - data0 = texelFetch(hairPointBuffer, ofs_id - 1); - data1 = texelFetch(hairPointBuffer, ofs_id); - data2 = texelFetch(hairPointBuffer, ofs_id + 1); - data3 = texelFetch(hairPointBuffer, ofs_id + 2); + data0 = texelFetch(hairPointBuffer, ofs_id - 1); + data1 = texelFetch(hairPointBuffer, ofs_id); + data2 = texelFetch(hairPointBuffer, ofs_id + 1); + data3 = texelFetch(hairPointBuffer, ofs_id + 2); - if (id <= 0) { - /* root points. Need to reconstruct previous data. */ - data0 = data1 * 2.0 - data2; - } - if (id + 1 >= strand_segments) { - /* tip points. Need to reconstruct next data. */ - data3 = data2 * 2.0 - data1; - } + if (id <= 0) { + /* root points. Need to reconstruct previous data. */ + data0 = data1 * 2.0 - data2; + } + if (id + 1 >= strand_segments) { + /* tip points. Need to reconstruct next data. */ + data3 = data2 * 2.0 - data1; + } } #endif @@ -97,102 +98,109 @@ void hair_get_interp_attrs(out vec4 data0, out vec4 data1, out vec4 data2, out v #ifndef HAIR_PHASE_SUBDIV int hair_get_strand_id(void) { - return gl_VertexID / (hairStrandsRes * hairThicknessRes); + return gl_VertexID / (hairStrandsRes * hairThicknessRes); } int hair_get_base_id(void) { - return gl_VertexID / hairThicknessRes; + return gl_VertexID / hairThicknessRes; } /* Copied from cycles. */ float hair_shaperadius(float shape, float root, float tip, float time) { - float radius = 1.0 - time; + float radius = 1.0 - time; - if (shape < 0.0) { - radius = pow(radius, 1.0 + shape); - } - else { - radius = pow(radius, 1.0 / (1.0 - shape)); - } + if (shape < 0.0) { + radius = pow(radius, 1.0 + shape); + } + else { + radius = pow(radius, 1.0 / (1.0 - shape)); + } - if (hairCloseTip && (time > 0.99)) { - return 0.0; - } + if (hairCloseTip && (time > 0.99)) { + return 0.0; + } - return (radius * (root - tip)) + tip; + return (radius * (root - tip)) + tip; } -#ifdef OS_MAC +# ifdef OS_MAC in float dummy; -#endif - -void hair_get_pos_tan_binor_time( - bool is_persp, mat4 invmodel_mat, vec3 camera_pos, vec3 camera_z, - out vec3 wpos, out vec3 wtan, out vec3 wbinor, out float time, out float thickness, out float thick_time) +# endif + +void hair_get_pos_tan_binor_time(bool is_persp, + mat4 invmodel_mat, + vec3 camera_pos, + vec3 camera_z, + out vec3 wpos, + out vec3 wtan, + out vec3 wbinor, + out float time, + out float thickness, + out float thick_time) { - int id = hair_get_base_id(); - vec4 data = texelFetch(hairPointBuffer, id); - wpos = data.point_position; - time = data.point_time; - -#ifdef OS_MAC - /* Generate a dummy read to avoid the driver bug with shaders having no - * vertex reads on macOS (T60171) */ - wpos.y += dummy * 0.0; -#endif - - if (time == 0.0) { - /* Hair root */ - wtan = texelFetch(hairPointBuffer, id + 1).point_position - wpos; - } - else { - wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position; - } - - wpos = (hairDupliMatrix * vec4(wpos, 1.0)).xyz; - wtan = mat3(hairDupliMatrix) * wtan; - - vec3 camera_vec = (is_persp) ? wpos - camera_pos : -camera_z; - wbinor = normalize(cross(camera_vec, wtan)); - - thickness = hair_shaperadius(hairRadShape, hairRadRoot, hairRadTip, time); - - if (hairThicknessRes > 1) { - thick_time = float(gl_VertexID % hairThicknessRes) / float(hairThicknessRes - 1); - thick_time = thickness * (thick_time * 2.0 - 1.0); - - /* Take object scale into account. - * NOTE: This only works fine with uniform scaling. */ - float scale = 1.0 / length(mat3(invmodel_mat) * wbinor); - - wpos += wbinor * thick_time * scale; - } + int id = hair_get_base_id(); + vec4 data = texelFetch(hairPointBuffer, id); + wpos = data.point_position; + time = data.point_time; + +# ifdef OS_MAC + /* Generate a dummy read to avoid the driver bug with shaders having no + * vertex reads on macOS (T60171) */ + wpos.y += dummy * 0.0; +# endif + + if (time == 0.0) { + /* Hair root */ + wtan = texelFetch(hairPointBuffer, id + 1).point_position - wpos; + } + else { + wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position; + } + + wpos = (hairDupliMatrix * vec4(wpos, 1.0)).xyz; + wtan = mat3(hairDupliMatrix) * wtan; + + vec3 camera_vec = (is_persp) ? wpos - camera_pos : -camera_z; + wbinor = normalize(cross(camera_vec, wtan)); + + thickness = hair_shaperadius(hairRadShape, hairRadRoot, hairRadTip, time); + + if (hairThicknessRes > 1) { + thick_time = float(gl_VertexID % hairThicknessRes) / float(hairThicknessRes - 1); + thick_time = thickness * (thick_time * 2.0 - 1.0); + + /* Take object scale into account. + * NOTE: This only works fine with uniform scaling. */ + float scale = 1.0 / length(mat3(invmodel_mat) * wbinor); + + wpos += wbinor * thick_time * scale; + } } vec2 hair_get_customdata_vec2(const samplerBuffer cd_buf) { - int id = hair_get_strand_id(); - return texelFetch(cd_buf, id).rg; + int id = hair_get_strand_id(); + return texelFetch(cd_buf, id).rg; } vec3 hair_get_customdata_vec3(const samplerBuffer cd_buf) { - int id = hair_get_strand_id(); - return texelFetch(cd_buf, id).rgb; + int id = hair_get_strand_id(); + return texelFetch(cd_buf, id).rgb; } vec4 hair_get_customdata_vec4(const samplerBuffer cd_buf) { - int id = hair_get_strand_id(); - return texelFetch(cd_buf, id).rgba; + int id = hair_get_strand_id(); + return texelFetch(cd_buf, id).rgba; } vec3 hair_get_strand_pos(void) { - int id = hair_get_strand_id() * hairStrandsRes; - return texelFetch(hairPointBuffer, id).point_position; + int id = hair_get_strand_id() * hairStrandsRes; + return texelFetch(hairPointBuffer, id).point_position; } #endif diff --git a/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl b/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl index c193c307e01..3f5e3f8226f 100644 --- a/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl +++ b/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl @@ -5,43 +5,43 @@ out vec4 finalColor; vec4 get_weights_cardinal(float t) { - float t2 = t * t; - float t3 = t2 * t; + float t2 = t * t; + float t3 = t2 * t; #if defined(CARDINAL) - float fc = 0.71; + float fc = 0.71; #else /* defined(CATMULL_ROM) */ - float fc = 0.5; + float fc = 0.5; #endif - vec4 weights; - /* GLSL Optimized version of key_curve_position_weights() */ - float fct = t * fc; - float fct2 = t2 * fc; - float fct3 = t3 * fc; - weights.x = ( fct2 * 2.0 - fct3) - fct; - weights.y = ( t3 * 2.0 - fct3) + (-t2 * 3.0 + fct2) + 1.0; - weights.z = (-t3 * 2.0 + fct3) + ( t2 * 3.0 - (2.0 * fct2)) + fct; - weights.w = fct3 - fct2; - return weights; + vec4 weights; + /* GLSL Optimized version of key_curve_position_weights() */ + float fct = t * fc; + float fct2 = t2 * fc; + float fct3 = t3 * fc; + weights.x = (fct2 * 2.0 - fct3) - fct; + weights.y = (t3 * 2.0 - fct3) + (-t2 * 3.0 + fct2) + 1.0; + weights.z = (-t3 * 2.0 + fct3) + (t2 * 3.0 - (2.0 * fct2)) + fct; + weights.w = fct3 - fct2; + return weights; } /* TODO(fclem): This one is buggy, find why. (it's not the optimization!!) */ vec4 get_weights_bspline(float t) { - float t2 = t * t; - float t3 = t2 * t; + float t2 = t * t; + float t3 = t2 * t; - vec4 weights; - /* GLSL Optimized version of key_curve_position_weights() */ - weights.xz = vec2(-0.16666666, -0.5) * t3 + (0.5 * t2 + 0.5 * vec2(-t, t) + 0.16666666); - weights.y = ( 0.5 * t3 - t2 + 0.66666666); - weights.w = ( 0.16666666 * t3); - return weights; + vec4 weights; + /* GLSL Optimized version of key_curve_position_weights() */ + weights.xz = vec2(-0.16666666, -0.5) * t3 + (0.5 * t2 + 0.5 * vec2(-t, t) + 0.16666666); + weights.y = (0.5 * t3 - t2 + 0.66666666); + weights.w = (0.16666666 * t3); + return weights; } vec4 interp_data(vec4 v0, vec4 v1, vec4 v2, vec4 v3, vec4 w) { - return v0 * w.x + v1 * w.y + v2 * w.z + v3 * w.w; + return v0 * w.x + v1 * w.y + v2 * w.z + v3 * w.w; } #ifdef TF_WORKAROUND @@ -52,20 +52,20 @@ uniform int idOffset; void main(void) { - float interp_time; - vec4 data0, data1, data2, data3; - hair_get_interp_attrs(data0, data1, data2, data3, interp_time); + float interp_time; + vec4 data0, data1, data2, data3; + hair_get_interp_attrs(data0, data1, data2, data3, interp_time); - vec4 weights = get_weights_cardinal(interp_time); - finalColor = interp_data(data0, data1, data2, data3, weights); + vec4 weights = get_weights_cardinal(interp_time); + finalColor = interp_data(data0, data1, data2, data3, weights); #ifdef TF_WORKAROUND - int id = gl_VertexID - idOffset; - gl_Position.x = ((float(id % targetWidth) + 0.5) / float(targetWidth)) * 2.0 - 1.0; - gl_Position.y = ((float(id / targetWidth) + 0.5) / float(targetHeight)) * 2.0 - 1.0; - gl_Position.z = 0.0; - gl_Position.w = 1.0; + int id = gl_VertexID - idOffset; + gl_Position.x = ((float(id % targetWidth) + 0.5) / float(targetWidth)) * 2.0 - 1.0; + gl_Position.y = ((float(id / targetWidth) + 0.5) / float(targetHeight)) * 2.0 - 1.0; + gl_Position.z = 0.0; + gl_Position.w = 1.0; - gl_PointSize = 1.0; + gl_PointSize = 1.0; #endif } diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl index d261d263a6f..de9c4e2a96e 100644 --- a/source/blender/draw/modes/shaders/common_view_lib.glsl +++ b/source/blender/draw/modes/shaders/common_view_lib.glsl @@ -1,14 +1,15 @@ /* keep in sync with DRWManager.view_data */ -layout(std140) uniform viewBlock { - /* Same order as DRWViewportMatrixType */ - mat4 ViewProjectionMatrix; - mat4 ViewProjectionMatrixInverse; - mat4 ViewMatrix; - mat4 ViewMatrixInverse; - mat4 ProjectionMatrix; - mat4 ProjectionMatrixInverse; +layout(std140) uniform viewBlock +{ + /* Same order as DRWViewportMatrixType */ + mat4 ViewProjectionMatrix; + mat4 ViewProjectionMatrixInverse; + mat4 ViewMatrix; + mat4 ViewMatrixInverse; + mat4 ProjectionMatrix; + mat4 ProjectionMatrixInverse; - vec4 CameraTexCoFactors; + vec4 CameraTexCoFactors; - vec4 clipPlanes[2]; + vec4 clipPlanes[2]; }; diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl index c2ab0ecfd40..0a152cefaed 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl @@ -1,7 +1,7 @@ /* Keep the same value of `ACTIVE_NURB` in `draw_cache_imp_curve.c` */ -#define ACTIVE_NURB 1 << 2 -#define EVEN_U_BIT 1 << 3 +#define ACTIVE_NURB 1 << 2 +#define EVEN_U_BIT 1 << 3 layout(lines) in; layout(triangle_strip, max_vertices = 10) out; @@ -15,88 +15,96 @@ out vec4 finalColor; void output_line(vec2 offset, vec4 color) { - finalColor = color; + finalColor = color; - gl_Position = gl_in[0].gl_Position; - gl_Position.xy += offset * gl_in[0].gl_Position.w; + gl_Position = gl_in[0].gl_Position; + gl_Position.xy += offset * gl_in[0].gl_Position.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); - gl_Position = gl_in[1].gl_Position; - gl_Position.xy += offset * gl_in[1].gl_Position.w; + gl_Position = gl_in[1].gl_Position; + gl_Position.xy += offset * gl_in[1].gl_Position.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); } void main() { - vec4 v1 = gl_in[0].gl_Position; - vec4 v2 = gl_in[1].gl_Position; - - int is_active_nurb = (vertFlag[1] & ACTIVE_NURB); - int color_id = (vertFlag[1] >> 4); - - /* Don't output any edges if we don't show handles */ - if (!showCurveHandles && (color_id < 5)) { - return; - } - - bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0); - - vec4 inner_color; - if (color_id == 0) inner_color = (edge_selected) ? colorHandleSelFree : colorHandleFree; - else if (color_id == 1) inner_color = (edge_selected) ? colorHandleSelAuto : colorHandleAuto; - else if (color_id == 2) inner_color = (edge_selected) ? colorHandleSelVect : colorHandleVect; - else if (color_id == 3) inner_color = (edge_selected) ? colorHandleSelAlign : colorHandleAlign; - else if (color_id == 4) inner_color = (edge_selected) ? colorHandleSelAutoclamp : colorHandleAutoclamp; - else { - bool is_selected = (((vertFlag[1] & vertFlag[0]) & VERT_SELECTED) != 0); - bool is_u_segment = (((vertFlag[1] ^ vertFlag[0]) & EVEN_U_BIT) != 0); - if (is_u_segment) { - inner_color = (is_selected) ? colorNurbSelUline : colorNurbUline; - } - else { - inner_color = (is_selected) ? colorNurbSelVline : colorNurbVline; - } - } - - vec4 outer_color = (is_active_nurb != 0) - ? mix(colorActiveSpline, inner_color, 0.25) /* Minimize active color bleeding on inner_color. */ - : vec4(inner_color.rgb, 0.0); - - vec2 v1_2 = (v2.xy/v2.w - v1.xy/v1.w); - vec2 offset = sizeEdge * 4.0 / viewportSize; /* 4.0 is eyeballed */ - - if (abs(v1_2.x * viewportSize.x) < abs(v1_2.y * viewportSize.y)) { - offset.y = 0.0; - } - else { - offset.x = 0.0; - } - - /* draw the transparent border (AA). */ - if (is_active_nurb != 0) { - offset *= 0.75; /* Don't make the active "halo" appear very thick. */ - output_line(offset * 2.0, vec4(colorActiveSpline.rgb, 0.0)); - } - - /* draw the outline. */ - output_line(offset, outer_color); - - /* draw the core of the line. */ - output_line(vec2(0.0), inner_color); - - /* draw the outline. */ - output_line(-offset, outer_color); - - /* draw the transparent border (AA). */ - if (is_active_nurb != 0) { - output_line(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0)); - } - - EndPrimitive(); + vec4 v1 = gl_in[0].gl_Position; + vec4 v2 = gl_in[1].gl_Position; + + int is_active_nurb = (vertFlag[1] & ACTIVE_NURB); + int color_id = (vertFlag[1] >> 4); + + /* Don't output any edges if we don't show handles */ + if (!showCurveHandles && (color_id < 5)) { + return; + } + + bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0); + + vec4 inner_color; + if (color_id == 0) + inner_color = (edge_selected) ? colorHandleSelFree : colorHandleFree; + else if (color_id == 1) + inner_color = (edge_selected) ? colorHandleSelAuto : colorHandleAuto; + else if (color_id == 2) + inner_color = (edge_selected) ? colorHandleSelVect : colorHandleVect; + else if (color_id == 3) + inner_color = (edge_selected) ? colorHandleSelAlign : colorHandleAlign; + else if (color_id == 4) + inner_color = (edge_selected) ? colorHandleSelAutoclamp : colorHandleAutoclamp; + else { + bool is_selected = (((vertFlag[1] & vertFlag[0]) & VERT_SELECTED) != 0); + bool is_u_segment = (((vertFlag[1] ^ vertFlag[0]) & EVEN_U_BIT) != 0); + if (is_u_segment) { + inner_color = (is_selected) ? colorNurbSelUline : colorNurbUline; + } + else { + inner_color = (is_selected) ? colorNurbSelVline : colorNurbVline; + } + } + + vec4 outer_color = (is_active_nurb != 0) ? + mix(colorActiveSpline, + inner_color, + 0.25) /* Minimize active color bleeding on inner_color. */ + : + vec4(inner_color.rgb, 0.0); + + vec2 v1_2 = (v2.xy / v2.w - v1.xy / v1.w); + vec2 offset = sizeEdge * 4.0 / viewportSize; /* 4.0 is eyeballed */ + + if (abs(v1_2.x * viewportSize.x) < abs(v1_2.y * viewportSize.y)) { + offset.y = 0.0; + } + else { + offset.x = 0.0; + } + + /* draw the transparent border (AA). */ + if (is_active_nurb != 0) { + offset *= 0.75; /* Don't make the active "halo" appear very thick. */ + output_line(offset * 2.0, vec4(colorActiveSpline.rgb, 0.0)); + } + + /* draw the outline. */ + output_line(offset, outer_color); + + /* draw the core of the line. */ + output_line(vec2(0.0), inner_color); + + /* draw the outline. */ + output_line(-offset, outer_color); + + /* draw the transparent border (AA). */ + if (is_active_nurb != 0) { + output_line(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0)); + } + + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl index f92aab3254c..b7166382b19 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl @@ -9,11 +9,11 @@ flat out int vertFlag; void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; - vertFlag = data; + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; + vertFlag = data; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl index b7ffb56ad30..4718f11db65 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl @@ -10,22 +10,22 @@ out vec4 finalColor; void main() { - if ((data & VERT_SELECTED) != 0) { - if ((data & VERT_ACTIVE) != 0) { - finalColor = colorEditMeshActive; - } - else { - finalColor = colorVertexSelect; - } - } - else { - finalColor = colorVertex; - } + if ((data & VERT_SELECTED) != 0) { + if ((data & VERT_ACTIVE) != 0) { + finalColor = colorEditMeshActive; + } + else { + finalColor = colorVertexSelect; + } + } + else { + finalColor = colorVertex; + } - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; - gl_PointSize = sizeVertex * 2.0; + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; + gl_PointSize = sizeVertex * 2.0; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl index da05d224283..02244086711 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl @@ -10,18 +10,18 @@ in float rad; void main() { - vec3 final_pos = pos; + vec3 final_pos = pos; - float flip = (gl_InstanceID != 0) ? -1.0 : 1.0; + float flip = (gl_InstanceID != 0) ? -1.0 : 1.0; - if (gl_VertexID % 2 == 0) { - final_pos += normalSize * rad * (flip * nor - tan); - } + if (gl_VertexID % 2 == 0) { + final_pos += normalSize * rad * (flip * nor - tan); + } - vec4 final_pos_4d = vec4(final_pos, 1.0); - gl_Position = ModelViewProjectionMatrix * final_pos_4d; + vec4 final_pos_4d = vec4(final_pos, 1.0); + gl_Position = ModelViewProjectionMatrix * final_pos_4d; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * final_pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * final_pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl index 92caa4620d7..e674b802f65 100644 --- a/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl @@ -5,15 +5,15 @@ out vec4 FragColor; void main() { - /* TODO: vertex size */ + /* TODO: vertex size */ - if ((vertFlag & VERT_SELECTED) != 0) { - FragColor = colorVertexSelect; - } - else if ((vertFlag & VERT_ACTIVE) != 0) { - FragColor = colorEditMeshActive; - } - else { - FragColor = colorVertex; - } + if ((vertFlag & VERT_SELECTED) != 0) { + FragColor = colorVertexSelect; + } + else if ((vertFlag & VERT_ACTIVE) != 0) { + FragColor = colorEditMeshActive; + } + else { + FragColor = colorVertex; + } } diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl index bf0357632e6..3cf808f3c52 100644 --- a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl @@ -20,26 +20,25 @@ flat out vec4 eData2; /* project to screen space */ vec2 proj(vec4 pos) { - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } void main() { - clipCase = 0; + clipCase = 0; - vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); - /* only vertex position 0 is used */ - eData1 = eData2 = vec4(1e10); - eData2.zw = proj(pPos); + /* only vertex position 0 is used */ + eData1 = eData2 = vec4(1e10); + eData2.zw = proj(pPos); - vertFlag = data; + vertFlag = data; - gl_PointSize = sizeVertex; - gl_Position = pPos; + gl_PointSize = sizeVertex; + gl_Position = pPos; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif - } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl index 6563945af39..ffabfd3fcee 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl @@ -3,68 +3,69 @@ uniform bool doEdges = true; vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, float bweight) { - vec4 color = vec4(0.0); - color = ((edge_flag & EDGE_FREESTYLE) != 0) ? colorEdgeFreestyle : color; - color = ((edge_flag & EDGE_SHARP) != 0) ? colorEdgeSharp : color; - color = (crease > 0.0) ? vec4(colorEdgeCrease.rgb, crease) : color; - color = (bweight > 0.0) ? vec4(colorEdgeBWeight.rgb, bweight) : color; - color = ((edge_flag & EDGE_SEAM) != 0) ? colorEdgeSeam : color; - return color; + vec4 color = vec4(0.0); + color = ((edge_flag & EDGE_FREESTYLE) != 0) ? colorEdgeFreestyle : color; + color = ((edge_flag & EDGE_SHARP) != 0) ? colorEdgeSharp : color; + color = (crease > 0.0) ? vec4(colorEdgeCrease.rgb, crease) : color; + color = (bweight > 0.0) ? vec4(colorEdgeBWeight.rgb, bweight) : color; + color = ((edge_flag & EDGE_SEAM) != 0) ? colorEdgeSeam : color; + return color; } vec4 EDIT_MESH_edge_color_inner(int edge_flag) { - vec4 color = colorWireEdit; - color = ((edge_flag & EDGE_SELECTED) != 0) ? colorEdgeSelect : color; - color = ((edge_flag & EDGE_ACTIVE) != 0) ? colorEditMeshActive : color; - return color; + vec4 color = colorWireEdit; + color = ((edge_flag & EDGE_SELECTED) != 0) ? colorEdgeSelect : color; + color = ((edge_flag & EDGE_ACTIVE) != 0) ? colorEditMeshActive : color; + return color; } vec4 EDIT_MESH_edge_vertex_color(int vertex_flag) { - vec4 color = colorWireEdit; - color = (doEdges && (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0) ? colorEdgeSelect : color; - return color; + vec4 color = colorWireEdit; + color = (doEdges && (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0) ? colorEdgeSelect : + color; + return color; } vec4 EDIT_MESH_vertex_color(int vertex_flag) { - if ((vertex_flag & VERT_ACTIVE) != 0) { - return vec4(colorEditMeshActive.xyz, 1.0); - } - else if ((vertex_flag & VERT_SELECTED) != 0) { - return colorVertexSelect; - } - else { - return colorVertex; - } + if ((vertex_flag & VERT_ACTIVE) != 0) { + return vec4(colorEditMeshActive.xyz, 1.0); + } + else if ((vertex_flag & VERT_SELECTED) != 0) { + return colorVertexSelect; + } + else { + return colorVertex; + } } vec4 EDIT_MESH_face_color(int face_flag) { - if ((face_flag & FACE_ACTIVE) != 0) { - return mix(colorFaceSelect, colorEditMeshActive, 0.5); - } - else if ((face_flag & FACE_SELECTED) != 0) { - return colorFaceSelect; - } - else if ((face_flag & FACE_FREESTYLE) != 0) { - return colorFaceFreestyle; - } - else { - return colorFace; - } + if ((face_flag & FACE_ACTIVE) != 0) { + return mix(colorFaceSelect, colorEditMeshActive, 0.5); + } + else if ((face_flag & FACE_SELECTED) != 0) { + return colorFaceSelect; + } + else if ((face_flag & FACE_FREESTYLE) != 0) { + return colorFaceFreestyle; + } + else { + return colorFace; + } } vec4 EDIT_MESH_facedot_color(float facedot_flag) { - if (facedot_flag < 0.0f) { - return colorEditMeshActive; - } - else if (facedot_flag > 0.0f) { - return colorFaceDot; - } - else { - return colorVertex; - } + if (facedot_flag < 0.0f) { + return colorEditMeshActive; + } + else if (facedot_flag > 0.0f) { + return colorFaceDot; + } + else { + return colorVertex; + } } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl index 2e729009a38..a8371958ec2 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl @@ -3,5 +3,5 @@ out vec4 FragColor; void main() { - FragColor = faceColor; + FragColor = faceColor; } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl index 1c2338f0913..c84d97fa1c5 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl @@ -10,13 +10,13 @@ flat out vec4 faceColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - ivec4 data_m = data & dataMask; + ivec4 data_m = data & dataMask; - faceColor = EDIT_MESH_face_color(data_m.x); + faceColor = EDIT_MESH_face_color(data_m.x); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl index 59fb8e7fc90..3418732afc2 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl @@ -1,5 +1,5 @@ -#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */ +#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */ /** * We want to know how much a pixel is covered by a line. @@ -22,15 +22,15 @@ out vec4 FragColor; void main() { - float dist = abs(edgeCoord_f) - max(sizeEdge * edgeScale - 0.5, 0.0); - float dist_outer = dist - max(sizeEdge * edgeScale, 1.0); + float dist = abs(edgeCoord_f) - max(sizeEdge * edgeScale - 0.5, 0.0); + float dist_outer = dist - max(sizeEdge * edgeScale, 1.0); #ifdef USE_SMOOTH_WIRE - float mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist); - float mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer); + float mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist); + float mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer); #else - float mix_w = step(0.5, dist); - float mix_w_outer = step(0.5, dist_outer); + float mix_w = step(0.5, dist); + float mix_w_outer = step(0.5, dist_outer); #endif - FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a); - FragColor.a *= 1.0 - (finalColorOuter_f.a > 0.0 ? mix_w_outer : mix_w); + FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a); + FragColor.a *= 1.0 - (finalColorOuter_f.a > 0.0 ? mix_w_outer : mix_w); } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl index d5d9f213b94..6e59de12260 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl @@ -16,65 +16,65 @@ noperspective out float edgeCoord_f; void do_vertex(const int i, vec4 pos, float coord, vec2 offset) { - finalColor_f = (selectOveride[0] == 0) ? finalColor[i] : finalColor[0]; - edgeCoord_f = coord; - gl_Position = pos; - /* Multiply offset by 2 because gl_Position range is [-1..1]. */ - gl_Position.xy += offset * 2.0 * pos.w; + finalColor_f = (selectOveride[0] == 0) ? finalColor[i] : finalColor[0]; + edgeCoord_f = coord; + gl_Position = pos; + /* Multiply offset by 2 because gl_Position range is [-1..1]. */ + gl_Position.xy += offset * 2.0 * pos.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); } void main() { - vec2 ss_pos[2]; - - /* Clip line against near plane to avoid deformed lines. */ - vec4 pos0 = gl_in[0].gl_Position; - vec4 pos1 = gl_in[1].gl_Position; - vec2 pz_ndc = vec2(pos0.z / pos0.w, pos1.z / pos1.w); - bvec2 clipped = lessThan(pz_ndc, vec2(-1.0)); - if (all(clipped)) { - /* Totally clipped. */ - return; - } - - vec4 pos01 = pos0 - pos1; - float ofs = abs((pz_ndc.y + 1.0) / (pz_ndc.x - pz_ndc.y)); - if (clipped.y) { - pos1 += pos01 * ofs; - } - else if (clipped.x) { - pos0 -= pos01 * (1.0 - ofs); - } - - ss_pos[0] = pos0.xy / pos0.w; - ss_pos[1] = pos1.xy / pos1.w; - - vec2 line = ss_pos[0] - ss_pos[1]; - line = abs(line) * viewportSize; - - finalColorOuter_f = finalColorOuter[0]; - float half_size = sizeEdge * edgeScale; - /* Enlarge edge for flag display. */ - half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge * edgeScale, 1.0) : 0.0; + vec2 ss_pos[2]; + + /* Clip line against near plane to avoid deformed lines. */ + vec4 pos0 = gl_in[0].gl_Position; + vec4 pos1 = gl_in[1].gl_Position; + vec2 pz_ndc = vec2(pos0.z / pos0.w, pos1.z / pos1.w); + bvec2 clipped = lessThan(pz_ndc, vec2(-1.0)); + if (all(clipped)) { + /* Totally clipped. */ + return; + } + + vec4 pos01 = pos0 - pos1; + float ofs = abs((pz_ndc.y + 1.0) / (pz_ndc.x - pz_ndc.y)); + if (clipped.y) { + pos1 += pos01 * ofs; + } + else if (clipped.x) { + pos0 -= pos01 * (1.0 - ofs); + } + + ss_pos[0] = pos0.xy / pos0.w; + ss_pos[1] = pos1.xy / pos1.w; + + vec2 line = ss_pos[0] - ss_pos[1]; + line = abs(line) * viewportSize; + + finalColorOuter_f = finalColorOuter[0]; + float half_size = sizeEdge * edgeScale; + /* Enlarge edge for flag display. */ + half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge * edgeScale, 1.0) : 0.0; #ifdef USE_SMOOTH_WIRE - /* Add 1 px for AA */ - half_size += 0.5; + /* Add 1 px for AA */ + half_size += 0.5; #endif - vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0); + vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0); - bool horizontal = line.x > line.y; - edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; + bool horizontal = line.x > line.y; + edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; - do_vertex(0, pos0, half_size, edge_ofs.xy); - do_vertex(0, pos0, -half_size, -edge_ofs.xy); - do_vertex(1, pos1, half_size, edge_ofs.xy); - do_vertex(1, pos1, -half_size, -edge_ofs.xy); + do_vertex(0, pos0, half_size, edge_ofs.xy); + do_vertex(0, pos0, -half_size, -edge_ofs.xy); + do_vertex(1, pos1, half_size, edge_ofs.xy); + do_vertex(1, pos1, -half_size, -edge_ofs.xy); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl index 3fd4d263aa2..9a53038a252 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl @@ -3,5 +3,5 @@ in vec2 pos; void main() { - gl_Position = vec4(pos, 1.0, 1.0); + gl_Position = vec4(pos, 1.0, 1.0); } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl index 8f94a105332..a3fcfd880d3 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl @@ -8,15 +8,15 @@ uniform float alpha; void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); - float wire_depth = texelFetch(wireDepth, uv, 0).r; - float scene_depth = texelFetch(sceneDepth, uv, 0).r; - vec4 wire_color = texelFetch(wireColor, uv, 0).rgba; + ivec2 uv = ivec2(gl_FragCoord.xy); + float wire_depth = texelFetch(wireDepth, uv, 0).r; + float scene_depth = texelFetch(sceneDepth, uv, 0).r; + vec4 wire_color = texelFetch(wireColor, uv, 0).rgba; - FragColor = wire_color; + FragColor = wire_color; - /* Modulate alpha if occluded */ - if (wire_depth > scene_depth) { - FragColor.a *= alpha; - } + /* Modulate alpha if occluded */ + if (wire_depth > scene_depth) { + FragColor.a *= alpha; + } } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl index c43ae6073c6..8c54470cd5a 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -26,75 +26,73 @@ out int selectOveride; void main() { #if !defined(FACE) - mat4 projmat = ProjectionMatrix; - projmat[3][2] -= ofs; + mat4 projmat = ProjectionMatrix; + projmat[3][2] -= ofs; - gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); + gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); #endif - ivec4 m_data = data & dataMask; + ivec4 m_data = data & dataMask; #if defined(VERT) - finalColor = EDIT_MESH_vertex_color(m_data.y); - gl_PointSize = sizeVertex * 2.0; - gl_Position.z -= 3e-5 * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0); - /* Make selected and active vertex always on top. */ - if ((data.x & VERT_SELECTED) != 0) { - gl_Position.z -= 1e-7; - } - if ((data.x & VERT_ACTIVE) != 0) { - gl_Position.z -= 1e-7; - } + finalColor = EDIT_MESH_vertex_color(m_data.y); + gl_PointSize = sizeVertex * 2.0; + gl_Position.z -= 3e-5 * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0); + /* Make selected and active vertex always on top. */ + if ((data.x & VERT_SELECTED) != 0) { + gl_Position.z -= 1e-7; + } + if ((data.x & VERT_ACTIVE) != 0) { + gl_Position.z -= 1e-7; + } #elif defined(EDGE) # ifdef FLAT - finalColor = EDIT_MESH_edge_color_inner(m_data.y); - selectOveride = 1; + finalColor = EDIT_MESH_edge_color_inner(m_data.y); + selectOveride = 1; # else - finalColor = EDIT_MESH_edge_vertex_color(m_data.y); - selectOveride = (m_data.y & EDGE_SELECTED); + finalColor = EDIT_MESH_edge_vertex_color(m_data.y); + selectOveride = (m_data.y & EDGE_SELECTED); # endif - float crease = float(m_data.z) / 255.0; - float bweight = float(m_data.w) / 255.0; - finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight); + float crease = float(m_data.z) / 255.0; + float bweight = float(m_data.w) / 255.0; + finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight); #elif defined(FACE) - finalColor = EDIT_MESH_face_color(m_data.x); - finalColor.a *= faceAlphaMod; + finalColor = EDIT_MESH_face_color(m_data.x); + finalColor.a *= faceAlphaMod; #elif defined(FACEDOT) - finalColor = EDIT_MESH_facedot_color(norAndFlag.w); - /* Bias Facedot Z position in clipspace. */ - gl_Position.z -= 0.00035; - gl_PointSize = sizeFaceDot; + finalColor = EDIT_MESH_facedot_color(norAndFlag.w); + /* Bias Facedot Z position in clipspace. */ + gl_Position.z -= 0.00035; + gl_PointSize = sizeFaceDot; #endif #if !defined(FACE) && !defined(EDGE_DECORATION) - /* Facing based color blend */ - vec4 vpos = ModelViewMatrix * vec4(pos, 1.0); - vec3 view_normal = normalize(NormalMatrix * vnor + 1e-4); - vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? - normalize(vpos.xyz) : - vec3(0.0, 0.0, 1.0); - float facing = dot(view_vec, view_normal); - facing = 1.0 - abs(facing) * 0.3; - - finalColor = mix(colorEditMeshMiddle, finalColor, facing); - finalColor.a = 1.0; + /* Facing based color blend */ + vec4 vpos = ModelViewMatrix * vec4(pos, 1.0); + vec3 view_normal = normalize(NormalMatrix * vnor + 1e-4); + vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? normalize(vpos.xyz) : vec3(0.0, 0.0, 1.0); + float facing = dot(view_vec, view_normal); + facing = 1.0 - abs(facing) * 0.3; + + finalColor = mix(colorEditMeshMiddle, finalColor, facing); + finalColor.a = 1.0; # if defined(EDGE) && !defined(FLAT) - /* Hack to blend color in pixel shader in case of overide. */ - finalColor.a = facing; + /* Hack to blend color in pixel shader in case of overide. */ + finalColor.a = facing; # endif #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/edit_normals_geom.glsl b/source/blender/draw/modes/shaders/edit_normals_geom.glsl index 91a57a79eb0..5f43c13478d 100644 --- a/source/blender/draw/modes/shaders/edit_normals_geom.glsl +++ b/source/blender/draw/modes/shaders/edit_normals_geom.glsl @@ -1,18 +1,18 @@ layout(points) in; -layout(line_strip, max_vertices=2) out; +layout(line_strip, max_vertices = 2) out; flat in vec4 v1[1]; flat in vec4 v2[1]; void main() { - for (int v = 0; v < 2; v++) { - gl_Position = (v == 0) ? v1[0] : v2[0]; + for (int v = 0; v < 2; v++) { + gl_Position = (v == 0) ? v1[0] : v2[0]; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); #endif - EmitVertex(); - } - EndPrimitive(); + EmitVertex(); + } + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl index 8d73a2f5ad2..2e34a132cb0 100644 --- a/source/blender/draw/modes/shaders/edit_normals_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl @@ -9,15 +9,15 @@ in vec3 pos; #ifdef LOOP_NORMALS in vec3 lnor; -#define nor lnor +# define nor lnor #elif defined(FACE_NORMALS) in vec4 norAndFlag; -#define nor norAndFlag.xyz +# define nor norAndFlag.xyz #else in vec3 vnor; -#define nor vnor +# define nor vnor #endif flat out vec4 v1; @@ -25,10 +25,10 @@ flat out vec4 v2; void main() { - v1 = ModelViewProjectionMatrix * vec4(pos, 1.0); - vec3 n = normalize(NormalMatrix * nor); /* viewspace */ - v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0); + v1 = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 n = normalize(NormalMatrix * nor); /* viewspace */ + v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl index 8de25de35ad..7fd955343fc 100644 --- a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl +++ b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl @@ -19,20 +19,20 @@ flat out vec4 finalColor; void main() { - float draw_size = 4.0 * size; - vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz; - vec3 loc = InstanceModelMatrix[3].xyz; - vec3 wpos = loc + chosen_axis * fract(axis) * draw_size; - vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y; - /* Scale uniformly by axis length */ - spos *= length(chosen_axis) * draw_size; + float draw_size = 4.0 * size; + vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz; + vec3 loc = InstanceModelMatrix[3].xyz; + vec3 wpos = loc + chosen_axis * fract(axis) * draw_size; + vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y; + /* Scale uniformly by axis length */ + spos *= length(chosen_axis) * draw_size; - vec4 pos_4d = vec4(wpos + spos, 1.0); - gl_Position = ViewProjectionMatrix * pos_4d; + vec4 pos_4d = vec4(wpos + spos, 1.0); + gl_Position = ViewProjectionMatrix * pos_4d; - finalColor = vec4(color, 1.0); + finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl index c20d70e3b06..386d05636f9 100644 --- a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl +++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl @@ -17,30 +17,30 @@ uniform bool useAlphaTest; void main() { #ifdef USE_WIRE - fragColor = finalColor; + fragColor = finalColor; #else - vec4 tex_col = texture(image, texCoord_interp); - fragColor = finalColor * tex_col; - - if (useAlphaTest) { - /* Arbitrary discard anything below 5% opacity. - * Note that this could be exposed to the User. */ - if (tex_col.a < 0.05) { - discard; - } - else { - fragColor.a = 1.0; - } - } + vec4 tex_col = texture(image, texCoord_interp); + fragColor = finalColor * tex_col; + + if (useAlphaTest) { + /* Arbitrary discard anything below 5% opacity. + * Note that this could be exposed to the User. */ + if (tex_col.a < 0.05) { + discard; + } + else { + fragColor.a = 1.0; + } + } #endif - if (depthMode == DEPTH_BACK) { - gl_FragDepth = 0.999999; - } - else if (depthMode == DEPTH_FRONT) { - gl_FragDepth = 0.000001; - } - else if (depthMode == DEPTH_UNCHANGED) { - gl_FragDepth = gl_FragCoord.z; - } + if (depthMode == DEPTH_BACK) { + gl_FragDepth = 0.999999; + } + else if (depthMode == DEPTH_FRONT) { + gl_FragDepth = 0.000001; + } + else if (depthMode == DEPTH_UNCHANGED) { + gl_FragDepth = gl_FragCoord.z; + } } diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl index e5ea42c0661..9694c63fef1 100644 --- a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl +++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl @@ -21,17 +21,17 @@ out vec2 texCoord_interp; void main() { - vec4 pos_4d = vec4((pos + offset) * (size * vec2(aspectX, aspectY)), 0.0, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; + vec4 pos_4d = vec4((pos + offset) * (size * vec2(aspectX, aspectY)), 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; #ifdef USE_WIRE - gl_Position.z -= 1e-5; - finalColor = vec4(color, 1.0); + gl_Position.z -= 1e-5; + finalColor = vec4(color, 1.0); #else - texCoord_interp = texCoord; - finalColor = objectColor; + texCoord_interp = texCoord; + finalColor = objectColor; #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index 7d89676fd47..841b4a95b21 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -18,23 +18,23 @@ uniform float lineKernel = 0.0; uniform float gridOneOverLogSubdiv; uniform sampler2D depthBuffer; -#define gridDistance gridSettings.x -#define gridResolution gridSettings.y -#define gridScale gridSettings.z -#define gridSubdiv gridSettings.w +#define gridDistance gridSettings.x +#define gridResolution gridSettings.y +#define gridScale gridSettings.z +#define gridSubdiv gridSettings.w uniform int gridFlag; -#define AXIS_X (1 << 0) -#define AXIS_Y (1 << 1) -#define AXIS_Z (1 << 2) -#define GRID (1 << 3) -#define PLANE_XY (1 << 4) -#define PLANE_XZ (1 << 5) -#define PLANE_YZ (1 << 6) +#define AXIS_X (1 << 0) +#define AXIS_Y (1 << 1) +#define AXIS_Z (1 << 2) +#define GRID (1 << 3) +#define PLANE_XY (1 << 4) +#define PLANE_XZ (1 << 5) +#define PLANE_YZ (1 << 6) #define GRID_BACK (1 << 9) /* grid is behind objects */ -#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */ +#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */ /** * We want to know how much a pixel is covered by a line. @@ -49,159 +49,161 @@ uniform int gridFlag; float get_grid(vec2 co, vec2 fwidthCos, float grid_size) { - float half_size = grid_size / 2.0; - /* triangular wave pattern, amplitude is [0, half_size] */ - vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size); - /* modulate by the absolute rate of change of the coordinates - * (make lines have the same width under perspective) */ - grid_domain /= fwidthCos; + float half_size = grid_size / 2.0; + /* triangular wave pattern, amplitude is [0, half_size] */ + vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size); + /* modulate by the absolute rate of change of the coordinates + * (make lines have the same width under perspective) */ + grid_domain /= fwidthCos; - /* collapse waves */ - float line_dist = min(grid_domain.x, grid_domain.y); + /* collapse waves */ + float line_dist = min(grid_domain.x, grid_domain.y); - return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, line_dist - lineKernel); + return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, line_dist - lineKernel); } vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size) { - vec3 axes_domain = abs(co); - /* modulate by the absolute rate of change of the coordinates - * (make line have the same width under perspective) */ - axes_domain /= fwidthCos; - - return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, axes_domain - (line_size + lineKernel)); + vec3 axes_domain = abs(co); + /* modulate by the absolute rate of change of the coordinates + * (make line have the same width under perspective) */ + axes_domain /= fwidthCos; + + return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, + GRID_LINE_SMOOTH_END, + axes_domain - (line_size + lineKernel)); } void main() { - vec3 wPos = local_pos * meshSize; - vec3 fwidthPos = fwidth(wPos); - wPos += cameraPos * planeAxes; - - float dist, fade; - /* if persp */ - if (ProjectionMatrix[3][3] == 0.0) { - vec3 viewvec = cameraPos - wPos; - dist = length(viewvec); - viewvec /= dist; - - float angle; - if ((gridFlag & PLANE_XZ) != 0) { - angle = viewvec.y; - } - else if ((gridFlag & PLANE_YZ) != 0) { - angle = viewvec.x; - } - else { - angle = viewvec.z; - } - - angle = 1.0 - abs(angle); - angle *= angle; - fade = 1.0 - angle * angle; - fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance); - } - else { - dist = abs(gl_FragCoord.z * 2.0 - 1.0); - fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5); - dist = 1.0; /* avoid branch after */ - - if ((gridFlag & PLANE_XY) != 0) { - float angle = 1.0 - abs(eye.z); - dist = 1.0 + angle * 2.0; - angle *= angle; - fade *= 1.0 - angle * angle; - } - } - - if ((gridFlag & GRID) != 0) { - float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv; - - float blend = fract(-max(grid_res, 0.0)); - float lvl = floor(grid_res); - - /* from biggest to smallest */ - float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0)); - float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0)); - float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0)); - - vec2 grid_pos, grid_fwidth; - if ((gridFlag & PLANE_XZ) != 0) { - grid_pos = wPos.xz; - grid_fwidth = fwidthPos.xz; - } - else if ((gridFlag & PLANE_YZ) != 0) { - grid_pos = wPos.yz; - grid_fwidth = fwidthPos.yz; - } - else { - grid_pos = wPos.xy; - grid_fwidth = fwidthPos.xy; - } - - float gridA = get_grid(grid_pos, grid_fwidth, scaleA); - float gridB = get_grid(grid_pos, grid_fwidth, scaleB); - float gridC = get_grid(grid_pos, grid_fwidth, scaleC); - - FragColor = colorGrid; - FragColor.a *= gridA * blend; - FragColor = mix(FragColor, mix(colorGrid, colorGridEmphasise, blend), gridB); - FragColor = mix(FragColor, colorGridEmphasise, gridC); - } - else { - FragColor = vec4(colorGrid.rgb, 0.0); - } - - if ((gridFlag & (AXIS_X | AXIS_Y | AXIS_Z)) != 0) { - /* Setup axes 'domains' */ - vec3 axes_dist, axes_fwidth; - - if ((gridFlag & AXIS_X) != 0) { - axes_dist.x = dot(wPos.yz, planeAxes.yz); - axes_fwidth.x = dot(fwidthPos.yz, planeAxes.yz); - } - if ((gridFlag & AXIS_Y) != 0) { - axes_dist.y = dot(wPos.xz, planeAxes.xz); - axes_fwidth.y = dot(fwidthPos.xz, planeAxes.xz); - } - if ((gridFlag & AXIS_Z) != 0) { - axes_dist.z = dot(wPos.xy, planeAxes.xy); - axes_fwidth.z = dot(fwidthPos.xy, planeAxes.xy); - } - - /* Computing all axes at once using vec3 */ - vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1); - - if ((gridFlag & AXIS_X) != 0) { - FragColor.a = max(FragColor.a, axes.x); - FragColor.rgb = (axes.x < 1e-8) ? FragColor.rgb : colorGridAxisX.rgb; - } - if ((gridFlag & AXIS_Y) != 0) { - FragColor.a = max(FragColor.a, axes.y); - FragColor.rgb = (axes.y < 1e-8) ? FragColor.rgb : colorGridAxisY.rgb; - } - if ((gridFlag & AXIS_Z) != 0) { - FragColor.a = max(FragColor.a, axes.z); - FragColor.rgb = (axes.z < 1e-8) ? FragColor.rgb : colorGridAxisZ.rgb; - } - } - - /* Add a small bias so the grid will always - * be on top of a mesh with the same depth. */ - float grid_depth = gl_FragCoord.z - 6e-8 - fwidth(gl_FragCoord.z); - float scene_depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; - if ((gridFlag & GRID_BACK) != 0) { - fade *= (scene_depth == 1.0) ? 1.0 : 0.0; - } - else { - /* Manual, non hard, depth test: - * Progressively fade the grid below occluders - * (avoids popping visuals due to depth buffer precision) */ - /* Harder settings tend to flicker more, - * but have less "see through" appearance. */ - const float test_hardness = 1e7; - fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); - } - - FragColor.a *= fade; + vec3 wPos = local_pos * meshSize; + vec3 fwidthPos = fwidth(wPos); + wPos += cameraPos * planeAxes; + + float dist, fade; + /* if persp */ + if (ProjectionMatrix[3][3] == 0.0) { + vec3 viewvec = cameraPos - wPos; + dist = length(viewvec); + viewvec /= dist; + + float angle; + if ((gridFlag & PLANE_XZ) != 0) { + angle = viewvec.y; + } + else if ((gridFlag & PLANE_YZ) != 0) { + angle = viewvec.x; + } + else { + angle = viewvec.z; + } + + angle = 1.0 - abs(angle); + angle *= angle; + fade = 1.0 - angle * angle; + fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance); + } + else { + dist = abs(gl_FragCoord.z * 2.0 - 1.0); + fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5); + dist = 1.0; /* avoid branch after */ + + if ((gridFlag & PLANE_XY) != 0) { + float angle = 1.0 - abs(eye.z); + dist = 1.0 + angle * 2.0; + angle *= angle; + fade *= 1.0 - angle * angle; + } + } + + if ((gridFlag & GRID) != 0) { + float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv; + + float blend = fract(-max(grid_res, 0.0)); + float lvl = floor(grid_res); + + /* from biggest to smallest */ + float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0)); + float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0)); + float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0)); + + vec2 grid_pos, grid_fwidth; + if ((gridFlag & PLANE_XZ) != 0) { + grid_pos = wPos.xz; + grid_fwidth = fwidthPos.xz; + } + else if ((gridFlag & PLANE_YZ) != 0) { + grid_pos = wPos.yz; + grid_fwidth = fwidthPos.yz; + } + else { + grid_pos = wPos.xy; + grid_fwidth = fwidthPos.xy; + } + + float gridA = get_grid(grid_pos, grid_fwidth, scaleA); + float gridB = get_grid(grid_pos, grid_fwidth, scaleB); + float gridC = get_grid(grid_pos, grid_fwidth, scaleC); + + FragColor = colorGrid; + FragColor.a *= gridA * blend; + FragColor = mix(FragColor, mix(colorGrid, colorGridEmphasise, blend), gridB); + FragColor = mix(FragColor, colorGridEmphasise, gridC); + } + else { + FragColor = vec4(colorGrid.rgb, 0.0); + } + + if ((gridFlag & (AXIS_X | AXIS_Y | AXIS_Z)) != 0) { + /* Setup axes 'domains' */ + vec3 axes_dist, axes_fwidth; + + if ((gridFlag & AXIS_X) != 0) { + axes_dist.x = dot(wPos.yz, planeAxes.yz); + axes_fwidth.x = dot(fwidthPos.yz, planeAxes.yz); + } + if ((gridFlag & AXIS_Y) != 0) { + axes_dist.y = dot(wPos.xz, planeAxes.xz); + axes_fwidth.y = dot(fwidthPos.xz, planeAxes.xz); + } + if ((gridFlag & AXIS_Z) != 0) { + axes_dist.z = dot(wPos.xy, planeAxes.xy); + axes_fwidth.z = dot(fwidthPos.xy, planeAxes.xy); + } + + /* Computing all axes at once using vec3 */ + vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1); + + if ((gridFlag & AXIS_X) != 0) { + FragColor.a = max(FragColor.a, axes.x); + FragColor.rgb = (axes.x < 1e-8) ? FragColor.rgb : colorGridAxisX.rgb; + } + if ((gridFlag & AXIS_Y) != 0) { + FragColor.a = max(FragColor.a, axes.y); + FragColor.rgb = (axes.y < 1e-8) ? FragColor.rgb : colorGridAxisY.rgb; + } + if ((gridFlag & AXIS_Z) != 0) { + FragColor.a = max(FragColor.a, axes.z); + FragColor.rgb = (axes.z < 1e-8) ? FragColor.rgb : colorGridAxisZ.rgb; + } + } + + /* Add a small bias so the grid will always + * be on top of a mesh with the same depth. */ + float grid_depth = gl_FragCoord.z - 6e-8 - fwidth(gl_FragCoord.z); + float scene_depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; + if ((gridFlag & GRID_BACK) != 0) { + fade *= (scene_depth == 1.0) ? 1.0 : 0.0; + } + else { + /* Manual, non hard, depth test: + * Progressively fade the grid below occluders + * (avoids popping visuals due to depth buffer precision) */ + /* Harder settings tend to flicker more, + * but have less "see through" appearance. */ + const float test_hardness = 1e7; + fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); + } + + FragColor.a *= fade; } diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl index 1cf6c49b733..e8f4b089b47 100644 --- a/source/blender/draw/modes/shaders/object_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -9,18 +9,18 @@ uniform vec3 planeAxes; uniform vec4 gridSettings; uniform float meshSize; -#define gridDistance gridSettings.x -#define gridResolution gridSettings.y -#define gridScale gridSettings.z -#define gridSubdiv gridSettings.w +#define gridDistance gridSettings.x +#define gridResolution gridSettings.y +#define gridScale gridSettings.z +#define gridSubdiv gridSettings.w uniform int gridFlag; -#define PLANE_XY (1 << 4) -#define PLANE_XZ (1 << 5) -#define PLANE_YZ (1 << 6) -#define CLIP_Z_POS (1 << 7) -#define CLIP_Z_NEG (1 << 8) +#define PLANE_XY (1 << 4) +#define PLANE_XZ (1 << 5) +#define PLANE_YZ (1 << 6) +#define CLIP_Z_POS (1 << 7) +#define CLIP_Z_NEG (1 << 8) in vec3 pos; @@ -28,32 +28,32 @@ out vec3 local_pos; void main() { - vec3 vert_pos; - - /* Project camera pos to the needed plane */ - if ((gridFlag & PLANE_XY) != 0) { - vert_pos = vec3(pos.x, pos.y, 0.0); - } - else if ((gridFlag & PLANE_XZ) != 0) { - vert_pos = vec3(pos.x, 0.0, pos.y); - } - else { - vert_pos = vec3(0.0, pos.x, pos.y); - } - - local_pos = vert_pos; - - vec3 real_pos = cameraPos * planeAxes + vert_pos * meshSize; - - /* Used for additional Z axis */ - if ((gridFlag & CLIP_Z_POS) != 0) { - real_pos.z = clamp(real_pos.z, 0.0, 1e30); - local_pos.z = clamp(local_pos.z, 0.0, 1.0); - } - if ((gridFlag & CLIP_Z_NEG) != 0) { - real_pos.z = clamp(real_pos.z, -1e30, 0.0); - local_pos.z = clamp(local_pos.z, -1.0, 0.0); - } - - gl_Position = ViewProjectionMatrix * vec4(real_pos, 1.0); + vec3 vert_pos; + + /* Project camera pos to the needed plane */ + if ((gridFlag & PLANE_XY) != 0) { + vert_pos = vec3(pos.x, pos.y, 0.0); + } + else if ((gridFlag & PLANE_XZ) != 0) { + vert_pos = vec3(pos.x, 0.0, pos.y); + } + else { + vert_pos = vec3(0.0, pos.x, pos.y); + } + + local_pos = vert_pos; + + vec3 real_pos = cameraPos * planeAxes + vert_pos * meshSize; + + /* Used for additional Z axis */ + if ((gridFlag & CLIP_Z_POS) != 0) { + real_pos.z = clamp(real_pos.z, 0.0, 1e30); + local_pos.z = clamp(local_pos.z, 0.0, 1.0); + } + if ((gridFlag & CLIP_Z_NEG) != 0) { + real_pos.z = clamp(real_pos.z, -1e30, 0.0); + local_pos.z = clamp(local_pos.z, -1.0, 0.0); + } + + gl_Position = ViewProjectionMatrix * vec4(real_pos, 1.0); } diff --git a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl index bcdf5adca55..61da94dd433 100644 --- a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl @@ -16,19 +16,18 @@ flat out uint finalId; void main() { - vec3 ls_cell_location; - /* Keep in sync with update_irradiance_probe */ - ls_cell_location.z = float(gl_VertexID % grid_resolution.z); - ls_cell_location.y = float((gl_VertexID / grid_resolution.z) % grid_resolution.y); - ls_cell_location.x = float(gl_VertexID / (grid_resolution.z * grid_resolution.y)); + vec3 ls_cell_location; + /* Keep in sync with update_irradiance_probe */ + ls_cell_location.z = float(gl_VertexID % grid_resolution.z); + ls_cell_location.y = float((gl_VertexID / grid_resolution.z) % grid_resolution.y); + ls_cell_location.x = float(gl_VertexID / (grid_resolution.z * grid_resolution.y)); - vec3 ws_cell_location = corner + - (increment_x * ls_cell_location.x + - increment_y * ls_cell_location.y + - increment_z * ls_cell_location.z); + vec3 ws_cell_location = corner + + (increment_x * ls_cell_location.x + increment_y * ls_cell_location.y + + increment_z * ls_cell_location.z); - gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0); - gl_PointSize = 2.0f; + gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0); + gl_PointSize = 2.0f; - finalId = uint(baseId + call_id); + finalId = uint(baseId + call_id); } diff --git a/source/blender/draw/modes/shaders/object_loose_points_frag.glsl b/source/blender/draw/modes/shaders/object_loose_points_frag.glsl index 66b3091a41c..5730cb2d96e 100644 --- a/source/blender/draw/modes/shaders/object_loose_points_frag.glsl +++ b/source/blender/draw/modes/shaders/object_loose_points_frag.glsl @@ -6,14 +6,14 @@ out vec4 fragColor; void main() { - vec2 centered = abs(gl_PointCoord - vec2(0.5)); - float dist = max(centered.x, centered.y); + vec2 centered = abs(gl_PointCoord - vec2(0.5)); + float dist = max(centered.x, centered.y); - float fac = dist * dist * 4.0; - fragColor = mix(innerColor, color, 0.45 + fac * 0.65); + float fac = dist * dist * 4.0; + fragColor = mix(innerColor, color, 0.45 + fac * 0.65); - /* Make the effect more like a fresnel by offsetting - * the depth and creating mini-spheres. - * Disabled as it has performance impact. */ - // gl_FragDepth = gl_FragCoord.z + 1e-6 * fac; + /* Make the effect more like a fresnel by offsetting + * the depth and creating mini-spheres. + * Disabled as it has performance impact. */ + // gl_FragDepth = gl_FragCoord.z + 1e-6 * fac; } diff --git a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl index a2bd08be3c1..c395ed01bca 100644 --- a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl +++ b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl @@ -3,7 +3,6 @@ * and scales the shape according to per-instance attributes * Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */ - uniform mat4 ViewProjectionMatrix; uniform mat4 ModelMatrix; uniform vec3 screen_vecs[2]; @@ -20,20 +19,19 @@ flat out vec4 finalColor; void main() { - mat3 Scamat = mat3(ScaleTranslationMatrix); - vec4 world_pos = vec4( - ScaleTranslationMatrix[0][3], - ScaleTranslationMatrix[1][3], - ScaleTranslationMatrix[2][3], - 1.0); + mat3 Scamat = mat3(ScaleTranslationMatrix); + vec4 world_pos = vec4(ScaleTranslationMatrix[0][3], + ScaleTranslationMatrix[1][3], + ScaleTranslationMatrix[2][3], + 1.0); - vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; - world_pos.xyz += Scamat * (screen_pos * radius); + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + world_pos.xyz += Scamat * (screen_pos * radius); - gl_Position = ViewProjectionMatrix * world_pos; - finalColor = vec4(color, 1.0); + gl_Position = ViewProjectionMatrix * world_pos; + finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * world_pos).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * world_pos).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl index 6545104c3c6..7668a0c2c94 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -14,78 +14,78 @@ uniform vec2 viewportSize; vec4 convert_id_to_color(int id) { - if (id == 0) { - return vec4(0.0); - } - if (id < idOffsets[1]) { - return colorActive; - } - else if (id < idOffsets[2]) { - return colorSelect; - } - else if (id < idOffsets[3]) { - return colorDupliSelect; - } - else { - return colorTransform; - } + if (id == 0) { + return vec4(0.0); + } + if (id < idOffsets[1]) { + return colorActive; + } + else if (id < idOffsets[2]) { + return colorSelect; + } + else if (id < idOffsets[3]) { + return colorDupliSelect; + } + else { + return colorTransform; + } } void main() { - ivec2 texel = ivec2(gl_FragCoord.xy); + ivec2 texel = ivec2(gl_FragCoord.xy); #ifdef GPU_ARB_texture_gather - vec2 texel_size = 1.0 / vec2(textureSize(outlineId, 0).xy); - vec2 uv = ceil(gl_FragCoord.xy) * texel_size; + vec2 texel_size = 1.0 / vec2(textureSize(outlineId, 0).xy); + vec2 uv = ceil(gl_FragCoord.xy) * texel_size; - /* Samples order is CW starting from top left. */ - uvec4 tmp1 = textureGather(outlineId, uv - texel_size); - uvec4 tmp2 = textureGather(outlineId, uv); + /* Samples order is CW starting from top left. */ + uvec4 tmp1 = textureGather(outlineId, uv - texel_size); + uvec4 tmp2 = textureGather(outlineId, uv); - uint ref_id = tmp1.y; - uvec4 id = uvec4(tmp1.xz, tmp2.xz); + uint ref_id = tmp1.y; + uvec4 id = uvec4(tmp1.xz, tmp2.xz); #else - uvec4 id; - uint ref_id = texelFetch(outlineId, texel, 0).r; - id.x = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r; - id.y = texelFetchOffset(outlineId, texel, 0, ivec2( 0, -1)).r; - id.z = texelFetchOffset(outlineId, texel, 0, ivec2( 0, 1)).r; - id.w = texelFetchOffset(outlineId, texel, 0, ivec2( 1, 0)).r; + uvec4 id; + uint ref_id = texelFetch(outlineId, texel, 0).r; + id.x = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r; + id.y = texelFetchOffset(outlineId, texel, 0, ivec2(0, -1)).r; + id.z = texelFetchOffset(outlineId, texel, 0, ivec2(0, 1)).r; + id.w = texelFetchOffset(outlineId, texel, 0, ivec2(1, 0)).r; #endif #ifdef WIRE - /* We want only 2px outlines. */ - /* TODO optimize, don't sample if we don't need to. */ - id.xy = uvec2(ref_id); + /* We want only 2px outlines. */ + /* TODO optimize, don't sample if we don't need to. */ + id.xy = uvec2(ref_id); #endif - bool outline = any(notEqual(id, uvec4(ref_id))); - - ivec2 depth_texel = texel; - /* If texel is an outline but has no valid id ... - * replace id and depth texel by a valid one. - * This keeps the outline thickness consistent everywhere. */ - if (ref_id == 0u && outline) { - depth_texel = (id.x != 0u) ? texel + ivec2(-1, 0) : depth_texel; - depth_texel = (id.y != 0u) ? texel + ivec2( 0, -1) : depth_texel; - depth_texel = (id.z != 0u) ? texel + ivec2( 0, 1) : depth_texel; - depth_texel = (id.w != 0u) ? texel + ivec2( 1, 0) : depth_texel; - - ref_id = (id.x != 0u) ? id.x : ref_id; - ref_id = (id.y != 0u) ? id.y : ref_id; - ref_id = (id.z != 0u) ? id.z : ref_id; - ref_id = (id.w != 0u) ? id.w : ref_id; - } - - float ref_depth = texelFetch(outlineDepth, depth_texel, 0).r; - float scene_depth = texelFetch(sceneDepth, depth_texel, 0).r; - - /* Avoid bad cases of zfighting for occlusion only. */ - const float epsilon = 3.0 / 8388608.0; - bool occluded = (ref_depth > scene_depth + epsilon); - - FragColor = convert_id_to_color(int(ref_id)); - FragColor.a *= (occluded) ? alphaOcclu : 1.0; - FragColor.a = (outline) ? FragColor.a : 0.0; + bool outline = any(notEqual(id, uvec4(ref_id))); + + ivec2 depth_texel = texel; + /* If texel is an outline but has no valid id ... + * replace id and depth texel by a valid one. + * This keeps the outline thickness consistent everywhere. */ + if (ref_id == 0u && outline) { + depth_texel = (id.x != 0u) ? texel + ivec2(-1, 0) : depth_texel; + depth_texel = (id.y != 0u) ? texel + ivec2(0, -1) : depth_texel; + depth_texel = (id.z != 0u) ? texel + ivec2(0, 1) : depth_texel; + depth_texel = (id.w != 0u) ? texel + ivec2(1, 0) : depth_texel; + + ref_id = (id.x != 0u) ? id.x : ref_id; + ref_id = (id.y != 0u) ? id.y : ref_id; + ref_id = (id.z != 0u) ? id.z : ref_id; + ref_id = (id.w != 0u) ? id.w : ref_id; + } + + float ref_depth = texelFetch(outlineDepth, depth_texel, 0).r; + float scene_depth = texelFetch(sceneDepth, depth_texel, 0).r; + + /* Avoid bad cases of zfighting for occlusion only. */ + const float epsilon = 3.0 / 8388608.0; + bool occluded = (ref_depth > scene_depth + epsilon); + + FragColor = convert_id_to_color(int(ref_id)); + FragColor.a *= (occluded) ? alphaOcclu : 1.0; + FragColor.a = (outline) ? FragColor.a : 0.0; } diff --git a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl index 8b5603919c4..cb9fe0e7c36 100644 --- a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl @@ -10,42 +10,42 @@ uniform bool doExpand; void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); - FragColor = texelFetch(outlineColor, uv, 0).rgba; + ivec2 uv = ivec2(gl_FragCoord.xy); + FragColor = texelFetch(outlineColor, uv, 0).rgba; - vec4 color[4]; - color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 1, 0)).rgba; - color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 1)).rgba; - color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba; - color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -1)).rgba; + vec4 color[4]; + color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2(1, 0)).rgba; + color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, 1)).rgba; + color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba; + color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, -1)).rgba; - vec4 values = vec4(color[0].a, color[1].a, color[2].a, color[3].a); + vec4 values = vec4(color[0].a, color[1].a, color[2].a, color[3].a); - vec4 tests = step(vec4(1e-6), values); /* (color.a != 0.0) */ - bvec4 btests = equal(tests, vec4(1.0)); + vec4 tests = step(vec4(1e-6), values); /* (color.a != 0.0) */ + bvec4 btests = equal(tests, vec4(1.0)); - if (FragColor.a != 0.0) { - return; - } + if (FragColor.a != 0.0) { + return; + } #ifdef LARGE_OUTLINE - if (!any(btests)) { - color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 2, 0)).rgba; - color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 2)).rgba; - color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-2, 0)).rgba; - color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -2)).rgba; + if (!any(btests)) { + color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2(2, 0)).rgba; + color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, 2)).rgba; + color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-2, 0)).rgba; + color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, -2)).rgba; - values = vec4(color[0].a, color[1].a, color[2].a, color[3].a); + values = vec4(color[0].a, color[1].a, color[2].a, color[3].a); - tests = step(vec4(1e-6), values); /* (color.a != 0.0) */ - btests = equal(tests, vec4(1.0)); - } + tests = step(vec4(1e-6), values); /* (color.a != 0.0) */ + btests = equal(tests, vec4(1.0)); + } #endif - FragColor = (btests.x) ? color[0] : FragColor; - FragColor = (btests.y) ? color[1] : FragColor; - FragColor = (btests.z) ? color[2] : FragColor; - FragColor = (btests.w) ? color[3] : FragColor; + FragColor = (btests.x) ? color[0] : FragColor; + FragColor = (btests.y) ? color[1] : FragColor; + FragColor = (btests.z) ? color[2] : FragColor; + FragColor = (btests.w) ? color[3] : FragColor; - FragColor.a *= (!doExpand) ? 0.0 : 1.0; + FragColor.a *= (!doExpand) ? 0.0 : 1.0; } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl index 776adb787ad..c3447456ea6 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl @@ -6,5 +6,5 @@ out uint outId; void main() { - outId = uint(baseId + callId); + outId = uint(baseId + callId); } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl index 36999267ef2..97d4bdacf07 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl @@ -9,45 +9,45 @@ in vec3 vPos[]; void vert_from_gl_in(int v) { - gl_Position = pPos[v]; + gl_Position = pPos[v]; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[v].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[v].gl_ClipDistance); #endif } void main() { - bool is_persp = (ProjectionMatrix[3][3] == 0.0); + bool is_persp = (ProjectionMatrix[3][3] == 0.0); - vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); + vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); - vec3 v10 = vPos[0] - vPos[1]; - vec3 v12 = vPos[2] - vPos[1]; - vec3 v13 = vPos[3] - vPos[1]; + vec3 v10 = vPos[0] - vPos[1]; + vec3 v12 = vPos[2] - vPos[1]; + vec3 v13 = vPos[3] - vPos[1]; - vec3 n0 = cross(v12, v10); - vec3 n3 = cross(v13, v12); + vec3 n0 = cross(v12, v10); + vec3 n3 = cross(v13, v12); - float fac0 = dot(view_vec, n0); - float fac3 = dot(view_vec, n3); + float fac0 = dot(view_vec, n0); + float fac3 = dot(view_vec, n3); - /* If both adjacent verts are facing the camera the same way, - * then it isn't an outline edge. */ - if (sign(fac0) == sign(fac3)) { - return; - } + /* If both adjacent verts are facing the camera the same way, + * then it isn't an outline edge. */ + if (sign(fac0) == sign(fac3)) { + return; + } - /* Don't outline if concave edge. */ - /* That would hide a lot of non useful edge but it flickers badly. - * TODO revisit later... */ - // if (dot(n0, v13) > 0.01) - // return; + /* Don't outline if concave edge. */ + /* That would hide a lot of non useful edge but it flickers badly. + * TODO revisit later... */ + // if (dot(n0, v13) > 0.01) + // return; - vert_from_gl_in(1); - EmitVertex(); + vert_from_gl_in(1); + EmitVertex(); - vert_from_gl_in(2); - EmitVertex(); + vert_from_gl_in(2); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl index 744bf0ff1e3..0b5f4733ebc 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl @@ -10,12 +10,12 @@ out vec3 vPos; void main() { - vPos = (ModelViewMatrix * vec4(pos, 1.0)).xyz; - pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); - /* Small bias to always be on top of the geom. */ - pPos.z -= 1e-3; + vPos = (ModelViewMatrix * vec4(pos, 1.0)).xyz; + pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + /* Small bias to always be on top of the geom. */ + pPos.z -= 1e-3; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl index 964ebe72e81..ba5d073a9c2 100644 --- a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl @@ -9,19 +9,13 @@ uniform vec2 rcpDimensions; void main() { #ifdef USE_FXAA - float aa_alpha = FxaaPixelShader( - uvcoordsvar.st, - outlineBluredColor, - rcpDimensions, - 1.0, - 0.166, - 0.0833 - ).r; + float aa_alpha = + FxaaPixelShader(uvcoordsvar.st, outlineBluredColor, rcpDimensions, 1.0, 0.166, 0.0833).r; #endif - FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba; + FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba; #ifdef USE_FXAA - FragColor.a = aa_alpha; + FragColor.a = aa_alpha; #endif } diff --git a/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl index e8bf7884701..d15580056b0 100644 --- a/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl +++ b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl @@ -8,45 +8,46 @@ flat in float finalVal; out vec4 fragColor; -void main() { - float dist = length(gl_PointCoord - vec2(0.5)); - -// transparent outside of point -// --- 0 --- -// smooth transition -// --- 1 --- -// pure outline color -// --- 2 --- -// smooth transition -// --- 3 --- -// pure point color -// ... -// dist = 0 at center of point - - float midStroke = 0.5 * (radii[1] + radii[2]); - - if (dist > midStroke) { - if (finalVal < 0.0) { - fragColor.rgb = outlineColor; - } - else { - fragColor.rgb = texture(ramp, finalVal).rgb; - } - - fragColor.a = mix(1.0, 0.0, smoothstep(radii[1], radii[0], dist)); - } - else { - if (finalVal < 0.0) { - fragColor.rgb = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist)); - } - else { - fragColor.rgb = texture(ramp, finalVal).rgb; - } - - fragColor.a = 1.0; - } - - if (fragColor.a == 0.0) { - discard; - } +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); + + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure outline color + // --- 2 --- + // smooth transition + // --- 3 --- + // pure point color + // ... + // dist = 0 at center of point + + float midStroke = 0.5 * (radii[1] + radii[2]); + + if (dist > midStroke) { + if (finalVal < 0.0) { + fragColor.rgb = outlineColor; + } + else { + fragColor.rgb = texture(ramp, finalVal).rgb; + } + + fragColor.a = mix(1.0, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else { + if (finalVal < 0.0) { + fragColor.rgb = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist)); + } + else { + fragColor.rgb = texture(ramp, finalVal).rgb; + } + + fragColor.a = 1.0; + } + + if (fragColor.a == 0.0) { + discard; + } } diff --git a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl index 6dfc212a776..e51b829adb5 100644 --- a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl +++ b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl @@ -10,26 +10,28 @@ in float val; out vec4 radii; flat out float finalVal; -void main() { - gl_Position = ModelViewMatrix * vec4(pos, 1.0); +void main() +{ + gl_Position = ModelViewMatrix * vec4(pos, 1.0); - float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) : (size / pixel_size); + float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) : + (size / pixel_size); - gl_PointSize = psize; + gl_PointSize = psize; - // calculate concentric radii in pixels - float radius = 0.5 * psize; + // calculate concentric radii in pixels + float radius = 0.5 * psize; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; - radii[2] = radius - 1.0; - radii[3] = radius - 2.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - 1.0; + radii[3] = radius - 2.0; - // convert to PointCoord units - radii /= psize; + // convert to PointCoord units + radii /= psize; - gl_Position = ProjectionMatrix * gl_Position; + gl_Position = ProjectionMatrix * gl_Position; - finalVal = val; + finalVal = val; } diff --git a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl index 3df5115db76..0f626626498 100644 --- a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl +++ b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl @@ -18,42 +18,42 @@ flat out vec4 finalColor; vec3 rotate(vec3 vec, vec4 quat) { - /* The quaternion representation here stores the w component in the first index */ - return vec + 2.0 * cross(quat.yzw, cross(quat.yzw, vec) + quat.x * vec); + /* The quaternion representation here stores the w component in the first index */ + return vec + 2.0 * cross(quat.yzw, cross(quat.yzw, vec) + quat.x * vec); } void main() { - if (screen_space == 1) { - gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0); - gl_Position = ProjectionMatrix * gl_Position; - } - else { - float size = draw_size; + if (screen_space == 1) { + gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0); + gl_Position = ProjectionMatrix * gl_Position; + } + else { + float size = draw_size; - if (axis > -1) { - size *= 2; - } + if (axis > -1) { + size *= 2; + } - gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0); - } + gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0); + } #ifdef USE_AXIS - if (axis == 0) { - finalColor = vec4(1.0, 0.0, 0.0, 1.0); - } - else if (axis == 1) { - finalColor = vec4(0.0, 1.0, 0.0, 1.0); - } - else { - finalColor = vec4(0.0, 0.0, 1.0, 1.0); - } + if (axis == 0) { + finalColor = vec4(1.0, 0.0, 0.0, 1.0); + } + else if (axis == 1) { + finalColor = vec4(0.0, 1.0, 0.0, 1.0); + } + else { + finalColor = vec4(0.0, 0.0, 1.0, 1.0); + } #else - if (val < 0.0) { - finalColor = vec4(color, 1.0); - } - else { - finalColor = vec4(texture(ramp, val).rgb, 1.0); - } + if (val < 0.0) { + finalColor = vec4(color, 1.0); + } + else { + finalColor = vec4(texture(ramp, val).rgb, 1.0); + } #endif } diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl index 5b0ad7863d1..1ed35b4a421 100644 --- a/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl @@ -3,8 +3,7 @@ uniform vec3 color_outwards = vec3(1.0, 0.0, 0.0); out vec4 fragColor; - void main() { - fragColor = vec4(gl_FrontFacing ? color_towards: color_outwards, 0.7); + fragColor = vec4(gl_FrontFacing ? color_towards : color_outwards, 0.7); } diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl index f9f2679fe81..659e3cbd5f5 100644 --- a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl @@ -5,9 +5,9 @@ in vec3 pos; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl index 1a984b2fbc6..9414d25e71e 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl @@ -9,15 +9,15 @@ out vec4 fragColor; void main() { - if (edgeSharpness < 0.0) { - discard; - } + if (edgeSharpness < 0.0) { + discard; + } - float facing_clamped = clamp(abs(facing), 0.0, 1.0); + float facing_clamped = clamp(abs(facing), 0.0, 1.0); - vec3 final_front_col = mix(rimColor, wireColor, 0.4); - vec3 final_rim_col = mix(rimColor, wireColor, 0.1); + vec3 final_front_col = mix(rimColor, wireColor, 0.4); + vec3 final_rim_col = mix(rimColor, wireColor, 0.1); - fragColor.rgb = mix(final_rim_col, final_front_col, facing_clamped); - fragColor.a = 1.0f; + fragColor.rgb = mix(final_rim_col, final_front_col, facing_clamped); + fragColor.a = 1.0f; } diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl index 8f52c4fdf95..6ae52d43a48 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl @@ -19,42 +19,42 @@ flat out float edgeSharpness; void do_vertex(const int i, float coord, vec2 offset) { #ifndef SELECT_EDGES - edgeSharpness = edgeSharpness_g[i]; - facing = facing_g[i]; + edgeSharpness = edgeSharpness_g[i]; + facing = facing_g[i]; #endif - gl_Position = gl_in[i].gl_Position; - /* Multiply offset by 2 because gl_Position range is [-1..1]. */ - gl_Position.xy += offset * 2.0 * gl_Position.w; + gl_Position = gl_in[i].gl_Position; + /* Multiply offset by 2 because gl_Position range is [-1..1]. */ + gl_Position.xy += offset * 2.0 * gl_Position.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); } void main() { - vec2 ss_pos[2]; - ss_pos[0] = gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w; - ss_pos[1] = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w; + vec2 ss_pos[2]; + ss_pos[0] = gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w; + ss_pos[1] = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w; - vec2 line = ss_pos[0] - ss_pos[1]; - line = abs(line) * viewportSize; + vec2 line = ss_pos[0] - ss_pos[1]; + line = abs(line) * viewportSize; - float half_size = wireSize; + float half_size = wireSize; - vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0); + vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0); - bool horizontal = line.x > line.y; - edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; + bool horizontal = line.x > line.y; + edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; - if (edgeSharpness_g[0] < 0.0) { - return; - } + if (edgeSharpness_g[0] < 0.0) { + return; + } - do_vertex(0, half_size, edge_ofs.xy); - do_vertex(0, -half_size, -edge_ofs.xy); - do_vertex(1, half_size, edge_ofs.xy); - do_vertex(1, -half_size, -edge_ofs.xy); + do_vertex(0, half_size, edge_ofs.xy); + do_vertex(0, -half_size, -edge_ofs.xy); + do_vertex(1, half_size, edge_ofs.xy); + do_vertex(1, -half_size, -edge_ofs.xy); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl index 0424a49dd5d..96acba71233 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl @@ -14,10 +14,13 @@ in float wd; /* wiredata */ #ifndef USE_SCULPT float get_edge_sharpness(float wd) { - return ((wd == 0.0) ? -1.5 : wd) + wireStepParam; + return ((wd == 0.0) ? -1.5 : wd) + wireStepParam; } #else -float get_edge_sharpness(float wd) { return 1.0; } +float get_edge_sharpness(float wd) +{ + return 1.0; +} #endif /* Geometry shader version */ @@ -27,18 +30,18 @@ out float edgeSharpness_g; void main() { - edgeSharpness_g = get_edge_sharpness(wd); + edgeSharpness_g = get_edge_sharpness(wd); - mat4 projmat = ProjectionMatrix; - projmat[3][2] -= ofs; + mat4 projmat = ProjectionMatrix; + projmat[3][2] -= ofs; - gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); + gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); - facing_g = normalize(NormalMatrix * nor).z; + facing_g = normalize(NormalMatrix * nor).z; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); -#endif +# ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); +# endif } #else /* USE_GEOM */ @@ -47,18 +50,18 @@ flat out float edgeSharpness; void main() { - edgeSharpness = get_edge_sharpness(wd); + edgeSharpness = get_edge_sharpness(wd); - mat4 projmat = ProjectionMatrix; - projmat[3][2] -= ofs; + mat4 projmat = ProjectionMatrix; + projmat[3][2] -= ofs; - gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); + gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); - facing = normalize(NormalMatrix * nor).z; + facing = normalize(NormalMatrix * nor).z; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); -#endif +# ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); +# endif } #endif /* SELECT_EDGES */ diff --git a/source/blender/draw/modes/shaders/paint_face_vert.glsl b/source/blender/draw/modes/shaders/paint_face_vert.glsl index a850a130955..59b88d8d3a7 100644 --- a/source/blender/draw/modes/shaders/paint_face_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_face_vert.glsl @@ -7,14 +7,14 @@ in vec4 nor; /* select flag on the 4th component */ void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - /* Don't draw faces that are selected. */ - if (nor.w > 0.0) { - gl_Position = vec4(0.0, 0.0, 0.0, 1.0); - } - else { + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + /* Don't draw faces that are selected. */ + if (nor.w > 0.0) { + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + } + else { #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif - } + } } diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl index aadbf8c58c0..c7e110122c5 100644 --- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl +++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl @@ -18,24 +18,24 @@ uniform bool maskingInvertStencil; void main() { - vec2 uv = uv_interp; - if (nearestInterp) { - vec2 tex_size = vec2(textureSize(image, 0).xy); - uv = (floor(uv_interp * tex_size) + 0.5) / tex_size; - } + vec2 uv = uv_interp; + if (nearestInterp) { + vec2 tex_size = vec2(textureSize(image, 0).xy); + uv = (floor(uv_interp * tex_size) + 0.5) / tex_size; + } - vec4 color = texture(image, uv); - color.a *= alpha; + vec4 color = texture(image, uv); + color.a *= alpha; #ifdef TEXTURE_PAINT_MASK - vec4 mask = vec4(texture(maskingImage, masking_uv_interp).rgb, 1.0); - if (maskingInvertStencil) { - mask.rgb = 1.0 - mask.rgb; - } - float mask_step = smoothstep(0, 3.0, mask.r+mask.g+mask.b); - mask.rgb *= maskingColor; - color = mix(color, mask, mask_step); + vec4 mask = vec4(texture(maskingImage, masking_uv_interp).rgb, 1.0); + if (maskingInvertStencil) { + mask.rgb = 1.0 - mask.rgb; + } + float mask_step = smoothstep(0, 3.0, mask.r + mask.g + mask.b); + mask.rgb *= maskingColor; + color = mix(color, mask, mask_step); #endif - fragColor = color; + fragColor = color; } diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl index 43a353f0278..03d933b9196 100644 --- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl @@ -17,15 +17,15 @@ out vec2 masking_uv_interp; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - uv_interp = u; + uv_interp = u; #ifdef TEXTURE_PAINT_MASK - masking_uv_interp = mu; + masking_uv_interp = mu; #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/paint_vert_frag.glsl b/source/blender/draw/modes/shaders/paint_vert_frag.glsl index 3042ddf9770..3303dfa6173 100644 --- a/source/blender/draw/modes/shaders/paint_vert_frag.glsl +++ b/source/blender/draw/modes/shaders/paint_vert_frag.glsl @@ -4,14 +4,14 @@ out vec4 fragColor; void main() { - vec2 centered = gl_PointCoord - vec2(0.5); - float dist_squared = dot(centered, centered); - const float rad_squared = 0.25; + vec2 centered = gl_PointCoord - vec2(0.5); + float dist_squared = dot(centered, centered); + const float rad_squared = 0.25; - // round point with jaggy edges - if (dist_squared > rad_squared) { - discard; - } + // round point with jaggy edges + if (dist_squared > rad_squared) { + discard; + } - fragColor = finalColor; + fragColor = finalColor; } diff --git a/source/blender/draw/modes/shaders/paint_vertex_frag.glsl b/source/blender/draw/modes/shaders/paint_vertex_frag.glsl index 6dd97b36ee7..426dbada812 100644 --- a/source/blender/draw/modes/shaders/paint_vertex_frag.glsl +++ b/source/blender/draw/modes/shaders/paint_vertex_frag.glsl @@ -4,15 +4,16 @@ in vec3 finalColor; out vec4 fragColor; uniform float white_factor = 1.0; -vec3 linear_to_srgb_attr(vec3 c) { - c = max(c, vec3(0.0)); - vec3 c1 = c * 12.92; - vec3 c2 = 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055; - return mix(c1, c2, step(vec3(0.0031308), c)); +vec3 linear_to_srgb_attr(vec3 c) +{ + c = max(c, vec3(0.0)); + vec3 c1 = c * 12.92; + vec3 c2 = 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055; + return mix(c1, c2, step(vec3(0.0031308), c)); } void main() { - fragColor.rgb = mix(linear_to_srgb_attr(finalColor), vec3(1.0), white_factor); - fragColor.a = 1.0; + fragColor.rgb = mix(linear_to_srgb_attr(finalColor), vec3(1.0), white_factor); + fragColor.a = 1.0; } diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl index 39f59a29756..54f6d1a4aea 100644 --- a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl @@ -7,20 +7,21 @@ in vec3 c; /* active color */ out vec3 finalColor; -vec3 srgb_to_linear_attr(vec3 c) { - c = max(c, vec3(0.0)); - vec3 c1 = c * (1.0 / 12.92); - vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4)); - return mix(c1, c2, step(vec3(0.04045), c)); +vec3 srgb_to_linear_attr(vec3 c) +{ + c = max(c, vec3(0.0)); + vec3 c1 = c * (1.0 / 12.92); + vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4)); + return mix(c1, c2, step(vec3(0.04045), c)); } void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalColor = srgb_to_linear_attr(c); + finalColor = srgb_to_linear_attr(c); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/paint_weight_frag.glsl b/source/blender/draw/modes/shaders/paint_weight_frag.glsl index 7460eabedbe..8b0e03ac31c 100644 --- a/source/blender/draw/modes/shaders/paint_weight_frag.glsl +++ b/source/blender/draw/modes/shaders/paint_weight_frag.glsl @@ -10,91 +10,91 @@ uniform bool drawContours = false; float contours(float value, float steps, float width_px, float max_rel_width, float gradient) { - /* Minimum visible and minimum full strength line width in screen space for fade out. */ - const float min_width_px = 1.3, fade_width_px = 2.3; - /* Line is thinner towards the increase in the weight gradient by this factor. */ - const float hi_bias = 2.0; + /* Minimum visible and minimum full strength line width in screen space for fade out. */ + const float min_width_px = 1.3, fade_width_px = 2.3; + /* Line is thinner towards the increase in the weight gradient by this factor. */ + const float hi_bias = 2.0; - /* Don't draw lines at 0 or 1. */ - float rel_value = value * steps; + /* Don't draw lines at 0 or 1. */ + float rel_value = value * steps; - if (rel_value < 0.5 || rel_value > steps - 0.5) { - return 0.0; - } + if (rel_value < 0.5 || rel_value > steps - 0.5) { + return 0.0; + } - /* Check if completely invisible due to fade out. */ - float rel_gradient = gradient * steps; - float rel_min_width = min_width_px * rel_gradient; + /* Check if completely invisible due to fade out. */ + float rel_gradient = gradient * steps; + float rel_min_width = min_width_px * rel_gradient; - if (max_rel_width <= rel_min_width) { - return 0.0; - } + if (max_rel_width <= rel_min_width) { + return 0.0; + } - /* Main shape of the line, accounting for width bias and maximum weight space width. */ - float rel_width = width_px * rel_gradient; + /* Main shape of the line, accounting for width bias and maximum weight space width. */ + float rel_width = width_px * rel_gradient; - float offset = fract(rel_value + 0.5) - 0.5; + float offset = fract(rel_value + 0.5) - 0.5; - float base_alpha = 1.0 - max(offset * hi_bias, -offset) / min(max_rel_width, rel_width); + float base_alpha = 1.0 - max(offset * hi_bias, -offset) / min(max_rel_width, rel_width); - /* Line fadeout when too thin in screen space. */ - float rel_fade_width = fade_width_px * rel_gradient; + /* Line fadeout when too thin in screen space. */ + float rel_fade_width = fade_width_px * rel_gradient; - float fade_alpha = (max_rel_width - rel_min_width) / (rel_fade_width - rel_min_width); + float fade_alpha = (max_rel_width - rel_min_width) / (rel_fade_width - rel_min_width); - return clamp(base_alpha, 0.0, 1.0) * clamp(fade_alpha, 0.0, 1.0); + return clamp(base_alpha, 0.0, 1.0) * clamp(fade_alpha, 0.0, 1.0); } vec4 contour_grid(float weight, float weight_gradient) { - /* Fade away when the gradient is too low to avoid big fills and noise. */ - float flt_eps = max(1e-8, 1e-6 * weight); + /* Fade away when the gradient is too low to avoid big fills and noise. */ + float flt_eps = max(1e-8, 1e-6 * weight); - if (weight_gradient <= flt_eps) { - return vec4(0.0); - } + if (weight_gradient <= flt_eps) { + return vec4(0.0); + } - /* Three levels of grid lines */ - float grid10 = contours(weight, 10.0, 5.0, 0.3, weight_gradient); - float grid100 = contours(weight, 100.0, 3.5, 0.35, weight_gradient) * 0.6; - float grid1000 = contours(weight, 1000.0, 2.5, 0.4, weight_gradient) * 0.25; + /* Three levels of grid lines */ + float grid10 = contours(weight, 10.0, 5.0, 0.3, weight_gradient); + float grid100 = contours(weight, 100.0, 3.5, 0.35, weight_gradient) * 0.6; + float grid1000 = contours(weight, 1000.0, 2.5, 0.4, weight_gradient) * 0.25; - /* White lines for 0.1 and 0.01, and black for 0.001 */ - vec4 grid = vec4(1.0) * max(grid10, grid100); + /* White lines for 0.1 and 0.01, and black for 0.001 */ + vec4 grid = vec4(1.0) * max(grid10, grid100); - grid.a = max(grid.a, grid1000); + grid.a = max(grid.a, grid1000); - return grid * clamp((weight_gradient - flt_eps) / flt_eps, 0.0, 1.0); + return grid * clamp((weight_gradient - flt_eps) / flt_eps, 0.0, 1.0); } void main() { - float alert = weight_interp.y; - vec4 color; - - /* Missing vertex group alert color. Uniform in practice. */ - if (alert > 1.1) { - color = colorVertexMissingData; - } - /* Weights are available */ - else { - float weight = weight_interp.x; - vec4 weight_color = texture(colorramp, weight, 0); - - /* Contour display */ - if (drawContours) { - /* This must be executed uniformly for all fragments */ - float weight_gradient = length(vec2(dFdx(weight), dFdy(weight))); - - vec4 grid = contour_grid(weight, weight_gradient); - - weight_color = grid + weight_color * (1 - grid.a); - } - - /* Zero weight alert color. Nonlinear blend to reduce impact. */ - color = mix(weight_color, colorVertexUnreferenced, alert * alert); - } - - /* mix with 1.0 -> is like opacity when using multiply blend mode */ - fragColor = vec4(mix(vec3(1.0), color.rgb, opacity), 1.0); + float alert = weight_interp.y; + vec4 color; + + /* Missing vertex group alert color. Uniform in practice. */ + if (alert > 1.1) { + color = colorVertexMissingData; + } + /* Weights are available */ + else { + float weight = weight_interp.x; + vec4 weight_color = texture(colorramp, weight, 0); + + /* Contour display */ + if (drawContours) { + /* This must be executed uniformly for all fragments */ + float weight_gradient = length(vec2(dFdx(weight), dFdy(weight))); + + vec4 grid = contour_grid(weight, weight_gradient); + + weight_color = grid + weight_color * (1 - grid.a); + } + + /* Zero weight alert color. Nonlinear blend to reduce impact. */ + color = mix(weight_color, colorVertexUnreferenced, alert * alert); + } + + /* mix with 1.0 -> is like opacity when using multiply blend mode */ + fragColor = vec4(mix(vec3(1.0), color.rgb, opacity), 1.0); } diff --git a/source/blender/draw/modes/shaders/paint_weight_vert.glsl b/source/blender/draw/modes/shaders/paint_weight_vert.glsl index d111f3dc0a8..e95b116df79 100644 --- a/source/blender/draw/modes/shaders/paint_weight_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_weight_vert.glsl @@ -9,12 +9,12 @@ out vec2 weight_interp; /* (weight, alert) */ void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - /* Separate actual weight and alerts for independent interpolation */ - weight_interp = max(vec2(weight, -weight), 0.0); + /* Separate actual weight and alerts for independent interpolation */ + weight_interp = max(vec2(weight, -weight), 0.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/paint_wire_frag.glsl b/source/blender/draw/modes/shaders/paint_wire_frag.glsl index d738ed5ddb2..6c214534812 100644 --- a/source/blender/draw/modes/shaders/paint_wire_frag.glsl +++ b/source/blender/draw/modes/shaders/paint_wire_frag.glsl @@ -4,5 +4,5 @@ out vec4 fragColor; void main() { - fragColor = finalColor; + fragColor = finalColor; } diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl index b415be7841c..a163fd7e8b3 100644 --- a/source/blender/draw/modes/shaders/paint_wire_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl @@ -10,42 +10,42 @@ flat out vec4 finalColor; void main() { #ifdef USE_SELECT - bool is_select = (nor.w > 0.0); - bool is_hidden = (nor.w < 0.0); + bool is_select = (nor.w > 0.0); + bool is_hidden = (nor.w < 0.0); #else - bool is_select = false; - bool is_hidden = false; + bool is_select = false; + bool is_hidden = false; #endif - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - /* Add offset in Z to avoid zfighting and render selected wires on top. */ - /* TODO scale this bias using znear and zfar range. */ - gl_Position.z -= (is_select ? 2e-4 : 1e-4); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + /* Add offset in Z to avoid zfighting and render selected wires on top. */ + /* TODO scale this bias using znear and zfar range. */ + gl_Position.z -= (is_select ? 2e-4 : 1e-4); - if (is_hidden) { - gl_Position = vec4(-2.0, -2.0, -2.0, 1.0); - } + if (is_hidden) { + gl_Position = vec4(-2.0, -2.0, -2.0, 1.0); + } #ifdef VERTEX_MODE - vec4 colSel = colorEdgeSelect; - colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0); + vec4 colSel = colorEdgeSelect; + colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0); #else - const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0); + const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0); #endif #ifdef USE_SELECT - finalColor = (is_select) ? colSel : colorWire; + finalColor = (is_select) ? colSel : colorWire; #else # ifdef VERTEX_MODE - finalColor = colorWire; + finalColor = colorWire; # else - /* Weight paint needs a light color to contrasts with dark weights. */ - finalColor.xyz = vec3(0.8, 0.8, 0.8); + /* Weight paint needs a light color to contrasts with dark weights. */ + finalColor.xyz = vec3(0.8, 0.8, 0.8); # endif #endif - finalColor.a = nor.w; + finalColor.a = nor.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/draw/modes/shaders/particle_strand_frag.glsl b/source/blender/draw/modes/shaders/particle_strand_frag.glsl index 8bb213dbd30..578a4935b37 100644 --- a/source/blender/draw/modes/shaders/particle_strand_frag.glsl +++ b/source/blender/draw/modes/shaders/particle_strand_frag.glsl @@ -9,15 +9,15 @@ out vec4 fragColor; void main() { - fragColor = finalColor; + fragColor = finalColor; #ifdef USE_POINTS - float dist = length(gl_PointCoord - vec2(0.5)); + float dist = length(gl_PointCoord - vec2(0.5)); - fragColor.a = mix(finalColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); + fragColor.a = mix(finalColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); - if (fragColor.a == 0.0) { - discard; - } + if (fragColor.a == 0.0) { + discard; + } #endif } diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl index 9db62a581cb..745499800e5 100644 --- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl +++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl @@ -11,63 +11,63 @@ out vec2 radii; vec3 weight_to_rgb(float weight) { - vec3 r_rgb; - float blend = ((weight / 2.0) + 0.5); + vec3 r_rgb; + float blend = ((weight / 2.0) + 0.5); - if (weight <= 0.25) { /* blue->cyan */ - r_rgb[0] = 0.0; - r_rgb[1] = blend * weight * 4.0; - r_rgb[2] = blend; - } - else if (weight <= 0.50) { /* cyan->green */ - r_rgb[0] = 0.0; - r_rgb[1] = blend; - r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0)); - } - else if (weight <= 0.75) { /* green->yellow */ - r_rgb[0] = blend * ((weight - 0.50) * 4.0); - r_rgb[1] = blend; - r_rgb[2] = 0.0; - } - else if (weight <= 1.0) { /* yellow->red */ - r_rgb[0] = blend; - r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0)); - r_rgb[2] = 0.0; - } - else { - /* exceptional value, unclamped or nan, - * avoid uninitialized memory use */ - r_rgb[0] = 1.0; - r_rgb[1] = 0.0; - r_rgb[2] = 1.0; - } + if (weight <= 0.25) { /* blue->cyan */ + r_rgb[0] = 0.0; + r_rgb[1] = blend * weight * 4.0; + r_rgb[2] = blend; + } + else if (weight <= 0.50) { /* cyan->green */ + r_rgb[0] = 0.0; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0)); + } + else if (weight <= 0.75) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50) * 4.0); + r_rgb[1] = blend; + r_rgb[2] = 0.0; + } + else if (weight <= 1.0) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0)); + r_rgb[2] = 0.0; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0; + r_rgb[1] = 0.0; + r_rgb[2] = 1.0; + } - return r_rgb; + return r_rgb; } #define DECOMPRESS_RANGE 1.0039 void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); #ifdef USE_WEIGHT - finalColor = vec4(weight_to_rgb(color * DECOMPRESS_RANGE), 1.0); + finalColor = vec4(weight_to_rgb(color * DECOMPRESS_RANGE), 1.0); #else - finalColor = mix(colorWire, colorEdgeSelect, color); + finalColor = mix(colorWire, colorEdgeSelect, color); #endif #ifdef USE_POINTS - gl_PointSize = sizeVertex; + gl_PointSize = sizeVertex; - /* calculate concentric radii in pixels */ - float radius = 0.5 * sizeVertex; + /* calculate concentric radii in pixels */ + float radius = 0.5 * sizeVertex; - /* start at the outside and progress toward the center */ - radii[0] = radius; - radii[1] = radius - 1.0; + /* start at the outside and progress toward the center */ + radii[0] = radius; + radii[1] = radius - 1.0; - /* convert to PointCoord units */ - radii /= sizeVertex; + /* convert to PointCoord units */ + radii /= sizeVertex; #endif } diff --git a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl index 553a49f38df..5ae97ec5cb9 100644 --- a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl +++ b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl @@ -8,8 +8,8 @@ out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - float mask = 1.0 - msk * 0.75; - finalColor = vec4(mask, mask, mask, 1.0); + float mask = 1.0 - msk * 0.75; + finalColor = vec4(mask, mask, mask, 1.0); } diff --git a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl index 574c434920e..32207afa0b1 100644 --- a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl +++ b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl @@ -10,106 +10,104 @@ uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */ flat out vec4 finalColor; -const vec3 corners[4] = vec3[4]( - vec3(0.0, 0.2, -0.5), - vec3(-0.2 * 0.866, -0.2 * 0.5, -0.5), - vec3(0.2 * 0.866, -0.2 * 0.5, -0.5), - vec3(0.0, 0.0, 0.5) -); +const vec3 corners[4] = vec3[4](vec3(0.0, 0.2, -0.5), + vec3(-0.2 * 0.866, -0.2 * 0.5, -0.5), + vec3(0.2 * 0.866, -0.2 * 0.5, -0.5), + vec3(0.0, 0.0, 0.5)); -const int indices[12] = int[12](0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3); +const int indices[12] = int[12](0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3); /* Straight Port from BKE_defvert_weight_to_rgb() * TODO port this to a color ramp. */ vec3 weight_to_color(float weight) { - vec3 r_rgb = vec3(0.0); - float blend = ((weight / 2.0) + 0.5); - - if (weight <= 0.25) { /* blue->cyan */ - r_rgb.g = blend * weight * 4.0; - r_rgb.b = blend; - } - else if (weight <= 0.50) { /* cyan->green */ - r_rgb.g = blend; - r_rgb.b = blend * (1.0 - ((weight - 0.25) * 4.0)); - } - else if (weight <= 0.75) { /* green->yellow */ - r_rgb.r = blend * ((weight - 0.50) * 4.0); - r_rgb.g = blend; - } - else if (weight <= 1.0) { /* yellow->red */ - r_rgb.r = blend; - r_rgb.g = blend * (1.0 - ((weight - 0.75) * 4.0)); - } - else { - /* exceptional value, unclamped or nan, - * avoid uninitialized memory use */ - r_rgb = vec3(1.0, 0.0, 1.0); - } - - return r_rgb; + vec3 r_rgb = vec3(0.0); + float blend = ((weight / 2.0) + 0.5); + + if (weight <= 0.25) { /* blue->cyan */ + r_rgb.g = blend * weight * 4.0; + r_rgb.b = blend; + } + else if (weight <= 0.50) { /* cyan->green */ + r_rgb.g = blend; + r_rgb.b = blend * (1.0 - ((weight - 0.25) * 4.0)); + } + else if (weight <= 0.75) { /* green->yellow */ + r_rgb.r = blend * ((weight - 0.50) * 4.0); + r_rgb.g = blend; + } + else if (weight <= 1.0) { /* yellow->red */ + r_rgb.r = blend; + r_rgb.g = blend * (1.0 - ((weight - 0.75) * 4.0)); + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb = vec3(1.0, 0.0, 1.0); + } + + return r_rgb; } mat3 rotation_from_vector(vec3 v) { - /* Add epsilon to avoid NaN. */ - vec3 N = normalize(v + 1e-8); - vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0); - vec3 T = normalize(cross(UpVector, N)); - vec3 B = cross(N, T); - return mat3(T, B, N); + /* Add epsilon to avoid NaN. */ + vec3 N = normalize(v + 1e-8); + vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 T = normalize(cross(UpVector, N)); + vec3 B = cross(N, T); + return mat3(T, B, N); } void main() { #ifdef USE_NEEDLE - int cell = gl_VertexID / 12; + int cell = gl_VertexID / 12; #else - int cell = gl_VertexID / 2; + int cell = gl_VertexID / 2; #endif - ivec3 volume_size = textureSize(velocityX, 0); - float voxel_size = 1.0 / float(max(max(volume_size.x, volume_size.y), volume_size.z)); - - ivec3 cell_ofs = ivec3(0); - ivec3 cell_div = volume_size; - if (sliceAxis == 0) { - cell_ofs.x = int(slicePosition * float(volume_size.x)); - cell_div.x = 1; - } - else if (sliceAxis == 1) { - cell_ofs.y = int(slicePosition * float(volume_size.y)); - cell_div.y = 1; - } - else if (sliceAxis == 2) { - cell_ofs.z = int(slicePosition * float(volume_size.z)); - cell_div.z = 1; - } - - ivec3 cell_co; - cell_co.x = cell % cell_div.x; - cell_co.y = (cell / cell_div.x) % cell_div.y; - cell_co.z = cell / (cell_div.x * cell_div.y); - cell_co += cell_ofs; - - vec3 pos = (vec3(cell_co) + 0.5) / vec3(volume_size); - pos = pos * 2.0 - 1.0; - - vec3 velocity; - velocity.x = texelFetch(velocityX, cell_co, 0).r; - velocity.y = texelFetch(velocityY, cell_co, 0).r; - velocity.z = texelFetch(velocityZ, cell_co, 0).r; - - finalColor = vec4(weight_to_color(length(velocity)), 1.0); + ivec3 volume_size = textureSize(velocityX, 0); + float voxel_size = 1.0 / float(max(max(volume_size.x, volume_size.y), volume_size.z)); + + ivec3 cell_ofs = ivec3(0); + ivec3 cell_div = volume_size; + if (sliceAxis == 0) { + cell_ofs.x = int(slicePosition * float(volume_size.x)); + cell_div.x = 1; + } + else if (sliceAxis == 1) { + cell_ofs.y = int(slicePosition * float(volume_size.y)); + cell_div.y = 1; + } + else if (sliceAxis == 2) { + cell_ofs.z = int(slicePosition * float(volume_size.z)); + cell_div.z = 1; + } + + ivec3 cell_co; + cell_co.x = cell % cell_div.x; + cell_co.y = (cell / cell_div.x) % cell_div.y; + cell_co.z = cell / (cell_div.x * cell_div.y); + cell_co += cell_ofs; + + vec3 pos = (vec3(cell_co) + 0.5) / vec3(volume_size); + pos = pos * 2.0 - 1.0; + + vec3 velocity; + velocity.x = texelFetch(velocityX, cell_co, 0).r; + velocity.y = texelFetch(velocityY, cell_co, 0).r; + velocity.z = texelFetch(velocityZ, cell_co, 0).r; + + finalColor = vec4(weight_to_color(length(velocity)), 1.0); #ifdef USE_NEEDLE - mat3 rot_mat = rotation_from_vector(velocity); - vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]]; - pos += rotated_pos * length(velocity) * displaySize * voxel_size; + mat3 rot_mat = rotation_from_vector(velocity); + vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]]; + pos += rotated_pos * length(velocity) * displaySize * voxel_size; #else - pos += (((gl_VertexID % 2) == 1) ? velocity : vec3(0.0)) * displaySize * voxel_size; + pos += (((gl_VertexID % 2) == 1) ? velocity : vec3(0.0)) * displaySize * voxel_size; #endif - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); } |