diff options
8 files changed, 116 insertions, 65 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index cefd52db66c..2de6ee1f57d 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -377,6 +377,7 @@ data_to_c_simple(engines/overlay/shaders/edit_uv_verts_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_uv_verts_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_uv_faces_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_uv_face_dots_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_stencil_image_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_uv_stretching_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_frag.glsl SRC) diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c index 18400799d3c..e21b6b30d22 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_uv.c +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c @@ -26,11 +26,15 @@ #include "BKE_editmesh.h" #include "BKE_image.h" +#include "BKE_paint.h" +#include "DNA_brush_types.h" #include "DNA_mesh_types.h" #include "ED_image.h" +#include "IMB_imbuf_types.h" + #include "GPU_batch.h" #include "UI_interface.h" @@ -77,7 +81,8 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; const Scene *scene = draw_ctx->scene; - const ToolSettings *ts = scene->toolsettings; + ToolSettings *ts = scene->toolsettings; + const Brush *brush = BKE_paint_brush(&ts->imapaint.paint); const bool show_overlays = !pd->hide_overlays; Image *image = sima->image; @@ -99,6 +104,9 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) const bool do_uvstretching_overlay = is_image_type && is_uv_editor && is_edit_mode && ((sima->flag & SI_DRAW_STRETCH) != 0); const bool do_tex_paint_shadows = (sima->flag & SI_NO_DRAW_TEXPAINT) == 0; + const bool do_stencil_overlay = is_paint_mode && is_image_type && brush && + (brush->imagepaint_tool == PAINT_TOOL_CLONE) && + brush->clone.image; pd->edit_uv.do_faces = show_overlays && do_faces && !do_uvstretching_overlay; pd->edit_uv.do_face_dots = show_overlays && do_faces && do_face_dots; @@ -117,6 +125,7 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) pd->edit_uv.dash_length = 4.0f * UI_DPI_FAC; pd->edit_uv.line_style = edit_uv_line_style_from_space_image(sima); pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0); + pd->edit_uv.do_stencil_overlay = show_overlays && do_stencil_overlay; pd->edit_uv.draw_type = sima->dt_uvstretch; BLI_listbase_clear(&pd->edit_uv.totals); @@ -132,6 +141,12 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) OVERLAY_PassList *psl = vedata->psl; OVERLAY_PrivateData *pd = stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + Image *image = sima->image; + const Scene *scene = draw_ctx->scene; + ToolSettings *ts = scene->toolsettings; + if (pd->edit_uv.do_uv_overlay || pd->edit_uv.do_uv_shadow_overlay) { /* uv edges */ { @@ -224,9 +239,6 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) } if (pd->edit_uv.do_tiled_image_border_overlay) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; - Image *image = sima->image; GPUBatch *geom = DRW_cache_quad_wires_get(); float obmat[4][4]; unit_m4(obmat); @@ -265,10 +277,6 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) } if (pd->edit_uv.do_tiled_image_overlay) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; - Image *image = sima->image; - struct DRWTextStore *dt = DRW_text_cache_ensure(); uchar color[4]; /* Color Management: Exception here as texts are drawn in sRGB space directly. */ @@ -288,6 +296,42 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) color); } } + + if (pd->edit_uv.do_stencil_overlay) { + const Brush *brush = BKE_paint_brush(&ts->imapaint.paint); + + DRW_PASS_CREATE(psl->edit_uv_stencil_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL); + GPUShader *sh = OVERLAY_shader_edit_uv_stencil_image(); + GPUBatch *geom = DRW_cache_quad_get(); + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->edit_uv_stencil_ps); + Image *stencil_image = brush->clone.image; + ImBuf *stencil_ibuf = BKE_image_acquire_ibuf(stencil_image, NULL, &pd->edit_uv.stencil_lock); + pd->edit_uv.stencil_ibuf = stencil_ibuf; + pd->edit_uv.stencil_image = stencil_image; + GPUTexture *stencil_texture = BKE_image_get_gpu_texture(stencil_image, NULL, stencil_ibuf); + DRW_shgroup_uniform_texture(grp, "imgTexture", stencil_texture); + DRW_shgroup_uniform_bool_copy(grp, "imgPremultiplied", true); + DRW_shgroup_uniform_bool_copy(grp, "imgAlphaBlend", true); + DRW_shgroup_uniform_vec4_copy(grp, "color", (float[4]){1.0f, 1.0f, 1.0f, brush->clone.alpha}); + + float size_image[2]; + BKE_image_get_size_fl(image, NULL, size_image); + float size_stencil_image[2] = {stencil_ibuf->x, stencil_ibuf->y}; + + float obmat[4][4]; + unit_m4(obmat); + obmat[3][1] = brush->clone.offset[1]; + obmat[3][0] = brush->clone.offset[0]; + obmat[0][0] = size_stencil_image[0] / size_image[0]; + obmat[1][1] = size_stencil_image[1] / size_image[1]; + + DRW_shgroup_call_obmat(grp, geom, obmat); + } + else { + pd->edit_uv.stencil_ibuf = NULL; + pd->edit_uv.stencil_image = NULL; + } } void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob) @@ -379,6 +423,19 @@ static void edit_uv_stretching_update_ratios(OVERLAY_Data *vedata) BLI_freelistN(&pd->edit_uv.totals); } +static void OVERLAY_edit_uv_draw_finish(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.stencil_ibuf) { + BKE_image_release_ibuf( + pd->edit_uv.stencil_image, pd->edit_uv.stencil_ibuf, pd->edit_uv.stencil_lock); + pd->edit_uv.stencil_image = NULL; + pd->edit_uv.stencil_ibuf = NULL; + } +} + void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; @@ -393,6 +450,7 @@ void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata) edit_uv_stretching_update_ratios(vedata); DRW_draw_pass(psl->edit_uv_stretching_ps); } + if (pd->edit_uv.do_uv_overlay) { if (pd->edit_uv.do_faces) { DRW_draw_pass(psl->edit_uv_faces_ps); @@ -404,6 +462,10 @@ void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata) else if (pd->edit_uv.do_uv_shadow_overlay) { DRW_draw_pass(psl->edit_uv_edges_ps); } + if (pd->edit_uv.do_stencil_overlay) { + DRW_draw_pass(psl->edit_uv_stencil_ps); + } + OVERLAY_edit_uv_draw_finish(vedata); } -/* \{ */ +/* \} */ diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index b9d591a5642..d746fe4ba8f 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -37,6 +37,9 @@ extern "C" { /* Needed for eSpaceImage_UVDT_Stretch */ #include "DNA_space_types.h" +/* Forward declarations */ +struct ImBuf; + typedef struct OVERLAY_FramebufferList { struct GPUFrameBuffer *overlay_default_fb; struct GPUFrameBuffer *overlay_line_fb; @@ -95,6 +98,7 @@ typedef struct OVERLAY_PassList { DRWPass *edit_uv_faces_ps; DRWPass *edit_uv_stretching_ps; DRWPass *edit_uv_tiled_image_borders_ps; + DRWPass *edit_uv_stencil_ps; DRWPass *extra_ps[2]; DRWPass *extra_blend_ps; DRWPass *extra_centers_ps; @@ -363,6 +367,7 @@ typedef struct OVERLAY_PrivateData { bool do_uv_stretching_overlay; bool do_tiled_image_overlay; bool do_tiled_image_border_overlay; + bool do_stencil_overlay; bool do_faces; bool do_face_dots; @@ -380,6 +385,10 @@ typedef struct OVERLAY_PrivateData { float total_area_ratio; float total_area_ratio_inv; + /* stencil overlay */ + struct Image *stencil_image; + struct ImBuf *stencil_ibuf; + void * stencil_lock; } edit_uv; struct { bool transparent; @@ -680,6 +689,7 @@ GPUShader *OVERLAY_shader_edit_uv_verts_get(void); GPUShader *OVERLAY_shader_edit_uv_stretching_area_get(void); GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get(void); GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get(void); +GPUShader *OVERLAY_shader_edit_uv_stencil_image(void); GPUShader *OVERLAY_shader_extra(bool is_select); GPUShader *OVERLAY_shader_extra_groundline(void); GPUShader *OVERLAY_shader_extra_wire(bool use_object, bool is_select); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 5c1b7c786f4..f3840679d80 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -78,6 +78,7 @@ extern char datatoc_edit_uv_edges_frag_glsl[]; extern char datatoc_edit_uv_faces_vert_glsl[]; extern char datatoc_edit_uv_face_dots_vert_glsl[]; extern char datatoc_edit_uv_stretching_vert_glsl[]; +extern char datatoc_edit_uv_stencil_image_vert_glsl[]; extern char datatoc_edit_uv_tiled_image_borders_vert_glsl[]; extern char datatoc_extra_frag_glsl[]; extern char datatoc_extra_vert_glsl[]; @@ -183,6 +184,7 @@ typedef struct OVERLAY_Shaders { GPUShader *edit_uv_stretching_angle; GPUShader *edit_uv_stretching_area; GPUShader *edit_uv_tiled_image_borders; + GPUShader *edit_uv_stencil_image; GPUShader *extra; GPUShader *extra_select; GPUShader *extra_groundline; @@ -237,6 +239,7 @@ void OVERLAY_shader_library_ensure(void) /* NOTE: Theses needs to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_overlay_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_colormanagement_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); } } @@ -1062,6 +1065,16 @@ GPUShader *OVERLAY_shader_grid_image(void) return sh_data->grid_image; } +GPUShader *OVERLAY_shader_edit_uv_stencil_image(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_stencil_image) { + sh_data->edit_uv_stencil_image = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_stencil_image_vert_glsl, NULL, datatoc_image_frag_glsl, e_data.lib, NULL); + } + return sh_data->edit_uv_stencil_image; +} + GPUShader *OVERLAY_shader_image(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_stencil_image_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_stencil_image_vert.glsl new file mode 100644 index 00000000000..d22cc795e66 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_stencil_image_vert.glsl @@ -0,0 +1,14 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec3 pos; +out vec2 uvs; + +void main() +{ + /* `pos` contains the coordinates of a quad (-1..1). but we need the coordinates of an image + * plane (0..1) */ + vec3 image_pos = pos * 0.5 + 0.5; + vec4 position = point_object_to_ndc(image_pos); + gl_Position = position; + uvs = image_pos.xy; +} diff --git a/source/blender/draw/engines/overlay/shaders/image_frag.glsl b/source/blender/draw/engines/overlay/shaders/image_frag.glsl index 4d37f1599a3..6e68d156f25 100644 --- a/source/blender/draw/engines/overlay/shaders/image_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/image_frag.glsl @@ -1,3 +1,4 @@ +#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl) uniform sampler2D imgTexture; uniform bool imgPremultiplied; diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc index 703099477d6..39d8e45cc19 100644 --- a/source/blender/draw/tests/shaders_test.cc +++ b/source/blender/draw/tests/shaders_test.cc @@ -240,6 +240,7 @@ TEST_F(DrawTest, overlay_glsl_shaders) EXPECT_NE(OVERLAY_shader_edit_uv_stretching_area_get(), nullptr); EXPECT_NE(OVERLAY_shader_edit_uv_stretching_angle_get(), nullptr); EXPECT_NE(OVERLAY_shader_edit_uv_tiled_image_borders_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_stencil_image(), nullptr); EXPECT_NE(OVERLAY_shader_extra(false), nullptr); EXPECT_NE(OVERLAY_shader_extra(true), nullptr); EXPECT_NE(OVERLAY_shader_extra_groundline(), nullptr); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 7934d600cf1..63e5ae64a8c 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -741,46 +741,6 @@ void draw_image_sample_line(SpaceImage *sima) } } -static void draw_image_paint_helpers( - const bContext *C, ARegion *region, Scene *scene, float zoomx, float zoomy) -{ - Brush *brush; - int x, y; - ImBuf *ibuf; - - brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint); - - if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) { - ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); - - if (ibuf) { - void *cache_handle = NULL; - float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha}; - UI_view2d_view_to_region( - ®ion->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); - - uchar *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - if (!display_buffer) { - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - IMB_display_buffer_release(cache_handle); - return; - } - - GPU_blend(GPU_BLEND_ALPHA); - - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); - immDrawPixelsTex( - &state, x, y, ibuf->x, ibuf->y, GPU_RGBA8, false, display_buffer, zoomx, zoomy, col); - - GPU_blend(GPU_BLEND_NONE); - - BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); - IMB_display_buffer_release(cache_handle); - } - } -} - static void draw_udim_tile_grid(uint pos_attr, uint color_attr, ARegion *region, @@ -1007,24 +967,13 @@ void draw_image_main(const bContext *C, ARegion *region) void draw_image_main_helpers(const bContext *C, ARegion *region) { SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - Image *ima; - float zoomx, zoomy; - bool show_viewer, show_render, show_paint; + Image *ima = ED_space_image(sima); - ima = ED_space_image(sima); - ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); - - show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; - show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; - show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && - (show_render == false)); - /* paint helpers */ - if (show_paint) { - draw_image_paint_helpers(C, region, scene, zoomx, zoomy); - } - /* render info */ + const bool show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; + const bool show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; if (ima && show_render) { + float zoomx, zoomy; + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy); } } |