diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-05-02 17:05:23 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-05-02 17:05:23 +0300 |
commit | 43e6bb85cee0802887eae9489a2bd73836daf41d (patch) | |
tree | eaa106429af8341bf2123d7445fdab0af71b3dda /source/blender/draw | |
parent | 7daeb1f9aee284d958abe87622b43c70c21af967 (diff) | |
parent | ffaf91b5fc03f91e1fc90bd2f1d5dc5aa75656ff (diff) |
Merge 'master' into 'collada'
Diffstat (limited to 'source/blender/draw')
93 files changed, 2054 insertions, 979 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 0d1752af4dc..abbf8a2b47b 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -39,9 +39,9 @@ set(INC ../render/intern/include ../windowmanager + ../../../intern/atomic ../../../intern/glew-mx ../../../intern/guardedalloc - ../../../intern/atomic ) set(INC_SYS @@ -277,6 +277,8 @@ data_to_c_simple(modes/shaders/edit_mesh_overlay_geom.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_mesh_analysis_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_curve_overlay_handle_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_curve_overlay_handle_geom.glsl SRC) data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 161e28db2d3..da1f5c7863a 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -132,6 +132,9 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, struct GPUViewport *viewport); +void DRW_draw_depth_object(struct ARegion *ar, + struct GPUViewport *viewport, + struct Object *object); void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear); void DRW_framebuffer_select_id_release(struct ARegion *ar); @@ -152,6 +155,9 @@ void DRW_opengl_context_destroy(void); void DRW_opengl_context_enable(void); void DRW_opengl_context_disable(void); +/* For garbage collection */ +void DRW_cache_free_old_batches(struct Main *bmain); + /* Never use this. Only for closing blender. */ void DRW_opengl_context_enable_ex(bool restore); void DRW_opengl_context_disable_ex(bool restore); diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 16788c10680..05ee485e053 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -169,8 +169,8 @@ static void basic_cache_populate(void *vedata, Object *ob) const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING)); /* Depth Prepass */ - DRW_shgroup_call_add( - (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat); + DRW_shgroup_call_object_add( + (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob); } } diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index e5d33daa0d0..b0013151a70 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -206,31 +206,32 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved if ((effects->enabled_effects & EFFECT_BLOOM) != 0) { /** Bloom algorithm * - * Overview : + * Overview: * - Downsample the color buffer doing a small blur during each step. * - Accumulate bloom color using previously downsampled color buffers * and do an upsample blur for each new accumulated layer. * - Finally add accumulation buffer onto the source color buffer. * * [1/1] is original copy resolution (can be half or quarter res for performance) + * <pre> + * [DOWNSAMPLE CHAIN] [UPSAMPLE CHAIN] * - * [DOWNSAMPLE CHAIN] [UPSAMPLE CHAIN] - * - * Source Color ── [Blit] ──> Bright Color Extract [1/1] Final Color - * | Λ - * [Downsample First] Source Color ─> + [Resolve] - * v | - * Color Downsampled [1/2] ────────────> + Accumulation Buffer [1/2] - * | Λ - * ─── ─── - * Repeat Repeat - * ─── ─── - * v | - * Color Downsampled [1/N-1] ──────────> + Accumulation Buffer [1/N-1] - * | Λ - * [Downsample] [Upsample] - * v | - * Color Downsampled [1/N] ─────────────────────────┘ + * Source Color ─ [Blit] ─> Bright Color Extract [1/1] Final Color + * | Λ + * [Downsample First] Source Color ─> + [Resolve] + * v | + * Color Downsampled [1/2] ────────────> + Accumulation Buffer [1/2] + * | Λ + * ─── ─── + * Repeat Repeat + * ─── ─── + * v | + * Color Downsampled [1/N-1] ──────────> + Accumulation Buffer [1/N-1] + * | Λ + * [Downsample] [Upsample] + * v | + * Color Downsampled [1/N] ─────────────────────────┘ + * </pre> */ DRWShadingGroup *grp; const bool use_highres = true; diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index 62ccf30e12c..8fb73bd605f 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -141,10 +141,12 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), float focus_dist = BKE_camera_object_dof_distance(camera); float focal_len = cam->lens; - /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though - * because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ + /* this is factor that converts to the scene scale. focal length and sensor are expressed in + * mm unit.scale_length is how many meters per blender unit we have. We want to convert to + * blender units though because the shader reads coordinates in world space, which is in + * blender units. + * Note however that focus_distance is already in blender units and shall not be scaled here + * (see T48157). */ float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; float scale_camera = 0.001f / scale; /* we want radius here for the aperture number */ @@ -239,6 +241,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ if (use_alpha) { DRW_shgroup_uniform_texture_ref(grp, "scatterAlphaBuffer", &effects->dof_blur_alpha); + DRW_shgroup_uniform_bool_copy(grp, "unpremult", DRW_state_is_image_render()); } } } diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index e77d7b16c78..a8b4159e030 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -168,6 +168,11 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, effects->enabled_effects |= EFFECT_NORMAL_BUFFER; } + /* Alpha checker if background is not drawn in viewport. */ + if (!DRW_state_is_image_render() && !DRW_state_draw_background()) { + effects->enabled_effects |= EFFECT_ALPHA_CHECKER; + } + /** * Ping Pong buffer */ @@ -361,6 +366,23 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); DRW_shgroup_call_add(grp, quad, NULL); } + + if ((effects->enabled_effects & EFFECT_ALPHA_CHECKER) != 0) { + psl->alpha_checker = DRW_pass_create("Alpha Checker", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL_UNDER); + + GPUShader *checker_sh = GPU_shader_get_builtin_shader(GPU_SHADER_2D_CHECKER); + + DRWShadingGroup *grp = DRW_shgroup_create(checker_sh, psl->alpha_checker); + + copy_v4_fl4(effects->color_checker_dark, 0.15f, 0.15f, 0.15f, 1.0f); + copy_v4_fl4(effects->color_checker_light, 0.2f, 0.2f, 0.2f, 1.0f); + + DRW_shgroup_uniform_vec4(grp, "color1", effects->color_checker_dark, 1); + DRW_shgroup_uniform_vec4(grp, "color2", effects->color_checker_light, 1); + DRW_shgroup_uniform_int_copy(grp, "size", 8); + DRW_shgroup_call_add(grp, quad, NULL); + } } #if 0 /* Not required for now */ @@ -413,7 +435,8 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l GPU_framebuffer_texture_detach(stl->g_data->minzbuffer); /* Create lower levels */ - GPU_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata); + GPU_framebuffer_recursive_downsample( + fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata); DRW_stats_group_end(); #endif int minmax_size[3], depth_size[3]; @@ -490,22 +513,50 @@ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, i DRW_stats_group_end(); } -void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_draw_alpha_checker(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_ALPHA_CHECKER) != 0) { + float mat[4][4]; + unit_m4(mat); + + /* Fragile, rely on the fact that GPU_SHADER_2D_CHECKER + * only use the persmat. */ + DRW_viewport_matrix_override_set(mat, DRW_MAT_PERS); + + DRW_draw_pass(psl->alpha_checker); + + DRW_viewport_matrix_override_unset(DRW_MAT_PERS); + } +} + +static void EEVEE_velocity_resolve(EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; - EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - /* First resolve the velocity. */ if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + e_data.depth_src = dtxl->depth; DRW_viewport_matrix_get(effects->velocity_curr_persinv, DRW_MAT_PERSINV); GPU_framebuffer_bind(fbl->velocity_resolve_fb); DRW_draw_pass(psl->velocity_resolve); } DRW_viewport_matrix_get(effects->velocity_past_persmat, DRW_MAT_PERS); +} + +void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; /* only once per frame after the first post process */ effects->swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0); @@ -517,6 +568,14 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) /* Post process stack (order matters) */ EEVEE_motion_blur_draw(vedata); EEVEE_depth_of_field_draw(vedata); + + /* NOTE: Lookdev drawing happens before TAA but after + * motion blur and dof to avoid distortions. + * Velocity resolve use a hack to exclude lookdev + * balls from creating shimering reprojection vectors. */ + EEVEE_lookdev_draw(vedata); + EEVEE_velocity_resolve(vedata); + EEVEE_temporal_sampling_draw(vedata); EEVEE_bloom_draw(vedata); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 6232640aac8..962bc8e5efb 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -301,16 +301,15 @@ static void eevee_draw_background(void *vedata) } } - /* LookDev */ - EEVEE_lookdev_draw_background(vedata); - /* END */ - /* Tonemapping and transfer result to default framebuffer. */ bool use_render_settings = stl->g_data->use_color_render_settings; GPU_framebuffer_bind(dfbl->default_fb); DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); + /* Draw checkerboard with alpha under. */ + EEVEE_draw_alpha_checker(vedata); + /* Debug : Output buffer to view. */ switch (G.debug_value) { case 1: diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 9ebd9542ef5..33cb2e87dc7 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -92,38 +92,64 @@ typedef struct EEVEE_LightBake { struct Main *bmain; EEVEE_ViewLayerData *sldata; - LightProbe **probe; /* Current probe being rendered. */ - GPUTexture *rt_color; /* Target cube color texture. */ - GPUTexture *rt_depth; /* Target cube depth texture. */ - GPUFrameBuffer *rt_fb[6]; /* Target cube framebuffers. */ - GPUFrameBuffer *store_fb; /* Storage framebuffer. */ - int rt_res; /* Cube render target resolution. */ + /** Current probe being rendered. */ + LightProbe **probe; + /** Target cube color texture. */ + GPUTexture *rt_color; + /** Target cube depth texture. */ + GPUTexture *rt_depth; + /** Target cube framebuffers. */ + GPUFrameBuffer *rt_fb[6]; + /** Storage framebuffer. */ + GPUFrameBuffer *store_fb; + /** Cube render target resolution. */ + int rt_res; /* Shared */ - int layer; /* Target layer to store the data to. */ - float samples_ct, invsamples_ct; /* Sample count for the convolution. */ - float lod_factor; /* Sampling bias during convolution step. */ - float lod_max; /* Max cubemap LOD to sample when convolving. */ - int cube_len, grid_len; /* Number of probes to render + world probe. */ + /** Target layer to store the data to. */ + int layer; + /** Sample count for the convolution. */ + float samples_ct, invsamples_ct; + /** Sampling bias during convolution step. */ + float lod_factor; + /** Max cubemap LOD to sample when convolving. */ + float lod_max; + /** Number of probes to render + world probe. */ + int cube_len, grid_len; /* Irradiance grid */ - EEVEE_LightGrid *grid; /* Current probe being rendered (UBO data). */ - int irr_cube_res; /* Target cubemap at MIP 0. */ - int irr_size[3]; /* Size of the irradiance texture. */ - int total_irr_samples; /* Total for all grids */ - int grid_sample; /* Nth sample of the current grid being rendered. */ - int grid_sample_len; /* Total number of samples for the current grid. */ - int grid_curr; /* Nth grid in the cache being rendered. */ - int bounce_curr, bounce_len; /* The current light bounce being evaluated. */ - float vis_res; /* Resolution of the Visibility shadowmap. */ - GPUTexture *grid_prev; /* Result of previous light bounce. */ - LightProbe **grid_prb; /* Pointer to the id.data of the probe object. */ + /** Current probe being rendered (UBO data). */ + EEVEE_LightGrid *grid; + /** Target cubemap at MIP 0. */ + int irr_cube_res; + /** Size of the irradiance texture. */ + int irr_size[3]; + /** Total for all grids */ + int total_irr_samples; + /** Nth sample of the current grid being rendered. */ + int grid_sample; + /** Total number of samples for the current grid. */ + int grid_sample_len; + /** Nth grid in the cache being rendered. */ + int grid_curr; + /** The current light bounce being evaluated. */ + int bounce_curr, bounce_len; + /** Resolution of the Visibility shadowmap. */ + float vis_res; + /** Result of previous light bounce. */ + GPUTexture *grid_prev; + /** Pointer to the id.data of the probe object. */ + LightProbe **grid_prb; /* Reflection probe */ - EEVEE_LightProbe *cube; /* Current probe being rendered (UBO data). */ - int ref_cube_res; /* Target cubemap at MIP 0. */ - int cube_offset; /* Index of the current cube. */ - LightProbe **cube_prb; /* Pointer to the id.data of the probe object. */ + /** Current probe being rendered (UBO data). */ + EEVEE_LightProbe *cube; + /** Target cubemap at MIP 0. */ + int ref_cube_res; + /** Index of the current cube. */ + int cube_offset; + /** Pointer to the id.data of the probe object. */ + LightProbe **cube_prb; /* Dummy Textures */ struct GPUTexture *dummy_color, *dummy_depth; @@ -133,15 +159,18 @@ typedef struct EEVEE_LightBake { short *stop, *do_update; float *progress; - bool resource_only; /* For only handling the resources. */ + /** For only handling the resources. */ + bool resource_only; bool own_resources; - bool - own_light_cache; /* If the lightcache was created for baking, it's first owned by the baker. */ - int delay; /* ms. delay the start of the baking to not slowdown interactions (TODO remove) */ - int frame; /* Scene frame to bake. */ - - void *gl_context, - *gpu_context; /* If running in parallel (in a separate thread), use this context. */ + /** If the lightcache was created for baking, it's first owned by the baker. */ + bool own_light_cache; + /** ms. delay the start of the baking to not slowdown interactions (TODO remove) */ + int delay; + /** Scene frame to bake. */ + int frame; + + /** If running in parallel (in a separate thread), use this context. */ + void *gl_context, *gpu_context; ThreadMutex *mutex; } EEVEE_LightBake; diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 550821ee92a..a4a17de7a57 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -145,7 +145,8 @@ static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref) width, height, max_ii(1, num_planar_ref), GPU_DEPTH_COMPONENT24, 0, NULL); } else if (num_planar_ref == 0) { - /* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still bound to shader. */ + /* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still + * bound to shader. */ txl->planar_pool = DRW_texture_create_2d_array( 1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL); txl->planar_depth = DRW_texture_create_2d_array(1, 1, 1, GPU_DEPTH_COMPONENT24, 0, NULL); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index b118d7be3d0..270defb039b 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -680,7 +680,8 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */ 80.0f; /* XXX : Empirical, Fit cycles power */ if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { - /* Scale power to account for the lower area of the ellipse compared to the surrounding rectangle. */ + /* Scale power to account for the lower area of the ellipse compared to the surrounding + * rectangle. */ power *= 4.0f / M_PI; } } @@ -693,8 +694,9 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) } else { power = 1.0f / (evli->radius * evli->radius * M_PI); /* 1/(r²*Pi) */ - /* Make illumation power closer to cycles for bigger radii. Cycles uses a cos^3 term that we cannot reproduce - * so we account for that by scaling the light power. This function is the result of a rough manual fitting. */ + /* Make illumation power closer to cycles for bigger radii. Cycles uses a cos^3 term that we + * cannot reproduce so we account for that by scaling the light power. This function is the + * result of a rough manual fitting. */ power += 1.0f / (2.0f * M_PI); /* power *= 1 + r²/2 */ } return power; @@ -952,7 +954,7 @@ static void frustum_min_bounding_sphere(const float corners[8][3], } /* TODO try to reduce the radius further by moving the center. - * Remember we need a __stable__ solution! */ + * Remember we need a __stable__ solution! */ /* Try to reduce float imprecision leading to shimmering. */ *r_radius = (float)round_to_digits(sqrtf(*r_radius), 3); @@ -1383,7 +1385,8 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_draw_pass(psl->shadow_pass); } - /* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */ + /* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. + */ float filter_texture_size = la->soft * 0.001f; float filter_pixel_size = ceil(filter_texture_size / srd->cube_texel_size); linfo->filter_size = srd->cube_texel_size * ((filter_pixel_size > 1.0f) ? 1.5f : 0.0f); diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index b000eebb92e..4be87bf1a5e 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -24,6 +24,9 @@ #include "BKE_camera.h" #include "BKE_studiolight.h" +#include "BLI_rect.h" +#include "BLI_rand.h" + #include "DNA_screen_types.h" #include "DNA_world_types.h" @@ -62,11 +65,30 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, { EEVEE_StorageList *stl = vedata->stl; EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); View3D *v3d = draw_ctx->v3d; Scene *scene = draw_ctx->scene; + if (LOOK_DEV_OVERLAY_ENABLED(v3d)) { + /* Viewport / Ball size. */ + rcti rect; + ED_region_visible_rect(draw_ctx->ar, &rect); + + const int ball_size = max_ii(BLI_rcti_size_x(&rect) * 0.1f, 100.0f) * U.dpi_fac; + + if (ball_size != effects->ball_size || rect.xmax != effects->anchor[0] || + rect.ymin != effects->anchor[1]) { + /* If ball size or anchor point moves, reset TAA to avoid ghosting issue. + * This needs to happen early because we are changing taa_current_sample. */ + effects->ball_size = ball_size; + effects->anchor[0] = rect.xmax; + effects->anchor[1] = rect.ymin; + EEVEE_temporal_sampling_reset(vedata); + } + } + if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) { StudioLight *sl = BKE_studiolight_find(v3d->shading.lookdev_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE); @@ -157,56 +179,35 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, } } -void EEVEE_lookdev_draw_background(EEVEE_Data *vedata) +static void eevee_lookdev_apply_taa(const EEVEE_EffectsInfo *effects, + int ball_size, + float winmat[4][4]) +{ + if (DRW_state_is_image_render() || ((effects->enabled_effects & EFFECT_TAA) != 0)) { + double ht_point[2]; + double ht_offset[2] = {0.0, 0.0}; + uint ht_primes[2] = {2, 3}; + float ofs[2]; + + BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample, ht_point); + EEVEE_temporal_sampling_offset_calc(ht_point, 1.5f, ofs); + winmat[3][0] += ofs[0] / ball_size; + winmat[3][1] += ofs[1] / ball_size; + } +} + +void EEVEE_lookdev_draw(EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; EEVEE_EffectsInfo *effects = stl->effects; EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); const DRWContextState *draw_ctx = DRW_context_state_get(); - if (psl->lookdev_pass && LOOK_DEV_OVERLAY_ENABLED(draw_ctx->v3d)) { - DRW_stats_group_start("Look Dev"); - CameraParams params; - BKE_camera_params_init(¶ms); - View3D *v3d = draw_ctx->v3d; - RegionView3D *rv3d = draw_ctx->rv3d; - ARegion *ar = draw_ctx->ar; - - const float *viewport_size = DRW_viewport_size_get(); - rcti rect; - ED_region_visible_rect(draw_ctx->ar, &rect); - - const float viewport_size_target[2] = { - viewport_size[0] / 4, - viewport_size[1] / 4, - }; - const int viewport_inset[2] = { - max_ii(viewport_size_target[0], 300), - max_ii(viewport_size_target[0], 300) / 2, /* intentionally use 'x' here for 'y' value. */ - }; - - /* minimum size for preview spheres viewport */ - const float aspect[2] = { - viewport_inset[0] / viewport_size_target[0], - viewport_inset[1] / viewport_size_target[1], - }; - - BKE_camera_params_from_view3d(¶ms, draw_ctx->depsgraph, v3d, rv3d); - params.is_ortho = true; - params.ortho_scale = 3.0f; - params.zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; - params.offsetx = 0.0f; - params.offsety = 0.0f; - params.shiftx = 0.0f; - params.shifty = 0.0f; - params.clip_start = 0.001f; - params.clip_end = 20.0f; - BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, aspect[0], aspect[1]); - BKE_camera_params_compute_matrix(¶ms); - + if (psl->lookdev_diffuse_pass && LOOK_DEV_OVERLAY_ENABLED(draw_ctx->v3d)) { + /* Config renderer. */ EEVEE_CommonUniformBuffer *common = &sldata->common_data; common->la_num_light = 0; common->prb_num_planar = 0; @@ -218,34 +219,53 @@ void EEVEE_lookdev_draw_background(EEVEE_Data *vedata) DRW_uniformbuffer_update(sldata->common_ubo, common); /* override matrices */ - float winmat[4][4]; - float winmat_inv[4][4]; - copy_m4_m4(winmat, params.winmat); - invert_m4_m4(winmat_inv, winmat); - DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(winmat_inv, DRW_MAT_WININV); - float viewmat[4][4]; - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); - float persmat[4][4]; - float persmat_inv[4][4]; - mul_m4_m4m4(persmat, winmat, viewmat); - invert_m4_m4(persmat_inv, persmat); - DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(persmat_inv, DRW_MAT_PERSINV); - - GPUFrameBuffer *fb = effects->final_fb; - GPU_framebuffer_bind(fb); - GPU_framebuffer_viewport_set( - fb, rect.xmax - viewport_inset[0], rect.ymin, viewport_inset[0], viewport_inset[1]); - DRW_draw_pass(psl->lookdev_pass); + DRWMatrixState matstate; + unit_m4(matstate.winmat); + + eevee_lookdev_apply_taa(effects, effects->ball_size, matstate.winmat); + + /* "Remove" view matrix location. Leaving only rotation. */ + DRW_viewport_matrix_get(matstate.viewmat, DRW_MAT_VIEW); + zero_v3(matstate.viewmat[3]); + mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat); + invert_m4_m4(matstate.wininv, matstate.winmat); + invert_m4_m4(matstate.viewinv, matstate.viewmat); + invert_m4_m4(matstate.persinv, matstate.persmat); + + DRW_viewport_matrix_override_set_all(&matstate); + + /* Find the right framebuffers to render to. */ + GPUFrameBuffer *fb = (effects->target_buffer == fbl->effect_color_fb) ? fbl->main_fb : + fbl->effect_fb; + + DRW_stats_group_start("Look Dev"); - fb = dfbl->depth_only_fb; GPU_framebuffer_bind(fb); - GPU_framebuffer_viewport_set( - fb, rect.xmax - viewport_inset[0], rect.ymin, viewport_inset[0], viewport_inset[1]); - DRW_draw_pass(psl->lookdev_pass); - DRW_viewport_matrix_override_unset_all(); + const int ball_margin = effects->ball_size / 6.0f; + float offset[2] = {0.0f, ball_margin}; + + offset[0] = effects->ball_size + ball_margin; + GPU_framebuffer_viewport_set(fb, + effects->anchor[0] - offset[0], + effects->anchor[1] + offset[1], + effects->ball_size, + effects->ball_size); + + DRW_draw_pass(psl->lookdev_diffuse_pass); + + offset[0] = (effects->ball_size + ball_margin) + + (ball_margin + effects->ball_size + ball_margin); + GPU_framebuffer_viewport_set(fb, + effects->anchor[0] - offset[0], + effects->anchor[1] + offset[1], + effects->ball_size, + effects->ball_size); + + DRW_draw_pass(psl->lookdev_glossy_pass); + DRW_stats_group_end(); + + DRW_viewport_matrix_override_unset_all(); } } diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 9268f2e8a46..456f4bdb5f1 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -115,15 +115,15 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) static float samples_len = 8192.0f; static float inv_samples_len = 1.0f / 8192.0f; - char *lib_str = BLI_string_joinN( - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl); + char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl); - struct GPUShader *sh = DRW_shader_create_with_lib( - datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str, - "#define HAMMERSLEY_SIZE 8192\n" - "#define BRDF_LUT_SIZE 64\n" - "#define NOISE_SIZE 64\n"); + struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl, + datatoc_lightprobe_geom_glsl, + datatoc_bsdf_lut_frag_glsl, + lib_str, + "#define HAMMERSLEY_SIZE 8192\n" + "#define BRDF_LUT_SIZE 64\n" + "#define NOISE_SIZE 64\n"); DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); @@ -150,11 +150,14 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data); printf("{"); - for (int i = 0; i < w*h * 3; i+=3) { - printf("%ff, %ff, ", data[i], data[i+1]); i+=3; - printf("%ff, %ff, ", data[i], data[i+1]); i+=3; - printf("%ff, %ff, ", data[i], data[i+1]); i+=3; - printf("%ff, %ff, \n", data[i], data[i+1]); + for (int i = 0; i < w * h * 3; i += 3) { + printf("%ff, %ff, ", data[i], data[i + 1]); + i += 3; + printf("%ff, %ff, ", data[i], data[i + 1]); + i += 3; + printf("%ff, %ff, ", data[i], data[i + 1]); + i += 3; + printf("%ff, %ff, \n", data[i], data[i + 1]); } printf("}"); @@ -174,15 +177,13 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) static float inv_samples_len = 1.0f / 8192.0f; char *frag_str = BLI_string_joinN( - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_btdf_lut_frag_glsl); + datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl); struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str, - "#define HAMMERSLEY_SIZE 8192\n" - "#define BRDF_LUT_SIZE 64\n" - "#define NOISE_SIZE 64\n" - "#define LUT_SIZE 64\n"); + "#define HAMMERSLEY_SIZE 8192\n" + "#define BRDF_LUT_SIZE 64\n" + "#define NOISE_SIZE 64\n" + "#define LUT_SIZE 64\n"); MEM_freeN(frag_str); @@ -222,20 +223,28 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) # if 1 fprintf(f, "\t{\n\t\t"); - for (int i = 0; i < w*h * 3; i+=3) { + for (int i = 0; i < w * h * 3; i += 3) { fprintf(f, "%ff,", data[i]); - if (((i/3)+1) % 12 == 0) fprintf(f, "\n\t\t"); - else fprintf(f, " "); + if (((i / 3) + 1) % 12 == 0) + fprintf(f, "\n\t\t"); + else + fprintf(f, " "); } fprintf(f, "\n\t},\n"); # else - for (int i = 0; i < w*h * 3; i+=3) { - if (data[i] < 0.01) printf(" "); - else if (data[i] < 0.3) printf("."); - else if (data[i] < 0.6) printf("+"); - else if (data[i] < 0.9) printf("%%"); - else printf("#"); - if ((i/3+1) % 64 == 0) printf("\n"); + for (int i = 0; i < w * h * 3; i += 3) { + if (data[i] < 0.01) + printf(" "); + else if (data[i] < 0.3) + printf("."); + else if (data[i] < 0.6) + printf("+"); + else if (data[i] < 0.9) + printf("%%"); + else + printf("#"); + if ((i / 3 + 1) % 64 == 0) + printf("\n"); } # endif @@ -327,7 +336,10 @@ static char *eevee_get_defines(int options) BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n"); } if ((options & VAR_MAT_LOOKDEV) != 0) { + /* Auto config shadow method. Avoid more permutation. */ + BLI_assert((options & (VAR_MAT_VSM | VAR_MAT_ESM)) == 0); BLI_dynstr_append(ds, "#define LOOKDEV\n"); + BLI_dynstr_append(ds, "#define SHADOW_ESM\n"); } str = BLI_dynstr_get_cstring(ds); @@ -457,7 +469,7 @@ static void eevee_init_util_texture(void) texels_layer += 64 * 64; /* Copy bsdf_split_sum_ggx into 2nd layer red and green channels. - Copy ltc_mag_ggx into 2nd layer blue and alpha channel. */ + * Copy ltc_mag_ggx into 2nd layer blue and alpha channel. */ for (int i = 0; i < 64 * 64; i++) { texels_layer[i][0] = bsdf_split_sum_ggx[i * 2 + 0]; texels_layer[i][1] = bsdf_split_sum_ggx[i * 2 + 1]; @@ -582,6 +594,7 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, datatoc_lit_surface_frag_glsl, datatoc_lit_surface_frag_glsl, datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, datatoc_volumetric_lib_glsl); e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, @@ -985,42 +998,11 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa } } -/** - * Create a default shading group inside the lookdev pass without standard uniforms. - */ -static struct DRWShadingGroup *EEVEE_lookdev_shading_group_get(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - bool use_ssr, - int shadow_method) -{ - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; - - options |= eevee_material_shadow_option(shadow_method); - - if (e_data.default_lit[options] == NULL) { - create_default_shader(options); - } - - if (vedata->psl->lookdev_pass == NULL) { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | - DRW_STATE_CULL_BACK; - vedata->psl->lookdev_pass = DRW_pass_create("LookDev Pass", state); - - DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], - vedata->psl->lookdev_pass); - /* XXX / WATCH: This creates non persistent binds for the ubos and textures. - * But it's currently OK because the following shgroups does not add any bind. */ - add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false); - } - - return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); -} void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); /* Create Material Ghash */ { @@ -1034,16 +1016,13 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = NULL; - const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; World *wo = scene->world; const float *col = G_draw.block.colorBackground; - /* LookDev */ EEVEE_lookdev_cache_init( vedata, &grp, psl->background_pass, stl->g_data->background_alpha, wo, NULL); - /* END */ if (!grp && wo) { col = &wo->horr; @@ -1174,6 +1153,39 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } + + if (LOOK_DEV_OVERLAY_ENABLED(draw_ctx->v3d)) { + DRWShadingGroup *shgrp; + + struct GPUBatch *sphere = DRW_cache_sphere_get(); + static float color_chrome[3] = {1.0f, 1.0f, 1.0f}; + static float color_diffuse[3] = {0.8f, 0.8f, 0.8f}; + int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | + DRW_STATE_CULL_BACK; + + psl->lookdev_diffuse_pass = DRW_pass_create("LookDev Diffuse Pass", state); + shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass); + add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, true, true, false, false, false); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1); + DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f); + DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f); + DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f); + DRW_shgroup_call_add(shgrp, sphere, NULL); + + psl->lookdev_glossy_pass = DRW_pass_create("LookDev Glossy Pass", state); + shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass); + add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, true, true, false, false, false); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1); + DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f); + DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f); + DRW_shgroup_call_add(shgrp, sphere, NULL); + } } #define ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata) \ @@ -1399,9 +1411,9 @@ static void material_opaque(Material *ma, } else { if (use_translucency) { - /* NOTE: This is a nasty workaround, because the sss profile might not have been generated - * but the UBO is still declared in this case even if not used. But rendering without a - * bound UBO might result in crashes on certain platform. */ + /* NOTE: This is a nasty workaround, because the sss profile might not have been + * generated but the UBO is still declared in this case even if not used. + * But rendering without a bound UBO might result in crashes on certain platform. */ DRW_shgroup_uniform_block(*shgrp, "sssProfile", e_data.dummy_sss_profile); } } @@ -1605,12 +1617,10 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING)); - 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 is_sculpt_mode = (ob->sculpt != NULL); /* For now just force fully shaded with eevee when supported. */ - const bool is_sculpt_mode_draw = is_sculpt_mode && - ((ob->sculpt && ob->sculpt->pbvh) && - (BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES)); + const bool is_sculpt_mode_draw = ob->sculpt && ob->sculpt->pbvh && + BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES; const bool is_default_mode_shader = is_sculpt_mode; /* First get materials for this mesh. */ @@ -1871,6 +1881,13 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat); + if (!use_diffuse && !use_glossy && !use_refract) { + /* FIXME: Small hack to avoid issue when utilTex is needed for + * world_normals_get and none of the bsdfs that need it are present. + * This can try to bind utilTex even if not needed. */ + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + } + add_standard_uniforms(shgrp, sldata, vedata, @@ -1918,46 +1935,6 @@ void EEVEE_materials_cache_finish(EEVEE_Data *vedata) { EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; - /* Look-Dev */ - const DRWContextState *draw_ctx = DRW_context_state_get(); - const View3D *v3d = draw_ctx->v3d; - if (LOOK_DEV_OVERLAY_ENABLED(v3d)) { - EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); - EEVEE_LightsInfo *linfo = sldata->lights; - struct GPUBatch *sphere = DRW_cache_sphere_get(); - static float mat1[4][4]; - static float color[3] = {0.8f, 0.8f, 0.8f}; - static float metallic_on = 1.0f; - static float metallic_off = 0.00f; - static float specular_off = 0.5f; - static float specular_on = 1.0f; - static float roughness_off = 0.05f; - static float roughness_on = 1.00f; - - float view_mat[4][4]; - DRW_viewport_matrix_get(view_mat, DRW_MAT_VIEWINV); - - DRWShadingGroup *shgrp = EEVEE_lookdev_shading_group_get( - sldata, vedata, false, linfo->shadow_method); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_on, 1); - DRW_shgroup_uniform_float(shgrp, "specular", &specular_on, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_off, 1); - unit_m4(mat1); - mul_m4_m4m4(mat1, mat1, view_mat); - translate_m4(mat1, -1.5f, 0.0f, -5.0f); - DRW_shgroup_call_add(shgrp, sphere, mat1); - - shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_off, 1); - DRW_shgroup_uniform_float(shgrp, "specular", &specular_off, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_on, 1); - translate_m4(mat1, 3.0f, 0.0f, 0.0f); - DRW_shgroup_call_add(shgrp, sphere, mat1); - } - /* END */ - BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN); } diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index f2863d572c4..f8795a7ff0e 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -165,11 +165,7 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda #if 0 /* for future high quality blur */ /* Future matrix */ eevee_motion_blur_camera_get_matrix_at_time( - scene, - ar, rv3d, v3d, - ob_camera_eval, - ctime + delta, - effects->future_world_to_ndc); + scene, ar, rv3d, v3d, ob_camera_eval, ctime + delta, effects->future_world_to_ndc); #endif invert_m4_m4(effects->current_ndc_to_world, effects->current_world_to_ndc); } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 8e21c7f389c..c3cd25923b2 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -246,6 +246,7 @@ typedef struct EEVEE_PassList { struct DRWPass *color_downsample_cube_ps; struct DRWPass *velocity_resolve; struct DRWPass *taa_resolve; + struct DRWPass *alpha_checker; /* HiZ */ struct DRWPass *minz_downlevel_ps; @@ -275,7 +276,8 @@ typedef struct EEVEE_PassList { struct DRWPass *transparent_pass; struct DRWPass *background_pass; struct DRWPass *update_noise_pass; - struct DRWPass *lookdev_pass; + struct DRWPass *lookdev_glossy_pass; + struct DRWPass *lookdev_diffuse_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -537,6 +539,7 @@ typedef enum EEVEE_EffectsFlag { EFFECT_VELOCITY_BUFFER = (1 << 12), /* Not really an effect but a feature */ EFFECT_TAA_REPROJECT = (1 << 13), /* should be mutually exclusive with EFFECT_TAA */ EFFECT_DEPTH_DOUBLE_BUFFER = (1 << 14), /* Not really an effect but a feature */ + EFFECT_ALPHA_CHECKER = (1 << 15), /* Not really an effect but a feature */ } EEVEE_EffectsFlag; typedef struct EEVEE_EffectsInfo { @@ -598,8 +601,14 @@ typedef struct EEVEE_EffectsInfo { struct GPUTexture *dof_coc; struct GPUTexture *dof_blur; struct GPUTexture *dof_blur_alpha; + /* Alpha Checker */ + float color_checker_dark[4]; + float color_checker_light[4]; /* Other */ float prev_persmat[4][4]; + /* Lookdev */ + int ball_size; + int anchor[2]; /* Bloom */ int bloom_iteration_len; float source_texel_size[2]; @@ -1044,6 +1053,9 @@ void EEVEE_mist_free(void); /* eevee_temporal_sampling.c */ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata); int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_temporal_sampling_offset_calc(const double ht_point[2], + const float filter_size, + float r_offset[2]); void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], @@ -1073,6 +1085,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level); void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level); +void EEVEE_draw_alpha_checker(EEVEE_Data *vedata); void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_free(void); @@ -1099,7 +1112,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, float background_alpha, struct World *world, EEVEE_LightProbesInfo *pinfo); -void EEVEE_lookdev_draw_background(EEVEE_Data *vedata); +void EEVEE_lookdev_draw(EEVEE_Data *vedata); /** eevee_engine.c */ void EEVEE_cache_populate(void *vedata, Object *ob); diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index a3603fc3d64..22c7dd00b97 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -296,8 +296,9 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v /* Resolve at fullres */ int sample = (DRW_state_is_image_render()) ? effects->taa_render_sample : effects->taa_current_sample; - /* Doing a neighbor shift only after a few iteration. We wait for a prime number of cycles to avoid - * noise correlation. This reduces variance faster. */ + /* Doing a neighbor shift only after a few iteration. + * We wait for a prime number of cycles to avoid noise correlation. + * This reduces variance faster. */ effects->ssr_neighbor_ofs = ((sample / 5) % 8) * 4; switch ((sample / 11) % 4) { case 0: diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 54ceb1a167a..194fff9b93c 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -131,6 +131,14 @@ static void eevee_create_cdf_table_temporal_sampling(void) e_data.inited = true; } +void EEVEE_temporal_sampling_offset_calc(const double ht_point[2], + const float filter_size, + float r_offset[2]) +{ + r_offset[0] = eval_table(e_data.inverted_cdf, (float)(ht_point[0])) * filter_size; + r_offset[1] = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size; +} + void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], @@ -141,13 +149,11 @@ void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, Scene *scene = draw_ctx->scene; RenderData *rd = &scene->r; - float filter_size = rd->gauss; /* Sigh.. Stupid legacy naming. */ - - float ofs_x = eval_table(e_data.inverted_cdf, (float)(ht_point[0])) * filter_size; - float ofs_y = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size; + float ofs[2]; + EEVEE_temporal_sampling_offset_calc(ht_point, rd->gauss, ofs); window_translate_m4( - effects->overide_winmat, persmat, ofs_x / viewport_size[0], ofs_y / viewport_size[1]); + effects->overide_winmat, persmat, ofs[0] / viewport_size[0], ofs[1] / viewport_size[1]); mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat); invert_m4_m4(effects->overide_persinv, effects->overide_persmat); @@ -157,6 +163,7 @@ void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata) { vedata->stl->effects->taa_render_sample = 1; + vedata->stl->effects->taa_current_sample = 1; } int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl index f23303c5b93..32076b47d8c 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -1,7 +1,8 @@ /* Based on Practical Realtime Strategies for Accurate Indirect Occlusion * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf - * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx + */ #if defined(MESH_SHADER) # if !defined(USE_ALPHA_HASH) diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index fdaec58977f..3a5f20b952e 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -319,7 +319,8 @@ float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) { - /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ + /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ + */ vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; vec3 furthestplane = max(firstplane, secondplane); @@ -837,9 +838,16 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) # ifdef USE_SSS cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac); cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a; + # ifdef USE_SSS_ALBEDO /* TODO Find a solution to this. Dither? */ cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo; + /* Add radiance that was supposed to be filtered but was rejected. */ + cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb * cl2.sss_albedo : + cl1.sss_data.rgb * cl1.sss_albedo; +# else + /* Add radiance that was supposed to be filtered but was rejected. */ + cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb : cl1.sss_data.rgb; # endif # endif @@ -870,8 +878,10 @@ Closure closure_emission(vec3 rgb) return cl; } -# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && \ - !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY) +/* Breaking this across multiple lines causes issues for some older GLSL compilers. */ +/* clang-format off */ +# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY) +/* clang-format on */ layout(location = 0) out vec4 fragColor; layout(location = 1) out vec4 ssrNormals; layout(location = 2) out vec4 ssrData; @@ -918,10 +928,19 @@ void main() /* For Probe capture */ # ifdef USE_SSS + float fac = float(!sssToggle); + +# ifdef USE_REFRACTION + /* SSRefraction pass is done after the SSS pass. + * In order to not loose the diffuse light totally we + * need to merge the SSS radiance to the main radiance. */ + fac = 1.0; +# endif + # ifdef USE_SSS_ALBEDO - fragColor.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * float(!sssToggle); + fragColor.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * fac; # else - fragColor.rgb += cl.sss_data.rgb * float(!sssToggle); + fragColor.rgb += cl.sss_data.rgb * fac; # endif # endif } diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl index 8a10962c6ef..d8cec17af58 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl @@ -5,6 +5,7 @@ uniform sampler2D colorBuffer; uniform sampler2D depthBuffer; uniform vec2 dofParams; +uniform bool unpremult; #define dof_mul dofParams.x /* distance * aperturesize * invsensorsize */ #define dof_bias dofParams.y /* aperturesize * invsensorsize */ @@ -241,8 +242,12 @@ void main(void) fragColor = (far_col + near_col + focus_col) * inv_weight_sum; # ifdef USE_ALPHA_DOF - /* Unpremult */ - fragColor.rgb /= (fragColor.a > 0.0) ? fragColor.a : 1.0; + /* Sigh... viewport expect premult output but + * the final render output needs to be with + * associated alpha. */ + if (unpremult) { + fragColor.rgb /= (fragColor.a > 0.0) ? fragColor.a : 1.0; + } # endif } diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl index 3ec695fcdbc..ac6751fb5fb 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl @@ -14,7 +14,8 @@ vec4 safe_color(vec4 c) /** * Adapted from https://casual-effects.com/g3d/G3D10/data-files/shader/Film/Film_temporalAA.pix - * which is adapted from https://github.com/gokselgoktas/temporal-anti-aliasing/blob/master/Assets/Resources/Shaders/TemporalAntiAliasing.cginc + * which is adapted from + * https://github.com/gokselgoktas/temporal-anti-aliasing/blob/master/Assets/Resources/Shaders/TemporalAntiAliasing.cginc * which is adapted from https://github.com/playdeadgames/temporal * Optimization by Stubbesaurus and epsilon adjustment to avoid division by zero. * @@ -38,7 +39,6 @@ vec3 clip_to_aabb(vec3 color, vec3 minimum, vec3 maximum, vec3 average) void main() { ivec2 texel = ivec2(gl_FragCoord.xy); - float depth = texelFetch(depthBuffer, texel, 0).r; vec2 motion = texelFetch(velocityBuffer, texel, 0).rg; /* Decode from unsigned normalized 16bit texture. */ @@ -95,6 +95,9 @@ void main() color_history = (out_of_view) ? color : color_history; FragColor = safe_color(color_history); + /* There is some ghost issue if we use the alpha + * in the viewport. Overwritting alpha fixes it. */ + FragColor.a = color.a; } #else diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl index b9e038ceeaf..7d701bce5cb 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl @@ -17,6 +17,9 @@ void main() outData = uv - uv_history; + /* HACK: Reject lookdev spheres from TAA reprojection. */ + outData = (depth > 0.0) ? outData : vec2(0.0); + /* Encode to unsigned normalized 16bit texture. */ outData = outData * 0.5 + 0.5; } diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index 0c7be71d914..a70ac686efd 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -161,7 +161,8 @@ vec3 probe_evaluate_cube(int pd_id, vec3 W, vec3 R, float roughness) /* From Frostbite PBR Course * Distance based roughness - * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */ + * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf + */ float original_roughness = roughness; float linear_roughness = sqrt(roughness); float distance_roughness = saturate(dist * linear_roughness / length(intersection)); diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index 7dba3738c12..37b0ebb33cf 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -44,6 +44,14 @@ uniform int hairThicknessRes = 1; #define CLOSURE_GLOSSY #endif /* SURFACE_DEFAULT */ +#if !defined(SURFACE_DEFAULT_CLEARCOAT) && !defined(CLOSURE_NAME) +#define SURFACE_DEFAULT_CLEARCOAT +#define CLOSURE_NAME eevee_closure_default_clearcoat +#define CLOSURE_DIFFUSE +#define CLOSURE_GLOSSY +#define CLOSURE_CLEARCOAT +#endif /* SURFACE_DEFAULT_CLEARCOAT */ + #if !defined(SURFACE_PRINCIPLED) && !defined(CLOSURE_NAME) #define SURFACE_PRINCIPLED #define CLOSURE_NAME eevee_closure_principled @@ -274,7 +282,8 @@ void CLOSURE_NAME(vec3 N /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */ /* ---------------------------------------------------------------- */ - /* Accumulate incoming light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ + /* Accumulate incoming light from all sources until accumulator is full. Then apply Occlusion and + * BRDF. */ #ifdef CLOSURE_GLOSSY vec4 spec_accum = vec4(0.0); #endif diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl index 88dd9f46b55..2cf8501de9b 100644 --- a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl @@ -164,8 +164,8 @@ void ltc_transform_quad(vec3 N, vec3 V, mat3 Minv, inout vec3 corners[4]) corners[3] = normalize(Minv * corners[3]); } -/* If corners have already pass through ltc_transform_quad(), then N **MUST** be vec3(0.0, 0.0, 1.0), - * corresponding to the Up axis of the shading basis. */ +/* If corners have already pass through ltc_transform_quad(), + * then N **MUST** be vec3(0.0, 0.0, 1.0), corresponding to the Up axis of the shading basis. */ float ltc_evaluate_quad(vec3 corners[4], vec3 N) { /* Approximation using a sphere of the same solid angle than the quad. diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index 49c4569f585..82581f2327b 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -84,8 +84,8 @@ void prepare_raycast(vec3 ray_origin, ss_end.w = project_point(ProjectionMatrix, ray_end).z; /* XXX This is a hack a better method is welcome ! */ - /* We take the delta between the offseted depth and the depth and substract it from the ray depth. - * This will change the world space thickness appearance a bit but we can have negative + /* We take the delta between the offseted depth and the depth and substract it from the ray + * depth. This will change the world space thickness appearance a bit but we can have negative * values without worries. We cannot do this in viewspace because of the perspective division. */ ss_start.w = 2.0 * ss_start.z - ss_start.w; ss_end.w = 2.0 * ss_end.z - ss_end.w; diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl index 5c0f5adda27..f24032c4360 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl @@ -36,7 +36,8 @@ vec3 octahedral_to_cubemap_proj(vec2 co) } /* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */ -/* http://advances.realtimerendering.com/s2009/SIGGRAPH%202009%20-%20Lighting%20Research%20at%20Bungie.pdf Slide 55*/ +/* http://advances.realtimerendering.com/s2009/SIGGRAPH%202009%20-%20Lighting%20Research%20at%20Bungie.pdf + * Slide 55. */ #define ln_space_prefilter_step(ref, sample) exp(sample - ref) #define ln_space_prefilter_finalize(ref, sum) (ref + log(shadowInvSampleCount * sum)) diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 29749ce6712..ed8c609c01f 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -54,12 +54,12 @@ typedef struct EXTERNAL_StorageList { } EXTERNAL_StorageList; typedef struct EXTERNAL_FramebufferList { - struct GPUFrameBuffer *default_fb; + struct GPUFrameBuffer *depth_buffer_fb; } EXTERNAL_FramebufferList; typedef struct EXTERNAL_TextureList { /* default */ - struct GPUTexture *depth; + struct GPUTexture *depth_buffer_tx; } EXTERNAL_TextureList; typedef struct EXTERNAL_PassList { @@ -80,30 +80,77 @@ typedef struct EXTERNAL_Data { static struct { /* Depth Pre Pass */ struct GPUShader *depth_sh; + bool draw_depth; } e_data = {NULL}; /* Engine data */ typedef struct EXTERNAL_PrivateData { DRWShadingGroup *depth_shgrp; + + /* Do we need to update the depth or can we reuse the last calculated texture. */ + bool update_depth; + bool view_updated; + + float last_mat[4][4]; + float curr_mat[4][4]; } EXTERNAL_PrivateData; /* Transient data */ /* Functions */ -static void external_engine_init(void *UNUSED(vedata)) +static void external_engine_init(void *vedata) { + EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + /* Depth prepass */ if (!e_data.depth_sh) { e_data.depth_sh = DRW_shader_create_3d_depth_only(GPU_SHADER_CFG_DEFAULT); } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + stl->g_data->update_depth = true; + stl->g_data->view_updated = false; + } + + if (stl->g_data->update_depth == false) { + if (rv3d && rv3d->rflag & RV3D_NAVIGATING) { + stl->g_data->update_depth = true; + } + } + + if (stl->g_data->view_updated) { + stl->g_data->update_depth = true; + stl->g_data->view_updated = false; + } + + { + float view[4][4]; + float win[4][4]; + DRW_viewport_matrix_get(view, DRW_MAT_VIEW); + DRW_viewport_matrix_get(win, DRW_MAT_WIN); + mul_m4_m4m4(stl->g_data->curr_mat, view, win); + if (!equals_m4m4(stl->g_data->curr_mat, stl->g_data->last_mat)) { + stl->g_data->update_depth = true; + } + } } static void external_cache_init(void *vedata) { EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + EXTERNAL_TextureList *txl = ((EXTERNAL_Data *)vedata)->txl; + EXTERNAL_FramebufferList *fbl = ((EXTERNAL_Data *)vedata)->fbl; - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + { + DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0); + + GPU_framebuffer_ensure_config(&fbl->depth_buffer_fb, + { + GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_tx), + }); } /* Depth Pass */ @@ -112,6 +159,16 @@ static void external_cache_init(void *vedata) DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); } + + /* Do not draw depth pass when overlays are turned off. */ + e_data.draw_depth = false; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + if (v3d->flag2 & V3D_HIDE_OVERLAYS) { + /* mark `update_depth` for when overlays are turned on again. */ + stl->g_data->update_depth = true; + return; + } } static void external_cache_populate(void *vedata, Object *ob) @@ -122,10 +179,20 @@ static void external_cache_populate(void *vedata, Object *ob) return; } - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - /* Depth Prepass */ - DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat); + /* Do not draw depth pass when overlays are turned off. */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + if (v3d->flag2 & V3D_HIDE_OVERLAYS) { + return; + } + + if (stl->g_data->update_depth) { + e_data.draw_depth = true; + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + /* Depth Prepass */ + DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat); + } } } @@ -181,7 +248,10 @@ static void external_draw_scene_do(void *vedata) static void external_draw_scene(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); + EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; + EXTERNAL_FramebufferList *fbl = ((EXTERNAL_Data *)vedata)->fbl; + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); /* Will be NULL during OpenGL render. * OpenGL render is used for quick preview (thumbnails or sequencer preview) @@ -189,7 +259,28 @@ static void external_draw_scene(void *vedata) if (draw_ctx->evil_C) { external_draw_scene_do(vedata); } - DRW_draw_pass(psl->depth_pass); + + if (e_data.draw_depth) { + DRW_draw_pass(psl->depth_pass); + // copy result to tmp buffer + GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->depth_buffer_fb, 0, GPU_DEPTH_BIT); + stl->g_data->update_depth = false; + } + else { + // copy tmp buffer to default + GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT); + } + + copy_m4_m4(stl->g_data->last_mat, stl->g_data->curr_mat); +} + +static void external_view_update(void *vedata) +{ + EXTERNAL_Data *data = vedata; + EXTERNAL_StorageList *stl = data->stl; + if (stl && stl->g_data) { + stl->g_data->view_updated = true; + } } static void external_engine_free(void) @@ -211,12 +302,13 @@ static DrawEngineType draw_engine_external_type = { &external_cache_finish, NULL, &external_draw_scene, - NULL, + &external_view_update, NULL, NULL, }; -/* Note: currently unused, we should not register unless we want to see this when debugging the view. */ +/* Note: currently unused, + * we should not register unless we want to see this when debugging the view. */ RenderEngineType DRW_engine_viewport_external_type = { NULL, diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index 76ec0a61b8c..67ffe62f3c6 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -78,8 +78,8 @@ tGPencilObjectCache *gpencil_object_cache_add(tGPencilObjectCache *cache_array, tGPencilObjectCache *p = NULL; /* By default a cache is created with one block with a predefined number of free slots, - if the size is not enough, the cache is reallocated adding a new block of free slots. - This is done in order to keep cache small */ + * if the size is not enough, the cache is reallocated adding a new block of free slots. + * This is done in order to keep cache small. */ if (*gp_cache_used + 1 > *gp_cache_size) { if ((*gp_cache_size == 0) || (cache_array == NULL)) { p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, @@ -187,8 +187,8 @@ GpencilBatchGroup *gpencil_group_cache_add(GpencilBatchGroup *cache_array, GpencilBatchGroup *p = NULL; /* By default a cache is created with one block with a predefined number of free slots, - if the size is not enough, the cache is reallocated adding a new block of free slots. - This is done in order to keep cache small */ + * if the size is not enough, the cache is reallocated adding a new block of free slots. + * This is done in order to keep cache small. */ if (*grp_used + 1 > *grp_size) { if ((*grp_size == 0) || (cache_array == NULL)) { p = MEM_callocN(sizeof(struct GpencilBatchGroup) * GPENCIL_GROUPS_BLOCK_SIZE, diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 9e71791fbf3..7dabbcf4c41 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -71,6 +71,40 @@ static void gpencil_set_stroke_point(GPUVertBuf *vbo, GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x); } +/* Helper to add buffer_stroke point to vbo */ +static void gpencil_set_buffer_stroke_point(GPUVertBuf *vbo, + const bGPDspoint *pt, + int idx, + uint pos_id, + uint color_id, + uint thickness_id, + uint uvdata_id, + uint prev_pos_id, + float ref_pt[3], + short thickness, + const float ink[4]) +{ + + float alpha = ink[3] * pt->strength; + CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); + float col[4]; + ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha); + + GPU_vertbuf_attr_set(vbo, color_id, idx, col); + + /* transfer both values using the same shader variable */ + float uvdata[2] = {pt->uv_fac, pt->uv_rot}; + GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata); + + /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */ + float thick = max_ff(pt->pressure * thickness, 1.0f); + GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick); + + GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x); + /* reference point to follow drawing path */ + GPU_vertbuf_attr_set(vbo, prev_pos_id, idx, ref_pt); +} + /* Helper to add a new fill point and texture coordinates to vertex buffer */ static void gpencil_set_fill_point(GPUVertBuf *vbo, int idx, @@ -142,16 +176,20 @@ void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, /* use previous point to determine stroke direction */ bGPDspoint *pt2 = NULL; + float fpt[3]; if (i == 0) { if (gps->totpoints > 1) { /* extrapolate a point before first point */ - float fpt[3]; pt2 = &gps->points[1]; interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f); GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); } else { - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt->x); + /* add small offset to get a vector */ + copy_v3_v3(fpt, &pt->x); + fpt[0] += 0.00001f; + fpt[1] += 0.00001f; + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); } } else { @@ -433,12 +471,13 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness) int totpoints = gpd->runtime.sbuffer_size; static GPUVertFormat format = {0}; - static uint pos_id, color_id, thickness_id, uvdata_id; + static uint pos_id, color_id, thickness_id, uvdata_id, prev_pos_id; if (format.attr_len == 0) { pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + prev_pos_id = GPU_vertformat_attr_add(&format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); } GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); @@ -458,9 +497,43 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness) ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt); + /* use previous point to determine stroke direction (drawing path) */ + bGPDspoint pt2; + float ref_pt[3]; + + if (i == 0) { + if (totpoints > 1) { + /* extrapolate a point before first point */ + tGPspoint *tpt2 = &points[1]; + ED_gpencil_tpoint_to_point(ar, origin, tpt2, &pt2); + ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt2); + + interp_v3_v3v3(ref_pt, &pt2.x, &pt.x, 1.5f); + } + else { + copy_v3_v3(ref_pt, &pt.x); + } + } + else { + tGPspoint *tpt2 = &points[i - 1]; + ED_gpencil_tpoint_to_point(ar, origin, tpt2, &pt2); + ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt2); + + copy_v3_v3(ref_pt, &pt2.x); + } + /* set point */ - gpencil_set_stroke_point( - vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); + gpencil_set_buffer_stroke_point(vbo, + &pt, + idx, + pos_id, + color_id, + thickness_id, + uvdata_id, + prev_pos_id, + ref_pt, + thickness, + gpd->runtime.scolor); idx++; } @@ -561,8 +634,9 @@ GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd) float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, __func__); /* Convert points to array and triangulate - * Here a cache is not used because while drawing the information changes all the time, so the cache - * would be recalculated constantly, so it is better to do direct calculation for each function call + * Here a cache is not used because while drawing the information changes all the time, so the + * cache would be recalculated constantly, so it is better to do direct calculation for each + * function call */ for (int i = 0; i < totpoints; i++) { const tGPspoint *pt = &points[i]; diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 320b621f903..4b6c913785d 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -421,7 +421,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(GPENCIL_e_data *e_data, DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1); DRW_shgroup_uniform_float(grp, "layer_opacity", &gpl->opacity, 1); - stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0; + stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_FILL_TEX_MIX ? 1 : 0; DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1); stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0; @@ -450,7 +450,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(GPENCIL_e_data *e_data, DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); /* image texture */ - if ((gp_style->flag & GP_STYLE_COLOR_TEX_MIX) || + if ((gp_style->flag & GP_STYLE_FILL_TEX_MIX) || (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE)) { ImBuf *ibuf; Image *image = gp_style->ima; @@ -569,6 +569,12 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data, /* wire color */ set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false); DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); + + /* mix stroke factor */ + stl->shgroups[id].mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ? + gp_style->mix_stroke_factor : + 0.0f; + DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->shgroups[id].mix_stroke_factor, 1); } else { stl->storage->obj_scale = 1.0f; @@ -591,8 +597,16 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data, /* viewport x-ray */ DRW_shgroup_uniform_int(grp, "viewport_xray", &stl->storage->is_xray, 1); DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2); + + /* mix stroke factor */ + stl->storage->mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ? + gp_style->mix_stroke_factor : + 0.0f; + DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->storage->mix_stroke_factor, 1); } + DRW_shgroup_uniform_vec4(grp, "colormix", gp_style->stroke_rgba, 1); + if ((gpd) && (id > -1)) { stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1); @@ -703,6 +717,16 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data, /* wire color */ set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false); DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); + + /* mix stroke factor */ + stl->shgroups[id].mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ? + gp_style->mix_stroke_factor : + 0.0f; + DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->shgroups[id].mix_stroke_factor, 1); + + /* lock rotation of dots and boxes */ + stl->shgroups[id].use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; + DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->shgroups[id].use_follow_path, 1); } else { stl->storage->obj_scale = 1.0f; @@ -724,25 +748,28 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data, DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->storage->gradient_s, 1); /* viewport x-ray */ - stl->shgroups[id].is_xray = ((ob) && (ob->dt == OB_WIRE)) ? 1 : stl->storage->is_xray; - DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); + DRW_shgroup_uniform_int(grp, "viewport_xray", &stl->storage->is_xray, 1); DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2); + + /* mix stroke factor */ + stl->storage->mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ? + gp_style->mix_stroke_factor : + 0.0f; + DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->storage->mix_stroke_factor, 1); + + /* lock rotation of dots and boxes */ + DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->storage->use_follow_path, 1); } + DRW_shgroup_uniform_vec4(grp, "colormix", gp_style->stroke_rgba, 1); + if ((gpd) && (id > -1)) { stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&stl->shgroups[id].xray_mode, 1); - - /* lock rotation of dots and boxes */ - stl->shgroups[id].use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; - DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->shgroups[id].use_follow_path, 1); } else { /* for drawing always on predefined z-depth */ DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1); - - /* lock rotation of dots and boxes */ - DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->storage->use_follow_path, 1); } /* image texture */ @@ -1045,7 +1072,8 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache, DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps); } - /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */ + /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is + * enabled */ if ((stl->storage->simplify_fill) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) { if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || @@ -1340,7 +1368,8 @@ static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf) } } -/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */ +/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was + * modified) */ void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps) { BLI_assert(gps->totpoints >= 3); @@ -1429,6 +1458,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, View3D *v3d = draw_ctx->v3d; const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); + const bool is_paint_tool = (bool)((brush) && (brush->gpencil_tool == GPAINT_TOOL_DRAW)); bGPdata *gpd_eval = ob->data; /* need the original to avoid cow overhead while drawing */ bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id); @@ -1554,7 +1584,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) && ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0)); - if ((overlay) && (is_cppoint || is_speed_guide) && (is_show_gizmo) && + if ((overlay) && (is_paint_tool) && (is_cppoint || is_speed_guide) && (is_show_gizmo) && ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0)) { DRWShadingGroup *shgrp = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->drawing_pass); const float *viewport_size = DRW_viewport_size_get(); @@ -1621,6 +1651,16 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, int idx = 0; bool tag_first = false; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + + const bool overlay = draw_ctx->v3d != NULL ? + (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : + true; + const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; + const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion && + DRW_gpencil_onion_active(gpd) && overlay; + int start_stroke = 0; int start_point = 0; int start_fill = 0; @@ -1680,14 +1720,14 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, elm->onion, scale, cache_ob->shading_type); - - DRW_shgroup_call_range_add(shgrp, - cache->b_stroke.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_stroke, - len); - + if ((do_onion) || (elm->onion == false)) { + DRW_shgroup_call_range_add(shgrp, + cache->b_stroke.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_stroke, + len); + } stl->storage->shgroup_id++; start_stroke = elm->vertex_idx; break; @@ -1709,13 +1749,14 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, scale, cache_ob->shading_type); - DRW_shgroup_call_range_add(shgrp, - cache->b_point.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_point, - len); - + if ((do_onion) || (elm->onion == false)) { + DRW_shgroup_call_range_add(shgrp, + cache->b_point.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_point, + len); + } stl->storage->shgroup_id++; start_point = elm->vertex_idx; break; @@ -1734,13 +1775,14 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, stl->storage->shgroup_id, cache_ob->shading_type); - DRW_shgroup_call_range_add(shgrp, - cache->b_fill.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_fill, - len); - + if ((do_onion) || (elm->onion == false)) { + DRW_shgroup_call_range_add(shgrp, + cache->b_fill.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_fill, + len); + } stl->storage->shgroup_id++; start_fill = elm->vertex_idx; break; @@ -1870,6 +1912,28 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, cache->is_dirty = false; } +/* ensure there is a derived frame */ +static void gpencil_ensure_derived_frame(bGPdata *gpd, + bGPDlayer *gpl, + bGPDframe *gpf, + GpencilBatchCache *cache, + bGPDframe **derived_gpf) +{ + /* create derived frames array data or expand */ + int derived_idx = BLI_findindex(&gpd->layers, gpl); + *derived_gpf = &cache->derived_array[derived_idx]; + + /* if no derived frame or dirty cache, create a new one */ + if ((*derived_gpf == NULL) || (cache->is_dirty)) { + if (*derived_gpf != NULL) { + /* first clear temp data */ + BKE_gpencil_free_frame_runtime_data(*derived_gpf); + } + /* create new data (do not assign new memory)*/ + gpencil_copy_frame(gpf, *derived_gpf); + } +} + /* helper for populate a complete grease pencil datablock */ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, @@ -1887,9 +1951,6 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); bGPDframe *derived_gpf = NULL; - const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; - const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion && - DRW_gpencil_onion_active(gpd); const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; const bool time_remap = BKE_gpencil_has_time_modifiers(ob); @@ -1965,25 +2026,14 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, } /* create derived frames array data or expand */ - int derived_idx = BLI_findindex(&gpd->layers, gpl); - derived_gpf = &cache->derived_array[derived_idx]; - - /* if no derived frame or dirty cache, create a new one */ - if ((derived_gpf == NULL) || (cache->is_dirty)) { - if (derived_gpf != NULL) { - /* first clear temp data */ - BKE_gpencil_free_frame_runtime_data(derived_gpf); - } - /* create new data (do not assign new memory)*/ - gpencil_copy_frame(gpf, derived_gpf); - } + gpencil_ensure_derived_frame(gpd, gpl, gpf, cache, &derived_gpf); /* draw onion skins */ if (!ID_IS_LINKED(&gpd->id)) { - if ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) && + if ((gpl->onion_flag & GP_LAYER_ONIONSKIN) && ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) && (!cache_ob->is_dup_ob) && (gpd->id.us <= 1)) { - if (((!stl->storage->is_render) && (overlay)) || + if ((!stl->storage->is_render) || ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) { gpencil_draw_onionskins(cache, vedata, ob, gpd, gpl, gpf); } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 6fa07245396..ea578187765 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -328,7 +328,8 @@ void GPENCIL_cache_init(void *vedata) stl->g_data->shgrps_edit_point = NULL; if (!stl->shgroups) { - /* Alloc maximum size because count strokes is very slow and can be very complex due onion skinning. + /* Alloc maximum size because count strokes is very slow and can be very complex due onion + * skinning. */ stl->shgroups = MEM_mallocN(sizeof(GPENCIL_shgroup) * GPENCIL_MAX_SHGROUPS, "GPENCIL_shgroup"); } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 3add2cb0f1b..2ac1dc3211c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -134,6 +134,8 @@ typedef struct GPENCIL_shgroup { float gradient_f; float gradient_s[2]; + float mix_stroke_factor; + /* color of the wireframe */ float wire_color[4]; /* shading type and mode */ @@ -182,6 +184,8 @@ typedef struct GPENCIL_Storage { float gradient_s[2]; int use_follow_path; + float mix_stroke_factor; + /* Render Matrices and data */ float persmat[4][4], persinv[4][4]; float viewmat[4][4], viewinv[4][4]; diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index 282c4ca3a77..e6a3f45d60d 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -18,7 +18,7 @@ /** \file * \ingroup draw - */ + */ #include "BLI_rect.h" #include "DRW_render.h" @@ -36,9 +36,9 @@ #include "gpencil_engine.h" /* Get pixel size for render - * This function uses the same calculation used for viewport, because if use - * camera pixelsize, the result is not correct. - */ + * This function uses the same calculation used for viewport, because if use + * camera pixelsize, the result is not correct. + */ static float get_render_pixelsize(float persmat[4][4], int winx, int winy) { float v1[3], v2[3]; @@ -138,10 +138,12 @@ static void GPENCIL_render_update_viewvecs(float invproj[4][4], { /* view vectors for the corners of the view frustum. * Can be used to recreate the world space position easily */ - float view_vecs[4][4] = {{-1.0f, -1.0f, -1.0f, 1.0f}, - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f}, - {-1.0f, -1.0f, 1.0f, 1.0f}}; + float view_vecs[4][4] = { + {-1.0f, -1.0f, -1.0f, 1.0f}, + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f}, + {-1.0f, -1.0f, 1.0f, 1.0f}, + }; /* convert the view vectors to view space */ const bool is_persp = (winmat[3][3] == 0.0f); diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index b133d9310b0..355235618f6 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -119,10 +119,11 @@ static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2]) float focus_dist = BKE_camera_object_dof_distance(camera); float focal_len = cam->lens; - /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though - * because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ + /* This is factor that converts to the scene scale. focal length and sensor are expressed in mm + * unit.scale_length is how many meters per blender unit we have. We want to convert to blender + * units though because the shader reads coordinates in world space, which is in blender units. + * Note however that focus_distance is already in blender units and shall not be scaled here + * (see T48157). */ float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f; float scale_camera = 0.001f / scale; /* we want radius here for the aperture number */ diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl index b5d0a5bce71..8c3fd022004 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl @@ -16,6 +16,12 @@ vec2 toScreenSpace(vec4 vertex) return vec2(vertex.xy / vertex.w) * Viewport; } +/* get zdepth value */ +float getZdepth(vec4 point) +{ + return min(-0.05, (point.z / point.w)); +} + void main(void) { vec4 P0 = gl_in[0].gl_Position; @@ -26,22 +32,22 @@ void main(void) /* generate the triangle strip */ mTexCoord = vec2(0, 1); mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x - size, sp0.y + size) / Viewport, 0, 1.0); + gl_Position = vec4(vec2(sp0.x - size, sp0.y + size) / Viewport, getZdepth(P0), 1.0); EmitVertex(); mTexCoord = vec2(0, 0); mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x - size, sp0.y - size) / Viewport, 0, 1.0); + gl_Position = vec4(vec2(sp0.x - size, sp0.y - size) / Viewport, getZdepth(P0), 1.0); EmitVertex(); mTexCoord = vec2(1, 1); mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x + size, sp0.y + size) / Viewport, 0, 1.0); + gl_Position = vec4(vec2(sp0.x + size, sp0.y + size) / Viewport, getZdepth(P0), 1.0); EmitVertex(); mTexCoord = vec2(1, 0); mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x + size, sp0.y - size) / Viewport, 0, 1.0); + gl_Position = vec4(vec2(sp0.x + size, sp0.y - size) / Viewport, getZdepth(P0), 1.0); EmitVertex(); EndPrimitive(); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl index 632c63a39aa..acf60fc2d59 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl @@ -177,10 +177,11 @@ void main() /* set zdepth */ if (xraymode == GP_XRAY_FRONT) { - gl_FragDepth = 0.000001; + gl_FragDepth = min(-0.05, (gl_FragCoord.z / gl_FragCoord.w)); } else if (xraymode == GP_XRAY_3DSPACE) { - /* if 3D mode, move slightly the fill to avoid z-fighting between stroke and fill on same stroke */ + /* if 3D mode, move slightly the fill to avoid z-fighting between stroke and fill on same + * stroke */ if (drawmode == GP_DRAWMODE_3D) { gl_FragDepth = gl_FragCoord.z * 1.0001; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl index c8af822bc9e..cc47e12b303 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl @@ -5,6 +5,10 @@ uniform sampler2D myTexture; uniform float gradient_f; uniform vec2 gradient_s; +uniform vec4 colormix; +uniform float mix_stroke_factor; +uniform int shading_type[2]; + in vec4 mColor; in vec2 mTexCoord; out vec4 fragColor; @@ -20,50 +24,82 @@ out vec4 fragColor; #define GPENCIL_COLOR_TEXTURE 1 #define GPENCIL_COLOR_PATTERN 2 +#define OB_SOLID 3 +#define V3D_SHADING_TEXTURE_COLOR 3 + +bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR); + /* Function to check the point inside ellipse */ -float checkpoint(vec2 pt, vec2 radius) +float check_ellipse_point(vec2 pt, vec2 radius) { float p = (pow(pt.x, 2) / pow(radius.x, 2)) + (pow(pt.y, 2) / pow(radius.y, 2)); return p; } +/* Function to check the point inside box */ +vec2 check_box_point(vec2 pt, vec2 radius) +{ + vec2 rtn; + rtn.x = abs(pt.x) / radius.x; + rtn.y = abs(pt.y) / radius.y; + + return rtn; +} + void main() { vec2 centered = mTexCoord - vec2(0.5); - float ellip = checkpoint(centered, vec2(gradient_s / 2.0)); + float ellip = check_ellipse_point(centered, vec2(gradient_s / 2.0)); + vec2 box; if (mode != GPENCIL_MODE_BOX) { if (ellip > 1.0) { discard; } } + else { + box = check_box_point(centered, vec2(gradient_s / 2.0)); + if ((box.x > 1.0) || (box.y > 1.0)) { + discard; + } + } vec4 tmp_color = texture2D(myTexture, mTexCoord); /* Solid */ - if (color_type == GPENCIL_COLOR_SOLID) { + if ((color_type == GPENCIL_COLOR_SOLID) || (no_texture)) { fragColor = mColor; } /* texture */ - if (color_type == GPENCIL_COLOR_TEXTURE) { - fragColor = texture2D(myTexture, mTexCoord); + if ((color_type == GPENCIL_COLOR_TEXTURE) && (!no_texture)) { + vec4 text_color = texture2D(myTexture, mTexCoord); + if (mix_stroke_factor > 0.0) { + fragColor.rgb = mix(text_color.rgb, colormix.rgb, mix_stroke_factor); + fragColor.a = text_color.a; + } + else { + fragColor = text_color; + } + /* mult both alpha factor to use strength factor with texture */ fragColor.a = min(fragColor.a * mColor.a, fragColor.a); } /* pattern */ - if (color_type == GPENCIL_COLOR_PATTERN) { + if ((color_type == GPENCIL_COLOR_PATTERN) && (!no_texture)) { vec4 text_color = texture2D(myTexture, mTexCoord); fragColor = mColor; /* mult both alpha factor to use strength factor with color alpha limit */ fragColor.a = min(text_color.a * mColor.a, mColor.a); } - if ((mode == GPENCIL_MODE_DOTS) && (gradient_f < 1.0)) { - float dist = length(centered) * 2; + if (gradient_f < 1.0) { + float dist = length(centered) * 2.0; float decay = dist * (1.0 - gradient_f) * fragColor.a; fragColor.a = clamp(fragColor.a - decay, 0.0, 1.0); - fragColor.a = fragColor.a * (1.0 - ellip); + if (mode == GPENCIL_MODE_DOTS) { + fragColor.a = fragColor.a * (1.0 - ellip); + } } if (fragColor.a < 0.0035) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl index 2fb48ac5147..a64a7ecb9be 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl @@ -31,7 +31,7 @@ vec2 toScreenSpace(vec4 vertex) float getZdepth(vec4 point) { if (xraymode == GP_XRAY_FRONT) { - return 0.000001; + return min(-0.05, (point.z / point.w)); } if (xraymode == GP_XRAY_3DSPACE) { return (point.z / point.w); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl index 92c9acf1f2a..9cef7601770 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -42,7 +42,7 @@ void main() else { float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize); - finalThickness = max(size * objscale, 4.0); /* minimum 4 pixels */ + finalThickness = max(size * objscale, 0.5); /* set a minimum size */ } /* for wireframe override size and color */ diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl index 35d07306361..6b7cee888ea 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl @@ -3,6 +3,10 @@ uniform sampler2D myTexture; uniform float gradient_f; +uniform vec4 colormix; +uniform float mix_stroke_factor; +uniform int shading_type[2]; + in vec4 mColor; in vec2 mTexCoord; in vec2 uvfac; @@ -18,6 +22,11 @@ out vec4 fragColor; #define ENDCAP 1.0 +#define OB_SOLID 3 +#define V3D_SHADING_TEXTURE_COLOR 3 + +bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR); + void main() { @@ -30,8 +39,8 @@ void main() discard; } } - /* Solid */ - if (color_type == GPENCIL_COLOR_SOLID) { + + if ((color_type == GPENCIL_COLOR_SOLID) || (no_texture)) { fragColor = tColor; } @@ -45,13 +54,20 @@ void main() } /* texture */ - if (color_type == GPENCIL_COLOR_TEXTURE) { - fragColor = text_color; + if ((color_type == GPENCIL_COLOR_TEXTURE) && (!no_texture)) { + if (mix_stroke_factor > 0.0) { + fragColor.rgb = mix(text_color.rgb, colormix.rgb, mix_stroke_factor); + fragColor.a = text_color.a; + } + else { + fragColor = text_color; + } + /* mult both alpha factor to use strength factor */ fragColor.a = min(fragColor.a * tColor.a, fragColor.a); } /* pattern */ - if (color_type == GPENCIL_COLOR_PATTERN) { + if ((color_type == GPENCIL_COLOR_PATTERN) && (!no_texture)) { fragColor = tColor; /* mult both alpha factor to use strength factor with color alpha limit */ fragColor.a = min(text_color.a * tColor.a, tColor.a); @@ -63,7 +79,7 @@ void main() float d = abs(mTexCoord.y - 0.5) * (1.1 - gradient_f); float alpha = 1.0 - clamp((fragColor.a - (d * 2.0)), 0.03, 1.0); fragColor.a = smoothstep(fragColor.a, 0.0, alpha); - + } */ diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl index 7e62d6f0d64..b90f5b33a57 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl @@ -35,7 +35,7 @@ vec2 toScreenSpace(vec4 vertex) float getZdepth(vec4 point) { if (xraymode == GP_XRAY_FRONT) { - return 0.000001; + return min(-0.05, (point.z / point.w)); } if (xraymode == GP_XRAY_3DSPACE) { return (point.z / point.w); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl index 54440f7b120..0428b0d408c 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl @@ -362,9 +362,9 @@ void main() for (int dX = -1; dX <= 1; ++dX) { for (int dY = -1; dY <= 1; ++dY) { vec2 offset = vec2(float(dX), float(dY)); - /* If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + (dY + R) of the - * pixel array. This will fill the pixel array, with the top left pixel of the window at pixel[0] and the - * bottom right pixel of the window at pixel[N-1]. */ + /* If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + + * (dY + R) of the pixel array. This will fill the pixel array, with the top left pixel of + * the window at pixel[0] and the bottom right pixel of the window at pixel[N-1]. */ v[(dX + 1) * 3 + (dY + 1)] = toVec(texture(blurTex, uv + offset * pixel_size * rad)); } } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index e654141df5c..5eff0b41e20 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -25,6 +25,9 @@ in vec3 normal_viewport; #ifdef V3D_SHADING_TEXTURE_COLOR in vec2 uv_interp; #endif +#ifdef V3D_SHADING_VERTEX_COLOR +in vec3 vertexColor; +#endif #ifdef V3D_LIGHTING_MATCAP uniform sampler2D matcapImage; #endif @@ -42,11 +45,13 @@ void main() { vec4 diffuse_color; -#ifdef V3D_SHADING_TEXTURE_COLOR +#if defined(V3D_SHADING_TEXTURE_COLOR) diffuse_color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); if (diffuse_color.a < ImageTransparencyCutoff) { discard; } +#elif defined(V3D_SHADING_VERTEX_COLOR) + diffuse_color = vec4(vertexColor, 1.0); #else diffuse_color = vec4(materialDiffuseColor, 1.0); #endif /* V3D_SHADING_TEXTURE_COLOR */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 6b2962a66da..2596fc4cf88 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -16,6 +16,9 @@ in vec3 normal_viewport; #ifdef V3D_SHADING_TEXTURE_COLOR in vec2 uv_interp; #endif +#ifdef V3D_SHADING_VERTEX_COLOR +in vec3 vertexColor; +#endif #ifdef HAIR_SHADER flat in float hair_rand; @@ -37,11 +40,13 @@ void main() float metallic, roughness; vec4 color; -# ifdef V3D_SHADING_TEXTURE_COLOR +# if defined(V3D_SHADING_TEXTURE_COLOR) color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); if (color.a < ImageTransparencyCutoff) { discard; } +# elif defined(V3D_SHADING_VERTEX_COLOR) + color.rgb = vertexColor; # else color.rgb = materialDiffuseColor; # endif diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index dd737063f61..f2c684cdb6a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -10,6 +10,9 @@ uniform mat3 NormalMatrix; in vec3 pos; in vec3 nor; in vec2 u; /* active texture layer */ +# ifdef V3D_SHADING_VERTEX_COLOR +in vec3 c; /* active color */ +# endif # define uv u #else /* HAIR_SHADER */ # ifdef V3D_SHADING_TEXTURE_COLOR @@ -25,6 +28,9 @@ out vec3 normal_viewport; #ifdef V3D_SHADING_TEXTURE_COLOR out vec2 uv_interp; #endif +#ifdef V3D_SHADING_VERTEX_COLOR +out vec3 vertexColor; +#endif /* From http://libnoise.sourceforge.net/noisegen/index.html */ float integer_noise(int n) @@ -34,6 +40,16 @@ float integer_noise(int n) return (float(nn) / 1073741824.0); } +#ifdef V3D_SHADING_VERTEX_COLOR +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)); +} +#endif + void main() { #ifdef HAIR_SHADER @@ -68,6 +84,12 @@ void main() uv_interp = uv; #endif +#ifdef V3D_SHADING_VERTEX_COLOR +# ifndef HAIR_SHADER + vertexColor = srgb_to_linear_attr(c); +# endif +#endif + #ifdef NORMAL_VIEWPORT_PASS_ENABLED normal_viewport = NormalMatrix * nor; # ifndef HAIR_SHADER diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index 26ebe7a4553..a1c269d5a65 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -64,7 +64,8 @@ float max_v3(vec3 v) float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) { - /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ + /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ + */ vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; vec3 furthestplane = min(firstplane, secondplane); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 91f4f351c7b..5d7bdc72546 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -209,15 +209,15 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature) } static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair, eGPUShaderConfig sh_cfg) { WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg]; - int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair); + int index = workbench_material_get_prepass_shader_index(wpd, is_uniform_color, is_hair); if (sh_data->prepass_sh_cache[index] == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; - char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); + char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair); char *prepass_vert = workbench_build_prepass_vert(is_hair); char *prepass_frag = workbench_build_prepass_frag(); sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({ @@ -263,10 +263,10 @@ static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd) static void select_deferred_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) { - wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg); - wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg); - wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg); - wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg); + wpd->prepass_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg); + wpd->prepass_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg); + wpd->prepass_uniform_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg); + wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg); wpd->composite_sh = ensure_deferred_composite_shader(wpd); wpd->background_sh = ensure_background_shader(wpd); } @@ -846,8 +846,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat if (material == NULL) { material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); material->shgrp = DRW_shgroup_create( - (color_type == V3D_SHADING_TEXTURE_COLOR) ? wpd->prepass_texture_sh : - wpd->prepass_solid_sh, + (wpd->shading.color_type == color_type) ? wpd->prepass_sh : wpd->prepass_uniform_sh, (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass); workbench_material_copy(material, &material_template); DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); @@ -881,13 +880,13 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o ImageUser *iuser; int interp; workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); + int color_type = workbench_material_determine_color_type(wpd, image, ob, false); WORKBENCH_MaterialData *material = get_or_create_material_data( vedata, ob, mat, image, iuser, color_type, interp); - struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ? - wpd->prepass_solid_hair_sh : - wpd->prepass_texture_hair_sh; + struct GPUShader *shader = (wpd->shading.color_type == color_type) ? + wpd->prepass_hair_sh : + wpd->prepass_uniform_hair_sh; DRWShadingGroup *shgrp = DRW_shgroup_hair_create( ob, psys, @@ -936,7 +935,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) WORKBENCH_MaterialData *material; if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { 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 is_sculpt_mode = (ob->sculpt != NULL); const bool use_hide = is_active && DRW_object_use_hide_faces(ob); const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL; @@ -952,10 +951,10 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) ImageUser *iuser; int interp; workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); + int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode); if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) { material = workbench_forward_get_or_create_material_data( - vedata, ob, mat, image, iuser, color_type, 0); + vedata, ob, mat, image, iuser, color_type, 0, is_sculpt_mode); has_transp_mat = true; } else { @@ -969,24 +968,33 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) else if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_OBJECT_COLOR, - V3D_SHADING_RANDOM_COLOR)) { - if ((ob->color[3] < 1.0f) && (wpd->shading.color_type == V3D_SHADING_OBJECT_COLOR)) { + V3D_SHADING_RANDOM_COLOR, + V3D_SHADING_VERTEX_COLOR)) { + int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode); + + if ((ob->color[3] < 1.0f) && (color_type == V3D_SHADING_OBJECT_COLOR)) { /* Hack */ wpd->shading.xray_alpha = ob->color[3]; material = workbench_forward_get_or_create_material_data( - vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); + vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode); has_transp_mat = true; } else { /* Draw solid color */ - material = get_or_create_material_data( - vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); + material = get_or_create_material_data(vedata, ob, NULL, NULL, NULL, color_type, 0); } if (is_sculpt_mode) { DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); } else { - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + struct GPUBatch *geom; + if (color_type == V3D_SHADING_VERTEX_COLOR) { + geom = DRW_cache_mesh_surface_vertpaint_get(ob); + } + else { + geom = DRW_cache_object_surface_get(ob); + } + if (geom) { DRW_shgroup_call_object_add(material->shgrp, geom, ob); } @@ -1015,7 +1023,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) /* Hack */ wpd->shading.xray_alpha = mat->a; material = workbench_forward_get_or_create_material_data( - vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); has_transp_mat = true; } else { diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index 3e35f8120d7..3dea99a76cf 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -185,9 +185,12 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera) wpd->dof_blur_tx = DRW_texture_pool_query_2d( size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_workbench_solid); #if 0 - wpd->coc_temp_tx = DRW_texture_pool_query_2d(shrink_h_size[0], shrink_h_size[1], GPU_RG8, &draw_engine_workbench_solid); - wpd->coc_tiles_tx[0] = DRW_texture_pool_query_2d(shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); - wpd->coc_tiles_tx[1] = DRW_texture_pool_query_2d(shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); + wpd->coc_temp_tx = DRW_texture_pool_query_2d( + shrink_h_size[0], shrink_h_size[1], GPU_RG8, &draw_engine_workbench_solid); + wpd->coc_tiles_tx[0] = DRW_texture_pool_query_2d( + shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); + wpd->coc_tiles_tx[1] = DRW_texture_pool_query_2d( + shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); #endif GPU_framebuffer_ensure_config(&fbl->dof_downsample_fb, @@ -197,18 +200,21 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera) GPU_ATTACHMENT_TEXTURE(txl->coc_halfres_tx), }); #if 0 - GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_h_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->coc_temp_tx), - }); - GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_v_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[0]), - }); - GPU_framebuffer_ensure_config(&fbl->dof_coc_dilate_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[1]), - }); + GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_h_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->coc_temp_tx), + }); + GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_v_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[0]), + }); + GPU_framebuffer_ensure_config(&fbl->dof_coc_dilate_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[1]), + }); #endif GPU_framebuffer_ensure_config(&fbl->dof_blur1_fb, { @@ -237,9 +243,10 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera) /* TODO(fclem) deduplicate with eevee */ /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though - * because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ + * unit.scale_length is how many meters per blender unit we have. We want to convert to blender + * units though because the shader reads coordinates in world space, which is in blender units. + * Note however that focus_distance is already in blender units and shall not be scaled here + * (see T48157). */ float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; float scale_camera = 0.001f / scale; /* we want radius here for the aperture number */ @@ -318,12 +325,14 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata, } #if 0 { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_h_sh, psl->dof_flatten_h_ps); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_h_sh, + psl->dof_flatten_h_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); DRW_shgroup_call_add(grp, quad, NULL); } { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_v_sh, psl->dof_flatten_v_ps); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_v_sh, + psl->dof_flatten_v_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_temp_tx); DRW_shgroup_call_add(grp, quad, NULL); } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 782e85597d7..00590940ac3 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -137,7 +137,8 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ Image *ima, ImageUser *iuser, int color_type, - int interp) + int interp, + bool is_sculpt_mode) { const DRWContextState *draw_ctx = DRW_context_state_get(); WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; @@ -168,9 +169,9 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); /* transparent accum */ - grp = DRW_shgroup_create(color_type == V3D_SHADING_TEXTURE_COLOR ? - wpd->transparent_accum_texture_sh : - wpd->transparent_accum_sh, + grp = DRW_shgroup_create(wpd->shading.color_type == color_type ? + wpd->transparent_accum_sh : + wpd->transparent_accum_uniform_sh, psl->transparent_accum_pass); DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_float_copy(grp, "alpha", wpd->shading.xray_alpha); @@ -194,7 +195,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ material->shgrp = grp; /* Depth */ - if (workbench_material_determine_color_type(wpd, material->ima, ob) == + if (workbench_material_determine_color_type(wpd, material->ima, ob, is_sculpt_mode) == V3D_SHADING_TEXTURE_COLOR) { material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_texture_sh, psl->object_outline_pass); @@ -217,15 +218,15 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ } static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair, eGPUShaderConfig sh_cfg) { WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg]; - int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair); + int index = workbench_material_get_accum_shader_index(wpd, is_uniform_color, is_hair); if (sh_data->transparent_accum_sh_cache[index] == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; - char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); + char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair); char *transparent_accum_vert = workbench_build_forward_vert(is_hair); char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({ @@ -258,8 +259,8 @@ void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConf wpd->composite_sh = ensure_forward_composite_shaders(wpd); wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, sh_cfg); wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, sh_cfg); - wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg); - wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg); + wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg); + wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg); } void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) @@ -497,13 +498,13 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O ImageUser *iuser; int interp; workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); + int color_type = workbench_material_determine_color_type(wpd, image, ob, false); WORKBENCH_MaterialData *material = workbench_forward_get_or_create_material_data( - vedata, ob, mat, image, iuser, color_type, interp); + vedata, ob, mat, image, iuser, color_type, interp, false); - struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ? + struct GPUShader *shader = (wpd->shading.color_type == color_type) ? wpd->transparent_accum_hair_sh : - wpd->transparent_accum_texture_hair_sh; + wpd->transparent_accum_uniform_hair_sh; DRWShadingGroup *shgrp = DRW_shgroup_hair_create( ob, psys, md, psl->transparent_accum_pass, shader); DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); @@ -564,8 +565,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) WORKBENCH_MaterialData *material; if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { - 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 is_sculpt_mode = (ob->sculpt != NULL); bool is_drawn = false; if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) { @@ -579,9 +579,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) ImageUser *iuser; int interp; workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); + int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode); material = workbench_forward_get_or_create_material_data( - vedata, ob, mat, image, iuser, color_type, interp); + vedata, ob, mat, image, iuser, color_type, interp, is_sculpt_mode); DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } @@ -594,12 +594,21 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_OBJECT_COLOR, - V3D_SHADING_RANDOM_COLOR)) { + V3D_SHADING_RANDOM_COLOR, + V3D_SHADING_VERTEX_COLOR)) { /* No material split needed */ - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode); + + struct GPUBatch *geom; + if (color_type == V3D_SHADING_VERTEX_COLOR) { + geom = DRW_cache_mesh_surface_vertpaint_get(ob); + } + else { + geom = DRW_cache_object_surface_get(ob); + } if (geom) { material = workbench_forward_get_or_create_material_data( - vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); + vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode); if (is_sculpt_mode) { DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); if (!is_wire) { @@ -631,7 +640,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) Material *mat = give_current_material(ob, i + 1); material = workbench_forward_get_or_create_material_data( - vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); if (is_sculpt_mode) { DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); if (!is_wire) { diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index d73eee37a98..c403e358d6a 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -31,6 +31,7 @@ #include "BLI_hash.h" #include "DNA_node_types.h" +#include "DNA_mesh_types.h" #include "ED_uvedit.h" @@ -42,7 +43,8 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Material *mat, WORKBENCH_MaterialData *data) { - /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */ + /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no + * texture could be determined */ int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ? V3D_SHADING_MATERIAL_COLOR : wpd->shading.color_type; @@ -67,7 +69,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, hsv_to_rgb_v(hsv, data->diffuse_color); copy_v3_v3(data->base_color, data->diffuse_color); } - else if (color_type == V3D_SHADING_OBJECT_COLOR) { + else if (ELEM(color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_VERTEX_COLOR)) { copy_v3_v3(data->diffuse_color, ob->color); copy_v3_v3(data->base_color, data->diffuse_color); } @@ -90,9 +92,14 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, } } -char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) +char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, + bool is_uniform_color, + bool is_hair) { char *str = NULL; + bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color; + bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) && + !is_uniform_color; DynStr *ds = BLI_dynstr_new(); @@ -126,6 +133,9 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { BLI_dynstr_append(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n"); } + if (use_vertex_colors) { + BLI_dynstr_append(ds, "#define V3D_SHADING_VERTEX_COLOR\n"); + } if (use_textures) { BLI_dynstr_append(ds, "#define V3D_SHADING_TEXTURE_COLOR\n"); } @@ -160,6 +170,7 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool result += BLI_ghashutil_uinthash_v4_murmur(input); result += BLI_ghashutil_uinthash((uint)is_ghost); + result += BLI_ghashutil_uinthash(material_template->color_type); /* add texture reference */ if (material_template->ima) { @@ -184,9 +195,12 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd) } int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair) { + bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color; + bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) && + !is_uniform_color; /* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */ int index = 0; SET_FLAG_FROM_TEST(index, is_hair, 1 << 0); @@ -195,32 +209,46 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3); SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4); SET_FLAG_FROM_TEST(index, use_textures, 1 << 5); + SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 6); BLI_assert(index < MAX_PREPASS_SHADERS); return index; } int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair) { + bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color; + bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) && + !is_uniform_color; /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */ int index = 0; /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; SET_FLAG_FROM_TEST(index, use_textures, 1 << 2); - SET_FLAG_FROM_TEST(index, is_hair, 1 << 3); + SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 3); + SET_FLAG_FROM_TEST(index, is_hair, 1 << 4); /* 1 bits SHADOWS (only facing factor) */ - SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 4); + SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 5); BLI_assert(index < MAX_ACCUM_SHADERS); return index; } -int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob) +int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, + Image *ima, + Object *ob, + bool is_sculpt_mode) { int color_type = wpd->shading.color_type; - if ((color_type == V3D_SHADING_TEXTURE_COLOR && ima == NULL) || (ob->dt < OB_TEXTURE)) { + const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL; + + if ((color_type == V3D_SHADING_TEXTURE_COLOR && (ima == NULL || is_sculpt_mode)) || + (ob->dt < OB_TEXTURE)) { color_type = V3D_SHADING_MATERIAL_COLOR; } + if (color_type == V3D_SHADING_VERTEX_COLOR && (me == NULL || me->mloopcol == NULL)) { + color_type = V3D_SHADING_OBJECT_COLOR; + } return color_type; } @@ -264,7 +292,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, return; } - if (workbench_material_determine_color_type(wpd, material->ima, ob) == + if (workbench_material_determine_color_type(wpd, material->ima, ob, false) == V3D_SHADING_TEXTURE_COLOR) { ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, material->iuser, NULL); const bool do_color_correction = wpd->use_color_management && diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 0e2ef2f94d2..3cfb1283416 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -37,11 +37,12 @@ #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 #define MAX_COMPOSITE_SHADERS (1 << 6) -#define MAX_PREPASS_SHADERS (1 << 6) -#define MAX_ACCUM_SHADERS (1 << 5) +#define MAX_PREPASS_SHADERS (1 << 7) +#define MAX_ACCUM_SHADERS (1 << 6) #define MAX_CAVITY_SHADERS (1 << 3) #define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) +#define VERTEX_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) #define FLAT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_FLAT) #define STUDIOLIGHT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_STUDIO) #define MATCAP_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_MATCAP) @@ -69,7 +70,8 @@ (ELEM(wpd->shading.color_type, \ V3D_SHADING_MATERIAL_COLOR, \ V3D_SHADING_OBJECT_COLOR, \ - V3D_SHADING_TEXTURE_COLOR)) + V3D_SHADING_TEXTURE_COLOR, \ + V3D_SHADING_VERTEX_COLOR)) #define IS_NAVIGATING(wpd) \ ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)) @@ -213,16 +215,16 @@ BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16) typedef struct WORKBENCH_PrivateData { struct GHash *material_hash; struct GHash *material_transp_hash; - struct GPUShader *prepass_solid_sh; - struct GPUShader *prepass_solid_hair_sh; - struct GPUShader *prepass_texture_sh; - struct GPUShader *prepass_texture_hair_sh; + struct GPUShader *prepass_sh; + struct GPUShader *prepass_hair_sh; + struct GPUShader *prepass_uniform_sh; + struct GPUShader *prepass_uniform_hair_sh; struct GPUShader *composite_sh; struct GPUShader *background_sh; struct GPUShader *transparent_accum_sh; struct GPUShader *transparent_accum_hair_sh; - struct GPUShader *transparent_accum_texture_sh; - struct GPUShader *transparent_accum_texture_hair_sh; + struct GPUShader *transparent_accum_uniform_sh; + struct GPUShader *transparent_accum_uniform_hair_sh; View3DShading shading; StudioLight *studio_light; const UserDef *preferences; @@ -353,7 +355,8 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ Image *ima, ImageUser *iuser, int color_type, - int interp); + int interp, + bool is_sculpt_mode); /* workbench_effect_aa.c */ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx); @@ -382,11 +385,14 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata, void workbench_dof_draw_pass(WORKBENCH_Data *vedata); /* workbench_materials.c */ -int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob); +int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, + Image *ima, + Object *ob, + bool is_sculpt_mode); void workbench_material_get_image_and_mat( Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat); char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair); void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, @@ -395,10 +401,10 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost); int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd); int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair); int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, - bool use_textures, + bool is_uniform_color, bool is_hair); void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index 5c95a835adc..3fc83fea7c6 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -78,12 +78,12 @@ void studiolight_update_world(WORKBENCH_PrivateData *wpd, mul_v3_v3fl(wd->spherical_harmonics_coefs[0], sl->spherical_harmonics_coefs[0], M_1_PI); /* Swizzle to make shader code simpler. */ for (int i = 0; i < 3; ++i) { - copy_v3_fl3( - wd->spherical_harmonics_coefs[i + 1], - -sl->spherical_harmonics_coefs[3][i], - sl->spherical_harmonics_coefs[2][i], - -sl->spherical_harmonics_coefs[1][i]); - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], M_1_PI * 1.5f); /* 1.5f is to improve the contrast a bit. */ + copy_v3_fl3(wd->spherical_harmonics_coefs[i + 1], + -sl->spherical_harmonics_coefs[3][i], + sl->spherical_harmonics_coefs[2][i], + -sl->spherical_harmonics_coefs[1][i]); + mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], + M_1_PI * 1.5f); /* 1.5f is to improve the contrast a bit. */ } /* Precompute as much as we can. See shader code for derivation. */ diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index b0320a522f8..4d8fefbbc06 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -329,7 +329,7 @@ typedef enum { DRW_STATE_BLEND = (1 << 15), DRW_STATE_ADDITIVE = (1 << 16), DRW_STATE_MULTIPLY = (1 << 17), - /* DRW_STATE_TRANSMISSION = (1 << 18), */ /* Not used */ + DRW_STATE_BLEND_PREMUL_UNDER = (1 << 18), DRW_STATE_CLIP_PLANES = (1 << 19), /** Same as DRW_STATE_ADDITIVE but let alpha accumulate without premult. */ DRW_STATE_ADDITIVE_FULL = (1 << 20), diff --git a/source/blender/draw/intern/draw_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c index 8ff2916b040..a6026c9da3a 100644 --- a/source/blender/draw/intern/draw_anim_viz.c +++ b/source/blender/draw/intern/draw_anim_viz.c @@ -184,7 +184,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl, struct DRWTextStore *dt = DRW_text_cache_ensure(); int txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII; int cfra = (int)DEG_get_ctime(draw_ctx->depsgraph); - bool sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT); + bool sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->base_flag & BASE_SELECTED); bool show_keyframes = (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) != 0; int sfra, efra, stepsize; @@ -259,7 +259,8 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl, else if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) { bMotionPathVert *mpvP = (mpv - stepsize); bMotionPathVert *mpvN = (mpv + stepsize); - /* only draw framenum if several consecutive highlighted points don't occur on same point */ + /* only draw framenum if several consecutive highlighted points don't occur on same point + */ if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) { numstr_len = sprintf(numstr, " %d", frame); DRW_text_cache_add(dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, col); diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 12d4ca95a39..9b52f282944 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -345,36 +345,61 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg, Object *custom) { - /* grr, not re-using instances! */ struct GPUBatch *surf = DRW_cache_object_surface_get(custom); struct GPUBatch *edges = DRW_cache_object_edge_detection_get(custom, NULL); struct GPUBatch *ledges = DRW_cache_object_loose_edges_get(custom); float final_bonemat[4][4]; - /* XXXXXXX needs to be moved elsewhere. */ - drw_batch_cache_generate_requested(custom); - if (surf || edges || ledges) { mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); } + BLI_assert(g_data.passes.custom_shapes != NULL); + if (surf && g_data.passes.bone_solid != NULL) { - DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid( - g_data.passes.bone_solid, surf, g_data.transparent, sh_cfg); + DRWShadingGroup *shgrp_geom_solid = BLI_ghash_lookup(g_data.passes.custom_shapes, surf); + + if (shgrp_geom_solid == NULL) { + /* TODO(fclem) needs to be moved elsewhere. */ + drw_batch_cache_generate_requested(custom); + + /* NOTE! g_data.transparent require a separate shading group if the + * object is transparent. This is done by passing a different ghash + * for transparent armature in pose mode. */ + shgrp_geom_solid = shgroup_instance_bone_shape_solid( + g_data.passes.bone_solid, surf, g_data.transparent, sh_cfg); + BLI_ghash_insert(g_data.passes.custom_shapes, surf, shgrp_geom_solid); + } DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color); } if (edges && outline_color[3] > 0.0f) { - DRWShadingGroup *shgrp_geom_wire = shgroup_instance_bone_shape_outline( - g_data.passes.bone_outline, edges, sh_cfg); + DRWShadingGroup *shgrp_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, edges); + + if (shgrp_geom_wire == NULL) { + /* TODO(fclem) needs to be moved elsewhere. */ + drw_batch_cache_generate_requested(custom); + + shgrp_geom_wire = shgroup_instance_bone_shape_outline( + g_data.passes.bone_outline, edges, sh_cfg); + + BLI_ghash_insert(g_data.passes.custom_shapes, edges, shgrp_geom_wire); + } DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color); } if (ledges) { - DRWShadingGroup *shgrp_geom_ledges = shgroup_instance_wire(g_data.passes.bone_wire, ledges); - float final_color[4]; - copy_v3_v3(final_color, outline_color); - final_color[3] = 1.0f; /* hack */ + DRWShadingGroup *shgrp_geom_ledges = BLI_ghash_lookup(g_data.passes.custom_shapes, ledges); + + if (shgrp_geom_ledges == NULL) { + /* TODO(fclem) needs to be moved elsewhere. */ + drw_batch_cache_generate_requested(custom); + + shgrp_geom_ledges = shgroup_instance_wire(g_data.passes.bone_wire, ledges); + + BLI_ghash_insert(g_data.passes.custom_shapes, ledges, shgrp_geom_ledges); + } + float final_color[4] = {outline_color[0], outline_color[1], outline_color[2], 1.0f}; DRW_shgroup_call_dynamic_add(shgrp_geom_ledges, final_bonemat, final_color); } } @@ -383,18 +408,22 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float color[4], Object *custom) { - /* grr, not re-using instances! */ struct GPUBatch *geom = DRW_cache_object_all_edges_get(custom); - /* XXXXXXX needs to be moved elsewhere. */ - drw_batch_cache_generate_requested(custom); - if (geom) { - DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom); - float final_bonemat[4][4], final_color[4]; + DRWShadingGroup *shgrp_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, geom); + + if (shgrp_geom_wire == NULL) { + /* TODO(fclem) needs to be moved elsewhere. */ + drw_batch_cache_generate_requested(custom); + + shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom); + + BLI_ghash_insert(g_data.passes.custom_shapes, geom, shgrp_geom_wire); + } + float final_color[4] = {color[0], color[1], color[2], 1.0f}; + float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - copy_v3_v3(final_color, color); - final_color[3] = 1.0f; /* hack */ DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, final_color); } } @@ -1110,14 +1139,17 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S param.roll1 += prev->roll2; } - param.scaleIn = ebone->scaleIn; - param.scaleOut = ebone->scaleOut; + param.scale_in_x = ebone->scale_in_x; + param.scale_in_y = ebone->scale_in_y; + + param.scale_out_x = ebone->scale_out_x; + param.scale_out_y = ebone->scale_out_y; - param.curveInX = ebone->curveInX; - param.curveInY = ebone->curveInY; + param.curve_in_x = ebone->curve_in_x; + param.curve_in_y = ebone->curve_in_y; - param.curveOutX = ebone->curveOutX; - param.curveOutY = ebone->curveOutY; + param.curve_out_x = ebone->curve_out_x; + param.curve_out_y = ebone->curve_out_y; ebone->segments = BKE_pchan_bbone_spline_compute(¶m, false, (Mat4 *)result_array); } @@ -1153,8 +1185,8 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc size_to_mat4(s, (const float[3]){xwidth, length / bbone_segments, zwidth}); /* Compute BBones segment matrices... */ - /* Note that we need this even for one-segment bones, because box drawing need specific weirdo matrix for the box, - * that we cannot use to draw end points & co. */ + /* Note that we need this even for one-segment bones, because box drawing need specific weirdo + * matrix for the box, that we cannot use to draw end points & co. */ if (pchan) { Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix; if (bbone_segments > 1) { @@ -1765,7 +1797,8 @@ static void draw_bone_relations(EditBone *ebone, } else if (pchan && pchan->parent) { if (do_relations) { - /* Only draw if bone or its parent is selected - reduces viewport complexity with complex rigs */ + /* Only draw if bone or its parent is selected - reduces viewport complexity with complex + * rigs */ if ((boneflag & BONE_SELECTED) || (pchan->parent->bone && (pchan->parent->bone->flag & BONE_SELECTED))) { if ((boneflag & BONE_CONNECTED) == 0) { diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 74c87162afd..6b4c4cef9c8 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -161,9 +161,13 @@ static void UNUSED_FUNCTION(add_fancy_edge)(GPUVertBuf *vbo, } #if 0 /* UNUSED */ -static void add_lat_lon_vert( - GPUVertBuf *vbo, uint pos_id, uint nor_id, - uint *v_idx, const float rad, const float lat, const float lon) +static void add_lat_lon_vert(GPUVertBuf *vbo, + uint pos_id, + uint nor_id, + uint *v_idx, + const float rad, + const float lat, + const float lon) { float pos[3], nor[3]; nor[0] = sinf(lat) * cosf(lon); @@ -178,8 +182,10 @@ static void add_lat_lon_vert( static GPUVertBuf *fill_arrows_vbo(const float scale) { /* Position Only 3D format */ - static GPUVertFormat format = { 0 }; - static struct { uint pos; } attr_id; + 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); } @@ -476,8 +482,9 @@ GPUBatch *DRW_cache_empty_cube_get(void) {1.0f, 1.0f, 1.0f}, }; - const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, - 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6}; + const GLubyte indices[24] = { + 0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6, + }; /* Position Only 3D format */ static GPUVertFormat format = {0}; @@ -653,17 +660,20 @@ GPUBatch *DRW_cache_gpencil_axes_get(void) float v2[3] = {0.0f, 0.0f, 0.0f}; /* cube data */ - const GLfloat verts[8][3] = {{-0.25f, -0.25f, -0.25f}, - {-0.25f, -0.25f, 0.25f}, - {-0.25f, 0.25f, -0.25f}, - {-0.25f, 0.25f, 0.25f}, - {0.25f, -0.25f, -0.25f}, - {0.25f, -0.25f, 0.25f}, - {0.25f, 0.25f, -0.25f}, - {0.25f, 0.25f, 0.25f}}; - - const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, - 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6}; + const GLfloat verts[8][3] = { + {-0.25f, -0.25f, -0.25f}, + {-0.25f, -0.25f, 0.25f}, + {-0.25f, 0.25f, -0.25f}, + {-0.25f, 0.25f, 0.25f}, + {0.25f, -0.25f, -0.25f}, + {0.25f, -0.25f, 0.25f}, + {0.25f, 0.25f, -0.25f}, + {0.25f, 0.25f, 0.25f}, + }; + + const GLubyte indices[24] = { + 0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6, + }; /* Position Only 3D format */ static GPUVertFormat format = {0}; @@ -1740,11 +1750,13 @@ GPUBatch *DRW_cache_light_spot_volume_get(void) GPUBatch *DRW_cache_light_spot_square_get(void) { if (!SHC.drw_light_spot_square) { - float p[5][3] = {{0.0f, 0.0f, 0.0f}, - {1.0f, 1.0f, -1.0f}, - {1.0f, -1.0f, -1.0f}, - {-1.0f, -1.0f, -1.0f}, - {-1.0f, 1.0f, -1.0f}}; + float p[5][3] = { + {0.0f, 0.0f, 0.0f}, + {1.0f, 1.0f, -1.0f}, + {1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}, + }; uint v_idx = 0; @@ -1777,11 +1789,13 @@ GPUBatch *DRW_cache_light_spot_square_get(void) GPUBatch *DRW_cache_light_spot_square_volume_get(void) { if (!SHC.drw_light_spot_square_volume) { - float p[5][3] = {{0.0f, 0.0f, 0.0f}, - {1.0f, 1.0f, -1.0f}, - {1.0f, -1.0f, -1.0f}, - {-1.0f, -1.0f, -1.0f}, - {-1.0f, 1.0f, -1.0f}}; + float p[5][3] = { + {0.0f, 0.0f, 0.0f}, + {1.0f, 1.0f, -1.0f}, + {1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}, + }; uint v_idx = 0; @@ -2039,10 +2053,10 @@ static const float bone_octahedral_verts[6][3] = { static const float bone_octahedral_smooth_normals[6][3] = { {0.0f, -1.0f, 0.0f}, #if 0 /* creates problems for outlines when scaled */ - { 0.943608f * M_SQRT1_2, -0.331048f, 0.943608f * M_SQRT1_2}, - { 0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2}, - {-0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2}, - {-0.943608f * M_SQRT1_2, -0.331048f, 0.943608f * M_SQRT1_2}, + {0.943608f * M_SQRT1_2, -0.331048f, 0.943608f * M_SQRT1_2}, + {0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2}, + {-0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2}, + {-0.943608f * M_SQRT1_2, -0.331048f, 0.943608f * M_SQRT1_2}, #else {M_SQRT1_2, 0.0f, M_SQRT1_2}, {M_SQRT1_2, 0.0f, -M_SQRT1_2}, @@ -2055,17 +2069,13 @@ static const float bone_octahedral_smooth_normals[6][3] = { #if 0 /* UNUSED */ static const uint bone_octahedral_wire[24] = { - 0, 1, 1, 5, 5, 3, 3, 0, - 0, 4, 4, 5, 5, 2, 2, 0, - 1, 2, 2, 3, 3, 4, 4, 1, + 0, 1, 1, 5, 5, 3, 3, 0, 0, 4, 4, 5, 5, 2, 2, 0, 1, 2, 2, 3, 3, 4, 4, 1, }; /* aligned with bone_octahedral_wire * Contains adjacent normal index */ static const uint bone_octahedral_wire_adjacent_face[24] = { - 0, 3, 4, 7, 5, 6, 1, 2, - 2, 3, 6, 7, 4, 5, 0, 1, - 0, 4, 1, 5, 2, 6, 3, 7, + 0, 3, 4, 7, 5, 6, 1, 2, 2, 3, 6, 7, 4, 5, 0, 1, 0, 4, 1, 5, 2, 6, 3, 7, }; #endif @@ -2109,15 +2119,15 @@ static const uint bone_octahedral_wire_lines_adjacency[12][4] = { #if 0 /* UNUSED */ static const uint bone_octahedral_solid_tris_adjacency[8][6] = { - { 0, 12, 1, 10, 2, 3}, - { 3, 15, 4, 1, 5, 6}, - { 6, 18, 7, 4, 8, 9}, - { 9, 21, 10, 7, 11, 0}, - - {12, 22, 13, 2, 14, 17}, - {15, 13, 16, 5, 17, 20}, - {18, 16, 19, 8, 20, 23}, - {21, 19, 22, 11, 23, 14}, + {0, 12, 1, 10, 2, 3}, + {3, 15, 4, 1, 5, 6}, + {6, 18, 7, 4, 8, 9}, + {9, 21, 10, 7, 11, 0}, + + {12, 22, 13, 2, 14, 17}, + {15, 13, 16, 5, 17, 20}, + {18, 16, 19, 8, 20, 23}, + {21, 19, 22, 11, 23, 14}, }; #endif @@ -2219,17 +2229,13 @@ static const float bone_box_smooth_normals[8][3] = { #if 0 /* UNUSED */ static const uint bone_box_wire[24] = { - 0, 1, 1, 2, 2, 3, 3, 0, - 4, 5, 5, 6, 6, 7, 7, 4, - 0, 4, 1, 5, 2, 6, 3, 7, + 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7, }; /* aligned with bone_octahedral_wire * Contains adjacent normal index */ static const uint bone_box_wire_adjacent_face[24] = { - 0, 2, 0, 4, 1, 6, 1, 8, - 3, 10, 5, 10, 7, 11, 9, 11, - 3, 8, 2, 5, 4, 7, 6, 9, + 0, 2, 0, 4, 1, 6, 1, 8, 3, 10, 5, 10, 7, 11, 9, 11, 3, 8, 2, 5, 4, 7, 6, 9, }; #endif @@ -2274,23 +2280,23 @@ static const uint bone_box_wire_lines_adjacency[12][4] = { #if 0 /* UNUSED */ static const uint bone_box_solid_tris_adjacency[12][6] = { - { 0, 5, 1, 14, 2, 8}, - { 3, 26, 4, 20, 5, 1}, + {0, 5, 1, 14, 2, 8}, + {3, 26, 4, 20, 5, 1}, - { 6, 2, 7, 16, 8, 11}, - { 9, 7, 10, 32, 11, 24}, + {6, 2, 7, 16, 8, 11}, + {9, 7, 10, 32, 11, 24}, - {12, 0, 13, 22, 14, 17}, - {15, 13, 16, 30, 17, 6}, + {12, 0, 13, 22, 14, 17}, + {15, 13, 16, 30, 17, 6}, - {18, 3, 19, 28, 20, 23}, - {21, 19, 22, 33, 23, 12}, + {18, 3, 19, 28, 20, 23}, + {21, 19, 22, 33, 23, 12}, - {24, 4, 25, 10, 26, 29}, - {27, 25, 28, 34, 29, 18}, + {24, 4, 25, 10, 26, 29}, + {27, 25, 28, 34, 29, 18}, - {30, 9, 31, 15, 32, 35}, - {33, 31, 34, 21, 35, 27}, + {30, 9, 31, 15, 32, 35}, + {33, 31, 34, 21, 35, 27}, }; #endif @@ -2499,8 +2505,10 @@ GPUBatch *DRW_cache_bone_point_get(void) const float lat_inc = M_PI / lat_res; uint v_idx = 0; - static GPUVertFormat format = { 0 }; - static struct { uint pos, nor; } attr_id; + static GPUVertFormat format = {0}; + static struct { + uint pos, nor; + } attr_id; if (format.attr_len == 0) { attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); @@ -2515,15 +2523,17 @@ GPUBatch *DRW_cache_bone_point_get(void) float lat = 0.0f; for (int j = 0; j < lat_res; j++, lat += lat_inc) { if (j != lat_res - 1) { /* Pole */ - add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc); + add_lat_lon_vert( + vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc); add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon); - add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon); } if (j != 0) { /* Pole */ - add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon + lon_inc); - add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc); - add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon + lon_inc); + add_lat_lon_vert( + vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon); } } } @@ -2755,10 +2765,14 @@ static float z_axis_name[10][2] = { #define S_Y 0.007f static float axis_marker[8][2] = { #if 0 /* square */ - {-1.0f * S_X, 1.0f * S_Y}, { 1.0f * S_X, 1.0f * S_Y}, - { 1.0f * S_X, 1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y}, - { 1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y}, - {-1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, 1.0f * S_Y} + {-1.0f * S_X, 1.0f * S_Y}, + {1.0f * S_X, 1.0f * S_Y}, + {1.0f * S_X, 1.0f * S_Y}, + {1.0f * S_X, -1.0f * S_Y}, + {1.0f * S_X, -1.0f * S_Y}, + {-1.0f * S_X, -1.0f * S_Y}, + {-1.0f * S_X, -1.0f * S_Y}, + {-1.0f * S_X, 1.0f * S_Y} #else /* diamond */ {-S_X, 0.f}, {0.f, S_Y}, @@ -3003,7 +3017,8 @@ GPUBatch *DRW_cache_bone_dof_lines_get(void) * We could make these more generic functions. * although filling 1d lines is not common. * - * \note Use x coordinate to identify the vertex the vertex shader take care to place it appropriately. + * \note Use x coordinate to identify the vertex the vertex shader take care to place it + * appropriately. */ static const float camera_coords_frame_bounds[5] = { @@ -3269,6 +3284,12 @@ GPUBatch *DRW_cache_mesh_face_wireframe_get(Object *ob) return DRW_mesh_batch_cache_get_wireframes_face(ob->data); } +GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + return DRW_mesh_batch_cache_get_edit_mesh_analysis(ob->data); +} + void DRW_cache_mesh_sculpt_coords_ensure(Object *ob) { BLI_assert(ob->type == OB_MESH); @@ -3288,7 +3309,13 @@ GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob) BLI_assert(ob->type == OB_CURVE); struct Curve *cu = ob->data; - return DRW_curve_batch_cache_get_wire_edge(cu); + struct Mesh *mesh_eval = ob->runtime.mesh_eval; + if (mesh_eval != NULL) { + return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); + } + else { + return DRW_curve_batch_cache_get_wire_edge(cu); + } } GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob) @@ -3434,7 +3461,13 @@ GPUBatch *DRW_cache_text_edge_wire_get(Object *ob) BLI_assert(ob->type == OB_FONT); struct Curve *cu = ob->data; - return DRW_curve_batch_cache_get_wire_edge(cu); + struct Mesh *mesh_eval = ob->runtime.mesh_eval; + if (mesh_eval != NULL) { + return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); + } + else { + return DRW_curve_batch_cache_get_wire_edge(cu); + } } GPUBatch *DRW_cache_text_surface_get(Object *ob) @@ -3546,7 +3579,13 @@ GPUBatch *DRW_cache_surf_edge_wire_get(Object *ob) BLI_assert(ob->type == OB_SURF); struct Curve *cu = ob->data; - return DRW_curve_batch_cache_get_wire_edge(cu); + struct Mesh *mesh_eval = ob->runtime.mesh_eval; + if (mesh_eval != NULL) { + return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); + } + else { + return DRW_curve_batch_cache_get_wire_edge(cu); + } } GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob) @@ -4017,4 +4056,25 @@ void drw_batch_cache_generate_requested(Object *ob) } } +void DRW_batch_cache_free_old(Object *ob, int ctime) +{ + struct Mesh *mesh_eval = ob->runtime.mesh_eval; + + switch (ob->type) { + case OB_MESH: + DRW_mesh_batch_cache_free_old((Mesh *)ob->data, ctime); + break; + case OB_CURVE: + case OB_FONT: + case OB_SURF: + if (mesh_eval) { + DRW_mesh_batch_cache_free_old(mesh_eval, ctime); + } + break; + /* TODO all cases */ + default: + break; + } +} + /** \} */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index c9ae0a01cb9..129b180957a 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -140,6 +140,7 @@ struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_vertpaint_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob); +struct GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob); void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob); diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 94d8a82f2e4..4ef8f5a9326 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -61,6 +61,11 @@ void DRW_particle_batch_cache_free(struct ParticleSystem *psys); void DRW_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd); void DRW_gpencil_batch_cache_free(struct bGPdata *gpd); +/* Garbage collection */ +void DRW_batch_cache_free_old(struct Object *ob, int ctime); + +void DRW_mesh_batch_cache_free_old(struct Mesh *me, int ctime); + /* Curve */ void DRW_curve_batch_cache_create_requested(struct Object *ob); @@ -152,6 +157,7 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me); /* For Image UV editor. */ struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me); void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me); @@ -199,10 +205,19 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *ob struct PTCacheEdit *edit); /* Common */ -#define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ - (flag |= DRW_vbo_requested(vbo) ? (value) : 0) -#define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ - (flag |= DRW_ibo_requested(ibo) ? (value) : 0) +// #define DRW_DEBUG_MESH_CACHE_REQUEST + +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST +# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ + (flag |= DRW_vbo_requested(vbo) ? (printf(" VBO requested " #vbo "\n") ? value : value) : 0) +# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ + (flag |= DRW_ibo_requested(ibo) ? (printf(" IBO requested " #ibo "\n") ? value : value) : 0) +#else +# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ + (flag |= DRW_vbo_requested(vbo) ? (value) : 0) +# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ + (flag |= DRW_ibo_requested(ibo) ? (value) : 0) +#endif /* Test and assign NULL if test fails */ #define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL)) diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index 8e7a2253e21..33b872109a5 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -988,6 +988,10 @@ void DRW_curve_batch_cache_create_requested(Object *ob) } } +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST + printf("-- %s %s --\n", __func__, ob->id.name + 2); +#endif + /* Generate MeshRenderData flags */ int mr_flag = 0; DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, CU_DATATYPE_SURFACE); @@ -1011,6 +1015,10 @@ void DRW_curve_batch_cache_create_requested(Object *ob) DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], CU_DATATYPE_SURFACE); } +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST + printf(" mr_flag %d\n\n", mr_flag); +#endif + CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag); /* DispLists */ diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index ded9d0963b7..1d8c7f0e5a7 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -304,7 +304,7 @@ typedef struct MeshRenderData { bool *edge_visible_bool; } MeshRenderData; -enum { +typedef enum eMRDataType { MR_DATATYPE_VERT = 1 << 0, MR_DATATYPE_EDGE = 1 << 1, MR_DATATYPE_LOOPTRI = 1 << 2, @@ -317,11 +317,16 @@ enum { MR_DATATYPE_LOOPUV = 1 << 9, MR_DATATYPE_LOOSE_VERT = 1 << 10, MR_DATATYPE_LOOSE_EDGE = 1 << 11, -}; + MR_DATATYPE_LOOP_NORMALS = 1 << 12, +} eMRDataType; + +#define MR_DATATYPE_VERT_LOOP_POLY (MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP) +#define MR_DATATYPE_VERT_LOOP_TRI_POLY (MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_LOOPTRI) +#define MR_DATATYPE_LOOSE_VERT_EGDE (MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE) /** - * These functions look like they would be slow but they will typically return true on the first iteration. - * Only false when all attached elements are hidden. + * These functions look like they would be slow but they will typically return true on the first + * iteration. Only false when all attached elements are hidden. */ static bool bm_vert_has_visible_edge(const BMVert *v) { @@ -364,6 +369,11 @@ BLI_INLINE bool mesh_cd_layers_type_overlap(DRW_MeshCDMask a, DRW_MeshCDMask b) return (*((uint32_t *)&a) & *((uint32_t *)&b)) == *((uint32_t *)&b); } +BLI_INLINE bool mesh_cd_layers_type_equal(DRW_MeshCDMask a, DRW_MeshCDMask b) +{ + return *((uint32_t *)&a) == *((uint32_t *)&b); +} + BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b) { atomic_fetch_and_or_uint32((uint32_t *)a, *(uint32_t *)&b); @@ -670,9 +680,17 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me, bm_ensure_types |= BM_LOOP; } if (types & MR_DATATYPE_LOOP) { - int totloop = bm->totloop; + rdata->loop_len = bm->totloop; + bm_ensure_types |= BM_LOOP; + } + if (types & MR_DATATYPE_POLY) { + rdata->poly_len = bm->totface; + bm_ensure_types |= BM_FACE; + } + if (types & MR_DATATYPE_LOOP_NORMALS) { + BLI_assert(types & MR_DATATYPE_LOOP); if (is_auto_smooth) { - rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__); + rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * bm->totloop, __func__); int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); BM_loops_calc_normal_vcos(bm, NULL, @@ -686,12 +704,6 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me, cd_loop_clnors_offset, false); } - rdata->loop_len = totloop; - bm_ensure_types |= BM_LOOP; - } - if (types & MR_DATATYPE_POLY) { - rdata->poly_len = bm->totface; - bm_ensure_types |= BM_FACE; } if (types & MR_DATATYPE_OVERLAY) { rdata->efa_act_uv = EDBM_uv_active_face_get(embm, false, false); @@ -828,7 +840,9 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me, if (types & MR_DATATYPE_LOOP) { rdata->loop_len = me->totloop; rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); - + } + if (types & MR_DATATYPE_LOOP_NORMALS) { + BLI_assert(types & MR_DATATYPE_LOOP); if (is_auto_smooth) { mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata); } @@ -1145,7 +1159,8 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me, /* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT', * not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */ - /* note: normally we'd use 'i_src' here, but 'i_dst' is in sync with 'rdata->cd.output' */ + /* note: normally we'd use 'i_src' here, but 'i_dst' is in sync with 'rdata->cd.output' + */ rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n( &rdata->cd.output.ldata, CD_TANGENT, i_dst); if (rdata->tri_len != 0) { @@ -1344,10 +1359,6 @@ static int mesh_render_data_polys_len_get_maybe_mapped(const MeshRenderData *rda /* ---------------------------------------------------------------------- */ -/* TODO remove prototype. */ -static void mesh_create_edit_facedots(MeshRenderData *rdata, - GPUVertBuf *vbo_facedots_pos_nor_data); - /** \name Internal Cache (Lazy Initialization) * \{ */ @@ -1645,7 +1656,7 @@ static void mesh_render_data_edge_flag(const MeshRenderData *rdata, * specular highlights make it hard to see T55456#510873. * * This isn't ideal since it can't be used when mixing edge/face modes - * but it's still better then not being able to see the active face. */ + * but it's still better then not being able to see the active face. */ if (is_face_only_select_mode) { if (rdata->efa_act != NULL) { if (BM_edge_in_face(eed, rdata->efa_act)) { @@ -1906,6 +1917,7 @@ typedef struct MeshBatchCache { GPUVertBuf *loop_data; GPUVertBuf *loop_lnor; GPUVertBuf *facedots_pos_nor_data; + GPUVertBuf *loop_mesh_analysis; /* UV data without modifier applied. * Vertex count is always the one of the cage. */ GPUVertBuf *loop_uv; @@ -1953,6 +1965,7 @@ typedef struct MeshBatchCache { GPUBatch *edit_edges; GPUBatch *edit_lnor; GPUBatch *edit_facedots; + GPUBatch *edit_mesh_analysis; /* Edit UVs */ GPUBatch *edituv_faces_strech_area; GPUBatch *edituv_faces_strech_angle; @@ -1997,7 +2010,9 @@ typedef struct MeshBatchCache { struct DRW_MeshWeightState weight_state; - DRW_MeshCDMask cd_used, cd_needed; + DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time; + + int lastmatch; /* XXX, only keep for as long as sculpt mode uses shaded drawing. */ bool is_sculpt_points_tag; @@ -2121,6 +2136,8 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) MEM_SAFE_FREE(cache->auto_layer_names); MEM_SAFE_FREE(cache->auto_layer_is_srgb); + mesh_cd_layers_type_clear(&cache->cd_used); + cache->mat_len = 0; } @@ -2160,8 +2177,13 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_BATCH_DISCARD_SAFE(cache->batch.edit_vertices); GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges); GPU_BATCH_DISCARD_SAFE(cache->batch.edit_facedots); - /* Paint mode selection */ - /* TODO only do that in paint mode. */ + GPU_BATCH_DISCARD_SAFE(cache->batch.edit_mesh_analysis); + /* Because visible UVs depends on edit mode selection, discard everything. */ + mesh_batch_cache_discard_uvedit(cache); + break; + case BKE_MESH_BATCH_DIRTY_SELECT_PAINT: + /* Paint mode selection flag is packed inside the nor attrib. + * Note that it can be slow if auto smooth is enabled. (see T63946) */ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_pos_nor); GPU_BATCH_DISCARD_SAFE(cache->batch.surface); GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops); @@ -2170,8 +2192,6 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]); } } - /* Because visible UVs depends on edit mode selection, discard everything. */ - mesh_batch_cache_discard_uvedit(cache); break; case BKE_MESH_BATCH_DIRTY_ALL: cache->is_dirty = true; @@ -3128,7 +3148,8 @@ static void mesh_create_loop_uv_and_tan(MeshRenderData *rdata, GPUVertBuf *vbo) for (uint i = 0; i < uv_len; i++) { const char *attr_name = mesh_render_data_uv_layer_uuid_get(rdata, i); #if 0 /* these are clamped. Maybe use them as an option in the future */ - uv_id[i] = GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); + uv_id[i] = GPU_vertformat_attr_add( + &format, attr_name, GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); #else uv_id[i] = GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); #endif @@ -3373,6 +3394,71 @@ static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_fac } } +static void mesh_create_edit_mesh_analysis(MeshRenderData *rdata, GPUVertBuf *vbo_mesh_analysis) +{ + const MeshStatVis *mesh_stat_vis = &rdata->toolsettings->statvis; + + int mesh_analysis_len_used = 0; + + const uint loops_len = mesh_render_data_loops_len_get(rdata); + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter_efa, iter_loop; + BMFace *efa; + BMLoop *loop; + + static struct { + uint weight; + } attr_id; + static GPUVertFormat mesh_analysis_format = {0}; + if (mesh_analysis_format.attr_len == 0) { + attr_id.weight = GPU_vertformat_attr_add( + &mesh_analysis_format, "weight_color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + /* TODO(jbakker): Maybe move data generation to mesh_render_data_create() */ + BKE_editmesh_statvis_calc(rdata->edit_bmesh, rdata->edit_data, mesh_stat_vis); + + if (DRW_TEST_ASSIGN_VBO(vbo_mesh_analysis)) { + GPU_vertbuf_init_with_format(vbo_mesh_analysis, &mesh_analysis_format); + GPU_vertbuf_data_alloc(vbo_mesh_analysis, loops_len); + } + + const bool is_vertex_data = mesh_stat_vis->type == SCE_STATVIS_SHARP; + if (is_vertex_data) { + BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) { + uint vertex_index = BM_elem_index_get(loop->v); + GPU_vertbuf_attr_set(vbo_mesh_analysis, + attr_id.weight, + mesh_analysis_len_used, + &rdata->edit_bmesh->derivedVertColor[vertex_index]); + mesh_analysis_len_used += 1; + } + } + } + else { + uint face_index; + BM_ITER_MESH_INDEX (efa, &iter_efa, bm, BM_FACES_OF_MESH, face_index) { + BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) { + GPU_vertbuf_attr_set(vbo_mesh_analysis, + attr_id.weight, + mesh_analysis_len_used, + &rdata->edit_bmesh->derivedFaceColor[face_index]); + mesh_analysis_len_used += 1; + } + } + } + + // Free temp data in edit bmesh + BKE_editmesh_color_free(rdata->edit_bmesh); + + /* Resize & Finish */ + if (mesh_analysis_len_used != loops_len) { + if (vbo_mesh_analysis != NULL) { + GPU_vertbuf_data_resize(vbo_mesh_analysis, mesh_analysis_len_used); + } + } +} /* Indices */ #define NO_EDGE INT_MAX @@ -4185,6 +4271,12 @@ GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me) return DRW_batch_request(&cache->batch.wire_edges); } +GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + return DRW_batch_request(&cache->batch.edit_mesh_analysis); +} + GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len, @@ -4197,16 +4289,16 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, BLI_assert(gpumat_array_len == cache->mat_len); - bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cd_needed); - if (!cd_overlap) { - mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); + mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); + if (!mesh_cd_layers_type_overlap(cache->cd_used, cd_needed)) { mesh_cd_extract_auto_layers_names_and_srgb(me, cache->cd_needed, &cache->auto_layer_names, &cache->auto_layer_is_srgb, &cache->auto_layer_len); } + if (auto_layer_names) { *auto_layer_names = cache->auto_layer_names; *auto_layer_is_srgb = cache->auto_layer_is_srgb; @@ -4419,8 +4511,7 @@ BLI_INLINE void edit_uv_preprocess_stretch_angle(float (*auv)[2], BMLoop *l; BMIter liter; int i; - BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) - { + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset); @@ -4433,8 +4524,10 @@ BLI_INLINE void edit_uv_preprocess_stretch_angle(float (*auv)[2], } #if 0 /* here for reference, this is done in shader now. */ -BLI_INLINE float edit_uv_get_loop_stretch_angle( - const float auv0[2], const float auv1[2], const float av0[3], const float av1[3]) +BLI_INLINE float edit_uv_get_loop_stretch_angle(const float auv0[2], + const float auv1[2], + const float av0[3], + const float av1[3]) { float uvang = angle_normalized_v2v2(auv0, auv1); float ang = angle_normalized_v3v3(av0, av1); @@ -4509,16 +4602,25 @@ static void uvedit_fill_buffer_data(MeshRenderData *rdata, } /* Skip hidden faces. */ - if (elb_face && face_visible) { - for (i = 0; i < efa->len; ++i) { - GPU_indexbuf_add_generic_vert(elb_face, vidx + i); - GPU_indexbuf_add_generic_vert(elb_vert, vidx + i); - GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % efa->len); + if (face_visible) { + if (elb_face) { + for (i = 0; i < efa->len; ++i) { + GPU_indexbuf_add_generic_vert(elb_face, vidx + i); + } + } + if (elb_vert) { + for (i = 0; i < efa->len; ++i) { + GPU_indexbuf_add_generic_vert(elb_vert, vidx + i); + } + } + if (elb_edge) { + for (i = 0; i < efa->len; ++i) { + GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % efa->len); + } } } - BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) - { + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (vbo_area) { GPU_vertbuf_attr_set(vbo_area, uv_attr_id.area, vidx, &area_stretch); @@ -4578,18 +4680,24 @@ static void uvedit_fill_buffer_data(MeshRenderData *rdata, GPU_vertbuf_attr_set(vbo_fdots_data, uv_attr_id.fdots_flag, fdot_idx, &face_flag); } /* Skip hidden faces. */ - if (elb_face && face_visible) { - for (i = 0; i < mpoly->totloop; ++i) { - GPU_indexbuf_add_generic_vert(elb_face, vidx + i); - if (e_origindex[l[i].e] != ORIGINDEX_NONE) { + if (face_visible) { + if (elb_face) { + for (i = 0; i < mpoly->totloop; ++i) { + GPU_indexbuf_add_generic_vert(elb_face, vidx + i); + } + GPU_indexbuf_add_generic_vert(elb_face, vidx); + GPU_indexbuf_add_primitive_restart(elb_face); + } + if (elb_edge && e_origindex[l[i].e] != ORIGINDEX_NONE) { + for (i = 0; i < mpoly->totloop; ++i) { GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % mpoly->totloop); } - if (v_origindex[l[i].v] != ORIGINDEX_NONE) { + } + if (elb_vert && v_origindex[l[i].v] != ORIGINDEX_NONE) { + for (i = 0; i < mpoly->totloop; ++i) { GPU_indexbuf_add_generic_vert(elb_vert, vidx + i); } } - GPU_indexbuf_add_generic_vert(elb_face, vidx); - GPU_indexbuf_add_primitive_restart(elb_face); } for (i = 0; i < mpoly->totloop; i++, l++) { /* TODO support stretch. */ @@ -4714,6 +4822,28 @@ static void mesh_create_uvedit_buffers(MeshRenderData *rdata, /** \name Grouped batch generation * \{ */ +/* Thread safety need to be assured by caller. Don't call this during drawing. + * Note: For now this only free the shading batches / vbo if any cd layers is + * not needed anymore. */ +void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + + if (cache == NULL) { + return; + } + + if (mesh_cd_layers_type_equal(cache->cd_used_over_time, cache->cd_used)) { + cache->lastmatch = ctime; + } + + if (ctime - cache->lastmatch > U.vbotimeout) { + mesh_batch_cache_discard_shaded_tri(cache); + } + + mesh_cd_layers_type_clear(&cache->cd_used_over_time); +} + /* Can be called for any surface type. Mesh *me is the final mesh. */ void DRW_mesh_batch_cache_create_requested( Object *ob, Mesh *me, const ToolSettings *ts, const bool is_paint_mode, const bool use_hide) @@ -4730,6 +4860,18 @@ void DRW_mesh_batch_cache_create_requested( drw_mesh_weight_state_clear(&wstate); } + /* Optimization : Only create orco layer if mesh is deformed. */ + if (cache->cd_needed.orco != 0) { + CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata; + if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && ob->modifiers.first != NULL) { + /* Orco layer is needed. */ + } + else if (cache->cd_needed.tan_orco == 0) { + /* Skip orco calculation if not needed by tangent generation. */ + cache->cd_needed.orco = 0; + } + } + /* Verify that all surface batches have needed attribute layers. */ /* TODO(fclem): We could be a bit smarter here and only do it per material. */ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed); @@ -4754,6 +4896,7 @@ void DRW_mesh_batch_cache_create_requested( mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed); } + mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed); mesh_cd_layers_type_clear(&cache->cd_needed); /* Discard UV batches if sync_selection changes */ @@ -4779,8 +4922,10 @@ void DRW_mesh_batch_cache_create_requested( } } + bool has_request = false; /* Init batches and request VBOs & IBOs */ if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) { + has_request = true; DRW_ibo_request(cache->batch.surface, &cache->ibo.loops_tris); DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_pos_nor); /* For paint overlay. Active layer should have been queried. */ @@ -4792,35 +4937,43 @@ void DRW_mesh_batch_cache_create_requested( } } if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) { + has_request = true; DRW_vbo_request(cache->batch.all_verts, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.all_edges, GPU_PRIM_LINES)) { + has_request = true; DRW_ibo_request(cache->batch.all_edges, &cache->ibo.edges_lines); DRW_vbo_request(cache->batch.all_edges, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)) { + has_request = true; DRW_ibo_request(cache->batch.loose_edges, &cache->ibo.loose_edges_lines); DRW_vbo_request(cache->batch.loose_edges, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) { + has_request = true; DRW_ibo_request(cache->batch.edge_detection, &cache->ibo.edges_adj_lines); DRW_vbo_request(cache->batch.edge_detection, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.surface_weights, GPU_PRIM_TRIS)) { + has_request = true; DRW_ibo_request(cache->batch.surface_weights, &cache->ibo.surf_tris); DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.pos_nor); DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.weights); } if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINE_STRIP)) { + has_request = true; DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_line_strips); DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor); } if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) { + has_request = true; DRW_ibo_request(cache->batch.wire_edges, &cache->ibo.loops_lines); DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_pos_nor); DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_edge_fac); } if (DRW_batch_requested(cache->batch.wire_loops_uvs, GPU_PRIM_LINE_STRIP)) { + has_request = true; DRW_ibo_request(cache->batch.wire_loops_uvs, &cache->ibo.loops_line_strips); /* For paint overlay. Active layer should have been queried. */ if (cache->cd_used.uv != 0) { @@ -4830,58 +4983,77 @@ void DRW_mesh_batch_cache_create_requested( /* Edit Mesh */ if (DRW_batch_requested(cache->batch.edit_triangles, GPU_PRIM_TRIS)) { + has_request = true; DRW_ibo_request(cache->batch.edit_triangles, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.loop_data); } if (DRW_batch_requested(cache->batch.edit_vertices, GPU_PRIM_POINTS)) { + has_request = true; DRW_ibo_request(cache->batch.edit_vertices, &cache->ibo.edit_loops_points); DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.loop_data); } if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) { + has_request = true; DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_loops_lines); DRW_vbo_request(cache->batch.edit_edges, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_edges, &cache->edit.loop_data); } if (DRW_batch_requested(cache->batch.edit_lnor, GPU_PRIM_POINTS)) { + has_request = true; DRW_ibo_request(cache->batch.edit_lnor, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_lnor, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_lnor, &cache->edit.loop_lnor); } if (DRW_batch_requested(cache->batch.edit_facedots, GPU_PRIM_POINTS)) { + has_request = true; DRW_vbo_request(cache->batch.edit_facedots, &cache->edit.facedots_pos_nor_data); } + /* Mesh Analysis */ + if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) { + has_request = true; + DRW_ibo_request(cache->batch.edit_mesh_analysis, &cache->ibo.edit_loops_tris); + DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_pos_nor); + DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_mesh_analysis); + } + /* Edit UV */ if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRI_FAN)) { + has_request = true; DRW_ibo_request(cache->batch.edituv_faces, &cache->ibo.edituv_loops_tri_fans); DRW_vbo_request(cache->batch.edituv_faces, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_faces, &cache->edit.loop_uv_data); } if (DRW_batch_requested(cache->batch.edituv_faces_strech_area, GPU_PRIM_TRI_FAN)) { + has_request = true; DRW_ibo_request(cache->batch.edituv_faces_strech_area, &cache->ibo.edituv_loops_tri_fans); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_uv_data); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_stretch_area); } if (DRW_batch_requested(cache->batch.edituv_faces_strech_angle, GPU_PRIM_TRI_FAN)) { + has_request = true; DRW_ibo_request(cache->batch.edituv_faces_strech_angle, &cache->ibo.edituv_loops_tri_fans); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_uv_data); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_stretch_angle); } if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) { + has_request = true; DRW_ibo_request(cache->batch.edituv_edges, &cache->ibo.edituv_loops_line_strips); DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv_data); } if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) { + has_request = true; DRW_ibo_request(cache->batch.edituv_verts, &cache->ibo.edituv_loops_points); DRW_vbo_request(cache->batch.edituv_verts, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_verts, &cache->edit.loop_uv_data); } if (DRW_batch_requested(cache->batch.edituv_facedots, GPU_PRIM_POINTS)) { + has_request = true; DRW_vbo_request(cache->batch.edituv_facedots, &cache->edit.facedots_uv); DRW_vbo_request(cache->batch.edituv_facedots, &cache->edit.facedots_uv_data); } @@ -4889,21 +5061,25 @@ void DRW_mesh_batch_cache_create_requested( /* Selection */ /* TODO reuse ordered.loop_pos_nor if possible. */ if (DRW_batch_requested(cache->batch.edit_selection_verts, GPU_PRIM_POINTS)) { + has_request = true; DRW_ibo_request(cache->batch.edit_selection_verts, &cache->ibo.edit_loops_points); DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_vert_idx); } if (DRW_batch_requested(cache->batch.edit_selection_edges, GPU_PRIM_LINES)) { + has_request = true; DRW_ibo_request(cache->batch.edit_selection_edges, &cache->ibo.edit_loops_lines); DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_edge_idx); } if (DRW_batch_requested(cache->batch.edit_selection_faces, GPU_PRIM_TRIS)) { + has_request = true; DRW_ibo_request(cache->batch.edit_selection_faces, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_face_idx); } if (DRW_batch_requested(cache->batch.edit_selection_facedots, GPU_PRIM_POINTS)) { + has_request = true; DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_pos_nor_data); DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_idx); } @@ -4911,6 +5087,7 @@ void DRW_mesh_batch_cache_create_requested( /* Per Material */ for (int i = 0; i < cache->mat_len; ++i) { if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) { + has_request = true; if (cache->mat_len > 1) { DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]); } @@ -4926,47 +5103,39 @@ void DRW_mesh_batch_cache_create_requested( DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_vcol); } if (cache->cd_used.orco != 0) { - /* OPTI : Only do that if there is modifiers that modify orcos. */ - CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata; - if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && ob->modifiers.first != NULL) { - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_orco); - } - else if (cache->cd_used.tan_orco == 0) { - /* Skip orco calculation if not needed by tangent generation. */ - cache->cd_used.orco = 0; - } + DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_orco); } } } + /* Early out if no request. */ + if (!has_request) { + return; + } + +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST + printf("-- %s %s --\n", __func__, ob->id.name + 2); +#endif + /* Generate MeshRenderData flags */ - int mr_flag = 0, mr_edit_flag = 0; - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, MR_DATATYPE_VERT); + eMRDataType mr_flag = 0, mr_edit_flag = 0; + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_flag, cache->ordered.pos_nor, MR_DATATYPE_VERT /* A comment to wrap the line ;) */); DRW_ADD_FLAG_FROM_VBO_REQUEST( mr_flag, cache->ordered.weights, MR_DATATYPE_VERT | MR_DATATYPE_DVERT); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, - cache->ordered.loop_pos_nor, - MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, - cache->ordered.loop_uv_tan, - MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | - MR_DATATYPE_SHADING | MR_DATATYPE_LOOPTRI); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, - cache->ordered.loop_orco, - MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | - MR_DATATYPE_SHADING); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, - cache->ordered.loop_vcol, - MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | - MR_DATATYPE_SHADING); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, - cache->ordered.loop_edge_fac, - MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_EDGE | - MR_DATATYPE_LOOP); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, - cache->ibo.surf_tris, - MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | - MR_DATATYPE_LOOPTRI); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_flag, cache->ordered.loop_pos_nor, MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_LOOP_NORMALS); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_flag, cache->ordered.loop_uv_tan, MR_DATATYPE_VERT_LOOP_TRI_POLY | MR_DATATYPE_SHADING); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_flag, cache->ordered.loop_orco, MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_SHADING); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_flag, cache->ordered.loop_vcol, MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_SHADING); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_flag, cache->ordered.loop_edge_fac, MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_EDGE); + + DRW_ADD_FLAG_FROM_IBO_REQUEST( + mr_flag, cache->ibo.surf_tris, MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_LOOPTRI); DRW_ADD_FLAG_FROM_IBO_REQUEST( mr_flag, cache->ibo.loops_tris, MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI); DRW_ADD_FLAG_FROM_IBO_REQUEST( @@ -4975,74 +5144,69 @@ void DRW_mesh_batch_cache_create_requested( mr_flag, cache->ibo.loops_line_strips, MR_DATATYPE_LOOP | MR_DATATYPE_POLY); DRW_ADD_FLAG_FROM_IBO_REQUEST( mr_flag, cache->ibo.edges_lines, MR_DATATYPE_VERT | MR_DATATYPE_EDGE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, - cache->ibo.edges_adj_lines, - MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | - MR_DATATYPE_LOOPTRI); + DRW_ADD_FLAG_FROM_IBO_REQUEST( + mr_flag, cache->ibo.edges_adj_lines, MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_LOOPTRI); DRW_ADD_FLAG_FROM_IBO_REQUEST( mr_flag, cache->ibo.loose_edges_lines, MR_DATATYPE_VERT | MR_DATATYPE_EDGE); for (int i = 0; i < cache->mat_len; ++i) { - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, - cache->surf_per_mat_tris[i], - MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI); - } - - int combined_edit_flag = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | - MR_DATATYPE_POLY | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | - MR_DATATYPE_OVERLAY; - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_pos_nor, combined_edit_flag); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_lnor, combined_edit_flag); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_data, combined_edit_flag); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_uv_data, combined_edit_flag); + int combined_flag = MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI; + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], combined_flag); + } + + int combined_edit_flag = MR_DATATYPE_VERT_LOOP_POLY | MR_DATATYPE_EDGE | + MR_DATATYPE_LOOSE_VERT_EGDE; + int combined_edit_with_lnor_flag = combined_edit_flag | MR_DATATYPE_LOOP_NORMALS; + int combined_edituv_flag = combined_edit_flag | MR_DATATYPE_LOOPUV; + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_pos_nor, combined_edit_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_lnor, combined_edit_with_lnor_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_data, combined_edit_flag | MR_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_VBO_REQUEST( - mr_edit_flag, cache->edit.loop_uv, combined_edit_flag | MR_DATATYPE_LOOPUV); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, - cache->edit.loop_vert_idx, - MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | - MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, - cache->edit.loop_edge_idx, - MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | - MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, - cache->edit.loop_face_idx, - MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | - MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); + mr_edit_flag, cache->edit.loop_uv_data, combined_edit_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_uv, combined_edituv_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_stretch_angle, combined_edit_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_stretch_area, combined_edit_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.loop_mesh_analysis, MR_DATATYPE_VERT_LOOP_POLY); + + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_vert_idx, combined_edit_flag); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_edge_idx, combined_edit_flag); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_face_idx, combined_edit_flag); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.facedots_idx, MR_DATATYPE_POLY); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, - cache->edit.facedots_pos_nor_data, - MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | - MR_DATATYPE_OVERLAY); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_stretch_angle, combined_edit_flag); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_stretch_area, combined_edit_flag); + + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.facedots_pos_nor_data, MR_DATATYPE_POLY | MR_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_VBO_REQUEST( - mr_edit_flag, cache->edit.facedots_uv, combined_edit_flag | MR_DATATYPE_LOOPUV); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.facedots_uv_data, combined_edit_flag); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edituv_loops_points, combined_edit_flag); + mr_edit_flag, cache->edit.facedots_uv, combined_edituv_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST( + mr_edit_flag, cache->edit.facedots_uv_data, combined_edit_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_IBO_REQUEST( - mr_edit_flag, cache->ibo.edituv_loops_line_strips, combined_edit_flag); + mr_edit_flag, cache->ibo.edituv_loops_points, combined_edit_flag | MR_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_IBO_REQUEST( - mr_edit_flag, cache->ibo.edituv_loops_tri_fans, combined_edit_flag); - /* TODO: Some of the flags here may not be needed. */ - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, - cache->ibo.edit_loops_points, - MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | - MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | - MR_DATATYPE_LOOPTRI); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, - cache->ibo.edit_loops_lines, - MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | - MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | - MR_DATATYPE_LOOPTRI); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, - cache->ibo.edit_loops_tris, - MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | - MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | - MR_DATATYPE_LOOPTRI); + mr_edit_flag, cache->ibo.edituv_loops_line_strips, combined_edit_flag | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_IBO_REQUEST( + mr_edit_flag, cache->ibo.edituv_loops_tri_fans, combined_edit_flag | MR_DATATYPE_OVERLAY); + + DRW_ADD_FLAG_FROM_IBO_REQUEST( + mr_edit_flag, cache->ibo.edit_loops_points, combined_edit_flag | MR_DATATYPE_LOOPTRI); + DRW_ADD_FLAG_FROM_IBO_REQUEST( + mr_edit_flag, cache->ibo.edit_loops_lines, combined_edit_flag | MR_DATATYPE_LOOPTRI); + DRW_ADD_FLAG_FROM_IBO_REQUEST( + mr_edit_flag, cache->ibo.edit_loops_tris, combined_edit_flag | MR_DATATYPE_LOOPTRI); Mesh *me_original = me; MBC_GET_FINAL_MESH(me); +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST + printf(" mr_flag %u, mr_edit_flag %u\n\n", mr_flag, mr_edit_flag); +#endif + if (me_original == me) { mr_flag |= mr_edit_flag; } @@ -5140,6 +5304,9 @@ void DRW_mesh_batch_cache_create_requested( if (DRW_ibo_requested(cache->ibo.edit_loops_tris)) { mesh_create_edit_loops_tris(rdata, cache->ibo.edit_loops_tris); } + if (DRW_vbo_requested(cache->edit.loop_mesh_analysis)) { + mesh_create_edit_mesh_analysis(rdata, cache->edit.loop_mesh_analysis); + } /* UV editor */ /** diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c index 2c06d536f3d..432c5092274 100644 --- a/source/blender/draw/intern/draw_cache_impl_metaball.c +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -265,4 +265,4 @@ struct GPUBatch *DRW_metaball_batch_cache_get_edge_detection(struct Object *ob, } return cache->edge_detection; -}
\ No newline at end of file +} diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index e998b17a44f..9a15c51598f 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -99,7 +99,7 @@ typedef struct HairAttributeID { typedef struct EditStrandData { float pos[3]; - uchar color; + float color; } EditStrandData; static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id) @@ -110,7 +110,7 @@ static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_ /* Keep in sync with EditStrandData */ pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); color_id = GPU_vertformat_attr_add( - &edit_point_format, "color", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + &edit_point_format, "color", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); } *r_pos_id = pos_id; *r_color_id = color_id; @@ -693,12 +693,12 @@ static int particle_batch_cache_fill_segments_edit( float strand_t = (float)(j) / path->segments; if (particle) { float weight = particle_key_weight(particle, i, strand_t); - /* NaN or unclamped become 0xFF */ - seg_data->color = (uchar)((weight <= 1.0f) ? 0xFE * weight : 0xFF); + /* NaN or unclamped become 1.0f */ + seg_data->color = (weight < 1.0f) ? weight : 1.0f; } else { float selected = particle_key_select_ratio(edit, i, strand_t); - seg_data->color = (uchar)(0xFF * selected); + seg_data->color = selected; } GPU_indexbuf_add_generic_vert(elb, curr_point); curr_point++; @@ -1565,7 +1565,7 @@ static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit, const PTCacheEditPoint *point = &edit->points[point_index]; for (int key_index = 0; key_index < point->totkey - 1; key_index++) { PTCacheEditKey *key = &point->keys[key_index]; - uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00; + float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f; GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co); GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color); global_key_index++; @@ -1611,7 +1611,8 @@ static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, Particle for (int point_index = 0; point_index < edit->totpoint; point_index++) { const PTCacheEditPoint *point = &edit->points[point_index]; PTCacheEditKey *key = &point->keys[point->totkey - 1]; - uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00; + float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f; + GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co); GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, &color); } diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 465a4f7a897..b4eb354ec59 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -90,8 +90,8 @@ void DRW_globals_update(void) dot_v3v3(gb->colorEditMeshMiddle, (float[3]){0.3333f, 0.3333f, 0.3333f})); /* Desaturate */ interp_v4_v4v4(gb->colorDupliSelect, gb->colorBackground, gb->colorSelect, 0.5f); - /* Was 50% in 2.7x since the background was lighter making it easier to tell the color from black, - * with a darker background we need a more faded color. */ + /* Was 50% in 2.7x since the background was lighter making it easier to tell the color from + * black, with a darker background we need a more faded color. */ interp_v4_v4v4(gb->colorDupli, gb->colorBackground, gb->colorWire, 0.3f); #ifdef WITH_FREESTYLE @@ -142,7 +142,7 @@ void DRW_globals_update(void) UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, gb->colorOutline); UI_GetThemeColorShadeAlpha4fv(TH_LIGHT, 0, 255, gb->colorLightNoAlpha); - gb->sizeLightCenter = (U.obcenter_dia + 1.5f) * U.pixelsize; + gb->sizeLightCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.5f) * U.pixelsize; gb->sizeLightCircle = U.pixelsize * 9.0f; gb->sizeLightCircleShadow = gb->sizeLightCircle + U.pixelsize * 3.0f; @@ -1045,7 +1045,7 @@ struct GPUShader *volume_velocity_shader_get(bool use_needle) } } -/* ******************************************** COLOR UTILS *********************************************** */ +/* ******************************************** COLOR UTILS ************************************ */ /* TODO FINISH */ /** diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index db8f8d46e85..489bc7459df 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -216,6 +216,7 @@ typedef struct DRWArmaturePasses { struct DRWPass *bone_envelope; struct DRWPass *bone_axes; struct DRWPass *relationship_lines; + struct GHash *custom_shapes; } DRWArmaturePasses; void DRW_shgroup_armature_object(struct Object *ob, diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index b3081a44dfb..cb83265195a 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -193,7 +193,8 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f); DRW_shgroup_uniform_bool_copy( shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0); - /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling test. */ + /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling + * test. */ DRW_shgroup_call_object_add_no_cull( shgrp, hair_cache->final[subdiv].proc_hairs[thickness_res - 1], object); diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index 27e03a3495a..e8d91309e06 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -22,11 +22,11 @@ /** * DRW Instance Data Manager - * This is a special memory manager that keeps memory blocks ready to send as vbo data in one continuous allocation. - * This way we avoid feeding gawain each instance data one by one and unnecessary memcpy. - * Since we loose which memory block was used each #DRWShadingGroup we need to redistribute them in the same order/size - * to avoid to realloc each frame. - * This is why #DRWInstanceDatas are sorted in a list for each different data size. + * This is a special memory manager that keeps memory blocks ready to send as vbo data in one + * continuous allocation. This way we avoid feeding gawain each instance data one by one and + * unnecessary memcpy. Since we loose which memory block was used each #DRWShadingGroup we need to + * redistribute them in the same order/size to avoid to realloc each frame. This is why + * #DRWInstanceDatas are sorted in a list for each different data size. */ #include "draw_instance_data.h" diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 9e078fd2774..5c88c1f93db 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -35,6 +35,7 @@ #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_lattice.h" +#include "BKE_main.h" #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_object.h" @@ -404,7 +405,7 @@ void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST; break; default: - BLI_assert("Mulisample count unsupported by blit shader."); + BLI_assert(!"Mulisample count unsupported by blit shader."); builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST; break; } @@ -424,7 +425,7 @@ void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16; break; default: - BLI_assert("Mulisample count unsupported by blit shader."); + BLI_assert(!"Mulisample count unsupported by blit shader."); builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2; break; } @@ -518,11 +519,20 @@ static void drw_viewport_cache_resize(void) GPU_viewport_cache_release(DST.viewport); if (DST.vmempool != NULL) { + /* Release Image textures. */ + BLI_mempool_iter iter; + GPUTexture **tex; + BLI_mempool_iternew(DST.vmempool->images, &iter); + while ((tex = BLI_mempool_iterstep(&iter))) { + GPU_texture_free(*tex); + } + BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_len(DST.vmempool->calls)); BLI_mempool_clear_ex(DST.vmempool->states, BLI_mempool_len(DST.vmempool->states)); BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_len(DST.vmempool->shgroups)); BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_len(DST.vmempool->uniforms)); BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_len(DST.vmempool->passes)); + BLI_mempool_clear_ex(DST.vmempool->images, BLI_mempool_len(DST.vmempool->images)); } DRW_instance_data_list_free_unused(DST.idatalist); @@ -602,6 +612,10 @@ static void drw_viewport_var_init(void) if (DST.vmempool->passes == NULL) { DST.vmempool->passes = BLI_mempool_create(sizeof(DRWPass), 0, 64, 0); } + if (DST.vmempool->images == NULL) { + DST.vmempool->images = BLI_mempool_create( + sizeof(GPUTexture *), 0, 512, BLI_MEMPOOL_ALLOW_ITER); + } DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); DRW_instance_data_list_reset(DST.idatalist); @@ -966,6 +980,45 @@ static void drw_drawdata_unlink_dupli(ID *id) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Garbage Collection + * \{ */ + +void DRW_cache_free_old_batches(Main *bmain) +{ + Scene *scene; + ViewLayer *view_layer; + static int lasttime = 0; + int ctime = (int)PIL_check_seconds_timer(); + + if (U.vbotimeout == 0 || (ctime - lasttime) < U.vbocollectrate || ctime == lasttime) { + return; + } + + lasttime = ctime; + + for (scene = bmain->scenes.first; scene; scene = scene->id.next) { + for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false); + if (depsgraph == NULL) { + continue; + } + + /* TODO(fclem): This is not optimal since it iter over all dupli instances. + * In this case only the source object should be tagged. */ + int iter_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | + DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI; + + DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flags) { + DRW_batch_cache_free_old(ob, ctime); + } + DEG_OBJECT_ITER_END; + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Rendering (DRW_engines) * \{ */ @@ -1083,9 +1136,8 @@ static void drw_engines_draw_background(void) } /* No draw_background found, doing default background */ - if (DRW_state_draw_background()) { - DRW_draw_background(); - } + const bool do_alpha_checker = !DRW_state_draw_background(); + DRW_draw_background(do_alpha_checker); } static void drw_engines_draw_scene(void) @@ -1434,6 +1486,7 @@ void DRW_draw_view(const bContext *C) drw_state_prepare_clean_for_draw(&DST); DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0); + DST.options.draw_background = scene->r.alphamode == R_ADDSKY; DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C); } @@ -1500,11 +1553,10 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_world_update(scene); const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; - DEG_OBJECT_ITER_BEGIN (depsgraph, - ob, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI) { + const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; + DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) { if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { continue; } @@ -1951,11 +2003,10 @@ void DRW_render_object_iter( const int object_type_exclude_viewport = draw_ctx->v3d ? draw_ctx->v3d->object_type_exclude_viewport : 0; - DEG_OBJECT_ITER_BEGIN (depsgraph, - ob, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI) { + const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; + DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) { if ((object_type_exclude_viewport & (1 << ob->type)) == 0) { DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; @@ -2205,14 +2256,13 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, # endif } else { + const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; const int object_type_exclude_select = (v3d->object_type_exclude_viewport | v3d->object_type_exclude_select); bool filter_exclude = false; - DEG_OBJECT_ITER_BEGIN (depsgraph, - ob, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | - DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI) { + DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) { if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { continue; } @@ -2294,42 +2344,6 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, #endif /* USE_GPU_SELECT */ } -static void draw_depth_texture_to_screen(GPUTexture *texture) -{ - const float w = (float)GPU_texture_width(texture); - const float h = (float)GPU_texture_height(texture); - - GPUVertFormat *format = immVertexFormat(); - uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH_COPY); - - GPU_texture_bind(texture, 0); - - immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - - immBegin(GPU_PRIM_TRI_STRIP, 4); - - immAttr2f(texcoord, 0.0f, 0.0f); - immVertex2f(pos, 0.0f, 0.0f); - - immAttr2f(texcoord, 1.0f, 0.0f); - immVertex2f(pos, w, 0.0f); - - immAttr2f(texcoord, 0.0f, 1.0f); - immVertex2f(pos, 0.0f, h); - - immAttr2f(texcoord, 1.0f, 1.0f); - immVertex2f(pos, w, h); - - immEnd(); - - GPU_texture_unbind(texture); - - immUnbindProgram(); -} - /** * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing). */ @@ -2360,11 +2374,10 @@ static void drw_draw_depth_loop_imp(void) View3D *v3d = DST.draw_ctx.v3d; const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; - DEG_OBJECT_ITER_BEGIN (DST.draw_ctx.depsgraph, - ob, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI) { + const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; + DEG_OBJECT_ITER_BEGIN (DST.draw_ctx.depsgraph, ob, iter_flag) { if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { continue; } @@ -2446,21 +2459,6 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, drw_engines_disable(); - /* XXX Drawing the resulting buffer to the BACK_BUFFER */ - GPU_matrix_push(); - GPU_matrix_push_projection(); - wmOrtho2_region_pixelspace(DST.draw_ctx.ar); - GPU_matrix_identity_set(); - - glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */ - glDepthFunc(GL_ALWAYS); - DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(DST.viewport); - draw_depth_texture_to_screen(dtxl->depth); - glDepthFunc(GL_LEQUAL); - - GPU_matrix_pop(); - GPU_matrix_pop_projection(); - #ifdef DEBUG /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); @@ -2506,6 +2504,69 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, #endif } +/** + * Clears the Depth Buffer and draws only the specified object. + */ +void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) +{ + RegionView3D *rv3d = ar->regiondata; + + DRW_opengl_context_enable(); + + /* Setup framebuffer */ + DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); + + GPU_framebuffer_bind(fbl->depth_only_fb); + GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f); + GPU_depth_test(true); + GPU_matrix_mul(object->obmat); + + const float(*world_clip_planes)[4] = NULL; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + ED_view3d_clipping_local(rv3d, object->obmat); + world_clip_planes = rv3d->clip_local; + } + + switch (object->type) { + case OB_MESH: { + GPUBatch *batch; + + Mesh *me = object->data; + + if (object->mode & OB_MODE_EDIT) { + batch = DRW_mesh_batch_cache_get_edit_triangles(me); + } + else { + batch = DRW_mesh_batch_cache_get_surface(me); + } + + DRW_mesh_batch_cache_create_requested(object, me, NULL, false, true); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); + if (world_clip_planes != NULL) { + GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); + } + + GPU_batch_draw(batch); + } break; + case OB_CURVE: + case OB_SURF: + break; + } + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); + } + + GPU_matrix_set(rv3d->viewmat); + GPU_depth_test(false); + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); +} + /* Set an opengl context to be used with shaders that draw on U32 colors. */ void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) { @@ -2669,9 +2730,6 @@ bool DRW_state_draw_support(void) */ bool DRW_state_draw_background(void) { - if (DRW_state_is_image_render() == false) { - return true; - } return DST.options.draw_background; } diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 35e2ab86a80..a70438a2d37 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -56,7 +56,9 @@ # define PROFILE_TIMER_FALLOFF 0.04 -# define PROFILE_START(time_start) double time_start = PIL_check_seconds_timer(); +# define PROFILE_START(time_start) \ + double time_start = PIL_check_seconds_timer(); \ + ((void)0) # define PROFILE_END_ACCUM(time_accum, time_start) \ { \ @@ -251,10 +253,12 @@ struct DRWShadingGroup { }; }; - DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */ - DRWState - state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */ - uint stencil_mask; /* Stencil mask to use for stencil test / write operations */ + /** State changes for this batch only (or'd with the pass's state) */ + DRWState state_extra; + /** State changes for this batch only (and'd with the pass's state) */ + DRWState state_extra_disable; + /** Stencil mask to use for stencil test / write operations */ + uint stencil_mask; DRWShadingGroupType type; /* Builtin matrices locations */ @@ -393,10 +397,11 @@ typedef struct DRWManager { /* gl_context serves as the offset for clearing only * the top portion of the struct so DO NOT MOVE IT! */ - void *gl_context; /* Unique ghost context used by the draw manager. */ + /** Unique ghost context used by the draw manager. */ + void *gl_context; GPUContext *gpu_context; - TicketMutex - *gl_context_mutex; /* Mutex to lock the drw manager and avoid concurrent context usage. */ + /** Mutex to lock the drw manager and avoid concurrent context usage. */ + TicketMutex *gl_context_mutex; /** GPU Resource State: Memory storage between drawing. */ struct { diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 4a9f4fe910b..65ef2fa66fa 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -161,7 +161,8 @@ void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, con drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1); } -/* Same as DRW_shgroup_uniform_texture but is guaranteed to be bound if shader does not change between shgrp. */ +/* Same as DRW_shgroup_uniform_texture but is guaranteed to be bound if shader does not change + * between shgrp. */ void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) @@ -178,7 +179,8 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1); } -/* Same as DRW_shgroup_uniform_block but is guaranteed to be bound if shader does not change between shgrp. */ +/* Same as DRW_shgroup_uniform_block but is guaranteed to be bound if shader does not change + * between shgrp. */ void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo) @@ -634,6 +636,17 @@ void DRW_shgroup_call_generate_add(DRWShadingGroup *shgroup, BLI_LINKS_APPEND(&shgroup->calls, call); } +/* This function tests if the current draw engine draws the vertex colors + * It is used when drawing sculpts + * + * XXX: should we use a callback to a the draw engine to retrieve this + * setting, this makes the draw manager more clean? */ +static bool DRW_draw_vertex_color_active(const DRWContextState *draw_ctx) +{ + View3D *v3d = draw_ctx->v3d; + return v3d->shading.type == OB_SOLID && v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR; +} + static void sculpt_draw_cb(DRWShadingGroup *shgroup, void (*draw_fn)(DRWShadingGroup *shgroup, GPUBatch *geom), void *user_data) @@ -654,8 +667,16 @@ static void sculpt_draw_cb(DRWShadingGroup *shgroup, } if (pbvh) { - BKE_pbvh_draw_cb( - pbvh, NULL, NULL, fast_mode, false, false, (void (*)(void *, GPUBatch *))draw_fn, shgroup); + const bool show_vcol = DRW_draw_vertex_color_active(drwctx); + BKE_pbvh_draw_cb(pbvh, + NULL, + NULL, + fast_mode, + false, + false, + show_vcol, + (void (*)(void *, GPUBatch *))draw_fn, + shgroup); } } @@ -679,8 +700,15 @@ static void sculpt_draw_wires_cb(DRWShadingGroup *shgroup, } if (pbvh) { - BKE_pbvh_draw_cb( - pbvh, NULL, NULL, fast_mode, true, false, (void (*)(void *, GPUBatch *))draw_fn, shgroup); + BKE_pbvh_draw_cb(pbvh, + NULL, + NULL, + fast_mode, + true, + false, + false, + (void (*)(void *, GPUBatch *))draw_fn, + shgroup); } } @@ -955,8 +983,12 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, GPUTexture *tex = NULL; if (input->ima) { - tex = GPU_texture_from_blender( + GPUTexture **tex_ref = BLI_mempool_alloc(DST.vmempool->images); + + *tex_ref = tex = GPU_texture_from_blender( input->ima, input->iuser, GL_TEXTURE_2D, input->image_isdata); + + GPU_texture_ref(tex); } else { /* Color Ramps */ @@ -1148,7 +1180,7 @@ void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch /* PERF : This destroys the vaos cache so better check if it's necessary. */ /* Note: This WILL break if batch->verts[0] is destroyed and reallocated * at the same address. Bindings/VAOs would remain obsolete. */ - //if (shgroup->instancing_geom->inst != batch->verts[0]) + // if (shgroup->instancing_geom->inst != batch->verts[0]) GPU_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false); #ifdef USE_GPU_SELECT diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index db675ee0210..8e23a616ff5 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -205,7 +205,7 @@ void drw_state_set(DRWState state) int test; if (CHANGED_ANY_STORE_VAR(DRW_STATE_BLEND | DRW_STATE_BLEND_PREMUL | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_ADDITIVE_FULL | - DRW_STATE_BLEND_OIT, + DRW_STATE_BLEND_OIT | DRW_STATE_BLEND_PREMUL_UNDER, test)) { if (test) { glEnable(GL_BLEND); @@ -216,6 +216,9 @@ void drw_state_set(DRWState state) GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */ } + else if ((state & DRW_STATE_BLEND_PREMUL_UNDER) != 0) { + glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); + } else if ((state & DRW_STATE_BLEND_PREMUL) != 0) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } @@ -445,8 +448,9 @@ void DRW_state_clip_planes_set_from_rv3d(RegionView3D *rv3d) /* Extract the 8 corners from a Projection Matrix. * Although less accurate, this solution can be simplified as follows: - * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); - * for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, bbox.vec[i]);} + * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const + * float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, + * bbox.vec[i]);} */ static void draw_frustum_boundbox_calc(const float (*projmat)[4], BoundBox *r_bbox) { @@ -498,7 +502,8 @@ static void draw_clipping_setup_from_view(void) /* Extract Clipping Planes */ BoundBox bbox; #if 0 /* It has accuracy problems. */ - BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); + BKE_boundbox_init_from_minmax( + &bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) { mul_project_m4_v3(projinv, bbox.vec[i]); } @@ -616,9 +621,9 @@ static void draw_clipping_setup_from_view(void) float F = -1.0f, N; /* square distance of far and near point to origin */ float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */ float e, s; /* far and near clipping distance (<0) */ - float - c; /* slope of center line = distance of far clipping center to z axis / far clipping distance */ - float z; /* projection of sphere center on z axis (<0) */ + float c; /* slope of center line = distance of far clipping center + * to z axis / far clipping distance. */ + float z; /* projection of sphere center on z axis (<0) */ /* Find farthest corner and center of far clip plane. */ float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */ @@ -1230,12 +1235,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) # define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \ _start += _count; \ - } + } \ + ((void)0) #else # define GPU_SELECT_LOAD_IF_PICKSEL(select_id) # define GPU_SELECT_LOAD_IF_PICKSEL_CALL(call) -# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) +# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) ((void)0) # define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \ _start = 0; \ _count = _shgroup->instance_count; @@ -1259,11 +1265,10 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) if (shgroup->instance_count > 0) { uint count, start; draw_geometry_prepare(shgroup, NULL); - GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) - { + GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) { draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true); } - GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) + GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count); } } } @@ -1272,11 +1277,10 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) if (shgroup->instance_count > 0) { uint count, start; draw_geometry_prepare(shgroup, NULL); - GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) - { + GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) { draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false); } - GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) + GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count); } } } diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 9cb3c1bf226..b60a41ab0c9 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -161,8 +161,10 @@ static void drw_deferred_shader_compilation_free(void *custom_data) static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) { - /* Do not deferre the compilation if we are rendering for image. */ - if (DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION || !deferred) { + /* Do not deferre the compilation if we are rendering for image. + * deferred rendering is only possible when `evil_C` is available */ + if (DST.draw_ctx.evil_C == NULL || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION || + !deferred) { /* Double checking that this GPUMaterial is not going to be * compiled by another thread. */ DRW_deferred_shader_remove(mat); @@ -181,7 +183,8 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) /* Use original scene ID since this is what the jobs template tests for. */ Scene *scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id); - /* Get the running job or a new one if none is running. Can only have one job per type & owner. */ + /* Get the running job or a new one if none is running. Can only have one job per type & owner. + */ wmJob *wm_job = WM_jobs_get(wm, win, scene, diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 1543e381d8c..7aa2e007f79 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -61,19 +61,35 @@ void DRW_draw_region_info(void) /* ************************* Background ************************** */ -void DRW_draw_background(void) +void DRW_draw_background(bool do_alpha_checker) { /* Just to make sure */ glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilMask(0xFF); - if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + if (do_alpha_checker) { + /* Transparent render, do alpha checker. */ + GPU_depth_test(false); + + GPU_matrix_push(); + GPU_matrix_identity_set(); + GPU_matrix_identity_projection_set(); + + imm_draw_box_checker_2d(-1.0f, -1.0f, 1.0f, 1.0f); + + GPU_matrix_pop(); + + GPU_clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT); + + GPU_depth_test(true); + } + else if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { float m[4][4]; unit_m4(m); /* Gradient background Color */ - glDisable(GL_DEPTH_TEST); + GPU_depth_test(false); GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -104,14 +120,15 @@ void DRW_draw_background(void) GPU_matrix_pop(); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + GPU_clear(GPU_DEPTH_BIT | GPU_STENCIL_BIT); - glEnable(GL_DEPTH_TEST); + GPU_depth_test(true); } else { /* Solid background Color */ UI_ThemeClearColorAlpha(TH_BACK, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT); } } diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h index 08a8e984c87..715c3c0d40c 100644 --- a/source/blender/draw/intern/draw_view.h +++ b/source/blender/draw/intern/draw_view.h @@ -24,7 +24,7 @@ #define __DRAW_VIEW_H__ void DRW_draw_region_info(void); -void DRW_draw_background(void); +void DRW_draw_background(bool do_alpha_checker); void DRW_draw_cursor(void); void DRW_draw_gizmo_3d(void); void DRW_draw_gizmo_2d(void); diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c index 12bf4982ffb..d1ef0d0e104 100644 --- a/source/blender/draw/modes/edit_armature_mode.c +++ b/source/blender/draw/modes/edit_armature_mode.c @@ -126,6 +126,7 @@ static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob) .bone_envelope = psl->bone_envelope[ghost], .bone_axes = psl->bone_axes, .relationship_lines = psl->relationship[ghost], + .custom_shapes = NULL, /* Not needed in edit mode. */ }; DRW_shgroup_armature_edit(ob, passes, transp); } diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index b3b6acf9b7d..ffe7fe5845c 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -55,6 +55,8 @@ extern char datatoc_edit_mesh_overlay_geom_glsl[]; extern char datatoc_edit_mesh_overlay_mix_frag_glsl[]; extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[]; extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[]; +extern char datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl[]; +extern char datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl[]; extern char datatoc_edit_normals_vert_glsl[]; extern char datatoc_edit_normals_geom_glsl[]; extern char datatoc_common_globals_lib_glsl[]; @@ -75,6 +77,7 @@ typedef struct EDIT_MESH_PassList { struct DRWPass *edit_face_occluded; struct DRWPass *mix_occlude; struct DRWPass *facefill_occlude; + struct DRWPass *mesh_analysis_pass; struct DRWPass *normals; } EDIT_MESH_PassList; @@ -115,6 +118,10 @@ typedef struct EDIT_MESH_Shaders { GPUShader *normals_loop; GPUShader *normals; GPUShader *depth; + + /* Mesh analysis shader */ + GPUShader *mesh_analysis_face; + GPUShader *mesh_analysis_vertex; } EDIT_MESH_Shaders; /* *********** STATIC *********** */ @@ -149,6 +156,7 @@ typedef struct EDIT_MESH_PrivateData { DRWShadingGroup *facedot_shgrp_in_front; DRWShadingGroup *facefill_occluded_shgrp; + DRWShadingGroup *mesh_analysis_shgrp; int data_mask[4]; int ghost_ob; @@ -278,6 +286,22 @@ static void EDIT_MESH_engine_init(void *vedata) .defs = (const char *[]){sh_cfg_data->def, NULL}, }); + /* Mesh Analysis */ + sh_data->mesh_analysis_face = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define FACE_COLOR\n", NULL}, + }); + sh_data->mesh_analysis_vertex = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define VERTEX_COLOR\n", NULL}, + }); + sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg); } } @@ -300,8 +324,6 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, 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; @@ -336,8 +358,8 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, 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); + DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face); if (rv3d->rflag & RV3D_CLIPPING) { DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); } @@ -354,7 +376,8 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, 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_uniform_bool_copy(grp, "selectEdges", select_edge); + DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); /* To match blender loop structure. */ DRW_shgroup_state_enable(grp, DRW_STATE_FIRST_VERTEX_CONVENTION); @@ -422,9 +445,6 @@ static void EDIT_MESH_cache_init(void *vedata) 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; } @@ -513,6 +533,18 @@ static void EDIT_MESH_cache_init(void *vedata) } } + { + /* Mesh Analysis Pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; + psl->mesh_analysis_pass = DRW_pass_create("Mesh Analysis", state); + const bool is_vertex_color = scene->toolsettings->statvis.type == SCE_STATVIS_SHARP; + stl->g_data->mesh_analysis_shgrp = DRW_shgroup_create( + is_vertex_color ? sh_data->mesh_analysis_vertex : sh_data->mesh_analysis_face, + psl->mesh_analysis_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->mesh_analysis_shgrp, rv3d); + } + } /* For in front option */ psl->edit_face_overlay_in_front = edit_mesh_create_overlay_pass( &face_mod, @@ -538,7 +570,8 @@ static void EDIT_MESH_cache_init(void *vedata) &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 */ + /* 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, @@ -632,6 +665,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *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 do_show_mesh_analysis = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_STATVIS) != 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; @@ -660,6 +694,19 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) DRW_shgroup_call_add(g_data->fweights_shgrp, geom, ob->obmat); } + if (do_show_mesh_analysis) { + Mesh *me = (Mesh *)ob->data; + BMEditMesh *embm = me->edit_mesh; + const bool is_original = embm->mesh_eval_final && + (embm->mesh_eval_final->runtime.is_original == true); + if (is_original) { + geom = DRW_cache_mesh_surface_mesh_analysis_get(ob); + if (geom) { + DRW_shgroup_call_add(g_data->mesh_analysis_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 : @@ -735,6 +782,7 @@ static void EDIT_MESH_draw_scene(void *vedata) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DRW_draw_pass(psl->weight_faces); + DRW_draw_pass(psl->mesh_analysis_pass); DRW_draw_pass(psl->depth_hidden_wire); diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c index 90396785eb3..f3630a77e9a 100644 --- a/source/blender/draw/modes/edit_mesh_mode_text.c +++ b/source/blender/draw/modes/edit_mesh_mode_text.c @@ -47,8 +47,8 @@ void DRW_edit_mesh_mode_text_measure_stats(ARegion *ar, 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. + /* 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); @@ -157,12 +157,12 @@ void DRW_edit_mesh_mode_text_measure_stats(ARegion *ar, 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 */ + /* 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 */ + /* 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) || @@ -319,7 +319,8 @@ void DRW_edit_mesh_mode_text_measure_stats(ARegion *ar, } } - /* This option is for mesh ops and addons debugging; only available in UI if Blender starts with --debug */ + /* 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; diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index 90c5676727f..aa7c6863423 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -126,7 +126,7 @@ static void EDIT_METABALL_cache_init(void *vedata) /* 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_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; if (ob->type == OB_MBALL) { diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index ec49b4dbe51..ee2c660ca06 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -53,6 +53,8 @@ #include "BKE_particle.h" #include "BKE_tracking.h" +#include "BLI_ghash.h" + #include "ED_view3d.h" #include "GPU_batch.h" @@ -273,6 +275,8 @@ typedef struct OBJECT_PrivateData { OBJECT_ShadingGroupList sgl; OBJECT_ShadingGroupList sgl_ghost; + GHash *custom_shapes; + /* Outlines */ DRWShadingGroup *outlines_active; DRWShadingGroup *outlines_select; @@ -511,6 +515,7 @@ static void OBJECT_engine_init(void *vedata) 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; + const bool show_ortho_grid = (v3d->gridflag & V3D_SHOW_ORTHO_GRID) != 0; e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor; DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); @@ -559,15 +564,15 @@ static void OBJECT_engine_init(void *vedata) grid_res = viewdist / grid_scale; if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) { - e_data.draw_grid = true; + e_data.draw_grid = show_ortho_grid; 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.draw_grid = show_ortho_grid; 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.draw_grid = show_ortho_grid; e_data.grid_flag = PLANE_XZ | SHOW_AXIS_X | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK; } else { /* RV3D_VIEW_USER */ @@ -948,7 +953,8 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, return; } - /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, see: T59347 */ + /* 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; @@ -1039,6 +1045,8 @@ static void OBJECT_cache_init(void *vedata) g_data->xray_enabled_and_not_wire = g_data->xray_enabled && draw_ctx->v3d->shading.type > OB_WIRE; + g_data->custom_shapes = BLI_ghash_ptr_new(__func__); + { DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; @@ -1494,7 +1502,7 @@ static void OBJECT_cache_init(void *vedata) psl->ob_center = DRW_pass_create("Obj Center Pass", state); outlineWidth = 1.0f * U.pixelsize; - size = U.obcenter_dia * U.pixelsize + outlineWidth; + size = UI_GetThemeValuef(TH_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); @@ -1853,8 +1861,10 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl 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}}; + 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]; @@ -1877,9 +1887,11 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl /* 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}}; + 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]; @@ -3115,11 +3127,10 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) ((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)); + 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 selecting. */ + (((rv3d->persp == RV3D_CAMOB) && ((ID *)v3d->camera == ob->id.orig_id)) == 0)); if (do_outlines) { if (!BKE_object_is_in_editmode(ob) && @@ -3284,6 +3295,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) .bone_envelope = sgl->bone_envelope, .bone_axes = sgl->bone_axes, .relationship_lines = NULL, /* Don't draw relationship lines */ + .custom_shapes = stl->g_data->custom_shapes, }; DRW_shgroup_armature_object(ob, view_layer, passes, is_wire); } @@ -3391,6 +3403,11 @@ static void OBJECT_cache_finish(void *vedata) DRW_pass_sort_shgroup_z(stl->g_data->sgl.image_empties); DRW_pass_sort_shgroup_z(stl->g_data->sgl_ghost.image_empties); + + if (stl->g_data->custom_shapes) { + /* TODO(fclem): Do not free it for each frame but reuse it. Avoiding alloc cost. */ + BLI_ghash_free(stl->g_data->custom_shapes, NULL, NULL); + } } static void OBJECT_draw_scene(void *vedata) diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index 4d583066f44..ed96b2a05bc 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -359,8 +359,7 @@ static void overlay_cache_populate(void *vedata, Object *ob) 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 is_sculpt_mode = (ob->sculpt != NULL); 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 && diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index 84852ff7ab3..3e292f4e4bc 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -294,7 +294,7 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob) 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; + 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; diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c index 5e3353414f5..a37901a1fa9 100644 --- a/source/blender/draw/modes/pose_mode.c +++ b/source/blender/draw/modes/pose_mode.c @@ -72,6 +72,7 @@ typedef struct POSE_Data { typedef struct POSE_PrivateData { DRWShadingGroup *bone_selection_shgrp; DRWShadingGroup *bone_selection_invert_shgrp; + GHash *custom_shapes[2]; float blend_color[4]; float blend_color_invert[4]; bool transparent_bones; @@ -139,6 +140,8 @@ static void POSE_cache_init(void *vedata) 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); + + ppd->custom_shapes[i] = BLI_ghash_ptr_new(__func__); } { @@ -213,6 +216,7 @@ static void POSE_cache_populate(void *vedata, Object *ob) .bone_envelope = psl->bone_envelope[ghost], .bone_axes = psl->bone_axes, .relationship_lines = psl->relationship[ghost], + .custom_shapes = ppd->custom_shapes[transp], }; DRW_shgroup_armature_pose(ob, passes, transp); } @@ -231,6 +235,16 @@ static void POSE_cache_populate(void *vedata, Object *ob) } } +static void POSE_cache_finish(void *vedata) +{ + POSE_PrivateData *ppd = ((POSE_Data *)vedata)->stl->g_data; + + /* TODO(fclem): Do not free it for each frame but reuse it. Avoiding alloc cost. */ + for (int i = 0; i < 2; i++) { + BLI_ghash_free(ppd->custom_shapes[i], NULL, NULL); + } +} + /** * Return true if armature should be handled by the pose mode engine. */ @@ -323,7 +337,7 @@ DrawEngineType draw_engine_pose_type = { &POSE_engine_free, &POSE_cache_init, &POSE_cache_populate, - NULL, + &POSE_cache_finish, NULL, &POSE_draw_scene, NULL, diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c index b25a8af795b..8adae0a4238 100644 --- a/source/blender/draw/modes/sculpt_mode.c +++ b/source/blender/draw/modes/sculpt_mode.c @@ -135,9 +135,15 @@ static void SCULPT_cache_init(void *vedata) } { + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + 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); + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.shader_smooth, psl->pass); + DRW_shgroup_uniform_float(shgrp, "maskOpacity", &v3d->overlay.sculpt_mode_mask_opacity, 1); + stl->g_data->group_smooth = shgrp; } } @@ -155,6 +161,7 @@ static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup, false, false, true, + false, (void (*)(void *, struct GPUBatch *))draw_fn, shgroup); } @@ -193,7 +200,8 @@ static void SCULPT_cache_populate(void *vedata, Object *ob) 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) */ + * 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) */ diff --git a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl index dcb7c0ba7f2..d9e78855dc9 100644 --- a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl +++ b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl @@ -674,7 +674,7 @@ vec4 FxaaPixelShader( 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) @@ -696,7 +696,7 @@ vec4 FxaaPixelShader( 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) @@ -718,10 +718,10 @@ vec4 FxaaPixelShader( posP.x += offNP.x * FXAA_QUALITY__P12; if (!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; - /*--------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------*/ } # endif - /*--------------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------*/ } # endif /*--------------------------------------------------------------------------*/ diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl index 02254908232..1c0a31c59fd 100644 --- a/source/blender/draw/modes/shaders/common_hair_lib.glsl +++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl @@ -38,8 +38,8 @@ uniform usamplerBuffer hairStrandBuffer; /* R32UI */ uniform usamplerBuffer hairStrandSegBuffer; /* R16UI */ /* Not used, use one buffer per uv layer */ -//uniform samplerBuffer hairUVBuffer; /* RG32F */ -//uniform samplerBuffer hairColBuffer; /* RGBA16 linear color */ +// uniform samplerBuffer hairUVBuffer; /* RG32F */ +// uniform samplerBuffer hairColBuffer; /* RGBA16 linear color */ /* -- Subdivision stage -- */ /** 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 ffabfd3fcee..7d4cba66933 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 @@ -1,5 +1,7 @@ uniform bool doEdges = true; +uniform bool selectFaces = true; +uniform bool selectEdges = true; vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, float bweight) { @@ -15,16 +17,21 @@ vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, floa 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; + vec4 color_select = (selectEdges) ? colorEdgeSelect : colorFaceSelect; + color = (doEdges && ((edge_flag & EDGE_SELECTED) != 0)) ? color_select : color; + color = (doEdges && ((edge_flag & EDGE_ACTIVE) != 0)) ? colorEditMeshActive : color; + + float non_edge_select_alpha = (selectFaces && (edge_flag & EDGE_SELECTED) != 0) ? 0.75 : 0.4; + color.a = (selectEdges) ? 1.0 : non_edge_select_alpha; 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; + vec4 color_select = (selectEdges) ? colorEdgeSelect : colorFaceSelect; + color = (doEdges && (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0) ? color_select : color; + color.a = (selectEdges) ? 1.0 : 0.4; return color; } @@ -43,18 +50,15 @@ vec4 EDIT_MESH_vertex_color(int vertex_flag) 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; - } + vec4 color = colorFace; + vec4 color_active = mix(colorFaceSelect, colorEditMeshActive, 0.5); + color = ((face_flag & FACE_FREESTYLE) != 0) ? colorFaceFreestyle : color; + color = ((face_flag & FACE_SELECTED) != 0) ? colorFaceSelect : color; + color = ((face_flag & FACE_ACTIVE) != 0) ? color_active : color; + color.a *= ((face_flag & (FACE_FREESTYLE | FACE_SELECTED | FACE_ACTIVE)) == 0 || selectFaces) ? + 1.0 : + 0.5; + return color; } vec4 EDIT_MESH_facedot_color(float facedot_flag) 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 3418732afc2..7fe3cea8a42 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl @@ -5,15 +5,13 @@ * We want to know how much a pixel is covered by a line. * We replace the square pixel with acircle of the same area and try to find the intersection area. * The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment - * The formula for the area uses inverse trig function and is quite complexe. - * Instead, we approximate it by using the smoothstep function and a 1.05 factor to the disc radius. + * The formula for the area uses inverse trig function and is quite complexe. Instead, + * we approximate it by using the smoothstep function and a 1.05 factor to the disc radius. */ #define DISC_RADIUS (M_1_SQRTPI * 1.05) #define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS) #define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS) -uniform float edgeScale; - flat in vec4 finalColorOuter_f; in vec4 finalColor_f; noperspective in float edgeCoord_f; @@ -22,8 +20,8 @@ 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 - 0.5, 0.0); + float dist_outer = dist - max(sizeEdge, 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); @@ -31,6 +29,8 @@ void main() float mix_w = step(0.5, dist); float mix_w_outer = step(0.5, dist_outer); #endif + /* Line color & alpha. */ FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a); + /* Line edges shape. */ 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 6e59de12260..047bd1dccc6 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl @@ -4,7 +4,6 @@ layout(triangle_strip, max_vertices = 4) out; uniform vec2 viewportSize; uniform vec2 viewportSizeInv; -uniform float edgeScale; in vec4 finalColor[2]; in vec4 finalColorOuter[2]; @@ -14,14 +13,16 @@ flat out vec4 finalColorOuter_f; out vec4 finalColor_f; noperspective out float edgeCoord_f; -void do_vertex(const int i, vec4 pos, float coord, vec2 offset) +void do_vertex(vec4 color, vec4 pos, float coord, vec2 offset) { - finalColor_f = (selectOveride[0] == 0) ? finalColor[i] : finalColor[0]; + finalColor_f = color; 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 + /* Correct but fails due to an AMD compiler bug, see: T62792. + * Do inline instead. */ +#if 0 world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); #endif EmitVertex(); @@ -57,9 +58,9 @@ void main() line = abs(line) * viewportSize; finalColorOuter_f = finalColorOuter[0]; - float half_size = sizeEdge * edgeScale; + float half_size = sizeEdge; /* Enlarge edge for flag display. */ - half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge * edgeScale, 1.0) : 0.0; + half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge, 1.0) : 0.0; #ifdef USE_SMOOTH_WIRE /* Add 1 px for AA */ @@ -71,10 +72,20 @@ void main() 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); +#ifdef USE_WORLD_CLIP_PLANES + /* Due to an AMD glitch, this line was moved out of the `do_vertex` + * function (see T62792). */ + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); +#endif + do_vertex(finalColor[0], pos0, half_size, edge_ofs.xy); + do_vertex(finalColor[0], pos0, -half_size, -edge_ofs.xy); + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); +#endif + vec4 final_color = (selectOveride[0] == 0) ? finalColor[1] : finalColor[0]; + do_vertex(final_color, pos1, half_size, edge_ofs.xy); + do_vertex(final_color, pos1, -half_size, -edge_ofs.xy); EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_frag.glsl new file mode 100644 index 00000000000..8581453e810 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_frag.glsl @@ -0,0 +1,14 @@ +out vec4 fragColor; + +#ifdef FACE_COLOR +flat in vec4 weightColor; +#endif + +#ifdef VERTEX_COLOR +in vec4 weightColor; +#endif + +void main() +{ + fragColor = weightColor; +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl new file mode 100644 index 00000000000..94d8d2e701c --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl @@ -0,0 +1,23 @@ +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; + +in vec3 pos; +in vec4 weight_color; + +#ifdef FACE_COLOR +flat out vec4 weightColor; +#endif + +#ifdef VERTEX_COLOR +out vec4 weightColor; +#endif + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + weightColor = vec4(weight_color.rgb, 1.0); + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); +#endif +} 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 8c54470cd5a..d700e69fb57 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -74,21 +74,15 @@ void main() #endif -#if !defined(FACE) && !defined(EDGE_DECORATION) +#if !defined(FACE) /* 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 = 1.0 - abs(facing) * 0.2; -# if defined(EDGE) && !defined(FLAT) - /* Hack to blend color in pixel shader in case of overide. */ - finalColor.a = facing; -# endif + finalColor.rgb = mix(colorEditMeshMiddle.rgb, finalColor.rgb, facing); #endif diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index 841b4a95b21..df2cfe7be82 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -40,8 +40,8 @@ uniform int gridFlag; * We want to know how much a pixel is covered by a line. * We replace the square pixel with acircle of the same area and try to find the intersection area. * The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment - * The formula for the area uses inverse trig function and is quite complexe. - * Instead, we approximate it by using the smoothstep function and a 1.05 factor to the disc radius. + * The formula for the area uses inverse trig function and is quite complexe. Instead, + * we approximate it by using the smoothstep function and a 1.05 factor to the disc radius. */ #define DISC_RADIUS (M_1_SQRTPI * 1.05) #define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS) diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl index 745499800e5..6dac6d6b980 100644 --- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl +++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl @@ -45,14 +45,12 @@ vec3 weight_to_rgb(float weight) return r_rgb; } -#define DECOMPRESS_RANGE 1.0039 - void main() { 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), 1.0); #else finalColor = mix(colorWire, colorEdgeSelect, color); #endif diff --git a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl index 5ae97ec5cb9..e5e34fee57e 100644 --- a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl +++ b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl @@ -1,5 +1,6 @@ uniform mat4 ModelViewProjectionMatrix; +uniform float maskOpacity; in vec3 pos; in float msk; @@ -10,6 +11,6 @@ void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - float mask = 1.0 - msk * 0.75; + float mask = 1.0 - (msk * maskOpacity); finalColor = vec4(mask, mask, mask, 1.0); } |