Image Editor: Remove drawing artifacts #106173

Closed
Jeroen Bakker wants to merge 13 commits from Jeroen-Bakker:image-editor-drawing-artifacts into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
8 changed files with 146 additions and 3 deletions
Showing only changes of commit cfdbf82cb7 - Show all commits

View File

@ -732,6 +732,8 @@ set(GLSL_SRC
engines/image/shaders/image_engine_color_vert.glsl
engines/image/shaders/image_engine_depth_frag.glsl
engines/image/shaders/image_engine_depth_vert.glsl
engines/image/shaders/image_engine_color_depth_frag.glsl
engines/image/shaders/image_engine_color_depth_vert.glsl
)
set(GLSL_C)

View File

@ -585,7 +585,6 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
if (!instance_data->flags.do_tile_drawing) {
add_depth_shgroups(*instance_data, image, iuser);
}
add_shgroups(instance_data);
}
void draw_finish(IMAGE_Data *vedata) const override
@ -612,6 +611,65 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
DRW_view_set_active(nullptr);
GPU_framebuffer_bind(dfbl->default_fb);
}
}; // namespace clipping
};
/**
* Drawing mode that uses the GPU textures stored alongside the image for drawing.
*
* This is better for images with a dimension smaller than 8K as it will lead to smoother
* interaction. Bigger images are required to use #ScreenSpaceDrawingMode.
*/
class ImageBasedDrawingMode : public AbstractDrawingMode {
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);
}
public:
void begin_sync(IMAGE_Data *vedata) const override
{
IMAGE_InstanceData *instance_data = vedata->instance_data;
DRWState state = static_cast<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
instance_data->passes.image_pass = DRW_pass_create("Image", state);
instance_data->passes.depth_pass = nullptr;
}
void image_sync(IMAGE_Data *vedata, Image *image, ImageUser *iuser) const override
{
IMAGE_InstanceData *instance_data = vedata->instance_data;
const bool is_tiled_texture = image->source == IMA_SRC_TILED;
GPUTexture *texture = nullptr;
if (is_tiled_texture) {
}
else {
texture = BKE_image_get_gpu_texture(image, iuser, nullptr);
}
if (texture == nullptr) {
return;
}
// Add full screen rect.
GPUShader *shader = IMAGE_shader_color_depth_get();
DRWShadingGroup *grp = DRW_shgroup_create(shader, instance_data->passes.image_pass);
DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
}
void draw_viewport(IMAGE_Data *vedata) const override
{
IMAGE_InstanceData *instance_data = vedata->instance_data;
DRW_draw_pass(instance_data->passes.image_pass);
}
void draw_finish(IMAGE_Data * /*vedata*/) const override
{
}
};
} // namespace blender::draw::image_engine

View File

@ -53,7 +53,8 @@ template<
*
* Useful during development to switch between drawing implementations.
*/
typename DrawingMode = ScreenSpaceDrawingMode<ScreenTileTextures<3>>>
typename DrawingMode = ImageBasedDrawingMode>
/*ScreenSpaceDrawingMode<ScreenTileTextures<3>>*/
class ImageEngine {
private:
const DRWContextState *draw_ctx;

View File

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

View File

@ -19,6 +19,7 @@ namespace blender::draw::image_engine {
struct IMAGE_Shaders {
GPUShader *image_sh;
GPUShader *depth_sh;
GPUShader *color_depth_sh;
};
static struct {
@ -43,6 +44,15 @@ GPUShader *IMAGE_shader_depth_get()
return sh_data->depth_sh;
}
GPUShader *IMAGE_shader_color_depth_get()
{
IMAGE_Shaders *sh_data = &e_data.shaders;
if (sh_data->color_depth_sh == nullptr) {
sh_data->color_depth_sh = GPU_shader_create_from_info_name("image_engine_color_depth_shader");
}
return sh_data->color_depth_sh;
}
void IMAGE_shader_free()
{
GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders;

View File

@ -0,0 +1,39 @@
#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl)
/* Keep in sync with image_engine.c */
#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 FAR_DISTANCE farNearDistances.x
#define NEAR_DISTANCE farNearDistances.y
void main()
{
ivec2 uvs_clamped = ivec2(uv_screen);
float depth = texelFetch(depth_texture, uvs_clamped, 0).r;
if (depth == 1.0) {
discard;
return;
}
vec4 tex_color = texelFetch(imageTexture, uvs_clamped - offset, 0);
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_SHUFFLING) != 0) {
tex_color = vec4(dot(tex_color, shuffle));
}
if ((drawFlags & IMAGE_DRAW_FLAG_SHOW_ALPHA) == 0) {
tex_color.a = 1.0;
}
fragColor = tex_color;
}

View File

@ -0,0 +1,10 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
vec3 image_pos = vec3(pos, 0.0);
uv_screen = image_pos.xy;
vec4 position = point_world_to_ndc(image_pos);
gl_Position = position;
}

View File

@ -32,3 +32,25 @@ GPU_SHADER_CREATE_INFO(image_engine_depth_shader)
.additional_info("draw_modelmat")
.depth_write(DepthWrite::ANY)
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(image_engine_color_depth_base)
.vertex_in(0, Type::IVEC2, "pos")
.vertex_in(1, Type::VEC2, "uv")
.vertex_out(image_engine_color_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.push_constant(Type::VEC4, "min_max_uv")
.push_constant(Type::VEC4, "shuffle")
.push_constant(Type::VEC2, "farNearDistances")
.push_constant(Type::IVEC2, "offset")
.push_constant(Type::INT, "drawFlags")
.push_constant(Type::BOOL, "imgPremultiplied")
.sampler(0, ImageType::FLOAT_2D, "imageTexture")
.vertex_source("image_engine_color_depth_vert.glsl")
.fragment_source("image_engine_color_depth_frag.glsl")
.additional_info("draw_modelmat");
GPU_SHADER_CREATE_INFO(image_engine_color_depth_shader)
.additional_info("image_engine_color_depth_base")
.sampler(0, ImageType::FLOAT_2D, "image_texture")
.do_static_compilation(true);
;