Use DrawManager for Image/UV Editor

This project moves the current UV/Image editor drawing to the draw manager.
Why would we do this:

**Performance**:

Current implementation would draw each texel per time. Multiple texels could be
drawn per pixel what would overwrite the previous result. You can notice this
when working with large textures. Repeat image drawing made this visible by
drawing for a small period of time and stop drawing the rest. Now the rendering
is fast and all repeated images are drawn.

**Alpha drawing**:

Current implementation would draw directly in display space. Giving incorrect
results when displaying alpha transparent images.
This addresses {T52680}, {T74709}, {T79518}
The image editor now can show emission only colors. See {D8234} for
examples.

**Current Limitations**

Using images that are larger than supported by your GPU are resized (eg larger
than 16000x16000 are resized to 8k). This leaves some blurring artifacts. It is
a low priority to add support back of displaying individual pixels of huge
images. There is a design task {T80113} with more detail.

**Implementation overview**
Introduced an Image Engine in the draw module. this engine is responsible for
drawing the texture in the main area of the UV/Image editor. The overlay engine
has a edit_uv overlay which is responsible to draw the UV's, shadows and
overlays specifically for the UV Image editor. The background + checker pattern
is drawn by the overlay_background.

The patch will allow us to share overlays between the 3d viewport and UV/Image
editor more easily. In most cases we just need to switch the `pos` with the `u`
attribute in the vertex shader.

The project can be activated in the user preferences as experimental features.
In a later commit this will be reversed.

Reviewed By: Clément Foucault

Differential Revision: https://developer.blender.org/D8234
This commit is contained in:
Jeroen Bakker 2020-09-11 07:59:48 +02:00
parent d023c4104c
commit d6525e8d13
Notes: blender-bot 2024-01-31 11:35:08 +01:00
Referenced by commit 344c001eae, Fix T81669: Vertex size in UV Editor changes using Face Dot Size in themes
Referenced by commit 6759b8a224, Cleanup: silence [-Wmissing-braces] warning.
Referenced by issue #96575, Vertex Color in UV Editor
Referenced by issue #84398, Multiview images show only one view
Referenced by issue #81575, Vectorscope in Image Editor is not working correctly
Referenced by issue #81126, Assert going to Texture Paint workspace without a UVMap
Referenced by issue #80931, UV Editor proportional editing circle draws wrong
Referenced by issue #80787, 2.91 Image Editor Quick Smoke (Fire) Pure Emission is displayed as (1.0, 1.0, 1.0) even when the actual values are 5 orders of magnitude lower.
Referenced by issue #80705, Texture Paint, New Single image, Segmentation fault: 11
Referenced by issue #67530, DesignTask: Add Drawing Of Image/UV Editor to the Draw Manager
Referenced by issue #52680, Alpha difference Viewport/F12
48 changed files with 2291 additions and 152 deletions

View File

@ -714,6 +714,7 @@ const bTheme U_theme_default = {
.paint_curve_pivot = RGBA(0xff7f7f7f),
.paint_curve_handle = RGBA(0x7fff7f7f),
.metadatatext = RGBA(0xffffffff),
.grid = RGBA(0x505050ff),
},
.space_text = {
.back = RGBA(0x30303000),

View File

@ -2176,6 +2176,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
self._draw_items(
context, (
({"property": "use_new_hair_type"}, "T68981"),
({"property": "use_drw_image_editor"}, "T67530"),
),
)

View File

@ -272,6 +272,13 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
* context and might as well ensure we have as much space free as possible. */
gpu_free_unused_buffers();
/* Free GPU textures when requesting a different render pass/layer. */
if (ima->gpu_pass != iuser->pass || ima->gpu_layer != iuser->layer) {
ima->gpu_pass = iuser->pass;
ima->gpu_layer = iuser->layer;
ima->gpuflag |= IMA_GPU_REFRESH;
}
/* currently, gpu refresh tagging is used by ima sequences */
if (ima->gpuflag & IMA_GPU_REFRESH) {
image_free_gpu(ima, true);
@ -282,7 +289,10 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
BKE_image_tag_time(ima);
/* Test if we already have a texture. */
GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, iuser ? iuser->multiview_eye : 0);
const int current_view = iuser ? ((iuser->flag & IMA_SHOW_STEREO) != 0 ? iuser->multiview_eye :
iuser->view) :
0;
GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, current_view);
if (*tex) {
return *tex;
}

View File

@ -233,6 +233,8 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
* the outliner's, and it's less disruptive to just copy them. */
copy_v4_v4_uchar(btheme->space_file.back, btheme->space_outliner.back);
copy_v4_v4_uchar(btheme->space_file.row_alternate, btheme->space_outliner.row_alternate);
FROM_DEFAULT_V4_UCHAR(space_image.grid);
}
#undef FROM_DEFAULT_V4_UCHAR

View File

@ -190,7 +190,7 @@ void ViewerOperation::updateImage(rcti *rect)
rect->ymin,
rect->xmax,
rect->ymax);
this->m_image->gpuflag |= IMA_GPU_REFRESH;
this->updateDraw();
}

View File

@ -77,6 +77,8 @@ set(SRC
intern/draw_select_buffer.c
intern/draw_view.c
engines/basic/basic_engine.c
engines/image/image_engine.c
engines/image/image_shader.c
engines/eevee/eevee_bloom.c
engines/eevee/eevee_data.c
engines/eevee/eevee_depth_of_field.c
@ -132,6 +134,7 @@ set(SRC
engines/overlay/overlay_edit_curve.c
engines/overlay/overlay_edit_mesh.c
engines/overlay/overlay_edit_text.c
engines/overlay/overlay_edit_uv.c
engines/overlay/overlay_engine.c
engines/overlay/overlay_extra.c
engines/overlay/overlay_facing.c
@ -319,6 +322,7 @@ data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC)
data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC)
data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/common_overlay_lib.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC)
@ -362,6 +366,15 @@ data_to_c_simple(engines/overlay/shaders/edit_mesh_skin_root_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_particle_strand_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_particle_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_uv_edges_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_uv_edges_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_uv_edges_frag.glsl SRC)
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_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)
data_to_c_simple(engines/overlay/shaders/extra_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_groundline_vert.glsl SRC)
@ -402,6 +415,9 @@ data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC)
data_to_c_simple(engines/image/shaders/engine_image_frag.glsl SRC)
data_to_c_simple(engines/image/shaders/engine_image_vert.glsl SRC)
list(APPEND INC
)

View File

@ -99,6 +99,10 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
const bool do_color_management,
struct GPUOffScreen *ofs,
struct GPUViewport *viewport);
void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
struct ARegion *region,
struct GPUViewport *viewport,
const struct bContext *evil_C);
void DRW_draw_select_loop(struct Depsgraph *depsgraph,
struct ARegion *region,
struct View3D *v3d,

View File

@ -0,0 +1,304 @@
/*
* 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 2020, Blender Foundation.
*/
/** \file
* \ingroup draw_editors
*
* Draw engine to draw the Image/UV editor
*/
#include "DRW_render.h"
#include "BKE_image.h"
#include "BKE_object.h"
#include "DNA_camera_types.h"
#include "IMB_imbuf_types.h"
#include "ED_image.h"
#include "GPU_batch.h"
#include "image_engine.h"
#include "image_private.h"
#define SIMA_DRAW_FLAG_SHOW_ALPHA (1 << 0)
#define SIMA_DRAW_FLAG_APPLY_ALPHA (1 << 1)
#define SIMA_DRAW_FLAG_SHUFFLING (1 << 2)
#define SIMA_DRAW_FLAG_DEPTH (1 << 3)
#define SIMA_DRAW_FLAG_TILED (1 << 4)
#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5)
static void image_cache_image_add(DRWShadingGroup *grp, Image *image)
{
const bool is_tiled_texture = image && image->source == IMA_SRC_TILED;
float obmat[4][4];
unit_m4(obmat);
GPUBatch *geom = DRW_cache_quad_get();
if (is_tiled_texture) {
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);
}
}
else {
DRW_shgroup_call_obmat(grp, geom, obmat);
}
}
static void image_gpu_texture_get(Image *image,
ImageUser *iuser,
ImBuf *ibuf,
GPUTexture **r_gpu_texture,
bool *r_owns_texture,
GPUTexture **r_tex_tile_data)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
if (image) {
if (BKE_image_is_multilayer(image)) {
/* update multiindex and pass for the current eye */
BKE_image_multilayer_index(image->rr, &sima->iuser);
}
else {
BKE_image_multiview_index(image, &sima->iuser);
}
if (ibuf) {
if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
if (ibuf->zbuf) {
BLI_assert(!"Integer based depth buffers not supported");
}
else if (ibuf->zbuf_float) {
*r_gpu_texture = GPU_texture_create_2d(
__func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float);
*r_owns_texture = true;
}
else if (ibuf->rect_float && ibuf->channels == 1) {
*r_gpu_texture = GPU_texture_create_2d(
__func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float);
*r_owns_texture = true;
}
}
else if (image->source == IMA_SRC_TILED) {
*r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf);
*r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL);
*r_owns_texture = false;
}
else {
*r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
*r_owns_texture = false;
}
}
}
}
static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser, ImBuf *ibuf)
{
IMAGE_PassList *psl = vedata->psl;
IMAGE_StorageList *stl = vedata->stl;
IMAGE_PrivateData *pd = stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
GPUTexture *tex_tile_data = NULL;
image_gpu_texture_get(image, iuser, ibuf, &pd->texture, &pd->owns_texture, &tex_tile_data);
if (pd->texture) {
static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
static float shuffle[4] = {1.0f, 1.0f, 1.0f, 1.0f};
static float far_near[2] = {100.0f, 0.0f};
if (scene->camera && scene->camera->type == OB_CAMERA) {
far_near[1] = ((Camera *)scene->camera->data)->clip_start;
far_near[0] = ((Camera *)scene->camera->data)->clip_end;
}
const bool use_premul_alpha = image->alpha_mode == IMA_ALPHA_PREMUL;
const bool is_tiled_texture = tex_tile_data != NULL;
const bool do_repeat = (!is_tiled_texture) && ((sima->flag & SI_DRAW_TILE) != 0);
const bool is_zoom_out = sima->zoom < 1.0f;
/* use interpolation filtering when zooming out */
eGPUSamplerState state = 0;
SET_FLAG_FROM_TEST(state, is_zoom_out, GPU_SAMPLER_FILTER);
int draw_flags = 0;
SET_FLAG_FROM_TEST(draw_flags, do_repeat, SIMA_DRAW_FLAG_DO_REPEAT);
if ((sima->flag & SI_USE_ALPHA) != 0) {
/* Show RGBA */
draw_flags |= SIMA_DRAW_FLAG_SHOW_ALPHA | SIMA_DRAW_FLAG_APPLY_ALPHA;
}
else if ((sima->flag & SI_SHOW_ALPHA) != 0) {
draw_flags |= SIMA_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
}
else if ((sima->flag & SI_SHOW_ZBUF) != 0) {
draw_flags |= SIMA_DRAW_FLAG_DEPTH | SIMA_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
}
else if ((sima->flag & SI_SHOW_R) != 0) {
draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
}
else if ((sima->flag & SI_SHOW_G) != 0) {
draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
}
else if ((sima->flag & SI_SHOW_B) != 0) {
draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
}
else /* RGB */ {
draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA;
}
GPUShader *shader = IMAGE_shader_image_get();
DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass);
if (tex_tile_data != NULL) {
draw_flags |= SIMA_DRAW_FLAG_TILED;
DRW_shgroup_uniform_texture_ex(shgrp, "imageTileArray", pd->texture, state);
DRW_shgroup_uniform_texture(shgrp, "imageTileData", tex_tile_data);
}
else {
DRW_shgroup_uniform_texture_ex(shgrp, "imageTexture", pd->texture, state);
}
DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", far_near);
DRW_shgroup_uniform_vec4_copy(shgrp, "color", color);
DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", shuffle);
DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", draw_flags);
DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", use_premul_alpha);
image_cache_image_add(shgrp, image);
}
}
/* -------------------------------------------------------------------- */
/** \name Engine Callbacks
* \{ */
static void IMAGE_engine_init(void *ved)
{
IMAGE_shader_library_ensure();
IMAGE_Data *vedata = (IMAGE_Data *)ved;
IMAGE_StorageList *stl = vedata->stl;
if (!stl->pd) {
stl->pd = MEM_callocN(sizeof(IMAGE_PrivateData), __func__);
}
IMAGE_PrivateData *pd = stl->pd;
pd->ibuf = NULL;
pd->lock = NULL;
pd->texture = NULL;
}
static void IMAGE_cache_init(void *ved)
{
IMAGE_Data *vedata = (IMAGE_Data *)ved;
IMAGE_StorageList *stl = vedata->stl;
IMAGE_PrivateData *pd = stl->pd;
IMAGE_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
{
/* Write depth is needed for background overlay rendering. Near depth is used for
* transparency checker and Far depth is used for indicating the image size. */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
DRW_STATE_BLEND_ALPHA_PREMUL;
psl->image_pass = DRW_pass_create("Image", state);
}
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
GPU_framebuffer_bind(dfbl->default_fb);
static float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_framebuffer_clear_color_depth(dfbl->default_fb, clear_col, 1.0);
{
Image *image = ED_space_image(sima);
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &pd->lock, 0);
image_cache_image(vedata, image, &sima->iuser, ibuf);
pd->ibuf = ibuf;
}
}
static void IMAGE_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob))
{
/* Function intentional left empty. `cache_populate` is required to be implemented. */
}
static void image_draw_finish(IMAGE_Data *ved)
{
IMAGE_Data *vedata = (IMAGE_Data *)ved;
IMAGE_StorageList *stl = vedata->stl;
IMAGE_PrivateData *pd = stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
ED_space_image_release_buffer(sima, pd->ibuf, pd->lock);
if (pd->texture && pd->owns_texture) {
GPU_texture_free(pd->texture);
pd->owns_texture = false;
}
pd->texture = NULL;
}
static void IMAGE_draw_scene(void *ved)
{
IMAGE_Data *vedata = (IMAGE_Data *)ved;
IMAGE_PassList *psl = vedata->psl;
DRW_draw_pass(psl->image_pass);
image_draw_finish(vedata);
}
static void IMAGE_engine_free(void)
{
IMAGE_shader_free();
}
/* \} */
static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data);
DrawEngineType draw_engine_image_type = {
NULL, /* next */
NULL, /* prev */
N_("UV/Image"), /* idname */
&IMAGE_data_size, /* vedata_size */
&IMAGE_engine_init, /* engine_init */
&IMAGE_engine_free, /* engine_free */
&IMAGE_cache_init, /* cache_init */
&IMAGE_cache_populate, /* cache_populate */
NULL, /* cache_finish */
&IMAGE_draw_scene, /* draw_scene */
NULL, /* view_update */
NULL, /* id_update */
NULL, /* render_to_image */
};

View File

@ -0,0 +1,25 @@
/*
* 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 2020, Blender Foundation.
*/
/** \file
* \ingroup draw_editors
*/
#pragma once
extern DrawEngineType draw_engine_image_type;

View File

@ -0,0 +1,69 @@
/*
* 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 2020, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations */
struct rcti;
struct GPUBatch;
struct Image;
struct ImBuf;
struct GPUTexture;
/* *********** LISTS *********** */
/* GPUViewport.storage
* Is freed everytime the viewport engine changes */
typedef struct IMAGE_PassList {
DRWPass *image_pass;
} IMAGE_PassList;
typedef struct IMAGE_PrivateData {
void *lock;
struct ImBuf *ibuf;
struct GPUTexture *texture;
bool owns_texture;
} IMAGE_PrivateData;
typedef struct IMAGE_StorageList {
IMAGE_PrivateData *pd;
} IMAGE_StorageList;
typedef struct IMAGE_Data {
void *engine_type;
DRWViewportEmptyList *fbl;
DRWViewportEmptyList *txl;
IMAGE_PassList *psl;
IMAGE_StorageList *stl;
} IMAGE_Data;
/* image_shader.c */
GPUShader *IMAGE_shader_image_get(void);
void IMAGE_shader_library_ensure(void);
void IMAGE_shader_free(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,77 @@
/*
* 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 2020, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "BLI_dynstr.h"
#include "GPU_batch.h"
#include "image_engine.h"
#include "image_private.h"
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_engine_image_frag_glsl[];
extern char datatoc_engine_image_vert_glsl[];
typedef struct IMAGE_Shaders {
GPUShader *image_sh;
} IMAGE_Shaders;
static struct {
IMAGE_Shaders shaders;
DRWShaderLibrary *lib;
} e_data = {0}; /* Engine data */
void IMAGE_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_colormanagement_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib);
}
}
GPUShader *IMAGE_shader_image_get(void)
{
IMAGE_Shaders *sh_data = &e_data.shaders;
if (!sh_data->image_sh) {
sh_data->image_sh = DRW_shader_create_with_shaderlib(
datatoc_engine_image_vert_glsl, NULL, datatoc_engine_image_frag_glsl, e_data.lib, NULL);
}
return sh_data->image_sh;
}
void IMAGE_shader_free(void)
{
GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders;
for (int i = 0; i < (sizeof(IMAGE_Shaders) / sizeof(GPUShader *)); i++) {
DRW_SHADER_FREE_SAFE(sh_data_as_array[i]);
}
DRW_SHADER_LIB_FREE_SAFE(e_data.lib);
}

View File

@ -0,0 +1,91 @@
#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl)
/* Keep in sync with image_engine.c */
#define SIMA_DRAW_FLAG_SHOW_ALPHA (1 << 0)
#define SIMA_DRAW_FLAG_APPLY_ALPHA (1 << 1)
#define SIMA_DRAW_FLAG_SHUFFLING (1 << 2)
#define SIMA_DRAW_FLAG_DEPTH (1 << 3)
#define SIMA_DRAW_FLAG_TILED (1 << 4)
#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5)
uniform sampler2DArray imageTileArray;
uniform sampler1DArray imageTileData;
uniform sampler2D imageTexture;
uniform bool imgPremultiplied;
uniform int drawFlags;
uniform vec2 farNearDistances;
uniform vec4 color;
uniform vec4 shuffle;
#define FAR_DISTANCE farNearDistances.x
#define NEAR_DISTANCE farNearDistances.y
in vec2 uvs;
out vec4 fragColor;
/* TODO(fclem) deduplicate code. */
bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
{
vec2 tile_pos = floor(co.xy);
if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) {
return false;
}
float tile = 10.0 * tile_pos.y + tile_pos.x;
if (tile >= textureSize(map, 0).x) {
return false;
}
/* Fetch tile information. */
float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x;
if (tile_layer < 0.0) {
return false;
}
vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0);
co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer);
return true;
}
void main()
{
vec4 tex_color;
/* Read texture */
if ((drawFlags & SIMA_DRAW_FLAG_TILED) != 0) {
vec3 co = vec3(uvs, 0.0);
if (node_tex_tile_lookup(co, imageTileArray, imageTileData)) {
tex_color = texture(imageTileArray, co);
}
else {
tex_color = vec4(1.0, 0.0, 1.0, 1.0);
}
}
else {
vec2 uvs_clamped = ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) ?
fract(uvs) :
clamp(uvs, vec2(0.0), vec2(1.0));
tex_color = texture(imageTexture, uvs_clamped);
}
if ((drawFlags & SIMA_DRAW_FLAG_APPLY_ALPHA) != 0) {
if (!imgPremultiplied && tex_color.a != 0.0 && tex_color.a != 1.0) {
tex_color.rgb *= tex_color.a;
}
}
if ((drawFlags & SIMA_DRAW_FLAG_DEPTH) != 0) {
tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color);
}
if ((drawFlags & SIMA_DRAW_FLAG_SHUFFLING) != 0) {
tex_color = color * dot(tex_color, shuffle);
}
if ((drawFlags & SIMA_DRAW_FLAG_SHOW_ALPHA) == 0) {
tex_color.a = 1.0;
}
fragColor = tex_color;
}

View File

@ -0,0 +1,31 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5)
uniform int drawFlags;
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;
if ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) {
gl_Position = vec4(pos.xy, 0.0, 1.0);
uvs = point_view_to_object(image_pos).xy;
}
else {
vec3 world_pos = point_object_to_world(image_pos);
vec4 position = point_world_to_ndc(world_pos);
/* Move drawn pixels to the front. In the overlay engine the depth is used
* to detect if a transparency texture or the background color should be drawn.
* 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. */
position.z = 0.75;
gl_Position = position;
uvs = world_pos.xy;
}
}

View File

@ -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;
}

View File

@ -0,0 +1,393 @@
/*
* 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 = (sima->flag & SI_SMOOTH_UV) != 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_copy(pd->edit_uv_shadow_edges_grp, "doSmoothWire", true);
}
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);
}
}
/* \{ */

View File

@ -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);

View File

@ -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);

View File

@ -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];
@ -78,6 +89,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;
@ -244,6 +260,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;
@ -286,6 +308,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;
@ -324,6 +347,29 @@ typedef struct OVERLAY_PrivateData {
bool use_weight;
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;
@ -472,6 +518,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);
@ -570,6 +621,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);
@ -599,6 +651,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);
@ -607,6 +666,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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -736,9 +736,11 @@ bool DRW_state_draw_background(void);
/* Avoid too many lookups while drawing */
typedef struct DRWContextState {
struct ARegion *region; /* 'CTX_wm_region(C)' */
struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */
struct View3D *v3d; /* 'CTX_wm_view3d(C)' */
struct ARegion *region; /* 'CTX_wm_region(C)' */
struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */
struct View3D *v3d; /* 'CTX_wm_view3d(C)' */
struct SpaceLink *space_data; /* 'CTX_wm_space_data(C)' */
struct Scene *scene; /* 'CTX_data_scene(C)' */
struct ViewLayer *view_layer; /* 'CTX_data_view_layer(C)' */

View File

@ -178,6 +178,9 @@ void DRW_globals_update(void)
UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, gb->colorOutline);
UI_GetThemeColorShadeAlpha4fv(TH_LIGHT, 0, 255, gb->colorLightNoAlpha);
/* UV colors */
UI_GetThemeColor4fv(TH_UV_SHADOW, gb->colorUVShadow);
gb->sizePixel = U.pixelsize;
gb->sizeObjectCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.0f) * U.pixelsize;
gb->sizeLightCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.5f) * U.pixelsize;
@ -210,7 +213,7 @@ void DRW_globals_update(void)
/* TODO more accurate transform. */
srgb_to_linearrgb_v4(color, color);
color += 4;
} while (color != gb->UBO_LAST_COLOR);
} while (color <= gb->UBO_LAST_COLOR);
}
if (G_draw.block_ubo == NULL) {

View File

@ -33,7 +33,7 @@ struct RegionView3D;
struct ViewLayer;
#define UBO_FIRST_COLOR colorWire
#define UBO_LAST_COLOR colorFaceFront
#define UBO_LAST_COLOR colorUVShadow
/* Used as ubo but colors can be directly referenced as well */
/* Keep in sync with: common_globals_lib.glsl (globalsBlock) */
@ -141,6 +141,8 @@ typedef struct GlobalsUboStorage {
float colorFaceBack[4];
float colorFaceFront[4];
float colorUVShadow[4];
/* NOTE! Put all color before UBO_LAST_COLOR */
float screenVecs[2][4]; /* padded as vec4 */
float sizeViewport[2], sizeViewportInv[2]; /* packed as vec4 in glsl */

View File

@ -78,6 +78,7 @@
#include "RE_pipeline.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "WM_api.h"
#include "wm_window.h"
@ -94,6 +95,7 @@
#include "engines/eevee/eevee_engine.h"
#include "engines/external/external_engine.h"
#include "engines/gpencil/gpencil_engine.h"
#include "engines/image/image_engine.h"
#include "engines/overlay/overlay_engine.h"
#include "engines/select/select_engine.h"
#include "engines/workbench/workbench_engine.h"
@ -126,6 +128,25 @@ static void drw_state_ensure_not_reused(DRWManager *dst)
}
#endif
static bool drw_draw_show_annotation(void)
{
if (DST.draw_ctx.space_data == NULL) {
View3D *v3d = DST.draw_ctx.v3d;
return (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
}
switch (DST.draw_ctx.space_data->spacetype) {
case SPACE_IMAGE: {
SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data;
return (sima->flag & SI_SHOW_GPENCIL) != 0;
}
default:
BLI_assert("");
return false;
}
}
/* -------------------------------------------------------------------- */
/** \name Threading
* \{ */
@ -287,6 +308,7 @@ struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob))
/** \name Color Management
* \{ */
/* TODO(fclem) This should be a render engine callback to determine if we need CM or not. */
static void drw_viewport_colormanagement_set(void)
{
Scene *scene = DST.draw_ctx.scene;
@ -296,21 +318,43 @@ static void drw_viewport_colormanagement_set(void)
ColorManagedViewSettings view_settings;
float dither = 0.0f;
/* TODO(fclem) This should be a render engine callback to determine if we need CM or not. */
bool use_workbench = BKE_scene_uses_blender_workbench(scene);
bool use_render_settings = false;
bool use_view_transform = false;
bool use_scene_lights = (!v3d ||
((v3d->shading.type == OB_MATERIAL) &&
(v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) ||
((v3d->shading.type == OB_RENDER) &&
(v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER)));
bool use_scene_world =
(!v3d ||
((v3d->shading.type == OB_MATERIAL) && (v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) ||
((v3d->shading.type == OB_RENDER) && (v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER)));
bool use_view_transform = v3d && (v3d->shading.type >= OB_MATERIAL);
bool use_render_settings = v3d && ((use_workbench && use_view_transform) || use_scene_lights ||
use_scene_world);
if (v3d) {
bool use_workbench = BKE_scene_uses_blender_workbench(scene);
bool use_scene_lights = (!v3d ||
((v3d->shading.type == OB_MATERIAL) &&
(v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) ||
((v3d->shading.type == OB_RENDER) &&
(v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER)));
bool use_scene_world = (!v3d ||
((v3d->shading.type == OB_MATERIAL) &&
(v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) ||
((v3d->shading.type == OB_RENDER) &&
(v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER)));
use_view_transform = v3d && (v3d->shading.type >= OB_MATERIAL);
use_render_settings = v3d && ((use_workbench && use_view_transform) || use_scene_lights ||
use_scene_world);
}
else if (DST.draw_ctx.space_data && DST.draw_ctx.space_data->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data;
Image *image = sima->image;
/* Use inverse logic as there isn't a setting for `Color And Alpha`. */
const eSpaceImage_Flag display_channels_mode = sima->flag;
const bool display_color_channel = (display_channels_mode & (SI_SHOW_ALPHA | SI_SHOW_ZBUF)) ==
0;
if (display_color_channel && image && (image->source != IMA_SRC_GENERATED) &&
((image->flag & IMA_VIEW_AS_RENDER) != 0)) {
use_render_settings = true;
}
}
else {
use_render_settings = true;
use_view_transform = false;
}
if (use_render_settings) {
/* Use full render settings, for renders with scene lighting. */
@ -495,6 +539,8 @@ static void draw_unit_state_create(void)
static void drw_viewport_var_init(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
ARegion *region = DST.draw_ctx.region;
/* Refresh DST.size */
if (DST.viewport) {
int size[2];
@ -585,6 +631,24 @@ static void drw_viewport_var_init(void)
DST.view_active = DST.view_default;
DST.view_previous = NULL;
}
else if (region) {
View2D *v2d = &region->v2d;
float viewmat[4][4];
float winmat[4][4];
rctf region_space = {0.0f, 1.0f, 0.0f, 1.0f};
BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &region_space, viewmat);
unit_m4(winmat);
winmat[0][0] = 2.0f;
winmat[1][1] = 2.0f;
winmat[3][0] = -1.0f;
winmat[3][1] = -1.0f;
DST.view_default = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
DST.view_active = DST.view_default;
DST.view_previous = NULL;
}
else {
zero_v3(DST.screenvecs[0]);
zero_v3(DST.screenvecs[1]);
@ -596,7 +660,7 @@ static void drw_viewport_var_init(void)
}
/* fclem: Is this still needed ? */
if (DST.draw_ctx.object_edit) {
if (DST.draw_ctx.object_edit && rv3d) {
ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
}
@ -1163,6 +1227,19 @@ static void drw_engines_enable_basic(void)
use_drw_engine(&draw_engine_basic_type);
}
static void drw_engines_enable_editors(void)
{
SpaceLink *space_data = DST.draw_ctx.space_data;
if (!space_data) {
return;
}
if (space_data->spacetype == SPACE_IMAGE) {
use_drw_engine(&draw_engine_image_type);
use_drw_engine(&draw_engine_overlay_type);
}
}
static void drw_engines_enable(ViewLayer *UNUSED(view_layer),
RenderEngineType *engine_type,
bool gpencil_engine_needed)
@ -1299,8 +1376,7 @@ void DRW_draw_callbacks_post_scene(void)
View3D *v3d = DST.draw_ctx.v3d;
Depsgraph *depsgraph = DST.draw_ctx.depsgraph;
const bool do_annotations = (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
const bool do_annotations = drw_draw_show_annotation();
if (DST.draw_ctx.evil_C) {
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
@ -1387,21 +1463,30 @@ struct DRWTextStore *DRW_text_cache_ensure(void)
* for each relevant engine / mode engine. */
void DRW_draw_view(const bContext *C)
{
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
GPUViewport *viewport = WM_draw_region_get_bound_viewport(region);
if (v3d) {
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
ARegion *region = CTX_wm_region(C);
Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
GPUViewport *viewport = WM_draw_region_get_bound_viewport(region);
/* Reset before using it. */
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) ||
(v3d->shading.type != OB_RENDER);
DST.options.do_color_management = true;
DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, C);
/* Reset before using it. */
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) ||
(v3d->shading.type != OB_RENDER);
DST.options.do_color_management = true;
DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, C);
}
else {
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
ARegion *ar = CTX_wm_region(C);
GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar);
drw_state_prepare_clean_for_draw(&DST);
DRW_draw_render_loop_2d_ex(depsgraph, ar, viewport, C);
}
}
/**
@ -1909,6 +1994,171 @@ void DRW_cache_restart(void)
copy_v2_v2(DST.inv_size, inv_size);
}
void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
ARegion *region,
GPUViewport *viewport,
const bContext *evil_C)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
DST.draw_ctx.evil_C = evil_C;
DST.viewport = viewport;
/* Setup viewport */
DST.draw_ctx = (DRWContextState){
.region = region,
.scene = scene,
.view_layer = view_layer,
.obact = OBACT(view_layer),
.depsgraph = depsgraph,
.space_data = CTX_wm_space_data(evil_C),
/* reuse if caller sets */
.evil_C = DST.draw_ctx.evil_C,
};
drw_context_state_init();
drw_viewport_var_init();
drw_viewport_colormanagement_set();
/* TODO(jbakker): Only populate when editor needs to draw object.
* for the image editor this is when showing UV's.*/
const bool do_populate_loop = true;
const bool do_annotations = drw_draw_show_annotation();
/* Get list of enabled engines */
drw_engines_enable_editors();
drw_engines_data_validate();
/* Update ubos */
DRW_globals_update();
drw_debug_init();
/* No framebuffer allowed before drawing. */
BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get());
GPU_framebuffer_bind(DST.default_framebuffer);
GPU_framebuffer_clear_depth_stencil(DST.default_framebuffer, 1.0f, 0xFF);
/* Init engines */
drw_engines_init();
drw_task_graph_init();
/* Cache filling */
{
PROFILE_START(stime);
drw_engines_cache_init();
/* Only iterate over objects when overlay uses object data. */
if (do_populate_loop) {
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
drw_engines_cache_populate(ob);
}
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
}
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
#ifdef USE_PROFILE
double *cache_time = GPU_viewport_cache_time_get(DST.viewport);
PROFILE_END_UPDATE(*cache_time, stime);
#endif
}
drw_task_graph_deinit();
DRW_stats_begin();
GPU_framebuffer_bind(DST.default_framebuffer);
/* Start Drawing */
DRW_state_reset();
if (DST.draw_ctx.evil_C) {
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_PRE_VIEW);
}
drw_engines_draw_scene();
/* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
GPU_flush();
if (DST.draw_ctx.evil_C) {
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DRW_state_reset();
GPU_framebuffer_bind(dfbl->overlay_fb);
if (do_annotations) {
GPU_depth_test(false);
GPU_matrix_push_projection();
wmOrtho2(
region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax);
ED_annotation_draw_view2d(DST.draw_ctx.evil_C, true);
GPU_matrix_pop_projection();
GPU_depth_test(true);
}
GPU_depth_test(false);
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW);
GPU_depth_test(true);
/* Callback can be nasty and do whatever they want with the state.
* Don't trust them! */
DRW_state_reset();
GPU_depth_test(false);
drw_engines_draw_text();
GPU_depth_test(true);
if (do_annotations) {
GPU_depth_test(false);
ED_annotation_draw_view2d(DST.draw_ctx.evil_C, false);
GPU_depth_test(true);
}
}
DRW_draw_cursor_2d();
ED_region_pixelspace(DST.draw_ctx.region);
{
GPU_depth_test(false);
DRW_draw_gizmo_2d();
GPU_depth_test(true);
}
DRW_stats_reset();
if (G.debug_value > 20 && G.debug_value < 30) {
GPU_depth_test(false);
/* local coordinate visible rect inside region, to accommodate overlapping ui */
const rcti *rect = ED_region_visible_rect(DST.draw_ctx.region);
DRW_stats_draw(rect);
GPU_depth_test(true);
}
if (WM_draw_region_get_bound_viewport(region)) {
/* Don't unbind the framebuffer yet in this case and let
* GPU_viewport_unbind do it, so that we can still do further
* drawing of action zones on top. */
}
else {
GPU_framebuffer_restore();
}
DRW_state_reset();
drw_engines_disable();
drw_viewport_cache_resize();
#ifdef DEBUG
/* Avoid accidental reuse. */
drw_state_ensure_not_reused(&DST);
#endif
}
static struct DRWSelectBuffer {
struct GPUFrameBuffer *framebuffer_depth_only;
struct GPUTexture *texture_depth;
@ -2637,6 +2887,8 @@ void DRW_engines_register(void)
DRW_engine_register(&draw_engine_select_type);
DRW_engine_register(&draw_engine_basic_type);
DRW_engine_register(&draw_engine_image_type);
/* setup callbacks */
{
BKE_mball_batch_cache_dirty_tag_cb = DRW_mball_batch_cache_dirty_tag;

View File

@ -24,6 +24,7 @@
#include "BLI_math.h"
#include "BLI_memiter.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BKE_editmesh.h"
@ -122,77 +123,106 @@ void DRW_text_cache_add(DRWTextStore *dt,
}
}
void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d)
static void drw_text_cache_draw_ex(DRWTextStore *dt, ARegion *region)
{
RegionView3D *rv3d = region->regiondata;
ViewCachedString *vos;
int tot = 0;
/* project first and test */
BLI_memiter_handle it;
int col_pack_prev = 0;
float original_proj[4][4];
GPU_matrix_projection_get(original_proj);
wmOrtho2_region_pixelspace(region);
GPU_matrix_push();
GPU_matrix_identity_set();
const int font_id = BLF_default();
const uiStyle *style = UI_style_get();
BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi);
BLI_memiter_iter_init(dt->cache_strings, &it);
while ((vos = BLI_memiter_iter_step(&it))) {
if (ED_view3d_project_short_ex(
region,
(vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
(vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0,
vos->vec,
vos->sco,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
tot++;
}
else {
vos->sco[0] = IS_CLIPPED;
if (vos->sco[0] != IS_CLIPPED) {
if (col_pack_prev != vos->col.pack) {
BLF_color4ubv(font_id, vos->col.ub);
col_pack_prev = vos->col.pack;
}
BLF_position(
font_id, (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f);
((vos->flag & DRW_TEXT_CACHE_ASCII) ? BLF_draw_ascii : BLF_draw)(
font_id,
(vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str,
vos->str_len);
}
}
if (tot) {
int col_pack_prev = 0;
/* Disable clipping for text */
if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
GPU_clip_distances(0);
}
float original_proj[4][4];
GPU_matrix_projection_get(original_proj);
wmOrtho2_region_pixelspace(region);
GPU_matrix_push();
GPU_matrix_identity_set();
const int font_id = BLF_default();
const uiStyle *style = UI_style_get();
BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi);
GPU_matrix_pop();
GPU_matrix_projection_set(original_proj);
}
void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d)
{
ViewCachedString *vos;
if (v3d) {
RegionView3D *rv3d = region->regiondata;
int tot = 0;
/* project first and test */
BLI_memiter_handle it;
BLI_memiter_iter_init(dt->cache_strings, &it);
while ((vos = BLI_memiter_iter_step(&it))) {
if (vos->sco[0] != IS_CLIPPED) {
if (col_pack_prev != vos->col.pack) {
BLF_color4ubv(font_id, vos->col.ub);
col_pack_prev = vos->col.pack;
}
BLF_position(
font_id, (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f);
((vos->flag & DRW_TEXT_CACHE_ASCII) ? BLF_draw_ascii : BLF_draw)(
font_id,
(vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str,
vos->str_len);
if (ED_view3d_project_short_ex(
region,
(vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
(vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0,
vos->vec,
vos->sco,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) ==
V3D_PROJ_RET_OK) {
tot++;
}
else {
vos->sco[0] = IS_CLIPPED;
}
}
GPU_matrix_pop();
GPU_matrix_projection_set(original_proj);
if (tot) {
/* Disable clipping for text */
const bool rv3d_clipping_enabled = RV3D_CLIPPING_ENABLED(v3d, rv3d);
if (rv3d_clipping_enabled) {
GPU_clip_distances(0);
}
if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
GPU_clip_distances(6);
drw_text_cache_draw_ex(dt, region);
if (rv3d_clipping_enabled) {
GPU_clip_distances(6);
}
}
}
else {
/* project first */
BLI_memiter_handle it;
BLI_memiter_iter_init(dt->cache_strings, &it);
View2D *v2d = &region->v2d;
float viewmat[4][4];
rctf region_space = {0.0f, region->winx, 0.0f, region->winy};
BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &region_space, viewmat);
while ((vos = BLI_memiter_iter_step(&it))) {
float p[3];
copy_v3_v3(p, vos->vec);
mul_m4_v3(viewmat, p);
vos->sco[0] = p[0];
vos->sco[1] = p[1];
}
drw_text_cache_draw_ex(dt, region);
}
}
/* Copied from drawobject.c */

View File

@ -35,6 +35,7 @@
#include "GPU_shader.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "WM_types.h"
@ -196,6 +197,65 @@ void DRW_draw_cursor(void)
}
}
/* -------------------------------------------------------------------- */
/** \name 2D Cursor
* \{ */
static bool is_cursor_visible_2d(const DRWContextState *draw_ctx)
{
SpaceInfo *space_data = (SpaceInfo *)draw_ctx->space_data;
if (space_data == NULL) {
return false;
}
if (space_data->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
return sima->mode == SI_MODE_UV;
}
return false;
}
void DRW_draw_cursor_2d(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
ARegion *region = draw_ctx->region;
GPU_color_mask(true, true, true, true);
GPU_depth_mask(false);
GPU_depth_test(GPU_DEPTH_NONE);
if (is_cursor_visible_2d(draw_ctx)) {
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
int co[2];
UI_view2d_view_to_region(&region->v2d, sima->cursor[0], sima->cursor[1], &co[0], &co[1]);
/* Draw nice Anti Aliased cursor. */
GPU_line_width(1.0f);
GPU_blend(true);
GPU_line_smooth(true);
/* Draw lines */
float original_proj[4][4];
GPU_matrix_projection_get(original_proj);
GPU_matrix_push();
ED_region_pixelspace(region);
GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
GPUBatch *cursor_batch = DRW_cache_cursor_get(true);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR);
GPU_batch_set_shader(cursor_batch, shader);
GPU_batch_draw(cursor_batch);
GPU_blend(false);
GPU_line_smooth(false);
GPU_matrix_pop();
GPU_matrix_projection_set(original_proj);
}
}
/* \} */
/* **************************** 3D Gizmo ******************************** */
void DRW_draw_gizmo_3d(void)

View File

@ -25,5 +25,6 @@
void DRW_draw_region_info(void);
void DRW_clear_background(void);
void DRW_draw_cursor(void);
void DRW_draw_cursor_2d(void);
void DRW_draw_gizmo_3d(void);
void DRW_draw_gizmo_2d(void);

View File

@ -103,6 +103,8 @@ layout(std140) uniform globalsBlock
vec4 colorFaceBack;
vec4 colorFaceFront;
vec4 colorUVShadow;
vec4 screenVecs[2];
vec4 sizeViewport; /* Inverted size in zw. */

View File

@ -11,6 +11,7 @@
#include "engines/eevee/eevee_private.h"
#include "engines/gpencil/gpencil_engine.h"
#include "engines/image/image_private.h"
#include "engines/overlay/overlay_private.h"
#include "engines/workbench/workbench_private.h"
@ -151,8 +152,19 @@ TEST_F(DrawTest, gpencil_glsl_shaders)
GPENCIL_shader_free();
}
TEST_F(DrawTest, image_glsl_shaders)
{
IMAGE_shader_library_ensure();
EXPECT_NE(IMAGE_shader_image_get(), nullptr);
IMAGE_shader_free();
}
TEST_F(DrawTest, overlay_glsl_shaders)
{
OVERLAY_shader_library_ensure();
for (int i = 0; i < 2; i++) {
eGPUShaderConfig sh_cfg = i == 0 ? GPU_SHADER_CFG_DEFAULT : GPU_SHADER_CFG_CLIPPED;
DRW_draw_state_init_gtests(sh_cfg);
@ -189,6 +201,13 @@ TEST_F(DrawTest, overlay_glsl_shaders)
EXPECT_NE(OVERLAY_shader_edit_mesh_vert(), nullptr);
EXPECT_NE(OVERLAY_shader_edit_particle_strand(), nullptr);
EXPECT_NE(OVERLAY_shader_edit_particle_point(), nullptr);
EXPECT_NE(OVERLAY_shader_edit_uv_edges_get(), nullptr);
EXPECT_NE(OVERLAY_shader_edit_uv_face_get(), nullptr);
EXPECT_NE(OVERLAY_shader_edit_uv_face_dots_get(), nullptr);
EXPECT_NE(OVERLAY_shader_edit_uv_verts_get(), nullptr);
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_extra(false), nullptr);
EXPECT_NE(OVERLAY_shader_extra(true), nullptr);
EXPECT_NE(OVERLAY_shader_extra_groundline(), nullptr);
@ -201,6 +220,7 @@ TEST_F(DrawTest, overlay_glsl_shaders)
EXPECT_NE(OVERLAY_shader_facing(), nullptr);
EXPECT_NE(OVERLAY_shader_gpencil_canvas(), nullptr);
EXPECT_NE(OVERLAY_shader_grid(), nullptr);
EXPECT_NE(OVERLAY_shader_grid_image(), nullptr);
EXPECT_NE(OVERLAY_shader_image(), nullptr);
EXPECT_NE(OVERLAY_shader_motion_path_line(), nullptr);
EXPECT_NE(OVERLAY_shader_motion_path_vert(), nullptr);

View File

@ -604,6 +604,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL) {
image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname);
}
ima->gpuflag |= IMA_GPU_REFRESH;
/* make jobs timer to send notifier */
*(rj->do_update) = true;

View File

@ -865,7 +865,7 @@ void draw_image_main(const bContext *C, ARegion *region)
Image *ima;
ImBuf *ibuf;
float zoomx, zoomy;
bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer;
bool show_viewer, show_stereo3d, show_multilayer;
void *lock;
/* XXX can we do this in refresh? */
@ -898,9 +898,6 @@ void draw_image_main(const bContext *C, ARegion *region)
}
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));
show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO));
show_multilayer = ima && BKE_image_is_multilayer(ima);
@ -998,16 +995,32 @@ void draw_image_main(const bContext *C, ARegion *region)
}
draw_udim_tile_grids(region, sima, ima);
/* paint helpers */
if (show_paint) {
draw_image_paint_helpers(C, region, scene, zoomx, zoomy);
}
draw_image_main_helpers(C, region);
if (show_viewer) {
BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
}
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;
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 */
if (ima && show_render) {
draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy);

View File

@ -37,6 +37,7 @@ extern const char *image_context_dir[]; /* doc access */
/* image_draw.c */
void draw_image_main(const struct bContext *C, struct ARegion *region);
void draw_image_main_helpers(const struct bContext *C, struct ARegion *region);
void draw_image_cache(const struct bContext *C, struct ARegion *region);
void draw_image_grease_pencil(struct bContext *C, bool onlyv2d);
void draw_image_sample_line(struct SpaceImage *sima);

View File

@ -76,6 +76,7 @@
#include "GPU_framebuffer.h"
#include "GPU_viewport.h"
#include "DRW_engine.h"
#include "DRW_engine_types.h"
#include "image_intern.h"
@ -638,8 +639,6 @@ static void image_main_region_draw(const bContext *C, ARegion *region)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
View2D *v2d = &region->v2d;
// View2DScrollers *scrollers;
float col[3];
GPUViewport *viewport = WM_draw_region_get_viewport(region);
GPUFrameBuffer *framebuffer_default, *framebuffer_overlay;
@ -647,35 +646,14 @@ static void image_main_region_draw(const bContext *C, ARegion *region)
framebuffer_default = GPU_viewport_framebuffer_default_get(viewport);
framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport);
GPU_framebuffer_bind(framebuffer_default);
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
GPU_framebuffer_bind(framebuffer_overlay);
/* XXX not supported yet, disabling for now */
scene->r.scemode &= ~R_COMP_CROP;
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
srgb_to_linearrgb_v3_v3(col, col);
GPU_clear_color(col[0], col[1], col[2], 1.0f);
GPU_depth_test(GPU_DEPTH_NONE);
image_user_refresh_scene(C, sima);
/* we set view2d from own zoom and offset each time */
image_main_region_set_view2d(sima, region);
/* we draw image in pixelspace */
draw_image_main(C, region);
/* and uvs in 0.0-1.0 space */
UI_view2d_view_ortho(v2d);
ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph);
/* check for mask (delay draw) */
if (ED_space_image_show_uvedit(sima, obedit)) {
show_uvedit = true;
@ -687,21 +665,52 @@ static void image_main_region_draw(const bContext *C, ARegion *region)
show_curve = true;
}
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
/* we draw image in pixelspace */
if (U.experimental.use_drw_image_editor) {
DRW_draw_view(C);
draw_image_main_helpers(C, region);
if (sima->flag & SI_SHOW_GPENCIL) {
/* Grease Pencil too (in addition to UV's) */
draw_image_grease_pencil((bContext *)C, true);
/* sample line */
UI_view2d_view_ortho(v2d);
draw_image_sample_line(sima);
UI_view2d_view_restore(C);
}
else {
GPU_framebuffer_bind(framebuffer_default);
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
/* sample line */
draw_image_sample_line(sima);
GPU_framebuffer_bind(framebuffer_overlay);
UI_view2d_view_restore(C);
float col[3];
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
srgb_to_linearrgb_v3_v3(col, col);
GPU_clear_color(col[0], col[1], col[2], 1.0f);
GPU_depth_test(GPU_DEPTH_NONE);
draw_image_main(C, region);
if (sima->flag & SI_SHOW_GPENCIL) {
/* draw Grease Pencil - screen space only */
draw_image_grease_pencil((bContext *)C, false);
/* and uvs in 0.0-1.0 space */
UI_view2d_view_ortho(v2d);
ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph);
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
if (sima->flag & SI_SHOW_GPENCIL) {
/* Grease Pencil too (in addition to UV's) */
draw_image_grease_pencil((bContext *)C, true);
}
/* sample line */
draw_image_sample_line(sima);
UI_view2d_view_restore(C);
if (sima->flag & SI_SHOW_GPENCIL) {
/* draw Grease Pencil - screen space only */
draw_image_grease_pencil((bContext *)C, false);
}
}
if (mask) {
@ -741,7 +750,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region)
C);
}
if (show_uvedit || mask || show_curve) {
if ((show_uvedit || mask || show_curve) && !U.experimental.use_drw_image_editor) {
UI_view2d_view_ortho(v2d);
ED_image_draw_cursor(region, sima->cursor);
UI_view2d_view_restore(C);

View File

@ -36,6 +36,8 @@
.gen_type = IMA_GENTYPE_GRID, \
\
.gpuframenr = INT_MAX, \
.gpu_pass = SHRT_MAX, \
.gpu_layer = SHRT_MAX, \
}
/** \} */

View File

@ -147,9 +147,11 @@ typedef struct Image {
int lastframe;
/* GPU texture flag. */
short gpuflag;
char _pad2[2];
int gpuframenr;
short gpuflag;
short gpu_pass;
short gpu_layer;
char _pad2[6];
/** Deprecated. */
struct PackedFile *packedfile DNA_DEPRECATED;

View File

@ -620,9 +620,10 @@ typedef struct UserDef_Experimental {
char use_new_hair_type;
char use_cycles_debug;
char use_sculpt_vertex_colors;
char use_drw_image_editor;
char use_tools_missing_icons;
/** `makesdna` does not allow empty structs. */
char _pad[2];
char _pad[1];
} UserDef_Experimental;
#define USER_EXPERIMENTAL_TEST(userdef, member) \

View File

@ -3061,6 +3061,11 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Metadata Text", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Grid", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
rna_def_userdef_theme_spaces_paint_curves(srna);
@ -6118,6 +6123,11 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_vertex_colors", 1);
RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "Use the new Vertex Painting system");
prop = RNA_def_property(srna, "use_drw_image_editor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_drw_image_editor", 1);
RNA_def_property_ui_text(
prop, "Image Editor Draw Engine", "Use draw manager for rendering the uv/image editor");
prop = RNA_def_property(srna, "use_tools_missing_icons", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_tools_missing_icons", 1);
RNA_def_property_ui_text(prop, "Tools with Missing Icons", "Show tools with missing icons");