Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/overlay')
-rw-r--r--source/blender/draw/engines/overlay/overlay_background.c7
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_uv.c394
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c47
-rw-r--r--source/blender/draw/engines/overlay/overlay_grid.c53
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h60
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c149
-rw-r--r--source/blender/draw/engines/overlay/shaders/background_frag.glsl7
-rw-r--r--source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl5
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl77
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl63
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl32
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl18
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl22
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl98
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl12
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl33
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl44
-rw-r--r--source/blender/draw/engines/overlay/shaders/grid_vert.glsl7
18 files changed, 1113 insertions, 15 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_background.c b/source/blender/draw/engines/overlay/overlay_background.c
index f52ae691a35..cb09d916a0f 100644
--- a/source/blender/draw/engines/overlay/overlay_background.c
+++ b/source/blender/draw/engines/overlay/overlay_background.c
@@ -31,6 +31,7 @@
#define BG_GRADIENT 1
#define BG_CHECKER 2
#define BG_RADIAL 3
+#define BG_SOLID_CHECKER 4
void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
{
@@ -40,7 +41,7 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
const RegionView3D *rv3d = draw_ctx->rv3d;
- const BoundBox *bb = rv3d->clipbb;
+ const BoundBox *bb = rv3d ? rv3d->clipbb : NULL;
const View3D *v3d = draw_ctx->v3d;
bool draw_clipping_bounds = (pd->clipping_state != 0);
@@ -50,9 +51,11 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) {
background_type = BG_SOLID;
- zero_v3(color_override);
color_override[3] = 1.0f;
}
+ else if (pd->is_image_editor) {
+ background_type = BG_SOLID_CHECKER;
+ }
else if (!DRW_state_draw_background()) {
background_type = BG_CHECKER;
}
diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c
new file mode 100644
index 00000000000..109db6433e0
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c
@@ -0,0 +1,394 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+#include "DRW_render.h"
+
+#include "draw_cache_impl.h"
+#include "draw_manager_text.h"
+
+#include "BKE_image.h"
+
+#include "DNA_mesh_types.h"
+
+#include "ED_image.h"
+
+#include "GPU_batch.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "overlay_private.h"
+
+typedef struct OVERLAY_StretchingAreaTotals {
+ void *next, *prev;
+ float *total_area;
+ float *total_area_uv;
+} OVERLAY_StretchingAreaTotals;
+
+static OVERLAY_UVLineStyle edit_uv_line_style_from_space_image(const SpaceImage *sima)
+{
+ const bool is_uv_editor = sima->mode == SI_MODE_UV;
+ if (is_uv_editor) {
+ switch (sima->dt_uv) {
+ case SI_UVDT_OUTLINE:
+ return OVERLAY_UV_LINE_STYLE_OUTLINE;
+ case SI_UVDT_BLACK:
+ return OVERLAY_UV_LINE_STYLE_BLACK;
+ case SI_UVDT_WHITE:
+ return OVERLAY_UV_LINE_STYLE_WHITE;
+ case SI_UVDT_DASH:
+ return OVERLAY_UV_LINE_STYLE_DASH;
+ default:
+ return OVERLAY_UV_LINE_STYLE_BLACK;
+ }
+ }
+ else {
+ return OVERLAY_UV_LINE_STYLE_SHADOW;
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Internal API
+ * \{ */
+
+void OVERLAY_edit_uv_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+ 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;
+
+ Image *image = sima->image;
+ /* By design no image is an image type. This so editor shows UV's by default. */
+ const bool is_image_type =
+ (image == NULL) || ELEM(image->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER, IMA_TYPE_UV_TEST);
+ const bool is_uv_editor = sima->mode == SI_MODE_UV;
+ const bool has_edit_object = (draw_ctx->object_edit) != NULL;
+ const bool is_paint_mode = sima->mode == SI_MODE_PAINT;
+ const bool is_view_mode = sima->mode == SI_MODE_VIEW;
+ const bool is_edit_mode = draw_ctx->object_mode == OB_MODE_EDIT;
+ const bool do_uv_overlay = is_image_type && is_uv_editor && has_edit_object;
+ const bool show_modified_uvs = sima->flag & SI_DRAWSHADOW;
+ const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
+ const bool do_faces = ((sima->flag & SI_NO_DRAWFACES) == 0);
+ const bool do_face_dots = (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode & SCE_SELECT_FACE) != 0 :
+ (ts->uv_selectmode == UV_SELECT_FACE);
+ const bool do_uvstretching_overlay = is_image_type && is_uv_editor && is_edit_mode &&
+ ((sima->flag & SI_DRAW_STRETCH) != 0);
+ pd->edit_uv.do_faces = do_faces && !do_uvstretching_overlay;
+ pd->edit_uv.do_face_dots = do_faces && do_face_dots;
+
+ pd->edit_uv.do_uv_overlay = do_uv_overlay;
+ pd->edit_uv.do_uv_shadow_overlay =
+ is_image_type &&
+ ((is_paint_mode &&
+ ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) ||
+ (is_view_mode && ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT)) != 0)) ||
+ (do_uv_overlay && (show_modified_uvs)));
+ pd->edit_uv.do_uv_stretching_overlay = do_uvstretching_overlay;
+ pd->edit_uv.uv_opacity = sima->uv_opacity;
+ pd->edit_uv.do_tiled_image_overlay = is_image_type && is_tiled_image;
+
+ 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.draw_type = sima->dt_uvstretch;
+ BLI_listbase_clear(&pd->edit_uv.totals);
+ pd->edit_uv.total_area_ratio = 0.0f;
+ pd->edit_uv.total_area_ratio_inv = 0.0f;
+
+ ED_space_image_get_uv_aspect(sima, &pd->edit_uv.aspect[0], &pd->edit_uv.aspect[1]);
+}
+
+void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ if (pd->edit_uv.do_uv_overlay || pd->edit_uv.do_uv_shadow_overlay) {
+ /* uv edges */
+ {
+ DRW_PASS_CREATE(psl->edit_uv_edges_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND_ALPHA);
+ GPUShader *sh = OVERLAY_shader_edit_uv_edges_get();
+ if (pd->edit_uv.do_uv_shadow_overlay) {
+ pd->edit_uv_shadow_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_shadow_edges_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_int_copy(
+ pd->edit_uv_shadow_edges_grp, "lineStyle", OVERLAY_UV_LINE_STYLE_SHADOW);
+ DRW_shgroup_uniform_float_copy(
+ pd->edit_uv_shadow_edges_grp, "alpha", pd->edit_uv.uv_opacity);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_shadow_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1);
+ DRW_shgroup_uniform_bool(
+ pd->edit_uv_shadow_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1);
+ }
+
+ if (pd->edit_uv.do_uv_overlay) {
+ pd->edit_uv_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_edges_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_int_copy(pd->edit_uv_edges_grp, "lineStyle", pd->edit_uv.line_style);
+ DRW_shgroup_uniform_float_copy(pd->edit_uv_edges_grp, "alpha", pd->edit_uv.uv_opacity);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1);
+ DRW_shgroup_uniform_bool(
+ pd->edit_uv_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1);
+ }
+ }
+ }
+
+ if (pd->edit_uv.do_uv_overlay) {
+ /* uv verts */
+ {
+ DRW_PASS_CREATE(psl->edit_uv_verts_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND_ALPHA);
+ GPUShader *sh = OVERLAY_shader_edit_uv_verts_get();
+ pd->edit_uv_verts_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps);
+
+ const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+
+ DRW_shgroup_uniform_block(pd->edit_uv_verts_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float_copy(
+ pd->edit_uv_verts_grp, "pointSize", (point_size + 1.5f) * M_SQRT2);
+ DRW_shgroup_uniform_float_copy(pd->edit_uv_verts_grp, "outlineWidth", 0.75f);
+ }
+
+ /* uv faces */
+ if (pd->edit_uv.do_faces) {
+ DRW_PASS_CREATE(psl->edit_uv_faces_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA);
+ GPUShader *sh = OVERLAY_shader_edit_uv_face_get();
+ pd->edit_uv_faces_grp = DRW_shgroup_create(sh, psl->edit_uv_faces_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_faces_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float(pd->edit_uv_faces_grp, "uvOpacity", &pd->edit_uv.uv_opacity, 1);
+ }
+
+ /* uv face dots */
+ if (pd->edit_uv.do_face_dots) {
+ const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+ GPUShader *sh = OVERLAY_shader_edit_uv_face_dots_get();
+ pd->edit_uv_face_dots_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_face_dots_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float_copy(pd->edit_uv_face_dots_grp, "pointSize", point_size);
+ }
+ }
+
+ /* uv stretching */
+ if (pd->edit_uv.do_uv_stretching_overlay) {
+ DRW_PASS_CREATE(psl->edit_uv_stretching_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA);
+ if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) {
+ GPUShader *sh = OVERLAY_shader_edit_uv_stretching_angle_get();
+ pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_vec2_copy(pd->edit_uv_stretching_grp, "aspect", pd->edit_uv.aspect);
+ }
+ else /* SI_UVDT_STRETCH_AREA */ {
+ GPUShader *sh = OVERLAY_shader_edit_uv_stretching_area_get();
+ pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_stretching_grp, "totalAreaRatio", &pd->edit_uv.total_area_ratio, 1);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_stretching_grp, "totalAreaRatioInv", &pd->edit_uv.total_area_ratio_inv, 1);
+ }
+ }
+
+ 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;
+ GPUBatch *geom = DRW_cache_quad_wires_get();
+ float obmat[4][4];
+ unit_m4(obmat);
+
+ DRW_PASS_CREATE(psl->edit_uv_tiled_image_borders_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS);
+ GPUShader *sh = OVERLAY_shader_edit_uv_tiled_image_borders_get();
+
+ float theme_color[4], selected_color[4];
+ UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color);
+ UI_GetThemeColor4fv(TH_FACE_SELECT, selected_color);
+ srgb_to_linearrgb_v4(theme_color, theme_color);
+ srgb_to_linearrgb_v4(selected_color, selected_color);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", theme_color);
+ DRW_shgroup_uniform_vec3_copy(grp, "offset", (float[3]){0.0f, 0.0f, 0.0f});
+
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ const int tile_x = ((tile->tile_number - 1001) % 10);
+ const int tile_y = ((tile->tile_number - 1001) / 10);
+ obmat[3][1] = (float)tile_y;
+ obmat[3][0] = (float)tile_x;
+ DRW_shgroup_call_obmat(grp, geom, obmat);
+ }
+
+ /* Active tile border */
+ ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index);
+ obmat[3][0] = (float)((active_tile->tile_number - 1001) % 10);
+ obmat[3][1] = (float)((active_tile->tile_number - 1001) / 10);
+ grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", selected_color);
+ DRW_shgroup_call_obmat(grp, geom, obmat);
+
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ uchar color[4];
+ /* Color Management: Exception here as texts are drawn in sRGB space directly. */
+ UI_GetThemeColorShade4ubv(TH_BACK, 60, color);
+ char text[16];
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ BLI_snprintf(text, 5, "%d", tile->tile_number);
+ float tile_location[3] = {
+ ((tile->tile_number - 1001) % 10), ((tile->tile_number - 1001) / 10), 0.0f};
+ DRW_text_cache_add(dt,
+ tile_location,
+ text,
+ strlen(text),
+ 10,
+ 10,
+ DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII,
+ color);
+ }
+ }
+}
+
+void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+ GPUBatch *geom;
+ const bool is_edit_object = DRW_object_is_in_edit_mode(ob);
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool draw_shadows = (draw_ctx->object_mode != OB_MODE_OBJECT) &&
+ (ob->mode == draw_ctx->object_mode);
+ if (is_edit_object) {
+ if (pd->edit_uv.do_uv_overlay) {
+ geom = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_edges_grp, geom, NULL);
+ }
+ geom = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_verts_grp, geom, NULL);
+ }
+ if (pd->edit_uv.do_faces) {
+ geom = DRW_mesh_batch_cache_get_edituv_faces(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_faces_grp, geom, NULL);
+ }
+ }
+ if (pd->edit_uv.do_face_dots) {
+ geom = DRW_mesh_batch_cache_get_edituv_facedots(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_face_dots_grp, geom, NULL);
+ }
+ }
+ }
+
+ if (pd->edit_uv.do_uv_stretching_overlay) {
+ Mesh *me = ob->data;
+
+ if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) {
+ geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(me);
+ }
+ else /* SI_UVDT_STRETCH_AREA */ {
+ OVERLAY_StretchingAreaTotals *totals = MEM_mallocN(sizeof(OVERLAY_StretchingAreaTotals),
+ __func__);
+ BLI_addtail(&pd->edit_uv.totals, totals);
+ geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_area(
+ me, &totals->total_area, &totals->total_area_uv);
+ }
+
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_stretching_grp, geom, NULL);
+ }
+ }
+ }
+
+ if (draw_shadows) {
+ if (pd->edit_uv.do_uv_shadow_overlay) {
+ geom = DRW_mesh_batch_cache_get_uv_edges(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_shadow_edges_grp, geom, NULL);
+ }
+ }
+ }
+}
+
+static void edit_uv_stretching_update_ratios(OVERLAY_Data *vedata)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_AREA) {
+ float total_area = 0.0f;
+ float total_area_uv = 0.0f;
+
+ LISTBASE_FOREACH (OVERLAY_StretchingAreaTotals *, totals, &pd->edit_uv.totals) {
+ total_area += *totals->total_area;
+ total_area_uv += *totals->total_area_uv;
+ }
+
+ if (total_area > FLT_EPSILON && total_area_uv > FLT_EPSILON) {
+ pd->edit_uv.total_area_ratio = total_area / total_area_uv;
+ pd->edit_uv.total_area_ratio_inv = total_area_uv / total_area;
+ }
+ }
+ BLI_freelistN(&pd->edit_uv.totals);
+}
+
+void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ if (pd->edit_uv.do_tiled_image_overlay) {
+ DRW_draw_pass(psl->edit_uv_tiled_image_borders_ps);
+ }
+
+ if (pd->edit_uv.do_uv_stretching_overlay) {
+ 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);
+ }
+ DRW_draw_pass(psl->edit_uv_edges_ps);
+
+ DRW_draw_pass(psl->edit_uv_verts_ps);
+ }
+ else if (pd->edit_uv.do_uv_shadow_overlay) {
+ DRW_draw_pass(psl->edit_uv_edges_ps);
+ }
+}
+
+/* \{ */
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index 1312408498a..9cdd371ec4e 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -29,9 +29,13 @@
#include "ED_view3d.h"
+#include "UI_interface.h"
+
#include "BKE_object.h"
#include "BKE_paint.h"
+#include "DNA_space_types.h"
+
#include "overlay_engine.h"
#include "overlay_private.h"
@@ -48,6 +52,10 @@ static void OVERLAY_engine_init(void *vedata)
const View3D *v3d = draw_ctx->v3d;
const Scene *scene = draw_ctx->scene;
const ToolSettings *ts = scene->toolsettings;
+ const SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
+ BLI_assert(v3d || sima);
+
+ OVERLAY_shader_library_ensure();
if (!stl->pd) {
/* Alloc transient pointers */
@@ -55,6 +63,14 @@ static void OVERLAY_engine_init(void *vedata)
}
OVERLAY_PrivateData *pd = stl->pd;
+ pd->is_image_editor = sima != NULL;
+
+ if (pd->is_image_editor) {
+ pd->clipping_state = 0;
+ OVERLAY_grid_init(data);
+ OVERLAY_edit_uv_init(data);
+ return;
+ }
pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0;
pd->ctx_mode = CTX_data_mode_enum_ex(
@@ -122,6 +138,13 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_StorageList *stl = data->stl;
OVERLAY_PrivateData *pd = stl->pd;
+ if (pd->is_image_editor) {
+ OVERLAY_background_cache_init(vedata);
+ OVERLAY_grid_cache_init(vedata);
+ OVERLAY_edit_uv_cache_init(vedata);
+ return;
+ }
+
switch (pd->ctx_mode) {
case CTX_MODE_EDIT_MESH:
OVERLAY_edit_mesh_cache_init(vedata);
@@ -240,6 +263,14 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
{
OVERLAY_Data *data = vedata;
OVERLAY_PrivateData *pd = data->stl->pd;
+
+ if (pd->is_image_editor) {
+ if (ob->type == OB_MESH) {
+ OVERLAY_edit_uv_cache_populate(vedata, ob);
+ }
+ return;
+ }
+
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_select = DRW_state_is_select();
const bool renderable = DRW_object_is_renderable(ob);
@@ -414,6 +445,12 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
static void OVERLAY_cache_finish(void *vedata)
{
+ OVERLAY_Data *data = vedata;
+ OVERLAY_PrivateData *pd = data->stl->pd;
+ if (pd->is_image_editor) {
+ return;
+ }
+
/* TODO(fclem) Only do this when really needed. */
{
/* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */
@@ -445,6 +482,16 @@ static void OVERLAY_draw_scene(void *vedata)
GPU_framebuffer_clear_color(dfbl->overlay_only_fb, clear_col);
}
+ if (pd->is_image_editor) {
+ OVERLAY_background_draw(data);
+ OVERLAY_grid_draw(data);
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(dfbl->overlay_fb);
+ }
+ OVERLAY_edit_uv_draw(data);
+ return;
+ }
+
OVERLAY_image_background_draw(vedata);
OVERLAY_background_draw(vedata);
diff --git a/source/blender/draw/engines/overlay/overlay_grid.c b/source/blender/draw/engines/overlay/overlay_grid.c
index e3079870d8f..7445dfc2e3d 100644
--- a/source/blender/draw/engines/overlay/overlay_grid.c
+++ b/source/blender/draw/engines/overlay/overlay_grid.c
@@ -26,6 +26,7 @@
#include "DEG_depsgraph_query.h"
+#include "ED_image.h"
#include "ED_view3d.h"
#include "overlay_private.h"
@@ -42,14 +43,31 @@ enum {
CLIP_ZNEG = (1 << 8),
GRID_BACK = (1 << 9),
GRID_CAMERA = (1 << 10),
+ PLANE_IMAGE = (1 << 11),
};
void OVERLAY_grid_init(OVERLAY_Data *vedata)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_ShadingData *shd = &pd->shdata;
-
const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ shd->grid_flag = 0;
+ shd->zneg_flag = 0;
+ shd->zpos_flag = 0;
+ shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
+
+ if (pd->is_image_editor) {
+ SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
+ shd->grid_flag = ED_space_image_has_buffer(sima) ? 0 : PLANE_IMAGE | SHOW_GRID;
+ shd->grid_distance = 1.0f;
+ shd->grid_mesh_size = 1.0f;
+ for (int step = 0; step < 8; step++) {
+ shd->grid_steps[step] = powf(4, step) * (1.0f / 16.0f);
+ }
+ return;
+ }
+
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
RegionView3D *rv3d = draw_ctx->rv3d;
@@ -60,10 +78,6 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
const bool show_floor = (pd->v3d_gridflag & V3D_SHOW_FLOOR) != 0;
const bool show_ortho_grid = (pd->v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0;
- shd->grid_flag = 0;
- shd->zneg_flag = 0;
- shd->zpos_flag = 0;
-
if (pd->hide_overlays || !(pd->v3d_gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z |
V3D_SHOW_FLOOR | V3D_SHOW_ORTHO_GRID))) {
return;
@@ -163,14 +177,16 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
}
shd->grid_distance = dist / 2.0f;
- shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
ED_view3d_grid_steps(scene, v3d, rv3d, shd->grid_steps);
}
void OVERLAY_grid_cache_init(OVERLAY_Data *vedata)
{
- OVERLAY_ShadingData *shd = &vedata->stl->pd->shdata;
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+ OVERLAY_ShadingData *shd = &pd->shdata;
+
OVERLAY_PassList *psl = vedata->psl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@@ -182,12 +198,29 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->grid_ps, state);
-
- GPUShader *sh = OVERLAY_shader_grid();
+ DRWShadingGroup *grp;
+ GPUShader *sh;
struct GPUBatch *geom = DRW_cache_grid_get();
+ if (pd->is_image_editor) {
+ /* add quad background */
+ sh = OVERLAY_shader_grid_image();
+ grp = DRW_shgroup_create(sh, psl->grid_ps);
+ DRW_shgroup_call(grp, DRW_cache_quad_get(), NULL);
+ float color_back[4];
+ interp_v4_v4v4(color_back, G_draw.block.colorBackground, G_draw.block.colorGrid, 0.5);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", color_back);
+
+ /* add wire border */
+ grp = DRW_shgroup_create(sh, psl->grid_ps);
+ DRW_shgroup_call(grp, DRW_cache_quad_wires_get(), NULL);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", G_draw.block.colorGrid);
+ }
+
+ sh = OVERLAY_shader_grid();
+
/* Create 3 quads to render ordered transparency Z axis */
- DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->grid_ps);
+ grp = DRW_shgroup_create(sh, psl->grid_ps);
DRW_shgroup_uniform_int(grp, "gridFlag", &shd->zneg_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", shd->zplane_axes, 1);
DRW_shgroup_uniform_float(grp, "gridDistance", &shd->grid_distance, 1);
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 86c1f077571..c1d29cf7450 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -34,6 +34,9 @@ extern "C" {
# define USE_GEOM_SHADER_WORKAROUND 0
#endif
+/* Needed for eSpaceImage_UVDT_Stretch */
+#include "DNA_space_types.h"
+
typedef struct OVERLAY_FramebufferList {
struct GPUFrameBuffer *overlay_default_fb;
struct GPUFrameBuffer *overlay_line_fb;
@@ -55,6 +58,14 @@ typedef struct OVERLAY_TextureList {
#define NOT_IN_FRONT 0
#define IN_FRONT 1
+typedef enum OVERLAY_UVLineStyle {
+ OVERLAY_UV_LINE_STYLE_OUTLINE = 0,
+ OVERLAY_UV_LINE_STYLE_DASH = 1,
+ OVERLAY_UV_LINE_STYLE_BLACK = 2,
+ OVERLAY_UV_LINE_STYLE_WHITE = 3,
+ OVERLAY_UV_LINE_STYLE_SHADOW = 4,
+} OVERLAY_UVLineStyle;
+
typedef struct OVERLAY_PassList {
DRWPass *antialiasing_ps;
DRWPass *armature_ps[2];
@@ -79,6 +90,11 @@ typedef struct OVERLAY_PassList {
DRWPass *edit_text_overlay_ps;
DRWPass *edit_text_darken_ps;
DRWPass *edit_text_wire_ps[2];
+ DRWPass *edit_uv_edges_ps;
+ DRWPass *edit_uv_verts_ps;
+ DRWPass *edit_uv_faces_ps;
+ DRWPass *edit_uv_stretching_ps;
+ DRWPass *edit_uv_tiled_image_borders_ps;
DRWPass *extra_ps[2];
DRWPass *extra_blend_ps;
DRWPass *extra_centers_ps;
@@ -247,6 +263,12 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *edit_particle_point_grp;
DRWShadingGroup *edit_text_overlay_grp;
DRWShadingGroup *edit_text_wire_grp[2];
+ DRWShadingGroup *edit_uv_verts_grp;
+ DRWShadingGroup *edit_uv_edges_grp;
+ DRWShadingGroup *edit_uv_shadow_edges_grp;
+ DRWShadingGroup *edit_uv_faces_grp;
+ DRWShadingGroup *edit_uv_face_dots_grp;
+ DRWShadingGroup *edit_uv_stretching_grp;
DRWShadingGroup *extra_grid_grp;
DRWShadingGroup *facing_grp[2];
DRWShadingGroup *motion_path_lines_grp;
@@ -289,6 +311,7 @@ typedef struct OVERLAY_PrivateData {
View3DOverlay overlay;
enum eContextObjectMode ctx_mode;
+ bool is_image_editor;
bool clear_in_front;
bool use_in_front;
bool wireframe_mode;
@@ -328,6 +351,29 @@ typedef struct OVERLAY_PrivateData {
int select_mode;
} edit_particle;
struct {
+ bool do_uv_overlay;
+ bool do_uv_shadow_overlay;
+ bool do_uv_stretching_overlay;
+ bool do_tiled_image_overlay;
+
+ bool do_faces;
+ bool do_face_dots;
+
+ float uv_opacity;
+ /* edge drawing */
+ OVERLAY_UVLineStyle line_style;
+ float dash_length;
+ int do_smooth_wire;
+
+ /* stretching overlay */
+ float aspect[2];
+ eSpaceImage_UVDT_Stretch draw_type;
+ ListBase totals;
+ float total_area_ratio;
+ float total_area_ratio_inv;
+
+ } edit_uv;
+ struct {
bool transparent;
bool show_relations;
bool do_pose_xray;
@@ -475,6 +521,11 @@ void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_particle_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_particle_draw(OVERLAY_Data *vedata);
+void OVERLAY_edit_uv_init(OVERLAY_Data *vedata);
+void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob);
+void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata);
+
void OVERLAY_extra_cache_init(OVERLAY_Data *vedata);
void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_extra_blend_draw(OVERLAY_Data *vedata);
@@ -573,6 +624,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
void OVERLAY_wireframe_draw(OVERLAY_Data *vedata);
void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *vedata);
+void OVERLAY_shader_library_ensure(void);
GPUShader *OVERLAY_shader_antialiasing(void);
GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void);
GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void);
@@ -602,6 +654,13 @@ GPUShader *OVERLAY_shader_edit_mesh_skin_root(void);
GPUShader *OVERLAY_shader_edit_mesh_vert(void);
GPUShader *OVERLAY_shader_edit_particle_strand(void);
GPUShader *OVERLAY_shader_edit_particle_point(void);
+GPUShader *OVERLAY_shader_edit_uv_edges_get(void);
+GPUShader *OVERLAY_shader_edit_uv_face_get(void);
+GPUShader *OVERLAY_shader_edit_uv_face_dots_get(void);
+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_extra(bool is_select);
GPUShader *OVERLAY_shader_extra_groundline(void);
GPUShader *OVERLAY_shader_extra_wire(bool use_object, bool is_select);
@@ -610,6 +669,7 @@ GPUShader *OVERLAY_shader_extra_point(void);
GPUShader *OVERLAY_shader_facing(void);
GPUShader *OVERLAY_shader_gpencil_canvas(void);
GPUShader *OVERLAY_shader_grid(void);
+GPUShader *OVERLAY_shader_grid_image(void);
GPUShader *OVERLAY_shader_image(void);
GPUShader *OVERLAY_shader_motion_path_line(void);
GPUShader *OVERLAY_shader_motion_path_vert(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index e3cb052890b..4530d6e8adf 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -70,6 +70,15 @@ extern char datatoc_edit_mesh_analysis_vert_glsl[];
extern char datatoc_edit_mesh_analysis_frag_glsl[];
extern char datatoc_edit_particle_strand_vert_glsl[];
extern char datatoc_edit_particle_point_vert_glsl[];
+extern char datatoc_edit_uv_verts_vert_glsl[];
+extern char datatoc_edit_uv_verts_frag_glsl[];
+extern char datatoc_edit_uv_edges_vert_glsl[];
+extern char datatoc_edit_uv_edges_geom_glsl[];
+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_tiled_image_borders_vert_glsl[];
extern char datatoc_extra_frag_glsl[];
extern char datatoc_extra_vert_glsl[];
extern char datatoc_extra_groundline_vert_glsl[];
@@ -113,6 +122,7 @@ extern char datatoc_xray_fade_frag_glsl[];
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[];
@@ -120,6 +130,7 @@ extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
extern char datatoc_gpencil_common_lib_glsl[];
+extern char datatoc_common_overlay_lib_glsl[];
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
@@ -164,6 +175,13 @@ typedef struct OVERLAY_Shaders {
GPUShader *edit_mesh_analysis;
GPUShader *edit_particle_strand;
GPUShader *edit_particle_point;
+ GPUShader *edit_uv_verts;
+ GPUShader *edit_uv_faces;
+ GPUShader *edit_uv_edges;
+ GPUShader *edit_uv_face_dots;
+ GPUShader *edit_uv_stretching_angle;
+ GPUShader *edit_uv_stretching_area;
+ GPUShader *edit_uv_tiled_image_borders;
GPUShader *extra;
GPUShader *extra_select;
GPUShader *extra_groundline;
@@ -175,6 +193,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *facing;
GPUShader *gpencil_canvas;
GPUShader *grid;
+ GPUShader *grid_image;
GPUShader *image;
GPUShader *motion_path_line;
GPUShader *motion_path_vert;
@@ -203,8 +222,20 @@ typedef struct OVERLAY_Shaders {
static struct {
OVERLAY_Shaders sh_data[GPU_SHADER_CFG_LEN];
+ DRWShaderLibrary *lib;
} e_data = {{{NULL}}};
+void OVERLAY_shader_library_ensure(void)
+{
+ if (e_data.lib == NULL) {
+ e_data.lib = DRW_shader_library_create();
+ /* 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_view_lib);
+ }
+}
+
GPUShader *OVERLAY_shader_antialiasing(void)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
@@ -1012,6 +1043,20 @@ GPUShader *OVERLAY_shader_grid(void)
return sh_data->grid;
}
+GPUShader *OVERLAY_shader_grid_image(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->grid_image) {
+ sh_data->grid_image = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_tiled_image_borders_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ e_data.lib,
+ "#define blender_srgb_to_framebuffer_space(a) a\n");
+ }
+ return sh_data->grid_image;
+}
+
GPUShader *OVERLAY_shader_image(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -1449,6 +1494,108 @@ GPUShader *OVERLAY_shader_xray_fade(void)
return sh_data->xray_fade;
}
+/* -------------------------------------------------------------------- */
+/** \name Edit UV shaders
+ * \{ */
+
+GPUShader *OVERLAY_shader_edit_uv_edges_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_edges) {
+ sh_data->edit_uv_edges = DRW_shader_create_with_shaderlib(datatoc_edit_uv_edges_vert_glsl,
+ datatoc_edit_uv_edges_geom_glsl,
+ datatoc_edit_uv_edges_frag_glsl,
+ e_data.lib,
+ NULL);
+ }
+ return sh_data->edit_uv_edges;
+}
+
+GPUShader *OVERLAY_shader_edit_uv_face_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_faces) {
+ sh_data->edit_uv_faces = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_faces_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ e_data.lib,
+ "#define blender_srgb_to_framebuffer_space(a) a\n");
+ }
+ return sh_data->edit_uv_faces;
+}
+
+GPUShader *OVERLAY_shader_edit_uv_face_dots_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_face_dots) {
+ sh_data->edit_uv_face_dots = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_face_dots_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ e_data.lib,
+ "#define blender_srgb_to_framebuffer_space(a) a\n");
+ }
+ return sh_data->edit_uv_face_dots;
+}
+
+GPUShader *OVERLAY_shader_edit_uv_verts_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_verts) {
+ sh_data->edit_uv_verts = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_verts_vert_glsl, NULL, datatoc_edit_uv_verts_frag_glsl, e_data.lib, NULL);
+ }
+
+ return sh_data->edit_uv_verts;
+}
+
+GPUShader *OVERLAY_shader_edit_uv_stretching_area_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_stretching_area) {
+ sh_data->edit_uv_stretching_area = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_stretching_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl,
+ e_data.lib,
+ "#define blender_srgb_to_framebuffer_space(a) a\n");
+ }
+
+ return sh_data->edit_uv_stretching_area;
+}
+
+GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_stretching_angle) {
+ sh_data->edit_uv_stretching_angle = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_stretching_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl,
+ e_data.lib,
+ "#define blender_srgb_to_framebuffer_space(a) a\n#define STRETCH_ANGLE\n");
+ }
+
+ return sh_data->edit_uv_stretching_angle;
+}
+
+GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_uv_tiled_image_borders) {
+ sh_data->edit_uv_tiled_image_borders = DRW_shader_create_with_shaderlib(
+ datatoc_edit_uv_tiled_image_borders_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ e_data.lib,
+ "#define blender_srgb_to_framebuffer_space(a) a\n");
+ }
+ return sh_data->edit_uv_tiled_image_borders;
+}
+
+/* \} */
+
static OVERLAY_InstanceFormats g_formats = {NULL};
OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void)
@@ -1521,6 +1668,8 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void)
void OVERLAY_shader_free(void)
{
+ DRW_SHADER_LIB_FREE_SAFE(e_data.lib);
+
for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
OVERLAY_Shaders *sh_data = &e_data.sh_data[sh_data_index];
GPUShader **sh_data_as_array = (GPUShader **)sh_data;
diff --git a/source/blender/draw/engines/overlay/shaders/background_frag.glsl b/source/blender/draw/engines/overlay/shaders/background_frag.glsl
index d5aaaf75b79..71bfd2f8e73 100644
--- a/source/blender/draw/engines/overlay/shaders/background_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/background_frag.glsl
@@ -13,6 +13,7 @@ out vec4 fragColor;
#define BG_GRADIENT 1
#define BG_CHECKER 2
#define BG_RADIAL 3
+#define BG_SOLID_CHECKER 4
#define SQRT2 1.4142135623730950488
/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
@@ -43,7 +44,11 @@ void main()
vec3 col_high;
vec3 col_low;
- switch (bgType) {
+ /* BG_SOLID_CHECKER selects BG_SOLID when no pixel has been drawn otherwise use the BG_CHERKER.
+ */
+ int bg_type = bgType == BG_SOLID_CHECKER ? (depth == 1.0 ? BG_SOLID : BG_CHECKER) : bgType;
+
+ switch (bg_type) {
case BG_SOLID:
bg_col = colorBackground.rgb;
break;
diff --git a/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl b/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl
new file mode 100644
index 00000000000..65aeb81a4ef
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl
@@ -0,0 +1,5 @@
+#define OVERLAY_UV_LINE_STYLE_OUTLINE 0
+#define OVERLAY_UV_LINE_STYLE_DASH 1
+#define OVERLAY_UV_LINE_STYLE_BLACK 2
+#define OVERLAY_UV_LINE_STYLE_WHITE 3
+#define OVERLAY_UV_LINE_STYLE_SHADOW 4
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl
new file mode 100644
index 00000000000..b81fdd2c712
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl
@@ -0,0 +1,77 @@
+#pragma BLENDER_REQUIRE(common_globals_lib.glsl)
+#pragma BLENDER_REQUIRE(common_overlay_lib.glsl)
+
+uniform int lineStyle;
+uniform bool doSmoothWire;
+uniform float alpha;
+uniform float dashLength;
+
+in float selectionFac_f;
+noperspective in float edgeCoord_f;
+noperspective in vec2 stipplePos_f;
+flat in vec2 stippleStart_f;
+
+layout(location = 0) out vec4 fragColor;
+
+#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
+
+/**
+ * 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.
+ */
+#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)
+
+void main()
+{
+ vec4 inner_color = vec4(vec3(0.0), 1.0);
+ vec4 outer_color = vec4(0.0);
+
+ vec2 dd = fwidth(stipplePos_f);
+ float line_distance = distance(stipplePos_f, stippleStart_f) / max(dd.x, dd.y);
+
+ if (lineStyle == OVERLAY_UV_LINE_STYLE_OUTLINE) {
+ inner_color = mix(colorWireEdit, colorEdgeSelect, selectionFac_f);
+ outer_color = vec4(vec3(0.0), 1.0);
+ }
+ else if (lineStyle == OVERLAY_UV_LINE_STYLE_DASH) {
+ if (fract(line_distance / dashLength) < 0.5) {
+ inner_color = mix(vec4(1.0), colorEdgeSelect, selectionFac_f);
+ }
+ }
+ else if (lineStyle == OVERLAY_UV_LINE_STYLE_BLACK) {
+ vec4 base_color = vec4(vec3(0.0), 1.0);
+ inner_color = mix(base_color, colorEdgeSelect, selectionFac_f);
+ }
+ else if (lineStyle == OVERLAY_UV_LINE_STYLE_WHITE) {
+ vec4 base_color = vec4(1.0);
+ inner_color = mix(base_color, colorEdgeSelect, selectionFac_f);
+ }
+ else if (lineStyle == OVERLAY_UV_LINE_STYLE_SHADOW) {
+ inner_color = colorUVShadow;
+ }
+
+ float dist = abs(edgeCoord_f) - max(sizeEdge - 0.5, 0.0);
+ float dist_outer = dist - max(sizeEdge, 1.0);
+ float mix_w;
+ float mix_w_outer;
+
+ if (doSmoothWire) {
+ mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist);
+ mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer);
+ }
+ else {
+ mix_w = step(0.5, dist);
+ mix_w_outer = step(0.5, dist_outer);
+ }
+
+ vec4 final_color = mix(outer_color, inner_color, 1.0 - mix_w * outer_color.a);
+ final_color.a *= 1.0 - (outer_color.a > 0.0 ? mix_w_outer : mix_w);
+ final_color.a *= alpha;
+
+ fragColor = final_color;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl
new file mode 100644
index 00000000000..4f8d553a220
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl
@@ -0,0 +1,63 @@
+#pragma BLENDER_REQUIRE(common_globals_lib.glsl)
+#pragma BLENDER_REQUIRE(common_overlay_lib.glsl)
+
+layout(lines) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in float selectionFac[2];
+flat in vec2 stippleStart[2];
+noperspective in vec2 stipplePos[2];
+
+uniform int lineStyle;
+uniform bool doSmoothWire;
+
+out float selectionFac_f;
+noperspective out float edgeCoord_f;
+noperspective out vec2 stipplePos_f;
+flat out vec2 stippleStart_f;
+
+void do_vertex(
+ vec4 pos, float selection_fac, vec2 stipple_start, vec2 stipple_pos, float coord, vec2 offset)
+{
+ selectionFac_f = selection_fac;
+ edgeCoord_f = coord;
+ stippleStart_f = stipple_start;
+ stipplePos_f = stipple_pos;
+
+ gl_Position = pos;
+ /* Multiply offset by 2 because gl_Position range is [-1..1]. */
+ gl_Position.xy += offset * 2.0;
+ EmitVertex();
+}
+
+void main()
+{
+ vec2 ss_pos[2];
+ vec4 pos0 = gl_in[0].gl_Position;
+ vec4 pos1 = gl_in[1].gl_Position;
+ ss_pos[0] = pos0.xy / pos0.w;
+ ss_pos[1] = pos1.xy / pos1.w;
+
+ float half_size = sizeEdge;
+ /* Enlarge edge for outline drawing. */
+ /* Factor of 3.0 out of nowhere! Seems to fix issues with float imprecision. */
+ half_size += (lineStyle == OVERLAY_UV_LINE_STYLE_OUTLINE) ?
+ max(sizeEdge * (doSmoothWire ? 1.0 : 3.0), 1.0) :
+ 0.0;
+ /* Add 1 px for AA */
+ if (doSmoothWire) {
+ half_size += 0.5;
+ }
+
+ vec2 line = ss_pos[0] - ss_pos[1];
+ vec2 line_dir = normalize(line);
+ vec2 line_perp = vec2(-line_dir.y, line_dir.x);
+ vec2 edge_ofs = line_perp * sizeViewportInv * ceil(half_size);
+
+ do_vertex(pos0, selectionFac[0], stippleStart[0], stipplePos[0], half_size, edge_ofs.xy);
+ do_vertex(pos0, selectionFac[0], stippleStart[0], stipplePos[0], -half_size, -edge_ofs.xy);
+ do_vertex(pos1, selectionFac[1], stippleStart[1], stipplePos[1], half_size, edge_ofs.xy);
+ do_vertex(pos1, selectionFac[1], stippleStart[1], stipplePos[1], -half_size, -edge_ofs.xy);
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl
new file mode 100644
index 00000000000..4661cf248e6
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl
@@ -0,0 +1,32 @@
+#pragma BLENDER_REQUIRE(common_globals_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+in vec3 pos;
+in vec2 u;
+in int flag;
+
+out float selectionFac;
+noperspective out vec2 stipplePos;
+flat out vec2 stippleStart;
+
+void main()
+{
+ vec3 world_pos = point_object_to_world(vec3(u, 0.0));
+ gl_Position = point_world_to_ndc(world_pos);
+ /* Snap vertices to the pixel grid to reduce artifacts. */
+ vec2 half_viewport_res = sizeViewport.xy * 0.5;
+ vec2 half_pixel_offset = sizeViewportInv * 0.5;
+ gl_Position.xy = floor(gl_Position.xy * half_viewport_res) / half_viewport_res +
+ half_pixel_offset;
+
+ bool is_select = (flag & VERT_UV_SELECT) != 0;
+ selectionFac = is_select ? 1.0 : 0.0;
+ /* Move selected edges to the top
+ * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4
+ * actual pixels are at 0.75, 1.0 is used for the background. */
+ float depth = is_select ? 0.25 : 0.35;
+ gl_Position.z = depth;
+
+ /* Avoid precision loss. */
+ stippleStart = stipplePos = 500.0 + 500.0 * (gl_Position.xy / gl_Position.w);
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl
new file mode 100644
index 00000000000..61152c83a29
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl
@@ -0,0 +1,18 @@
+#pragma BLENDER_REQUIRE(common_globals_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+uniform float pointSize;
+
+in vec2 u;
+in int flag;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 world_pos = point_object_to_world(vec3(u, 0.0));
+ gl_Position = point_world_to_ndc(world_pos);
+
+ finalColor = ((flag & FACE_UV_SELECT) != 0) ? colorVertexSelect : vec4(colorWire.rgb, 1.0);
+ gl_PointSize = pointSize;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl
new file mode 100644
index 00000000000..cf1018ae5f9
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl
@@ -0,0 +1,22 @@
+#pragma BLENDER_REQUIRE(common_globals_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+uniform float uvOpacity;
+
+in vec2 u;
+in int flag;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 world_pos = point_object_to_world(vec3(u, 0.0));
+ gl_Position = point_world_to_ndc(world_pos);
+
+ bool is_selected = (flag & FACE_UV_SELECT) != 0;
+ bool is_active = (flag & FACE_UV_ACTIVE) != 0;
+
+ finalColor = (is_selected) ? colorFaceSelect : colorFace;
+ finalColor = (is_active) ? colorEditMeshActive : finalColor;
+ finalColor.a *= uvOpacity;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl
new file mode 100644
index 00000000000..ce97f1e27ac
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl
@@ -0,0 +1,98 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+uniform vec2 aspect;
+in vec2 pos;
+
+#ifdef STRETCH_ANGLE
+in vec2 uv_angles;
+in float angle;
+
+#else
+in float ratio;
+uniform float totalAreaRatio;
+uniform float totalAreaRatioInv;
+
+#endif
+
+noperspective out vec4 finalColor;
+
+vec3 weight_to_rgb(float weight)
+{
+ vec3 r_rgb;
+ float blend = ((weight / 2.0) + 0.5);
+
+ if (weight <= 0.25) { /* blue->cyan */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend * weight * 4.0;
+ r_rgb[2] = blend;
+ }
+ else if (weight <= 0.50) { /* cyan->green */
+ r_rgb[0] = 0.0;
+ r_rgb[1] = blend;
+ r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0));
+ }
+ else if (weight <= 0.75) { /* green->yellow */
+ r_rgb[0] = blend * ((weight - 0.50) * 4.0);
+ r_rgb[1] = blend;
+ r_rgb[2] = 0.0;
+ }
+ else if (weight <= 1.0) { /* yellow->red */
+ r_rgb[0] = blend;
+ r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0));
+ r_rgb[2] = 0.0;
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb[0] = 1.0;
+ r_rgb[1] = 0.0;
+ r_rgb[2] = 1.0;
+ }
+
+ return r_rgb;
+}
+
+#define M_PI 3.1415926535897932
+
+vec2 angle_to_v2(float angle)
+{
+ return vec2(cos(angle), sin(angle));
+}
+
+/* Adapted from BLI_math_vector.h */
+float angle_normalized_v2v2(vec2 v1, vec2 v2)
+{
+ v1 = normalize(v1 * aspect);
+ v2 = normalize(v2 * aspect);
+ /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */
+ bool q = (dot(v1, v2) >= 0.0);
+ vec2 v = (q) ? (v1 - v2) : (v1 + v2);
+ float a = 2.0 * asin(length(v) / 2.0);
+ return (q) ? a : M_PI - a;
+}
+
+float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio)
+{
+ ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio;
+ return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
+}
+
+void main()
+{
+ vec3 world_pos = point_object_to_world(vec3(pos, 0.0));
+ gl_Position = point_world_to_ndc(world_pos);
+
+#ifdef STRETCH_ANGLE
+ vec2 v1 = angle_to_v2(uv_angles.x * M_PI);
+ vec2 v2 = angle_to_v2(uv_angles.y * M_PI);
+ float uv_angle = angle_normalized_v2v2(v1, v2) / M_PI;
+ float stretch = 1.0 - abs(uv_angle - angle);
+ stretch = stretch;
+ stretch = 1.0 - stretch * stretch;
+#else
+ float stretch = 1.0 - area_ratio_to_stretch(ratio, totalAreaRatio, totalAreaRatioInv);
+
+#endif
+
+ finalColor = vec4(weight_to_rgb(stretch), 1.0);
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl
new file mode 100644
index 00000000000..c762858a910
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl
@@ -0,0 +1,12 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+in vec3 pos;
+
+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;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl
new file mode 100644
index 00000000000..11694de38ca
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl
@@ -0,0 +1,33 @@
+
+uniform vec4 outlineColor;
+
+in vec4 radii;
+in vec4 fillColor;
+out vec4 fragColor;
+
+void main()
+{
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+ // transparent outside of point
+ // --- 0 ---
+ // smooth transition
+ // --- 1 ---
+ // pure outline color
+ // --- 2 ---
+ // smooth transition
+ // --- 3 ---
+ // pure fill color
+ // ...
+ // dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else {
+ fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist));
+ }
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl
new file mode 100644
index 00000000000..327a35ce6b2
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl
@@ -0,0 +1,44 @@
+#pragma BLENDER_REQUIRE(common_globals_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+uniform float pointSize;
+uniform float outlineWidth;
+
+in vec2 u;
+in int flag;
+
+out vec4 fillColor;
+out vec4 outlineColor;
+out vec4 radii;
+
+/* TODO Theme? */
+const vec4 pinned_col = vec4(1.0, 0.0, 0.0, 1.0);
+
+void main()
+{
+ bool is_selected = (flag & (VERT_UV_SELECT | FACE_UV_SELECT)) != 0;
+ bool is_pinned = (flag & VERT_UV_PINNED) != 0;
+ vec4 deselect_col = (is_pinned) ? pinned_col : vec4(colorWire.rgb, 1.0);
+ fillColor = (is_selected) ? colorVertexSelect : deselect_col;
+ outlineColor = (is_pinned) ? pinned_col : vec4(fillColor.rgb, 0.0);
+
+ vec3 world_pos = point_object_to_world(vec3(u, 0.0));
+ /* Move selected vertices to the top
+ * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4
+ * actual pixels are at 0.75, 1.0 is used for the background. */
+ float depth = is_selected ? 0.05 : 0.15;
+ gl_Position = vec4(point_world_to_ndc(world_pos).xy, depth, 1.0);
+ gl_PointSize = pointSize;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * pointSize;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= pointSize;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl
index dd0e771ad93..6df4ead9f2a 100644
--- a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl
@@ -12,7 +12,7 @@ uniform int gridFlag;
#define PLANE_YZ (1 << 6)
#define CLIP_Z_POS (1 << 7)
#define CLIP_Z_NEG (1 << 8)
-
+#define PLANE_IMAGE (1 << 11)
in vec3 pos;
out vec3 local_pos;
@@ -28,9 +28,12 @@ void main()
else if ((gridFlag & PLANE_XZ) != 0) {
vert_pos = vec3(pos.x, 0.0, pos.y);
}
- else {
+ else if ((gridFlag & PLANE_YZ) != 0) {
vert_pos = vec3(0.0, pos.x, pos.y);
}
+ else /* PLANE_IMAGE */ {
+ vert_pos = vec3(pos.xy * 0.5 + 0.5, 0.0);
+ }
local_pos = vert_pos;