Improved draw texture by drawing a line between mouse cursor coordinates (instead of discrete points). This allows to use smaller size of pencil.

This commit is contained in:
brunoherbelin
2025-11-16 16:36:01 +01:00
parent 8d26f5d78a
commit 84233e46cd
4 changed files with 38 additions and 22 deletions

View File

@@ -21,26 +21,27 @@ uniform vec3 brush;
uniform int option;
uniform int effect;
float sdBox( in vec2 p, in float b)
float sdBox( in vec2 v1, in vec2 v2, float r )
{
vec2 q = abs(p) - vec2(b);
vec2 ba = v2 - v1;
vec2 pa = -v1;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
vec2 q = abs(pa -h*ba) - vec2(r);
float d = min( max(q.x, q.y), 0.0) + length(max(q,0.0));
return 1.0 - abs(d) * step(d, 0.0);
return 1.0 - abs( mix( 0.5, 1.0, d) ) * step(d, 0.0);
}
float sdCircle( in vec2 p, in float b)
float sdSegment( in vec2 v1, in vec2 v2, float r )
{
return ( length( p ) / b );
vec2 ba = v2 - v1;
vec2 pa = -v1;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length(pa-h*ba) / r;
}
float sdElipse( in vec2 p, in float b)
{
return ( length( p ) / b );
}
const mat3 KERNEL = mat3( 0.0625, 0.125, 0.0625,
0.125, 0.25, 0.125,
0.0625, 0.125, 0.0625);
const mat3 KERNEL = mat3( 0.0555555, 0.111111, 0.0555555,
0.111111, 0.333334, 0.111111,
0.0555555, 0.111111, 0.0555555);
vec3 gaussian()
{
@@ -71,14 +72,15 @@ void main()
// fragment coordinates
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
// adjust coordinates to match scaling area
uv.x *= cursor.z ;
uv.y *= cursor.w ;
uv.x *= size.x ;
uv.y *= size.y ;
// cursor coordinates
vec2 cursor = vec2(cursor.x, - cursor.y);
vec2 cur = vec2(cursor.x, - cursor.y);
vec2 cur_prev = vec2(cursor.z, - cursor.w);
// use distance function relative to length brush.x (size), depending on brush.z (shape):
// - brush.z = 0 : circle shape
// - brush.z = 1 : square shape
float d = (1.0 -brush.z) * sdCircle(cursor-uv, brush.x) + brush.z * sdBox(uv-cursor, brush.x);
float d = (1.0 -brush.z) * sdSegment(cur_prev - uv, cur - uv, brush.x) + brush.z * sdBox(cur_prev - uv, cur - uv, brush.x);
// modify only the pixels inside the brush
if( d < 1.0 )

View File

@@ -19,6 +19,7 @@
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/constants.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_access.hpp>
#define GLM_ENABLE_EXPERIMENTAL
@@ -450,6 +451,8 @@ std::pair<Node *, glm::vec2> TextureView::pick(glm::vec2 P)
pick = { mask_cursor_circle_, P };
// adapt grid to prepare grab action
adaptGridToSource(current);
// reset previous brush position
previous_scene_brush_pos = glm::zero<glm::vec3>();
return pick;
}
// special case for cropping the mask shape
@@ -815,8 +818,8 @@ void TextureView::draw()
ImGuiToolkit::ToolTip("Size");
if (ImGui::BeginPopup("brush_size_popup", ImGuiWindowFlags_NoMove))
{
int pixel_size_min = int(0.05 * edit_source_->frame()->height() );
int pixel_size_max = int(2.0 * edit_source_->frame()->height() );
int pixel_size_min = int(BRUSH_MIN_SIZE * edit_source_->frame()->height() );
int pixel_size_max = int(BRUSH_MAX_SIZE * edit_source_->frame()->height() );
int pixel_size = int(Settings::application.brush.x * edit_source_->frame()->height() );
show_cursor_forced_ = true;
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
@@ -1106,16 +1109,26 @@ View::Cursor TextureView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pa
// set brush coordinates (used in mouse over)
scene_brush_pos = scene_to;
// no previous brush position : restart at same coordinates
if ( glm::length( previous_scene_brush_pos ) < EPSILON)
previous_scene_brush_pos = scene_brush_pos;
if ( pick.first == mask_cursor_circle_ ) {
// snap prush coordinates if grid is active
if (grid->active())
scene_brush_pos = grid->snap(scene_brush_pos);
// inform shader of a cursor action : coordinates and crop scaling
edit_source_->maskShader()->size = edit_source_->mixingsurface_->scale_;
// inform shader of a cursor action : coordinates and crop scaling
edit_source_->maskShader()->cursor = glm::vec4(scene_brush_pos.x - shift_crop_.x,
scene_brush_pos.y - shift_crop_.y,
edit_source_->mixingsurface_->scale_.x,
edit_source_->mixingsurface_->scale_.y);
previous_scene_brush_pos.x - shift_crop_.x,
previous_scene_brush_pos.y - shift_crop_.y);
edit_source_->touch(Source::SourceUpdate_Mask);
previous_scene_brush_pos = scene_brush_pos;
// action label
info << MaskShader::mask_names[MaskShader::PAINT] << " changed";
// cursor indication - no info, just cursor

View File

@@ -72,6 +72,7 @@ private:
void adaptGridToSource(Source *s = nullptr, Node *picked = nullptr);
glm::vec3 scene_brush_pos;
glm::vec3 previous_scene_brush_pos;
TranslationGrid *translation_grid_;
RotationGrid *rotation_grid_;
};

View File

@@ -90,7 +90,7 @@
#define APPEARANCE_DEFAULT_SCALE 2.f
#define APPEARANCE_MIN_SCALE 0.4f
#define APPEARANCE_MAX_SCALE 7.0f
#define BRUSH_MIN_SIZE 0.05f
#define BRUSH_MIN_SIZE 0.01f
#define BRUSH_MAX_SIZE 2.f
#define BRUSH_MIN_PRESS 0.005f
#define BRUSH_MAX_PRESS 1.f