Image Editor: Remove drawing artifacts #106173
@ -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<typename DataType, typename RectType>
|
||||
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<int, rcti>(pos, info.clipping_bounds);
|
||||
float uv[4][2];
|
||||
fill_tri_fan_from_rect<float, 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;
|
||||
}
|
||||
|
||||
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");
|
||||
|
@ -38,6 +38,8 @@ template<size_t Divisions> 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<size_t Divisions> 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<size_t Divisions> 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<size_t Divisions> 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<size_t Divisions> 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<typename TextureMethod> 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<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
|
||||
DRW_view_set_active(nullptr);
|
||||
GPU_framebuffer_bind(dfbl->default_fb);
|
||||
}
|
||||
}; // namespace clipping
|
||||
};
|
||||
|
||||
} // namespace blender::draw::image_engine
|
||||
|
@ -53,7 +53,7 @@ template<
|
||||
*
|
||||
* Useful during development to switch between drawing implementations.
|
||||
*/
|
||||
typename DrawingMode = ScreenSpaceDrawingMode<ScreenTileTextures<1>>>
|
||||
typename DrawingMode = ScreenSpaceDrawingMode<ScreenTileTextures<5>>>
|
||||
class ImageEngine {
|
||||
private:
|
||||
const DRWContextState *draw_ctx;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user