Fix T80748: Render Emissive Colors in Compositor Backdrop

This change will use the image engine to draw the backdrop of the compositor. With this patch the alpha blending will be done in Linear Scene Reference space and shows pure emissive colors.

See differential for an example image.

**Technical changes**

As only the backdrop drawing is done using the draw manager there are some technical changes.
1. The overlay buffer is partly drawn outside the draw manager. When drawing the backdrop image the overlay buffer needs to be masked to simulate premultiplied alpha under.
2. The backdrop of the node editor is done in region pixel space. A `DRWView` is constructed with this space.
3. UDIM textures uses world position to generate the UV coordinates. This has been implemented more strict by the `IMAGE_DRAW_FLAG_USE_WORLD_POS`. When the flag isn't used the local coordinates are used to generate the UV coordinates what is image space.
4. The draw manager now checks the actual `eSpaceType` of the space data to use different code paths. In the future the movie clip editor will be added.

NOTE: The preview images in nodes are drawn in display space and cannot show pure emissive colors. As preview images are used on more locations it is best to fix this in a separate patch.

Reviewed By: Clément Foucault

Differential Revision: https://developer.blender.org/D9451
This commit is contained in:
Jeroen Bakker 2020-11-24 13:18:57 +01:00
parent 82cc21d5e4
commit 278011e44d
Notes: blender-bot 2023-02-14 09:24:53 +01:00
Referenced by commit 38bfa8902b, Fix T87771: Immediate Crash on "Edit Source" in Compositor
Referenced by commit aeff59073b, Fix T86219: Compositor backdrop not using Color Management View
Referenced by issue #87771, Immediate Crash on "Edit Source" in Compositor
Referenced by issue #83547, UV Editor regression: stitching preview is gone
Referenced by issue #80748, Compositor backdrop handles alpha differently from image editor
12 changed files with 313 additions and 186 deletions

View File

@ -25,9 +25,11 @@
#include "DRW_render.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
#include "IMB_imbuf_types.h"
@ -38,26 +40,55 @@
#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_DO_REPEAT (1 << 4)
#define IMAGE_DRAW_FLAG_SHOW_ALPHA (1 << 0)
#define IMAGE_DRAW_FLAG_APPLY_ALPHA (1 << 1)
#define IMAGE_DRAW_FLAG_SHUFFLING (1 << 2)
#define IMAGE_DRAW_FLAG_DEPTH (1 << 3)
#define IMAGE_DRAW_FLAG_DO_REPEAT (1 << 4)
#define IMAGE_DRAW_FLAG_USE_WORLD_POS (1 << 5)
static void image_cache_image_add(DRWShadingGroup *grp, Image *image)
static void image_cache_image_add(DRWShadingGroup *grp, Image *image, ImBuf *ibuf)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
const ARegion *region = draw_ctx->region;
const char space_type = draw_ctx->space_data->spacetype;
float zoom_x = 1.0f;
float zoom_y = 1.0f;
float translate_x = 0.0f;
float translate_y = 0.0f;
/* User can freely move the backdrop in the space of the node editor */
if (space_type == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)draw_ctx->space_data;
const float ibuf_width = ibuf->x;
const float ibuf_height = ibuf->y;
const float x = (region->winx - snode->zoom * ibuf_width) / 2 + snode->xof;
const float y = (region->winy - snode->zoom * ibuf_height) / 2 + snode->yof;
zoom_x = ibuf_width * snode->zoom;
zoom_y = ibuf_height * snode->zoom;
translate_x = x;
translate_y = y;
}
const bool is_tiled_texture = image && image->source == IMA_SRC_TILED;
float obmat[4][4];
unit_m4(obmat);
GPUBatch *geom = DRW_cache_quad_get();
obmat[0][0] = zoom_x;
obmat[1][1] = zoom_y;
obmat[3][1] = translate_y;
obmat[3][0] = translate_x;
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;
obmat[3][1] = (float)tile_y + translate_y;
obmat[3][0] = (float)tile_x + translate_x;
DRW_shgroup_call_obmat(grp, geom, obmat);
}
}
@ -66,6 +97,63 @@ static void image_cache_image_add(DRWShadingGroup *grp, Image *image)
}
}
static void space_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 (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 space_node_gpu_texture_get(Image *image,
ImageUser *iuser,
ImBuf *ibuf,
GPUTexture **r_gpu_texture,
bool *r_owns_texture,
GPUTexture **r_tex_tile_data)
{
*r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf);
*r_owns_texture = false;
*r_tex_tile_data = NULL;
}
static void image_gpu_texture_get(Image *image,
ImageUser *iuser,
ImBuf *ibuf,
@ -73,45 +161,19 @@ static void image_gpu_texture_get(Image *image,
bool *r_owns_texture,
GPUTexture **r_tex_tile_data)
{
if (!image) {
return;
}
const DRWContextState *draw_ctx = DRW_context_state_get();
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
const char space_type = draw_ctx->space_data->spacetype;
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;
}
}
if (space_type == SPACE_IMAGE) {
space_image_gpu_texture_get(
image, iuser, ibuf, r_gpu_texture, r_owns_texture, r_tex_tile_data);
}
else if (space_type == SPACE_NODE) {
space_node_gpu_texture_get(image, iuser, ibuf, r_gpu_texture, r_owns_texture, r_tex_tile_data);
}
}
@ -122,8 +184,8 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser
IMAGE_PrivateData *pd = stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
const char space_type = draw_ctx->space_data->spacetype;
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);
@ -140,36 +202,66 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser
const bool use_premul_alpha = BKE_image_has_gpu_texture_premultiplied_alpha(image, ibuf);
const bool is_tiled_texture = tex_tile_data != NULL;
const bool do_repeat = (!is_tiled_texture) && ((sima->flag & SI_DRAW_TILE) != 0);
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;
if (space_type == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
const bool do_repeat = (!is_tiled_texture) && ((sima->flag & SI_DRAW_TILE) != 0);
SET_FLAG_FROM_TEST(draw_flags, do_repeat, IMAGE_DRAW_FLAG_DO_REPEAT);
SET_FLAG_FROM_TEST(draw_flags, is_tiled_texture, IMAGE_DRAW_FLAG_USE_WORLD_POS);
if ((sima->flag & SI_USE_ALPHA) != 0) {
/* Show RGBA */
draw_flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
}
else if ((sima->flag & SI_SHOW_ALPHA) != 0) {
draw_flags |= IMAGE_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 |= IMAGE_DRAW_FLAG_DEPTH | IMAGE_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 |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_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 |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_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 |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
}
else /* RGB */ {
draw_flags |= IMAGE_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;
if (space_type == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)draw_ctx->space_data;
if ((snode->flag & SNODE_USE_ALPHA) != 0) {
/* Show RGBA */
draw_flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
}
else if ((snode->flag & SNODE_SHOW_ALPHA) != 0) {
draw_flags |= IMAGE_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f);
}
else if ((snode->flag & SNODE_SHOW_R) != 0) {
draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f);
}
else if ((snode->flag & SNODE_SHOW_G) != 0) {
draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f);
}
else if ((snode->flag & SNODE_SHOW_B) != 0) {
draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA | IMAGE_DRAW_FLAG_SHUFFLING;
copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f);
}
else /* RGB */ {
draw_flags |= IMAGE_DRAW_FLAG_APPLY_ALPHA;
}
}
GPUShader *shader = IMAGE_shader_image_get(is_tiled_texture);
@ -186,7 +278,7 @@ static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser
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);
image_cache_image_add(shgrp, image, ibuf);
}
}
@ -214,9 +306,7 @@ static void IMAGE_cache_init(void *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
@ -226,15 +316,31 @@ static void IMAGE_cache_init(void *ved)
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);
{
const SpaceLink *space_link = draw_ctx->space_data;
const char space_type = space_link->spacetype;
pd->view = NULL;
if (space_type == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
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->image = image;
pd->ibuf = ibuf;
}
else if (space_type == SPACE_NODE) {
ARegion *region = draw_ctx->region;
Main *bmain = CTX_data_main(draw_ctx->evil_C);
Image *image = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &pd->lock);
{
/* Setup a screen pixel view. The backdrop of the node editor doesn't follow the region. */
float winmat[4][4], viewmat[4][4];
orthographic_m4(viewmat, 0.0, region->winx, 0.0, region->winy, 0.0, 1.0);
unit_m4(winmat);
pd->view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
}
image_cache_image(vedata, image, NULL, ibuf);
pd->image = image;
pd->ibuf = ibuf;
}
}
@ -250,9 +356,16 @@ static void image_draw_finish(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);
const char space_type = draw_ctx->space_data->spacetype;
if (space_type == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
ED_space_image_release_buffer(sima, pd->ibuf, pd->lock);
}
else if (space_type == SPACE_NODE) {
BKE_image_release_ibuf(pd->image, pd->ibuf, pd->lock);
}
pd->image = NULL;
pd->ibuf = NULL;
if (pd->texture && pd->owns_texture) {
GPU_texture_free(pd->texture);
@ -265,9 +378,16 @@ static void IMAGE_draw_scene(void *ved)
{
IMAGE_Data *vedata = (IMAGE_Data *)ved;
IMAGE_PassList *psl = vedata->psl;
IMAGE_PrivateData *pd = vedata->stl->pd;
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);
DRW_view_set_active(pd->view);
DRW_draw_pass(psl->image_pass);
DRW_view_set_active(NULL);
image_draw_finish(vedata);
}

View File

@ -42,6 +42,8 @@ typedef struct IMAGE_PassList {
typedef struct IMAGE_PrivateData {
void *lock;
struct ImBuf *ibuf;
struct Image *image;
struct DRWView* view;
struct GPUTexture *texture;
bool owns_texture;

View File

@ -1,11 +1,11 @@
#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_DO_REPEAT (1 << 4)
#define IMAGE_DRAW_FLAG_SHOW_ALPHA (1 << 0)
#define IMAGE_DRAW_FLAG_APPLY_ALPHA (1 << 1)
#define IMAGE_DRAW_FLAG_SHUFFLING (1 << 2)
#define IMAGE_DRAW_FLAG_DEPTH (1 << 3)
#define IMAGE_DRAW_FLAG_DO_REPEAT (1 << 4)
#ifdef TILED_IMAGE
uniform sampler2DArray imageTileArray;
@ -68,25 +68,25 @@ void main()
tex_color = vec4(1.0, 0.0, 1.0, 1.0);
}
#else
vec2 uvs_clamped = ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) ?
vec2 uvs_clamped = ((drawFlags & IMAGE_DRAW_FLAG_DO_REPEAT) != 0) ?
fract(uvs) :
clamp(uvs, vec2(0.0), vec2(1.0));
tex_color = texture(imageTexture, uvs_clamped);
#endif
if ((drawFlags & SIMA_DRAW_FLAG_APPLY_ALPHA) != 0) {
if ((drawFlags & IMAGE_DRAW_FLAG_APPLY_ALPHA) != 0) {
if (!imgPremultiplied) {
tex_color.rgb *= tex_color.a;
}
}
if ((drawFlags & SIMA_DRAW_FLAG_DEPTH) != 0) {
if ((drawFlags & IMAGE_DRAW_FLAG_DEPTH) != 0) {
tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color);
}
if ((drawFlags & SIMA_DRAW_FLAG_SHUFFLING) != 0) {
if ((drawFlags & IMAGE_DRAW_FLAG_SHUFFLING) != 0) {
tex_color = color * dot(tex_color, shuffle);
}
if ((drawFlags & SIMA_DRAW_FLAG_SHOW_ALPHA) == 0) {
if ((drawFlags & IMAGE_DRAW_FLAG_SHOW_ALPHA) == 0) {
tex_color.a = 1.0;
}

View File

@ -1,7 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 4)
#define IMAGE_DRAW_FLAG_DO_REPEAT (1 << 4)
#define IMAGE_DRAW_FLAG_USE_WORLD_POS (1 << 5)
#define IMAGE_Z_DEPTH 0.75
uniform int drawFlags;
@ -15,7 +15,7 @@ void main()
* plane (0..1) */
vec3 image_pos = pos * 0.5 + 0.5;
if ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) {
if ((drawFlags & IMAGE_DRAW_FLAG_DO_REPEAT) != 0) {
gl_Position = vec4(pos.xy, IMAGE_Z_DEPTH, 1.0);
uvs = point_view_to_object(image_pos).xy;
}
@ -28,6 +28,7 @@ void main()
* actual pixels are at 0.75, 1.0 is used for the background. */
position.z = IMAGE_Z_DEPTH;
gl_Position = position;
uvs = world_pos.xy;
/* UDIM texture uses the world position for tile selection. */
uvs = ((drawFlags & IMAGE_DRAW_FLAG_USE_WORLD_POS) != 0) ? world_pos.xy : image_pos.xy;
}
}

View File

@ -32,6 +32,7 @@
#define BG_CHECKER 2
#define BG_RADIAL 3
#define BG_SOLID_CHECKER 4
#define BG_MASK 5
void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
{
@ -46,6 +47,7 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
bool draw_clipping_bounds = (pd->clipping_state != 0);
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;
float color_override[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int background_type;
@ -53,9 +55,13 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
background_type = BG_SOLID;
color_override[3] = 1.0f;
}
else if (pd->is_image_editor) {
else if (pd->space_type == SPACE_IMAGE) {
background_type = BG_SOLID_CHECKER;
}
else if (pd->space_type == SPACE_NODE) {
background_type = BG_MASK;
state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL;
}
else if (!DRW_state_draw_background()) {
background_type = BG_CHECKER;
}
@ -87,7 +93,6 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata)
}
}
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;
DRW_PASS_CREATE(psl->background_ps, state);
GPUShader *sh = OVERLAY_shader_background();

View File

@ -52,8 +52,6 @@ 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();
@ -63,15 +61,21 @@ static void OVERLAY_engine_init(void *vedata)
}
OVERLAY_PrivateData *pd = stl->pd;
pd->is_image_editor = sima != NULL;
pd->space_type = v3d != NULL ? SPACE_VIEW3D : draw_ctx->space_data->spacetype;
if (pd->is_image_editor) {
if (pd->space_type == SPACE_IMAGE) {
const SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
pd->hide_overlays = (sima->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS) == 0;
pd->clipping_state = 0;
OVERLAY_grid_init(data);
OVERLAY_edit_uv_init(data);
return;
}
if (pd->space_type == SPACE_NODE) {
pd->hide_overlays = true;
pd->clipping_state = 0;
return;
}
pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0;
pd->ctx_mode = CTX_data_mode_enum_ex(
@ -140,12 +144,16 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_StorageList *stl = data->stl;
OVERLAY_PrivateData *pd = stl->pd;
if (pd->is_image_editor) {
if (pd->space_type == SPACE_IMAGE) {
OVERLAY_background_cache_init(vedata);
OVERLAY_grid_cache_init(vedata);
OVERLAY_edit_uv_cache_init(vedata);
return;
}
if (pd->space_type == SPACE_NODE) {
OVERLAY_background_cache_init(vedata);
return;
}
switch (pd->ctx_mode) {
case CTX_MODE_EDIT_MESH:
@ -289,7 +297,7 @@ 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 (pd->space_type == SPACE_IMAGE) {
if (ob->type == OB_MESH) {
OVERLAY_edit_uv_cache_populate(vedata, ob);
}
@ -481,7 +489,7 @@ static void OVERLAY_cache_finish(void *vedata)
{
OVERLAY_Data *data = vedata;
OVERLAY_PrivateData *pd = data->stl->pd;
if (pd->is_image_editor) {
if (ELEM(pd->space_type, SPACE_IMAGE, SPACE_NODE)) {
return;
}
@ -511,17 +519,21 @@ static void OVERLAY_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
/* Needs to be done first as it modifies the scene color and depth buffer. */
if (!pd->is_image_editor) {
if (pd->space_type == SPACE_VIEW3D) {
OVERLAY_image_scene_background_draw(vedata);
}
if (DRW_state_is_fbo()) {
const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_framebuffer_bind(dfbl->overlay_only_fb);
GPU_framebuffer_clear_color(dfbl->overlay_only_fb, clear_col);
/* Don't clear background for the node editor. The node editor draws the background and we
* need to mask out the image from the already drawn overlay color buffer. */
if (pd->space_type != SPACE_NODE) {
const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_framebuffer_clear_color(dfbl->overlay_only_fb, clear_col);
}
}
if (pd->is_image_editor) {
if (pd->space_type == SPACE_IMAGE) {
OVERLAY_background_draw(data);
OVERLAY_grid_draw(data);
if (DRW_state_is_fbo()) {
@ -530,6 +542,10 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_edit_uv_draw(data);
return;
}
if (pd->space_type == SPACE_NODE) {
OVERLAY_background_draw(data);
return;
}
OVERLAY_image_background_draw(vedata);
OVERLAY_background_draw(vedata);

View File

@ -59,7 +59,7 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
shd->zpos_flag = 0;
shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
if (pd->is_image_editor) {
if (pd->space_type == SPACE_IMAGE) {
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;
@ -205,7 +205,7 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *vedata)
GPUShader *sh;
struct GPUBatch *geom = DRW_cache_grid_get();
if (pd->is_image_editor) {
if (pd->space_type == SPACE_IMAGE) {
float mat[4][4];
/* add quad background */
@ -255,7 +255,7 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *vedata)
DRW_shgroup_call(grp, geom, NULL);
}
if (pd->is_image_editor) {
if (pd->space_type == SPACE_IMAGE) {
float theme_color[4];
UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color);
srgb_to_linearrgb_v4(theme_color, theme_color);

View File

@ -322,7 +322,7 @@ typedef struct OVERLAY_PrivateData {
View3DOverlay overlay;
enum eContextObjectMode ctx_mode;
bool is_image_editor;
char space_type;
bool clear_in_front;
bool use_in_front;
bool wireframe_mode;

View File

@ -14,6 +14,7 @@ out vec4 fragColor;
#define BG_CHECKER 2
#define BG_RADIAL 3
#define BG_SOLID_CHECKER 4
#define BG_MASK 5
#define SQRT2 1.4142135623730950488
/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
@ -81,6 +82,9 @@ void main()
bool check = mod(p.x, 2) == mod(p.y, 2);
bg_col = (check) ? colorCheckerPrimary.rgb : colorCheckerSecondary.rgb;
break;
case BG_MASK:
fragColor = vec4(vec3(1.0 - alpha), 0.0);
return;
}
bg_col = mix(bg_col, colorOverride.rgb, colorOverride.a);

View File

@ -141,6 +141,10 @@ static bool drw_draw_show_annotation(void)
SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data;
return (sima->flag & SI_SHOW_GPENCIL) != 0;
}
case SPACE_NODE:
/* Don't draw the annotation for the node editor. Annotations are handled by space_image as
* the draw manager is only used to draw the background. */
return false;
default:
BLI_assert("");
return false;
@ -351,6 +355,14 @@ static void drw_viewport_colormanagement_set(void)
use_render_settings = true;
}
}
else if (DST.draw_ctx.space_data && DST.draw_ctx.space_data->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)DST.draw_ctx.space_data;
const eSpaceImage_Flag display_channels_mode = snode->flag;
const bool display_color_channel = (display_channels_mode & (SI_SHOW_ALPHA)) == 0;
if (display_color_channel) {
use_render_settings = true;
}
}
else {
use_render_settings = true;
use_view_transform = false;
@ -1243,6 +1255,14 @@ static void drw_engines_enable_editors(void)
use_drw_engine(&draw_engine_image_type);
use_drw_engine(&draw_engine_overlay_type);
}
else if (space_data->spacetype == SPACE_NODE) {
/* Only enable when drawing the space image backdrop. */
SpaceNode *snode = (SpaceNode *)space_data;
if ((snode->flag & SNODE_BACKDRAW) != 0) {
use_drw_engine(&draw_engine_image_type);
use_drw_engine(&draw_engine_overlay_type);
}
}
}
static void drw_engines_enable(ViewLayer *UNUSED(view_layer),
@ -1998,7 +2018,8 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
#endif
}
/* Used when the render engine want to redo another cache populate inside the same render frame. */
/* Used when the render engine want to redo another cache populate inside the same render frame.
*/
void DRW_cache_restart(void)
{
/* Save viewport size. */
@ -2050,8 +2071,10 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
/* 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_populate_loop = (DST.draw_ctx.space_data->spacetype == SPACE_IMAGE);
const bool do_annotations = drw_draw_show_annotation();
const bool do_region_callbacks = (DST.draw_ctx.space_data->spacetype != SPACE_IMAGE);
const bool do_draw_gizmos = (DST.draw_ctx.space_data->spacetype != SPACE_IMAGE);
/* Get list of enabled engines */
drw_engines_enable_editors();
@ -2102,7 +2125,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
/* Start Drawing */
DRW_state_reset();
if (DST.draw_ctx.evil_C) {
if (do_region_callbacks && DST.draw_ctx.evil_C) {
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_PRE_VIEW);
}
@ -2124,8 +2147,10 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
if (do_annotations) {
ED_annotation_draw_view2d(DST.draw_ctx.evil_C, true);
}
GPU_depth_test(GPU_DEPTH_NONE);
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW);
if (do_region_callbacks) {
GPU_depth_test(GPU_DEPTH_NONE);
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW);
}
GPU_matrix_pop_projection();
/* Callback can be nasty and do whatever they want with the state.
* Don't trust them! */
@ -2143,7 +2168,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
DRW_draw_cursor_2d();
ED_region_pixelspace(DST.draw_ctx.region);
{
if (do_draw_gizmos) {
GPU_depth_test(GPU_DEPTH_NONE);
DRW_draw_gizmo_2d();
}

View File

@ -22,6 +22,7 @@ set(INC
../../blenlib
../../blentranslation
../../depsgraph
../../draw
../../gpu
../../imbuf
../../makesdna

View File

@ -47,11 +47,14 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_platform.h"
#include "GPU_state.h"
#include "DRW_engine.h"
#include "RNA_access.h"
#include "RNA_define.h"
@ -3534,8 +3537,6 @@ void draw_nodespace_back_pix(const bContext *C,
Main *bmain = CTX_data_main(C);
bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key :
NODE_INSTANCE_KEY_NONE);
float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_matrix_push_projection();
GPU_matrix_push();
wmOrtho2_region_pixelspace(region);
@ -3552,74 +3553,27 @@ void draw_nodespace_back_pix(const bContext *C,
return;
}
GPU_matrix_push_projection();
GPU_matrix_push();
/* The draw manager is used to draw the backdrop image. */
GPUFrameBuffer *old_fb = GPU_framebuffer_active_get();
GPU_framebuffer_restore();
DRW_draw_view(C);
GPU_framebuffer_bind_no_srgb(old_fb);
/* Draw manager changes the depth state. Set it back to NONE. Without this the node preview
* images aren't drawn correctly. */
GPU_depth_test(GPU_DEPTH_NONE);
void *lock;
Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
GPU_matrix_push_projection();
GPU_matrix_push();
/* somehow the offset has to be calculated inverse */
wmOrtho2_region_pixelspace(region);
const float x = (region->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
const float y = (region->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
if (ibuf->rect || ibuf->rect_float) {
uchar *display_buffer = NULL;
void *cache_handle = NULL;
if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
if (snode->flag & SNODE_SHOW_R) {
shuffle[0] = 1.0f;
}
else if (snode->flag & SNODE_SHOW_G) {
shuffle[1] = 1.0f;
}
else if (snode->flag & SNODE_SHOW_B) {
shuffle[2] = 1.0f;
}
else {
shuffle[3] = 1.0f;
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
immDrawPixelsTex(&state,
x,
y,
ibuf->x,
ibuf->y,
GPU_RGBA8,
false,
display_buffer,
snode->zoom,
snode->zoom,
NULL);
GPU_shader_unbind();
}
else if (snode->flag & SNODE_USE_ALPHA) {
GPU_blend(GPU_BLEND_ALPHA);
ED_draw_imbuf_ctx(C, ibuf, x, y, false, snode->zoom, snode->zoom);
GPU_blend(GPU_BLEND_NONE);
}
else {
ED_draw_imbuf_ctx(C, ibuf, x, y, false, snode->zoom, snode->zoom);
}
if (cache_handle) {
IMB_display_buffer_release(cache_handle);
}
}
/** \note draw selected info on backdrop */
if (snode->edittree) {
bNode *node = snode->edittree->nodes.first;
@ -3652,12 +3606,11 @@ void draw_nodespace_back_pix(const bContext *C,
immUnbindProgram();
}
}
GPU_matrix_pop_projection();
GPU_matrix_pop();
}
BKE_image_release_ibuf(ima, ibuf, lock);
GPU_matrix_pop_projection();
GPU_matrix_pop();
}
/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */