diff --git a/source/blender/draw/engines/image/image_batches.hh b/source/blender/draw/engines/image/image_batches.hh index 67a8e8976d1..739a2c800e8 100644 --- a/source/blender/draw/engines/image/image_batches.hh +++ b/source/blender/draw/engines/image/image_batches.hh @@ -44,24 +44,8 @@ class BatchUpdater { 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.clipping_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) + template + static void fill_tri_fan_from_rect(DataType result[4][2], RectType &rect) { result[0][0] = rect.xmin; result[0][1] = rect.ymin; @@ -73,10 +57,27 @@ class BatchUpdater { result[3][1] = rect.ymax; } + GPUVertBuf *create_vbo() + { + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 4); + int pos[4][2]; + fill_tri_fan_from_rect(pos, info.clipping_bounds); + float uv[4][2]; + fill_tri_fan_from_rect(uv, info.clipping_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; + } + 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, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT); GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); pos_id = GPU_vertformat_attr_id_get(&format, "pos"); diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh index 4169f8dd836..b875de29630 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.hh +++ b/source/blender/draw/engines/image/image_drawing_mode.hh @@ -38,6 +38,8 @@ template class ScreenTileTextures { struct TextureInfoBounds { TextureInfo *info = nullptr; rctf uv_bounds; + /* Offset of this tile to be drawn on the screen (number of tiles from bottom left corner). */ + int2 tile_id; }; IMAGE_InstanceData *instance_data; @@ -76,13 +78,22 @@ template class ScreenTileTextures { rctf region_uv_bounds; BLI_rctf_init( ®ion_uv_bounds, region_uv_min.x, region_uv_max.x, region_uv_min.y, region_uv_max.y); - update_region_bounds_from_uv_bounds(region_uv_bounds, float2(region->winx, region->winy)); + update_region_bounds_from_uv_bounds(region_uv_bounds, int2(region->winx, region->winy)); + } + + /** + * Get the texture size of a single texture for the current settings. + */ + int2 gpu_texture_size() const + { + float2 viewport_size = DRW_viewport_size_get(); + int2 texture_size(ceil(viewport_size.x / Divisions), ceil(viewport_size.y / Divisions)); + return texture_size; } void ensure_gpu_textures_allocation() { - float2 viewport_size = DRW_viewport_size_get(); - int2 texture_size(ceil(viewport_size.x / Divisions), ceil(viewport_size.y / Divisions)); + int2 texture_size = gpu_texture_size(); for (TextureInfo &info : instance_data->texture_infos) { info.ensure_gpu_texture(texture_size); } @@ -107,6 +118,7 @@ template class ScreenTileTextures { for (int x = 0; x < TexturesPerDimension; x++) { for (int y = 0; y < TexturesPerDimension; y++) { TextureInfoBounds texture_info_bounds; + texture_info_bounds.tile_id = int2(x, y); BLI_rctf_init(&texture_info_bounds.uv_bounds, uv_coords[x][y].x, uv_coords[x + 1][y + 1].x, @@ -127,6 +139,7 @@ template class ScreenTileTextures { if (info_bound.info == nullptr && BLI_rctf_compare(&info_bound.uv_bounds, &info.clipping_uv_bounds, 0.001)) { info_bound.info = &info; + info.tile_id = info_bound.tile_id; assigned = true; break; } @@ -143,20 +156,34 @@ template class ScreenTileTextures { for (TextureInfoBounds &info_bound : info_bounds) { if (info_bound.info == nullptr) { info_bound.info = unassigned_textures.pop_last(); + info_bound.info->tile_id = info_bound.tile_id; info_bound.info->need_full_update = true; info_bound.info->clipping_uv_bounds = info_bound.uv_bounds; } } } - void update_region_bounds_from_uv_bounds(const rctf ®ion_uv_bounds, const float2 region_size) + void update_region_bounds_from_uv_bounds(const rctf ®ion_uv_bounds, const int2 region_size) { rctf region_bounds; BLI_rctf_init(®ion_bounds, 0.0, region_size.x, 0.0, region_size.y); float4x4 uv_to_screen; BLI_rctf_transform_calc_m4_pivot_min(®ion_uv_bounds, ®ion_bounds, uv_to_screen.ptr()); + int2 tile_origin(0); + for (const TextureInfo &info : instance_data->texture_infos) { + if (info.tile_id == int2(0)) { + tile_origin = int2(math::transform_point( + uv_to_screen, + float3(info.clipping_uv_bounds.xmin, info.clipping_uv_bounds.ymin, 0.0))); + break; + } + } + + const int2 texture_size = gpu_texture_size(); for (TextureInfo &info : instance_data->texture_infos) { - info.update_region_bounds_from_uv_bounds(uv_to_screen); + int2 bottom_left = tile_origin + texture_size * info.tile_id; + int2 top_right = bottom_left + texture_size; + BLI_rcti_init(&info.clipping_bounds, bottom_left.x, top_right.x, bottom_left.y, top_right.y); } } }; @@ -497,7 +524,7 @@ template class ScreenSpaceDrawingMode : public AbstractD tile_buffer.y * (texture_info.clipping_uv_bounds.ymin - image_tile.get_tile_y_offset()), tile_buffer.y * (texture_info.clipping_uv_bounds.ymax - image_tile.get_tile_y_offset())); BLI_rctf_transform_calc_m4_pivot_min(&tile_area, &texture_area, uv_to_texel.ptr()); - invert_m4(uv_to_texel.ptr()); + uv_to_texel = math::invert(uv_to_texel); rctf crop_rect; rctf *crop_rect_ptr = nullptr; @@ -584,6 +611,6 @@ template class ScreenSpaceDrawingMode : public AbstractD DRW_view_set_active(nullptr); GPU_framebuffer_bind(dfbl->default_fb); } -}; // namespace clipping +}; } // 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 a836ee928cd..007a5ca4f14 100644 --- a/source/blender/draw/engines/image/image_engine.cc +++ b/source/blender/draw/engines/image/image_engine.cc @@ -53,7 +53,7 @@ template< * * Useful during development to switch between drawing implementations. */ - typename DrawingMode = ScreenSpaceDrawingMode>> + typename DrawingMode = ScreenSpaceDrawingMode>> class ImageEngine { private: const DRWContextState *draw_ctx; diff --git a/source/blender/draw/engines/image/image_private.hh b/source/blender/draw/engines/image/image_private.hh index 4780eea5bf5..a63ff0d308b 100644 --- a/source/blender/draw/engines/image/image_private.hh +++ b/source/blender/draw/engines/image/image_private.hh @@ -51,6 +51,7 @@ class AbstractDrawingMode { GPUShader *IMAGE_shader_image_get(); GPUShader *IMAGE_shader_depth_get(); +GPUShader *IMAGE_shader_color_depth_get(); void IMAGE_shader_free(); } // namespace blender::draw::image_engine diff --git a/source/blender/draw/engines/image/image_texture_info.hh b/source/blender/draw/engines/image/image_texture_info.hh index ead037196d6..1e0eb2162fb 100644 --- a/source/blender/draw/engines/image/image_texture_info.hh +++ b/source/blender/draw/engines/image/image_texture_info.hh @@ -24,15 +24,19 @@ struct TextureInfo { bool need_full_update : 1; /** \brief area of the texture in screen space. */ - rctf clipping_bounds; + rcti clipping_bounds; /** \brief uv area of the texture in screen space. */ rctf clipping_uv_bounds; + /* Which tile of the screen is used with this texture. Used to safely calculate the correct + * offset of the textures. */ + int2 tile_id; + /** * \brief Batch to draw the associated text on the screen. * * Contains a VBO with `pos` and `uv`. - * `pos` (2xF32) is relative to the origin of the space. + * `pos` (2xI32) is relative to the origin of the space. * `uv` (2xF32) reflect the uv bounds. */ GPUBatch *batch = nullptr; @@ -68,22 +72,6 @@ struct TextureInfo { return int2(clipping_bounds.xmin, clipping_bounds.ymin); } - /** - * \brief Update the region bounds from the uv bounds by applying the given transform matrix. - */ - void update_region_bounds_from_uv_bounds(const float4x4 &uv_to_region) - { - float3 bottom_left_uv = float3(clipping_uv_bounds.xmin, clipping_uv_bounds.ymin, 0.0f); - float3 top_right_uv = float3(clipping_uv_bounds.xmax, clipping_uv_bounds.ymax, 0.0f); - float3 bottom_left_region = math::transform_point(uv_to_region, bottom_left_uv); - float3 top_right_region = math::transform_point(uv_to_region, top_right_uv); - BLI_rctf_init(&clipping_bounds, - bottom_left_region.x, - top_right_region.x, - bottom_left_region.y, - top_right_region.y); - } - void ensure_gpu_texture(int2 texture_size) { const bool is_allocated = texture != nullptr; diff --git a/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl index fb72a132613..53b67032815 100644 --- a/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl +++ b/source/blender/draw/engines/image/shaders/image_engine_color_vert.glsl @@ -2,10 +2,9 @@ void main() { - vec3 image_pos = vec3(pos, 0.0); + vec3 image_pos = vec3(pos.x, pos.y, 0.0); uv_screen = image_pos.xy; - vec3 world_pos = point_object_to_world(image_pos); - vec4 position = point_world_to_ndc(world_pos); + vec4 position = point_world_to_ndc(image_pos); gl_Position = position; } diff --git a/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl b/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl index 3181a85ff55..c1516e09213 100644 --- a/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl +++ b/source/blender/draw/engines/image/shaders/image_engine_depth_vert.glsl @@ -2,10 +2,9 @@ void main() { - vec3 image_pos = vec3(pos, 0.0); + vec3 image_pos = vec3(pos.x, pos.y, 0.0); uv_image = uv; - vec3 world_pos = point_object_to_world(image_pos); - vec4 position = point_world_to_ndc(world_pos); + vec4 position = point_world_to_ndc(image_pos); gl_Position = position; } diff --git a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh index 3e6673b79a2..6495ee03326 100644 --- a/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh +++ b/source/blender/draw/engines/image/shaders/infos/engine_image_info.hh @@ -5,7 +5,7 @@ GPU_SHADER_INTERFACE_INFO(image_engine_color_iface, "").smooth(Type::VEC2, "uv_screen"); GPU_SHADER_CREATE_INFO(image_engine_color_shader) - .vertex_in(0, Type::VEC2, "pos") + .vertex_in(0, Type::IVEC2, "pos") .vertex_out(image_engine_color_iface) .fragment_out(0, Type::VEC4, "fragColor") .push_constant(Type::VEC4, "shuffle") @@ -23,7 +23,7 @@ GPU_SHADER_CREATE_INFO(image_engine_color_shader) GPU_SHADER_INTERFACE_INFO(image_engine_depth_iface, "").smooth(Type::VEC2, "uv_image"); GPU_SHADER_CREATE_INFO(image_engine_depth_shader) - .vertex_in(0, Type::VEC2, "pos") + .vertex_in(0, Type::IVEC2, "pos") .vertex_in(1, Type::VEC2, "uv") .vertex_out(image_engine_depth_iface) .push_constant(Type::VEC4, "min_max_uv")