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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_image_partial_update.hh2
-rw-r--r--source/blender/blenkernel/intern/image_gpu.cc8
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h1
-rw-r--r--source/blender/blenlib/intern/math_matrix.c11
-rw-r--r--source/blender/draw/CMakeLists.txt8
-rw-r--r--source/blender/draw/engines/image/image_batches.hh106
-rw-r--r--source/blender/draw/engines/image/image_drawing_mode.hh417
-rw-r--r--source/blender/draw/engines/image/image_drawing_mode_image_space.hh147
-rw-r--r--source/blender/draw/engines/image/image_engine.cc72
-rw-r--r--source/blender/draw/engines/image/image_instance_data.hh134
-rw-r--r--source/blender/draw/engines/image/image_partial_updater.hh78
-rw-r--r--source/blender/draw/engines/image/image_private.hh135
-rw-r--r--source/blender/draw/engines/image/image_shader_params.hh59
-rw-r--r--source/blender/draw/engines/image/image_space.hh99
-rw-r--r--source/blender/draw/engines/image/image_space_image.hh32
-rw-r--r--source/blender/draw/engines/image/image_space_node.hh51
-rw-r--r--source/blender/draw/engines/image/image_texture_info.hh76
-rw-r--r--source/blender/draw/engines/image/image_wrappers.hh49
-rw-r--r--source/blender/draw/engines/image/shaders/engine_image_frag.glsl91
-rw-r--r--source/blender/draw/engines/image/shaders/engine_image_vert.glsl34
20 files changed, 1174 insertions, 436 deletions
diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index 6af44b2c3c9..ca7c4f40593 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -295,4 +295,4 @@ template<typename TileData = NoTileData> struct PartialUpdateChecker {
};
} // namespace partial_update
-} // namespace blender::bke::image \ No newline at end of file
+} // namespace blender::bke::image
diff --git a/source/blender/blenkernel/intern/image_gpu.cc b/source/blender/blenkernel/intern/image_gpu.cc
index 91937e709da..eaee1fd2c30 100644
--- a/source/blender/blenkernel/intern/image_gpu.cc
+++ b/source/blender/blenkernel/intern/image_gpu.cc
@@ -58,14 +58,6 @@ static void image_free_gpu_limited_scale(Image *ima);
static void image_update_gputexture_ex(
Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h);
-/* Internal structs. */
-#define IMA_PARTIAL_REFRESH_TILE_SIZE 256
-struct ImagePartialRefresh {
- struct ImagePartialRefresh *next, *prev;
- int tile_x;
- int tile_y;
-};
-
bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
{
if (image) {
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 65d654bc930..03b6ff25a4f 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -404,6 +404,7 @@ void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4]);
void scale_m3_fl(float R[3][3], float scale);
void scale_m4_fl(float R[4][4], float scale);
+void scale_m4_v2(float R[4][4], const float scale[2]);
/**
* This computes the overall volume scale factor of a transformation matrix.
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index eaf76696a0a..f307672361b 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -2296,6 +2296,17 @@ void scale_m4_fl(float R[4][4], float scale)
R[3][0] = R[3][1] = R[3][2] = 0.0;
}
+void scale_m4_v2(float R[4][4], const float scale[2])
+{
+ R[0][0] = scale[0];
+ R[1][1] = scale[1];
+ R[2][2] = R[3][3] = 1.0;
+ R[0][1] = R[0][2] = R[0][3] = 0.0;
+ R[1][0] = R[1][2] = R[1][3] = 0.0;
+ R[2][0] = R[2][1] = R[2][3] = 0.0;
+ R[3][0] = R[3][1] = R[3][2] = 0.0;
+}
+
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
{
mat[3][0] += (Tx * mat[0][0] + Ty * mat[1][0] + Tz * mat[2][0]);
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 0c5b158ac80..b40fc88a076 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -227,11 +227,17 @@ set(SRC
engines/eevee/eevee_lut.h
engines/eevee/eevee_private.h
engines/external/external_engine.h
- engines/image/image_drawing_mode_image_space.hh
+ engines/image/image_batches.hh
+ engines/image/image_drawing_mode.hh
engines/image/image_engine.h
+ engines/image/image_instance_data.hh
+ engines/image/image_partial_updater.hh
engines/image/image_private.hh
+ engines/image/image_shader_params.hh
engines/image/image_space_image.hh
engines/image/image_space_node.hh
+ engines/image/image_space.hh
+ engines/image/image_wrappers.hh
engines/workbench/workbench_engine.h
engines/workbench/workbench_private.h
engines/workbench/workbench_shader_shared.h
diff --git a/source/blender/draw/engines/image/image_batches.hh b/source/blender/draw/engines/image/image_batches.hh
new file mode 100644
index 00000000000..489785d5d12
--- /dev/null
+++ b/source/blender/draw/engines/image/image_batches.hh
@@ -0,0 +1,106 @@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_texture_info.hh"
+
+/** \brief Create GPUBatch for a IMAGE_ScreenSpaceTextureInfo. */
+class BatchUpdater {
+ TextureInfo &info;
+
+ GPUVertFormat format = {0};
+ int pos_id;
+ int uv_id;
+
+ public:
+ BatchUpdater(TextureInfo &info) : info(info)
+ {
+ }
+
+ void update_batch()
+ {
+ ensure_clear_batch();
+ ensure_format();
+ init_batch();
+ }
+
+ void discard_batch()
+ {
+ GPU_BATCH_DISCARD_SAFE(info.batch);
+ }
+
+ private:
+ void ensure_clear_batch()
+ {
+ GPU_BATCH_CLEAR_SAFE(info.batch);
+ if (info.batch == nullptr) {
+ info.batch = GPU_batch_calloc();
+ }
+ }
+
+ void init_batch()
+ {
+ GPUVertBuf *vbo = create_vbo();
+ GPU_batch_init_ex(info.batch, GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
+ }
+
+ GPUVertBuf *create_vbo()
+ {
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 4);
+ float pos[4][2];
+ fill_tri_fan_from_rctf(pos, info.clipping_bounds);
+ float uv[4][2];
+ fill_tri_fan_from_rctf(uv, info.uv_bounds);
+
+ for (int i = 0; i < 4; i++) {
+ GPU_vertbuf_attr_set(vbo, pos_id, i, pos[i]);
+ GPU_vertbuf_attr_set(vbo, uv_id, i, uv[i]);
+ }
+
+ return vbo;
+ }
+
+ static void fill_tri_fan_from_rctf(float result[4][2], rctf &rect)
+ {
+ result[0][0] = rect.xmin;
+ result[0][1] = rect.ymin;
+ result[1][0] = rect.xmax;
+ result[1][1] = rect.ymin;
+ result[2][0] = rect.xmax;
+ result[2][1] = rect.ymax;
+ result[3][0] = rect.xmin;
+ result[3][1] = rect.ymax;
+ }
+
+ void ensure_format()
+ {
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ pos_id = GPU_vertformat_attr_id_get(&format, "pos");
+ uv_id = GPU_vertformat_attr_id_get(&format, "uv");
+ }
+ }
+};
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh
new file mode 100644
index 00000000000..8762a02458f
--- /dev/null
+++ b/source/blender/draw/engines/image/image_drawing_mode.hh
@@ -0,0 +1,417 @@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "BKE_image_partial_update.hh"
+
+#include "IMB_imbuf_types.h"
+
+#include "image_batches.hh"
+#include "image_private.hh"
+#include "image_wrappers.hh"
+
+namespace blender::draw::image_engine {
+
+constexpr float EPSILON_UV_BOUNDS = 0.00001f;
+
+/**
+ * \brief Screen space method using a single texture spawning the whole screen.
+ */
+struct OneTextureMethod {
+ IMAGE_InstanceData *instance_data;
+
+ OneTextureMethod(IMAGE_InstanceData *instance_data) : instance_data(instance_data)
+ {
+ }
+
+ /** \brief Update the texture slot uv and screen space bounds. */
+ void update_screen_space_bounds(const ARegion *region)
+ {
+ /* Create a single texture that covers the visible screen space. */
+ BLI_rctf_init(
+ &instance_data->texture_infos[0].clipping_bounds, 0, region->winx, 0, region->winy);
+ instance_data->texture_infos[0].visible = true;
+
+ /* Mark the other textures as invalid. */
+ for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ BLI_rctf_init_minmax(&instance_data->texture_infos[i].clipping_bounds);
+ instance_data->texture_infos[i].visible = false;
+ }
+ }
+
+ void update_uv_bounds(const ARegion *region)
+ {
+ TextureInfo &info = instance_data->texture_infos[0];
+ if (!BLI_rctf_compare(&info.uv_bounds, &region->v2d.cur, EPSILON_UV_BOUNDS)) {
+ info.uv_bounds = region->v2d.cur;
+ info.dirty = true;
+ }
+
+ /* Mark the other textures as invalid. */
+ for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ BLI_rctf_init_minmax(&instance_data->texture_infos[i].clipping_bounds);
+ }
+ }
+};
+
+using namespace blender::bke::image::partial_update;
+
+template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractDrawingMode {
+ private:
+ DRWPass *create_image_pass() const
+ {
+ /* 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 = static_cast<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
+ return DRW_pass_create("Image", state);
+ }
+
+ void add_shgroups(const IMAGE_InstanceData *instance_data) const
+ {
+ const ShaderParameters &sh_params = instance_data->sh_params;
+ GPUShader *shader = IMAGE_shader_image_get(false);
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create(shader, instance_data->passes.image_pass);
+ DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", sh_params.far_near);
+ DRW_shgroup_uniform_vec4_copy(shgrp, "color", ShaderParameters::color);
+ DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", sh_params.shuffle);
+ DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", sh_params.flags);
+ DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", sh_params.use_premul_alpha);
+ DRW_shgroup_uniform_vec2_copy(shgrp, "maxUv", instance_data->max_uv);
+ float image_mat[4][4];
+ unit_m4(image_mat);
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ const TextureInfo &info = instance_data->texture_infos[i];
+ if (!info.visible) {
+ continue;
+ }
+
+ DRWShadingGroup *shgrp_sub = DRW_shgroup_create_sub(shgrp);
+ DRW_shgroup_uniform_texture_ex(shgrp_sub, "imageTexture", info.texture, GPU_SAMPLER_DEFAULT);
+ DRW_shgroup_call_obmat(shgrp_sub, info.batch, image_mat);
+ }
+ }
+
+ /**
+ * \brief Update GPUTextures for drawing the image.
+ *
+ * GPUTextures that are marked dirty are rebuild. GPUTextures that aren't marked dirty are
+ * updated with changed region of the image.
+ */
+ void update_textures(IMAGE_InstanceData &instance_data,
+ Image *image,
+ ImageUser *image_user) const
+ {
+ PartialUpdateChecker<ImageTileData> checker(
+ image, image_user, instance_data.partial_update.user);
+ PartialUpdateChecker<ImageTileData>::CollectResult changes = checker.collect_changes();
+
+ switch (changes.get_result_code()) {
+ case ePartialUpdateCollectResult::FullUpdateNeeded:
+ instance_data.mark_all_texture_slots_dirty();
+ break;
+ case ePartialUpdateCollectResult::NoChangesDetected:
+ break;
+ case ePartialUpdateCollectResult::PartialChangesDetected:
+ /* Partial update when wrap repeat is enabled is not supported. */
+ if (instance_data.flags.do_tile_drawing) {
+ instance_data.mark_all_texture_slots_dirty();
+ }
+ else {
+ do_partial_update(changes, instance_data);
+ }
+ break;
+ }
+ do_full_update_for_dirty_textures(instance_data, image_user);
+ }
+
+ void do_partial_update(PartialUpdateChecker<ImageTileData>::CollectResult &iterator,
+ IMAGE_InstanceData &instance_data) const
+ {
+ while (iterator.get_next_change() == ePartialUpdateIterResult::ChangeAvailable) {
+ /* Quick exit when tile_buffer isn't availble. */
+ if (iterator.tile_data.tile_buffer == nullptr) {
+ continue;
+ }
+ ensure_float_buffer(*iterator.tile_data.tile_buffer);
+ const float tile_width = static_cast<float>(iterator.tile_data.tile_buffer->x);
+ const float tile_height = static_cast<float>(iterator.tile_data.tile_buffer->y);
+
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ const TextureInfo &info = instance_data.texture_infos[i];
+ /* Dirty images will receive a full update. No need to do a partial one now. */
+ if (info.dirty) {
+ continue;
+ }
+ if (!info.visible) {
+ continue;
+ }
+ GPUTexture *texture = info.texture;
+ const float texture_width = GPU_texture_width(texture);
+ const float texture_height = GPU_texture_height(texture);
+ // TODO
+ // early bound check.
+ ImageTileWrapper tile_accessor(iterator.tile_data.tile);
+ float tile_offset_x = static_cast<float>(tile_accessor.get_tile_x_offset());
+ float tile_offset_y = static_cast<float>(tile_accessor.get_tile_y_offset());
+ rcti *changed_region_in_texel_space = &iterator.changed_region.region;
+ rctf changed_region_in_uv_space;
+ BLI_rctf_init(&changed_region_in_uv_space,
+ static_cast<float>(changed_region_in_texel_space->xmin) /
+ static_cast<float>(iterator.tile_data.tile_buffer->x) +
+ tile_offset_x,
+ static_cast<float>(changed_region_in_texel_space->xmax) /
+ static_cast<float>(iterator.tile_data.tile_buffer->x) +
+ tile_offset_x,
+ static_cast<float>(changed_region_in_texel_space->ymin) /
+ static_cast<float>(iterator.tile_data.tile_buffer->y) +
+ tile_offset_y,
+ static_cast<float>(changed_region_in_texel_space->ymax) /
+ static_cast<float>(iterator.tile_data.tile_buffer->y) +
+ tile_offset_y);
+ rctf changed_overlapping_region_in_uv_space;
+ const bool region_overlap = BLI_rctf_isect(
+ &info.uv_bounds, &changed_region_in_uv_space, &changed_overlapping_region_in_uv_space);
+ if (!region_overlap) {
+ continue;
+ }
+ // convert the overlapping region to texel space and to ss_pixel space...
+ // TODO: first convert to ss_pixel space as integer based. and from there go back to texel
+ // space. But perhaps this isn't needed and we could use an extraction offset somehow.
+ rcti gpu_texture_region_to_update;
+ BLI_rcti_init(&gpu_texture_region_to_update,
+ floor((changed_overlapping_region_in_uv_space.xmin - info.uv_bounds.xmin) *
+ texture_width / BLI_rctf_size_x(&info.uv_bounds)),
+ floor((changed_overlapping_region_in_uv_space.xmax - info.uv_bounds.xmin) *
+ texture_width / BLI_rctf_size_x(&info.uv_bounds)),
+ ceil((changed_overlapping_region_in_uv_space.ymin - info.uv_bounds.ymin) *
+ texture_height / BLI_rctf_size_y(&info.uv_bounds)),
+ ceil((changed_overlapping_region_in_uv_space.ymax - info.uv_bounds.ymin) *
+ texture_height / BLI_rctf_size_y(&info.uv_bounds)));
+
+ rcti tile_region_to_extract;
+ BLI_rcti_init(
+ &tile_region_to_extract,
+ floor((changed_overlapping_region_in_uv_space.xmin - tile_offset_x) * tile_width),
+ floor((changed_overlapping_region_in_uv_space.xmax - tile_offset_x) * tile_width),
+ ceil((changed_overlapping_region_in_uv_space.ymin - tile_offset_y) * tile_height),
+ ceil((changed_overlapping_region_in_uv_space.ymax - tile_offset_y) * tile_height));
+
+ // Create an image buffer with a size
+ // extract and scale into an imbuf
+ const int texture_region_width = BLI_rcti_size_x(&gpu_texture_region_to_update);
+ const int texture_region_height = BLI_rcti_size_y(&gpu_texture_region_to_update);
+
+ ImBuf extracted_buffer;
+ IMB_initImBuf(
+ &extracted_buffer, texture_region_width, texture_region_height, 32, IB_rectfloat);
+
+ int offset = 0;
+ ImBuf *tile_buffer = iterator.tile_data.tile_buffer;
+ for (int y = gpu_texture_region_to_update.ymin; y < gpu_texture_region_to_update.ymax;
+ y++) {
+ float yf = y / (float)texture_height;
+ float v = info.uv_bounds.ymax * yf + info.uv_bounds.ymin * (1.0 - yf) - tile_offset_y;
+ for (int x = gpu_texture_region_to_update.xmin; x < gpu_texture_region_to_update.xmax;
+ x++) {
+ float xf = x / (float)texture_width;
+ float u = info.uv_bounds.xmax * xf + info.uv_bounds.xmin * (1.0 - xf) - tile_offset_x;
+ nearest_interpolation_color(tile_buffer,
+ nullptr,
+ &extracted_buffer.rect_float[offset * 4],
+ u * tile_buffer->x,
+ v * tile_buffer->y);
+ offset++;
+ }
+ }
+
+ GPU_texture_update_sub(texture,
+ GPU_DATA_FLOAT,
+ extracted_buffer.rect_float,
+ gpu_texture_region_to_update.xmin,
+ gpu_texture_region_to_update.ymin,
+ 0,
+ extracted_buffer.x,
+ extracted_buffer.y,
+ 0);
+ imb_freerectImbuf_all(&extracted_buffer);
+ }
+ }
+ }
+
+ void do_full_update_for_dirty_textures(IMAGE_InstanceData &instance_data,
+ const ImageUser *image_user) const
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ TextureInfo &info = instance_data.texture_infos[i];
+ if (!info.dirty) {
+ continue;
+ }
+ if (!info.visible) {
+ continue;
+ }
+ do_full_update_gpu_texture(info, instance_data, image_user);
+ }
+ }
+
+ void do_full_update_gpu_texture(TextureInfo &info,
+ IMAGE_InstanceData &instance_data,
+ const ImageUser *image_user) const
+ {
+
+ ImBuf texture_buffer;
+ const int texture_width = GPU_texture_width(info.texture);
+ const int texture_height = GPU_texture_height(info.texture);
+ IMB_initImBuf(&texture_buffer, texture_width, texture_height, 0, IB_rectfloat);
+ ImageUser tile_user = {0};
+ if (image_user) {
+ tile_user = *image_user;
+ }
+
+ void *lock;
+
+ Image *image = instance_data.image;
+ LISTBASE_FOREACH (ImageTile *, image_tile_ptr, &image->tiles) {
+ const ImageTileWrapper image_tile(image_tile_ptr);
+ tile_user.tile = image_tile.get_tile_number();
+
+ ImBuf *tile_buffer = BKE_image_acquire_ibuf(image, &tile_user, &lock);
+ if (tile_buffer == nullptr) {
+ /* Couldn't load the image buffer of the tile. */
+ continue;
+ }
+ do_full_update_texture_slot(instance_data, info, texture_buffer, *tile_buffer, image_tile);
+ BKE_image_release_ibuf(image, tile_buffer, lock);
+ }
+ GPU_texture_update(info.texture, GPU_DATA_FLOAT, texture_buffer.rect_float);
+ imb_freerectImbuf_all(&texture_buffer);
+ }
+
+ /**
+ * \brief Ensure that the float buffer of the given image buffer is available.
+ */
+ void ensure_float_buffer(ImBuf &image_buffer) const
+ {
+ if (image_buffer.rect_float == nullptr) {
+ IMB_float_from_rect(&image_buffer);
+ }
+ }
+
+ void do_full_update_texture_slot(const IMAGE_InstanceData &instance_data,
+ const TextureInfo &texture_info,
+ ImBuf &texture_buffer,
+ ImBuf &tile_buffer,
+ const ImageTileWrapper &image_tile) const
+ {
+ const int texture_width = texture_buffer.x;
+ const int texture_height = texture_buffer.y;
+ ensure_float_buffer(tile_buffer);
+
+ /* IMB_transform works in a non-consistent space. This should be documented or fixed!.
+ * Construct a variant of the info_uv_to_texture that adds the texel space
+ * transformation.*/
+ float uv_to_texel[4][4];
+ copy_m4_m4(uv_to_texel, instance_data.ss_to_texture);
+ float scale[3] = {static_cast<float>(texture_width) / static_cast<float>(tile_buffer.x),
+ static_cast<float>(texture_height) / static_cast<float>(tile_buffer.y),
+ 1.0f};
+ rescale_m4(uv_to_texel, scale);
+ uv_to_texel[3][0] += image_tile.get_tile_x_offset() / BLI_rctf_size_x(&texture_info.uv_bounds);
+ uv_to_texel[3][1] += image_tile.get_tile_y_offset() / BLI_rctf_size_y(&texture_info.uv_bounds);
+ uv_to_texel[3][0] *= texture_width;
+ uv_to_texel[3][1] *= texture_height;
+ invert_m4(uv_to_texel);
+
+ rctf crop_rect;
+ rctf *crop_rect_ptr = nullptr;
+ eIMBTransformMode transform_mode;
+ if (instance_data.flags.do_tile_drawing) {
+ transform_mode = IMB_TRANSFORM_MODE_WRAP_REPEAT;
+ }
+ else {
+ BLI_rctf_init(&crop_rect, 0.0, tile_buffer.x, 0.0, tile_buffer.y);
+ crop_rect_ptr = &crop_rect;
+ transform_mode = IMB_TRANSFORM_MODE_CROP_SRC;
+ }
+
+ IMB_transform(&tile_buffer,
+ &texture_buffer,
+ transform_mode,
+ IMB_FILTER_NEAREST,
+ uv_to_texel,
+ crop_rect_ptr);
+ }
+
+ public:
+ void cache_init(IMAGE_Data *vedata) const override
+ {
+ IMAGE_InstanceData *instance_data = vedata->instance_data;
+ instance_data->passes.image_pass = create_image_pass();
+ }
+
+ void cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser) const override
+ {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ IMAGE_InstanceData *instance_data = vedata->instance_data;
+ TextureMethod method(instance_data);
+
+ instance_data->partial_update.ensure_image(image);
+ instance_data->max_uv_update();
+ instance_data->clear_dirty_flag();
+
+ // Step: Find out which screen space textures are needed to draw on the screen. Remove the
+ // screen space textures that aren't needed.
+ const ARegion *region = draw_ctx->region;
+ method.update_screen_space_bounds(region);
+ method.update_uv_bounds(region);
+
+ // Step: Update the GPU textures based on the changes in the image.
+ instance_data->update_gpu_texture_allocations();
+ update_textures(*instance_data, image, iuser);
+
+ // Step: Add the GPU textures to the shgroup.
+ instance_data->update_batches();
+ add_shgroups(instance_data);
+ }
+
+ void draw_finish(IMAGE_Data *UNUSED(vedata)) const override
+ {
+ }
+
+ void draw_scene(IMAGE_Data *vedata) const override
+ {
+ IMAGE_InstanceData *instance_data = vedata->instance_data;
+
+ 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(instance_data->view);
+ DRW_draw_pass(instance_data->passes.image_pass);
+ DRW_view_set_active(nullptr);
+ }
+}; // namespace clipping
+
+} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_drawing_mode_image_space.hh b/source/blender/draw/engines/image/image_drawing_mode_image_space.hh
deleted file mode 100644
index 26f4bc28106..00000000000
--- a/source/blender/draw/engines/image/image_drawing_mode_image_space.hh
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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 2021, Blender Foundation.
- */
-
-/** \file
- * \ingroup draw_engine
- */
-
-#pragma once
-
-#include "image_private.hh"
-
-namespace blender::draw::image_engine {
-
-class ImageSpaceDrawingMode : public AbstractDrawingMode {
- private:
- DRWPass *create_image_pass() const
- {
- /* 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 = static_cast<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
- return DRW_pass_create("Image", state);
- }
-
- void add_to_shgroup(AbstractSpaceAccessor *space,
- DRWShadingGroup *grp,
- const Image *image,
- const ImBuf *image_buffer) const
- {
- float image_mat[4][4];
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const ARegion *region = draw_ctx->region;
- space->get_image_mat(image_buffer, region, image_mat);
-
- GPUBatch *geom = DRW_cache_quad_get();
-
- const float translate_x = image_mat[3][0];
- const float translate_y = image_mat[3][1];
- LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
- const int tile_x = ((tile->tile_number - 1001) % 10);
- const int tile_y = ((tile->tile_number - 1001) / 10);
- image_mat[3][0] = (float)tile_x + translate_x;
- image_mat[3][1] = (float)tile_y + translate_y;
- DRW_shgroup_call_obmat(grp, geom, image_mat);
- }
- }
-
- public:
- void cache_init(IMAGE_Data *vedata) const override
- {
- IMAGE_PassList *psl = vedata->psl;
-
- psl->image_pass = create_image_pass();
- }
-
- void cache_image(AbstractSpaceAccessor *space,
- IMAGE_Data *vedata,
- Image *image,
- ImageUser *iuser,
- ImBuf *image_buffer) const override
- {
- IMAGE_PassList *psl = vedata->psl;
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
-
- GPUTexture *tex_tile_data = nullptr;
- space->get_gpu_textures(
- image, iuser, image_buffer, &pd->texture, &pd->owns_texture, &tex_tile_data);
- if (pd->texture == nullptr) {
- return;
- }
- const bool is_tiled_texture = tex_tile_data != nullptr;
-
- ShaderParameters sh_params;
- sh_params.use_premul_alpha = BKE_image_has_gpu_texture_premultiplied_alpha(image,
- image_buffer);
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene = draw_ctx->scene;
- if (scene->camera && scene->camera->type == OB_CAMERA) {
- Camera *camera = static_cast<Camera *>(scene->camera->data);
- copy_v2_fl2(sh_params.far_near, camera->clip_end, camera->clip_start);
- }
- space->get_shader_parameters(sh_params, image_buffer, is_tiled_texture);
-
- GPUShader *shader = IMAGE_shader_image_get(is_tiled_texture);
- DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass);
- if (is_tiled_texture) {
- DRW_shgroup_uniform_texture_ex(shgrp, "imageTileArray", pd->texture, GPU_SAMPLER_DEFAULT);
- DRW_shgroup_uniform_texture(shgrp, "imageTileData", tex_tile_data);
- }
- else {
- DRW_shgroup_uniform_texture_ex(shgrp, "imageTexture", pd->texture, GPU_SAMPLER_DEFAULT);
- }
- DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", sh_params.far_near);
- DRW_shgroup_uniform_vec4_copy(shgrp, "color", ShaderParameters::color);
- DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", sh_params.shuffle);
- DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", sh_params.flags);
- DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", sh_params.use_premul_alpha);
-
- add_to_shgroup(space, shgrp, image, image_buffer);
- }
-
- void draw_finish(IMAGE_Data *vedata) const override
- {
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
-
- if (pd->texture && pd->owns_texture) {
- GPU_texture_free(pd->texture);
- pd->owns_texture = false;
- }
- pd->texture = nullptr;
- }
-
- void draw_scene(IMAGE_Data *vedata) const override
- {
- 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(nullptr);
- }
-};
-
-} // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_engine.cc b/source/blender/draw/engines/image/image_engine.cc
index be5946f34eb..840d4840f1b 100644
--- a/source/blender/draw/engines/image/image_engine.cc
+++ b/source/blender/draw/engines/image/image_engine.cc
@@ -41,7 +41,7 @@
#include "GPU_batch.h"
-#include "image_drawing_mode_image_space.hh"
+#include "image_drawing_mode.hh"
#include "image_engine.h"
#include "image_private.hh"
#include "image_space_image.hh"
@@ -68,7 +68,7 @@ template<
*
* Useful during development to switch between drawing implementations.
*/
- typename DrawingMode = ImageSpaceDrawingMode>
+ typename DrawingMode = ScreenSpaceDrawingMode<OneTextureMethod>>
class ImageEngine {
private:
const DRWContextState *draw_ctx;
@@ -86,48 +86,58 @@ class ImageEngine {
void cache_init()
{
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
-
+ IMAGE_InstanceData *instance_data = vedata->instance_data;
drawing_mode.cache_init(vedata);
- pd->view = nullptr;
- if (space->has_view_override()) {
- const ARegion *region = draw_ctx->region;
- pd->view = space->create_view_override(region);
- }
+
+ /* Setup full screen view matrix. */
+ const ARegion *region = draw_ctx->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);
+ instance_data->view = DRW_view_create(viewmat, winmat, nullptr, nullptr, nullptr);
}
void cache_populate()
{
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
+ IMAGE_InstanceData *instance_data = vedata->instance_data;
Main *bmain = CTX_data_main(draw_ctx->evil_C);
- pd->image = space->get_image(bmain);
- if (pd->image == nullptr) {
+ instance_data->image = space->get_image(bmain);
+ if (instance_data->image == nullptr) {
/* Early exit, nothing to draw. */
return;
}
- pd->ibuf = space->acquire_image_buffer(pd->image, &pd->lock);
+ instance_data->flags.do_tile_drawing = instance_data->image->source != IMA_SRC_TILED &&
+ space->use_tile_drawing();
+ void *lock;
+ ImBuf *image_buffer = space->acquire_image_buffer(instance_data->image, &lock);
+
+ /* Setup the matrix to go from screen UV coordinates to UV texture space coordinates. */
+ float image_resolution[2] = {image_buffer ? image_buffer->x : 1024.0f,
+ image_buffer ? image_buffer->y : 1024.0f};
+ space->init_ss_to_texture_matrix(
+ draw_ctx->region, image_resolution, instance_data->ss_to_texture);
+
+ const Scene *scene = DRW_context_state_get()->scene;
+ instance_data->sh_params.update(space.get(), scene, instance_data->image, image_buffer);
+ space->release_buffer(instance_data->image, image_buffer, lock);
+
ImageUser *iuser = space->get_image_user();
- drawing_mode.cache_image(space.get(), vedata, pd->image, iuser, pd->ibuf);
+ drawing_mode.cache_image(vedata, instance_data->image, iuser);
}
void draw_finish()
{
drawing_mode.draw_finish(vedata);
- IMAGE_StorageList *stl = vedata->stl;
- IMAGE_PrivateData *pd = stl->pd;
- space->release_buffer(pd->image, pd->ibuf, pd->lock);
- pd->image = nullptr;
- pd->ibuf = nullptr;
+ IMAGE_InstanceData *instance_data = vedata->instance_data;
+ instance_data->image = nullptr;
}
void draw_scene()
{
drawing_mode.draw_scene(vedata);
}
-};
+}; // namespace blender::draw::image_engine
/* -------------------------------------------------------------------- */
/** \name Engine Callbacks
@@ -137,15 +147,9 @@ 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 = static_cast<IMAGE_PrivateData *>(MEM_callocN(sizeof(IMAGE_PrivateData), __func__));
+ if (vedata->instance_data == nullptr) {
+ vedata->instance_data = MEM_new<IMAGE_InstanceData>(__func__);
}
- IMAGE_PrivateData *pd = stl->pd;
-
- pd->ibuf = nullptr;
- pd->lock = nullptr;
- pd->texture = nullptr;
}
static void IMAGE_cache_init(void *vedata)
@@ -174,6 +178,12 @@ static void IMAGE_engine_free()
IMAGE_shader_free();
}
+static void IMAGE_instance_free(void *_instance_data)
+{
+ IMAGE_InstanceData *instance_data = reinterpret_cast<IMAGE_InstanceData *>(_instance_data);
+ MEM_delete(instance_data);
+}
+
/** \} */
static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data);
@@ -191,7 +201,7 @@ DrawEngineType draw_engine_image_type = {
&IMAGE_data_size, /* vedata_size */
&IMAGE_engine_init, /* engine_init */
&IMAGE_engine_free, /* engine_free */
- nullptr, /* instance_free */
+ &IMAGE_instance_free, /* instance_free */
&IMAGE_cache_init, /* cache_init */
&IMAGE_cache_populate, /* cache_populate */
nullptr, /* cache_finish */
diff --git a/source/blender/draw/engines/image/image_instance_data.hh b/source/blender/draw/engines/image/image_instance_data.hh
new file mode 100644
index 00000000000..7fb0a6ca3eb
--- /dev/null
+++ b/source/blender/draw/engines/image/image_instance_data.hh
@@ -0,0 +1,134 @@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_batches.hh"
+#include "image_partial_updater.hh"
+#include "image_private.hh"
+#include "image_shader_params.hh"
+#include "image_texture_info.hh"
+#include "image_wrappers.hh"
+
+#include "DRW_render.h"
+
+/**
+ * \brief max allowed textures to use by the ScreenSpaceDrawingMode.
+ *
+ * 4 textures are used to reduce uploading screen space textures when translating the image.
+ */
+constexpr int SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN = 4;
+
+struct IMAGE_InstanceData {
+ struct Image *image;
+
+ PartialImageUpdater partial_update;
+
+ struct DRWView *view;
+ ShaderParameters sh_params;
+ struct {
+ /**
+ * \brief should we perform tiled drawing (wrap repeat).
+ *
+ * Option is true when image is capable of tile drawing (image is not tile) and the tiled
+ * option is set in the space.
+ */
+ bool do_tile_drawing : 1;
+ } flags;
+
+ struct {
+ DRWPass *image_pass;
+ } passes;
+
+ /** \brief Transform matrix to convert a normalized screen space coordinates to texture space. */
+ float ss_to_texture[4][4];
+ TextureInfo texture_infos[SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN];
+
+ /**
+ * \brief Maximum uv's that are on the border of the image.
+ *
+ * Larger UV coordinates would be drawn as a border. */
+ float max_uv[2];
+
+ public:
+ void max_uv_update()
+ {
+ copy_v2_fl2(max_uv, 1.0f, 1.0);
+ LISTBASE_FOREACH (ImageTile *, image_tile_ptr, &image->tiles) {
+ ImageTileWrapper image_tile(image_tile_ptr);
+ max_uv[0] = max_ii(max_uv[0], image_tile.get_tile_x_offset() + 1);
+ max_uv[1] = max_ii(max_uv[1], image_tile.get_tile_y_offset() + 1);
+ }
+ }
+
+ void clear_dirty_flag()
+ {
+ reset_dirty_flag(false);
+ }
+ void mark_all_texture_slots_dirty()
+ {
+ reset_dirty_flag(true);
+ }
+
+ void update_gpu_texture_allocations()
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ TextureInfo &info = texture_infos[i];
+ const bool is_allocated = info.texture != nullptr;
+ const bool is_visible = info.visible;
+ const bool should_be_freed = !is_visible && is_allocated;
+ const bool should_be_created = is_visible && !is_allocated;
+
+ if (should_be_freed) {
+ GPU_texture_free(info.texture);
+ info.texture = nullptr;
+ }
+
+ if (should_be_created) {
+ DRW_texture_ensure_fullscreen_2d(
+ &info.texture, GPU_RGBA16F, static_cast<DRWTextureFlag>(0));
+ }
+ info.dirty |= should_be_created;
+ }
+ }
+
+ void update_batches()
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ TextureInfo &info = texture_infos[i];
+ if (!info.dirty) {
+ continue;
+ }
+ BatchUpdater batch_updater(info);
+ batch_updater.update_batch();
+ }
+ }
+
+ private:
+ /** \brief Set dirty flag of all texture slots to the given value. */
+ void reset_dirty_flag(bool new_value)
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ texture_infos[i].dirty = new_value;
+ }
+ }
+};
diff --git a/source/blender/draw/engines/image/image_partial_updater.hh b/source/blender/draw/engines/image/image_partial_updater.hh
new file mode 100644
index 00000000000..f0c1db2331a
--- /dev/null
+++ b/source/blender/draw/engines/image/image_partial_updater.hh
@@ -0,0 +1,78 @@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "BKE_image.h"
+#include "BKE_image_partial_update.hh"
+
+struct PartialImageUpdater {
+ struct PartialUpdateUser *user;
+ const struct Image *image;
+
+ /**
+ * \brief Ensure that there is a partial update user for the given image.
+ */
+ void ensure_image(const Image *image)
+ {
+ if (!is_valid(image)) {
+ free();
+ create(image);
+ }
+ }
+
+ virtual ~PartialImageUpdater()
+ {
+ free();
+ }
+
+ private:
+ /**
+ * \brief check if the partial update user can still be used for the given image.
+ *
+ * When switching to a different image the partial update user should be recreated.
+ */
+ bool is_valid(const Image *new_image) const
+ {
+ if (image != new_image) {
+ return false;
+ }
+
+ return user != nullptr;
+ }
+
+ void create(const Image *image)
+ {
+ BLI_assert(user == nullptr);
+ user = BKE_image_partial_update_create(image);
+ image = image;
+ }
+
+ void free()
+ {
+ if (user != nullptr) {
+ BKE_image_partial_update_free(user);
+ user = nullptr;
+ image = nullptr;
+ }
+ }
+};
diff --git a/source/blender/draw/engines/image/image_private.hh b/source/blender/draw/engines/image/image_private.hh
index fc3ce72d0aa..05ed2881145 100644
--- a/source/blender/draw/engines/image/image_private.hh
+++ b/source/blender/draw/engines/image/image_private.hh
@@ -24,6 +24,11 @@
#include <optional>
+#include "BKE_image.h"
+
+#include "image_instance_data.hh"
+#include "image_texture_info.hh"
+
/* Forward declarations */
extern "C" {
struct GPUTexture;
@@ -35,32 +40,13 @@ struct Image;
namespace blender::draw::image_engine {
-/* GPUViewport.storage
- * Is freed every time the viewport engine changes. */
-struct IMAGE_PassList {
- DRWPass *image_pass;
-};
-
-struct IMAGE_PrivateData {
- void *lock;
- struct ImBuf *ibuf;
- struct Image *image;
- struct DRWView *view;
-
- struct GPUTexture *texture;
- bool owns_texture;
-};
-
-struct IMAGE_StorageList {
- IMAGE_PrivateData *pd;
-};
-
struct IMAGE_Data {
void *engine_type;
DRWViewportEmptyList *fbl;
DRWViewportEmptyList *txl;
- IMAGE_PassList *psl;
- IMAGE_StorageList *stl;
+ DRWViewportEmptyList *psl;
+ DRWViewportEmptyList *stl;
+ IMAGE_InstanceData *instance_data;
};
/* Shader parameters. */
@@ -69,105 +55,6 @@ struct IMAGE_Data {
#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)
-
-struct ShaderParameters {
- constexpr static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-
- int flags = 0;
- float shuffle[4];
- float far_near[2];
- bool use_premul_alpha = false;
-
- ShaderParameters()
- {
- copy_v4_fl(shuffle, 1.0f);
- copy_v2_fl2(far_near, 100.0f, 0.0f);
- }
-};
-
-/**
- * Space accessor.
- *
- * Image engine is used to draw the images inside multiple spaces \see SpaceLink.
- * The AbstractSpaceAccessor is an interface to communicate with a space.
- */
-class AbstractSpaceAccessor {
- public:
- virtual ~AbstractSpaceAccessor() = default;
-
- /**
- * Return the active image of the space.
- *
- * The returned image will be drawn in the space.
- *
- * The return value is optional.
- */
- virtual Image *get_image(Main *bmain) = 0;
-
- /**
- * Return the #ImageUser of the space.
- *
- * The return value is optional.
- */
- virtual ImageUser *get_image_user() = 0;
-
- /**
- * Acquire the image buffer of the image.
- *
- * \param image: Image to get the buffer from. Image is the same as returned from the #get_image
- * member.
- * \param lock: pointer to a lock object.
- * \return Image buffer of the given image.
- */
- virtual ImBuf *acquire_image_buffer(Image *image, void **lock) = 0;
-
- /**
- * Release a previous locked image from #acquire_image_buffer.
- */
- virtual void release_buffer(Image *image, ImBuf *image_buffer, void *lock) = 0;
-
- /**
- * Update the r_shader_parameters with space specific settings.
- *
- * Only update the #ShaderParameters.flags and #ShaderParameters.shuffle. Other parameters
- * are updated inside the image engine.
- */
- virtual void get_shader_parameters(ShaderParameters &r_shader_parameters,
- ImBuf *image_buffer,
- bool is_tiled) = 0;
-
- /**
- * Retrieve the gpu textures to draw.
- */
- virtual void get_gpu_textures(Image *image,
- ImageUser *iuser,
- ImBuf *image_buffer,
- GPUTexture **r_gpu_texture,
- bool *r_owns_texture,
- GPUTexture **r_tex_tile_data) = 0;
-
- /**
- * Does this space override the view.
- * When so this member should return true and the create_view_override must return the view to
- * use during drawing.
- */
- virtual bool has_view_override() const = 0;
-
- /**
- * Override the view for drawing.
- * Should match #has_view_override.
- */
- virtual DRWView *create_view_override(const ARegion *UNUSED(region)) = 0;
-
- /**
- * Initialize the matrix that will be used to draw the image. The matrix will be send as object
- * matrix to the drawing pipeline.
- */
- virtual void get_image_mat(const ImBuf *image_buffer,
- const ARegion *region,
- float r_mat[4][4]) const = 0;
-}; // namespace blender::draw::image_engine
/**
* Abstract class for a drawing mode of the image engine.
@@ -179,11 +66,7 @@ class AbstractDrawingMode {
public:
virtual ~AbstractDrawingMode() = default;
virtual void cache_init(IMAGE_Data *vedata) const = 0;
- virtual void cache_image(AbstractSpaceAccessor *space,
- IMAGE_Data *vedata,
- Image *image,
- ImageUser *iuser,
- ImBuf *image_buffer) const = 0;
+ virtual void cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser) const = 0;
virtual void draw_scene(IMAGE_Data *vedata) const = 0;
virtual void draw_finish(IMAGE_Data *vedata) const = 0;
};
diff --git a/source/blender/draw/engines/image/image_shader_params.hh b/source/blender/draw/engines/image/image_shader_params.hh
new file mode 100644
index 00000000000..fd16d9cdc4b
--- /dev/null
+++ b/source/blender/draw/engines/image/image_shader_params.hh
@@ -0,0 +1,59 @@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "DNA_camera_types.h"
+#include "DNA_image_types.h"
+#include "DNA_scene_types.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "BKE_image.h"
+
+#include "BLI_math.h"
+
+#include "image_space.hh"
+
+struct ShaderParameters {
+ constexpr static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ int flags = 0;
+ float shuffle[4];
+ float far_near[2];
+ bool use_premul_alpha = false;
+
+ void update(AbstractSpaceAccessor *space, const Scene *scene, Image *image, ImBuf *image_buffer)
+ {
+ copy_v4_fl(shuffle, 1.0f);
+ copy_v2_fl2(far_near, 100.0f, 0.0f);
+
+ use_premul_alpha = BKE_image_has_gpu_texture_premultiplied_alpha(image, image_buffer);
+
+ if (scene->camera && scene->camera->type == OB_CAMERA) {
+ Camera *camera = static_cast<Camera *>(scene->camera->data);
+ copy_v2_fl2(far_near, camera->clip_end, camera->clip_start);
+ }
+ const bool is_tiled_image = (image->source == IMA_SRC_TILED);
+ space->get_shader_parameters(*this, image_buffer, is_tiled_image);
+ }
+};
diff --git a/source/blender/draw/engines/image/image_space.hh b/source/blender/draw/engines/image/image_space.hh
new file mode 100644
index 00000000000..762f43a7337
--- /dev/null
+++ b/source/blender/draw/engines/image/image_space.hh
@@ -0,0 +1,99 @@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+class ShaderParameters;
+
+/**
+ * Space accessor.
+ *
+ * Image engine is used to draw the images inside multiple spaces \see SpaceLink.
+ * The AbstractSpaceAccessor is an interface to communicate with a space.
+ */
+class AbstractSpaceAccessor {
+ public:
+ virtual ~AbstractSpaceAccessor() = default;
+
+ /**
+ * Return the active image of the space.
+ *
+ * The returned image will be drawn in the space.
+ *
+ * The return value is optional.
+ */
+ virtual Image *get_image(Main *bmain) = 0;
+
+ /**
+ * Return the #ImageUser of the space.
+ *
+ * The return value is optional.
+ */
+ virtual ImageUser *get_image_user() = 0;
+
+ /**
+ * Acquire the image buffer of the image.
+ *
+ * \param image: Image to get the buffer from. Image is the same as returned from the #get_image
+ * member.
+ * \param lock: pointer to a lock object.
+ * \return Image buffer of the given image.
+ */
+ virtual ImBuf *acquire_image_buffer(Image *image, void **lock) = 0;
+
+ /**
+ * Release a previous locked image from #acquire_image_buffer.
+ */
+ virtual void release_buffer(Image *image, ImBuf *image_buffer, void *lock) = 0;
+
+ /**
+ * Update the r_shader_parameters with space specific settings.
+ *
+ * Only update the #ShaderParameters.flags and #ShaderParameters.shuffle. Other parameters
+ * are updated inside the image engine.
+ */
+ virtual void get_shader_parameters(ShaderParameters &r_shader_parameters,
+ ImBuf *image_buffer,
+ bool is_tiled) = 0;
+
+ /**
+ * Retrieve the gpu textures to draw.
+ */
+ virtual void get_gpu_textures(Image *image,
+ ImageUser *iuser,
+ ImBuf *image_buffer,
+ GPUTexture **r_gpu_texture,
+ bool *r_owns_texture,
+ GPUTexture **r_tex_tile_data) = 0;
+
+ /** \brief Is (wrap) repeat option enabled in the space. */
+ virtual bool use_tile_drawing() const = 0;
+
+ /**
+ * \brief Initialize r_uv_to_texture matrix to transform from normalized screen space coordinates
+ * (0..1) to texture space UV coordinates.
+ */
+ virtual void init_ss_to_texture_matrix(const ARegion *region,
+ const float image_resolution[2],
+ float r_uv_to_texture[4][4]) const = 0;
+
+}; // namespace blender::draw::image_engine
diff --git a/source/blender/draw/engines/image/image_space_image.hh b/source/blender/draw/engines/image/image_space_image.hh
index 7728a963254..900ac57c652 100644
--- a/source/blender/draw/engines/image/image_space_image.hh
+++ b/source/blender/draw/engines/image/image_space_image.hh
@@ -61,7 +61,6 @@ class SpaceImageAccessor : public AbstractSpaceAccessor {
const int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(image_buffer);
const bool do_repeat = (!is_tiled) && ((sima->flag & SI_DRAW_TILE) != 0);
SET_FLAG_FROM_TEST(r_shader_parameters.flags, do_repeat, IMAGE_DRAW_FLAG_DO_REPEAT);
- SET_FLAG_FROM_TEST(r_shader_parameters.flags, is_tiled, IMAGE_DRAW_FLAG_USE_WORLD_POS);
if ((sima_flag & SI_USE_ALPHA) != 0) {
/* Show RGBA */
r_shader_parameters.flags |= IMAGE_DRAW_FLAG_SHOW_ALPHA | IMAGE_DRAW_FLAG_APPLY_ALPHA;
@@ -102,15 +101,6 @@ class SpaceImageAccessor : public AbstractSpaceAccessor {
}
}
- bool has_view_override() const override
- {
- return false;
- }
- DRWView *create_view_override(const ARegion *UNUSED(region)) override
- {
- return nullptr;
- }
-
void get_gpu_textures(Image *image,
ImageUser *iuser,
ImBuf *image_buffer,
@@ -171,11 +161,25 @@ class SpaceImageAccessor : public AbstractSpaceAccessor {
}
}
- void get_image_mat(const ImBuf *UNUSED(image_buffer),
- const ARegion *UNUSED(region),
- float r_mat[4][4]) const override
+ bool use_tile_drawing() const override
+ {
+ return (sima->flag & SI_DRAW_TILE) != 0;
+ }
+
+ void init_ss_to_texture_matrix(const ARegion *region,
+ const float UNUSED(image_resolution[2]),
+ float r_uv_to_texture[4][4]) const override
{
- unit_m4(r_mat);
+ unit_m4(r_uv_to_texture);
+ float scale_x = 1.0 / BLI_rctf_size_x(&region->v2d.cur);
+ float scale_y = 1.0 / BLI_rctf_size_y(&region->v2d.cur);
+ float translate_x = scale_x * -region->v2d.cur.xmin;
+ float translate_y = scale_y * -region->v2d.cur.ymin;
+
+ r_uv_to_texture[0][0] = scale_x;
+ r_uv_to_texture[1][1] = scale_y;
+ r_uv_to_texture[3][0] = translate_x;
+ r_uv_to_texture[3][1] = translate_y;
}
};
diff --git a/source/blender/draw/engines/image/image_space_node.hh b/source/blender/draw/engines/image/image_space_node.hh
index 3ca18eec742..1ce8fdeb0f3 100644
--- a/source/blender/draw/engines/image/image_space_node.hh
+++ b/source/blender/draw/engines/image/image_space_node.hh
@@ -54,20 +54,6 @@ class SpaceNodeAccessor : public AbstractSpaceAccessor {
BKE_image_release_ibuf(image, ibuf, lock);
}
- bool has_view_override() const override
- {
- return true;
- }
-
- DRWView *create_view_override(const ARegion *region) override
- {
- /* 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);
- return DRW_view_create(viewmat, winmat, nullptr, nullptr, nullptr);
- }
-
void get_shader_parameters(ShaderParameters &r_shader_parameters,
ImBuf *ibuf,
bool UNUSED(is_tiled)) override
@@ -120,18 +106,33 @@ class SpaceNodeAccessor : public AbstractSpaceAccessor {
*r_tex_tile_data = nullptr;
}
- void get_image_mat(const ImBuf *image_buffer,
- const ARegion *region,
- float r_mat[4][4]) const override
+ bool use_tile_drawing() const override
+ {
+ return false;
+ }
+
+ /**
+ * The backdrop of the node editor isn't drawn in screen space UV space. But is locked with the
+ * screen.
+ */
+ void init_ss_to_texture_matrix(const ARegion *region,
+ const float image_resolution[2],
+ float r_uv_to_texture[4][4]) const override
{
- unit_m4(r_mat);
- const float ibuf_width = image_buffer->x;
- const float ibuf_height = image_buffer->y;
-
- r_mat[0][0] = ibuf_width * snode->zoom;
- r_mat[1][1] = ibuf_height * snode->zoom;
- r_mat[3][0] = (region->winx - snode->zoom * ibuf_width) / 2 + snode->xof;
- r_mat[3][1] = (region->winy - snode->zoom * ibuf_height) / 2 + snode->yof;
+ unit_m4(r_uv_to_texture);
+ float display_resolution[2];
+ mul_v2_v2fl(display_resolution, image_resolution, snode->zoom);
+ const float scale_x = display_resolution[0] / region->winx;
+ const float scale_y = display_resolution[1] / region->winy;
+ const float translate_x = ((region->winx - display_resolution[0]) * 0.5f + snode->xof) /
+ region->winx;
+ const float translate_y = ((region->winy - display_resolution[1]) * 0.5f + snode->yof) /
+ region->winy;
+
+ r_uv_to_texture[0][0] = scale_x;
+ r_uv_to_texture[1][1] = scale_y;
+ r_uv_to_texture[3][0] = translate_x;
+ r_uv_to_texture[3][1] = translate_y;
}
};
diff --git a/source/blender/draw/engines/image/image_texture_info.hh b/source/blender/draw/engines/image/image_texture_info.hh
new file mode 100644
index 00000000000..3ab4f6be864
--- /dev/null
+++ b/source/blender/draw/engines/image/image_texture_info.hh
@@ -0,0 +1,76 @@
+/*
+ * 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 2022, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "BLI_rect.h"
+
+#include "GPU_batch.h"
+#include "GPU_texture.h"
+
+struct TextureInfo {
+ /**
+ * \brief Is the texture clipped.
+ *
+ * Resources of clipped textures are freed and ignored when performing partial updates.
+ */
+ bool visible : 1;
+
+ /**
+ * \brief does this texture need a full update.
+ *
+ * When set to false the texture can be updated using a partial update.
+ */
+ bool dirty : 1;
+
+ /** \brief area of the texture in screen space. */
+ rctf clipping_bounds;
+ /** \brief uv area of the texture. */
+ rctf uv_bounds;
+
+ /**
+ * \brief Batch to draw the associated texton the screen.
+ *
+ * contans a VBO with `pos` and 'uv'.
+ * `pos` (2xF32) is relative to the origin of the space.
+ * `uv` (2xF32) reflect the uv bounds.
+ */
+ GPUBatch *batch;
+
+ /**
+ * \brief GPU Texture for a partial region of the image editor.
+ */
+ GPUTexture *texture;
+
+ ~TextureInfo()
+ {
+ if (batch != nullptr) {
+ GPU_batch_discard(batch);
+ batch = nullptr;
+ }
+
+ if (texture != nullptr) {
+ GPU_texture_free(texture);
+ texture = nullptr;
+ }
+ }
+};
diff --git a/source/blender/draw/engines/image/image_wrappers.hh b/source/blender/draw/engines/image/image_wrappers.hh
new file mode 100644
index 00000000000..63dbbde12ef
--- /dev/null
+++ b/source/blender/draw/engines/image/image_wrappers.hh
@@ -0,0 +1,49 @@
+/*
+ * 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 2022, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "DNA_image_types.h"
+
+struct ImageTileWrapper {
+ ImageTile *image_tile;
+ ImageTileWrapper(ImageTile *image_tile) : image_tile(image_tile)
+ {
+ }
+
+ int get_tile_number() const
+ {
+ return image_tile->tile_number;
+ }
+
+ int get_tile_x_offset() const
+ {
+ int tile_number = get_tile_number();
+ return (tile_number - 1001) % 10;
+ }
+
+ int get_tile_y_offset() const
+ {
+ int tile_number = get_tile_number();
+ return (tile_number - 1001) / 10;
+ }
+};
diff --git a/source/blender/draw/engines/image/shaders/engine_image_frag.glsl b/source/blender/draw/engines/image/shaders/engine_image_frag.glsl
index 55a2f2a72f1..604f9b807b3 100644
--- a/source/blender/draw/engines/image/shaders/engine_image_frag.glsl
+++ b/source/blender/draw/engines/image/shaders/engine_image_frag.glsl
@@ -7,12 +7,7 @@
#define IMAGE_DRAW_FLAG_DEPTH (1 << 3)
#define IMAGE_DRAW_FLAG_DO_REPEAT (1 << 4)
-#ifdef TILED_IMAGE
-uniform sampler2DArray imageTileArray;
-uniform sampler1DArray imageTileData;
-#else
uniform sampler2D imageTexture;
-#endif
uniform bool imgPremultiplied;
uniform int drawFlags;
@@ -20,75 +15,49 @@ uniform vec2 farNearDistances;
uniform vec4 color;
uniform vec4 shuffle;
+/* Maximum UV range.
+ * Negative UV coordinates and UV coordinates beyond maxUV would draw a border. */
+uniform vec2 maxUv;
+
#define FAR_DISTANCE farNearDistances.x
#define NEAR_DISTANCE farNearDistances.y
-in vec2 uvs;
+#define Z_DEPTH_BORDER 1.0
+#define Z_DEPTH_IMAGE 0.75
+
+in vec2 uv_screen;
+in vec2 uv_image;
out vec4 fragColor;
-#ifdef TILED_IMAGE
-/* TODO(fclem): deduplicate code. */
-bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
+bool is_border(vec2 uv)
{
- 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;
+ return (uv.x < 0.0 || uv.y < 0.0 || uv.x > maxUv.x || uv.y > maxUv.y);
}
-#endif
void main()
{
- vec4 tex_color;
- /* Read texture */
-#ifdef TILED_IMAGE
- 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 & 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 & IMAGE_DRAW_FLAG_APPLY_ALPHA) != 0) {
- if (!imgPremultiplied) {
- tex_color.rgb *= tex_color.a;
+ ivec2 uvs_clamped = ivec2(uv_screen);
+ vec4 tex_color = texelFetch(imageTexture, uvs_clamped, 0);
+
+ bool border = is_border(uv_image);
+ if (!border) {
+ if ((drawFlags & IMAGE_DRAW_FLAG_APPLY_ALPHA) != 0) {
+ if (!imgPremultiplied) {
+ tex_color.rgb *= tex_color.a;
+ }
+ }
+ if ((drawFlags & IMAGE_DRAW_FLAG_DEPTH) != 0) {
+ tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color);
}
- }
- if ((drawFlags & IMAGE_DRAW_FLAG_DEPTH) != 0) {
- tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color);
- }
- if ((drawFlags & IMAGE_DRAW_FLAG_SHUFFLING) != 0) {
- tex_color = color * dot(tex_color, shuffle);
- }
- if ((drawFlags & IMAGE_DRAW_FLAG_SHOW_ALPHA) == 0) {
- tex_color.a = 1.0;
+ if ((drawFlags & IMAGE_DRAW_FLAG_SHUFFLING) != 0) {
+ tex_color = color * dot(tex_color, shuffle);
+ }
+ if ((drawFlags & IMAGE_DRAW_FLAG_SHOW_ALPHA) == 0) {
+ tex_color.a = 1.0;
+ }
}
-
fragColor = tex_color;
+ gl_FragDepth = border ? Z_DEPTH_BORDER : Z_DEPTH_IMAGE;
}
diff --git a/source/blender/draw/engines/image/shaders/engine_image_vert.glsl b/source/blender/draw/engines/image/shaders/engine_image_vert.glsl
index da2b1907c41..71100a5681a 100644
--- a/source/blender/draw/engines/image/shaders/engine_image_vert.glsl
+++ b/source/blender/draw/engines/image/shaders/engine_image_vert.glsl
@@ -1,34 +1,24 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#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;
-in vec3 pos;
-out vec2 uvs;
+in vec2 pos;
+in vec2 uv;
+
+/* Normalized screen space uv coordinates. */
+out vec2 uv_screen;
+out vec2 uv_image;
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;
+ vec3 image_pos = vec3(pos, 0.0);
+ uv_screen = image_pos.xy;
+ uv_image = uv;
- 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;
- }
- 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 = IMAGE_Z_DEPTH;
- gl_Position = position;
- /* UDIM texture uses the world position for tile selection. */
- uvs = ((drawFlags & IMAGE_DRAW_FLAG_USE_WORLD_POS) != 0) ? world_pos.xy : image_pos.xy;
- }
+ vec3 world_pos = point_object_to_world(image_pos);
+ vec4 position = point_world_to_ndc(world_pos);
+ gl_Position = position;
}