diff --git a/paint/shaders/cursor.kong b/paint/shaders/cursor.kong index 98efc1dd..9d131011 100644 --- a/paint/shaders/cursor.kong +++ b/paint/shaders/cursor.kong @@ -8,6 +8,8 @@ const constants: { radius: float; camera_right: float3; tint: float3; + camera_up: float3; + camera_align: float; }; #[set(everything)] @@ -40,11 +42,6 @@ fun get_normal(p0: float3, uv: float2): float3 { return normalize(cross(p2 - p0, p1 - p0)); } -// fun create_basis(normal: float3, out tangent: float3, out binormal: float3) { -// tangent = normalize(constants.camera_right - normal * dot(constants.camera_right, normal)); -// binormal = cross(tangent, normal); -// } - fun cursor_vert(input: vert_in): vert_out { var keep: float = input.pos.x + input.nor.x; // hlsl @@ -59,9 +56,14 @@ fun cursor_vert(input: vert_in): vert_out { var n_tan: float3; var n_bin: float3; - // create_basis(n, n_tan, n_bin); - n_tan = normalize(constants.camera_right - n * dot(constants.camera_right, n)); - n_bin = cross(n_tan, n); + if (constants.camera_align > 0.0) { + n_tan = constants.camera_right; + n_bin = constants.camera_up; + } + else { + n_tan = normalize(constants.camera_right - n * dot(constants.camera_right, n)); + n_bin = cross(n_tan, n); + } if (vertex_id() == 0) { wpos += normalize(-n_tan - n_bin) * 0.7 * constants.radius; diff --git a/paint/sources/context.c b/paint/sources/context.c index d3ed8bbf..29ebfb53 100644 --- a/paint/sources/context.c +++ b/paint/sources/context.c @@ -426,8 +426,10 @@ bool context_is_decal_mask() { return context_is_decal() && operator_shortcut(any_map_get(g_keymap, "decal_mask"), SHORTCUT_TYPE_DOWN); } -bool context_is_decal_camera_align() { - return context_is_decal() && (g_context->decal_camera_align || operator_shortcut(any_map_get(g_keymap, "decal_camera_align"), SHORTCUT_TYPE_DOWN)); +bool context_is_brush_camera_align() { + bool brush = g_context->tool == TOOL_TYPE_BRUSH || g_context->tool == TOOL_TYPE_ERASER; + return (context_is_decal() || brush) && + (g_context->brush_camera_align || operator_shortcut(any_map_get(g_keymap, "brush_camera_align"), SHORTCUT_TYPE_DOWN)); } bool context_is_decal_mask_paint() { diff --git a/paint/sources/functions.h b/paint/sources/functions.h index f62778eb..3cfa5a22 100644 --- a/paint/sources/functions.h +++ b/paint/sources/functions.h @@ -257,7 +257,7 @@ bool context_in_browser(); bool context_is_decal(); bool context_is_decal_mask(); bool context_is_decal_mask_paint(); -bool context_is_decal_camera_align(); +bool context_is_brush_camera_align(); bool context_is_floating_toolbar(); void context_set_viewport_mode(viewport_mode_t mode); void context_load_envmap(); diff --git a/paint/sources/globals.h b/paint/sources/globals.h index b8a3612f..7eaa1527 100644 --- a/paint/sources/globals.h +++ b/paint/sources/globals.h @@ -83,6 +83,8 @@ i32 pipes_cursor_tex_step; i32 pipes_cursor_radius; i32 pipes_cursor_camera_right; i32 pipes_cursor_tint; +i32 pipes_cursor_camera_up; +i32 pipes_cursor_camera_align; i32 pipes_cursor_gbufferd; gpu_pipeline_t *pipes_cursor_decal; i32 pipes_cursor_decal_vp; diff --git a/paint/sources/keymap.c b/paint/sources/keymap.c index fa5cb111..986f00d5 100644 --- a/paint/sources/keymap.c +++ b/paint/sources/keymap.c @@ -83,7 +83,7 @@ any_map_t *keymap_get_default() { any_map_set(keymap, "node_search", "space"); any_map_set(keymap, "operator_search", "space"); any_map_set(keymap, "decal_mask", "ctrl"); - any_map_set(keymap, "decal_camera_align", "z"); + any_map_set(keymap, "brush_camera_align", "z"); any_map_set(keymap, "grid_snap", "x"); any_map_set(keymap, "select_material", "shift+number"); any_map_set(keymap, "select_layer", "alt+number"); diff --git a/paint/sources/nodes_neural/texture_mesh_node.c b/paint/sources/nodes_neural/texture_mesh_node.c index f53dae82..1616c036 100644 --- a/paint/sources/nodes_neural/texture_mesh_node.c +++ b/paint/sources/nodes_neural/texture_mesh_node.c @@ -251,7 +251,7 @@ static void texture_mesh_node_project(ui_node_t *node) { // Project a camera-aligned decal g_context->tool = TOOL_TYPE_DECAL; - g_context->decal_camera_align = true; + g_context->brush_camera_align = true; g_context->brush_opacity = 1.0; g_context->brush_angle = 0.0; g_context->brush_scale = 1.0; @@ -302,7 +302,7 @@ static void texture_mesh_node_project(ui_node_t *node) { g_context->pdirty = 0; g_context->tool = _tool; - g_context->decal_camera_align = false; + g_context->brush_camera_align = false; g_context->brush_radius = _brush_radius; g_context->brush_opacity = _brush_opacity; g_context->brush_angle = _brush_angle; diff --git a/paint/sources/pipes.c b/paint/sources/pipes.c index 39bd1864..6a24e38f 100644 --- a/paint/sources/pipes.c +++ b/paint/sources/pipes.c @@ -214,6 +214,8 @@ void pipes_init() { pipes_cursor_radius = pipes_get_constant_location("float"); pipes_cursor_camera_right = pipes_get_constant_location("float3"); pipes_cursor_tint = pipes_get_constant_location("float3"); + pipes_cursor_camera_up = pipes_get_constant_location("float3"); + pipes_cursor_camera_align = pipes_get_constant_location("float"); pipes_cursor_gbufferd = 0; } diff --git a/paint/sources/render/make_brush.c b/paint/sources/render/make_brush.c index 2b8232cc..b92a335f 100644 --- a/paint/sources/render/make_brush.c +++ b/paint/sources/render/make_brush.c @@ -56,15 +56,30 @@ void make_brush_run(node_shader_t *kong) { } node_shader_write_frag(kong, "var ba: float3 = winplast.xyz - winp.xyz;"); - if (g_context->brush_lazy_radius > 0 && g_context->brush_lazy_step > 0) { - // Sphere - node_shader_write_frag(kong, "dist = distance(input.wposition, winp.xyz);"); - } - else { - // Capsule - node_shader_write_frag(kong, "var h: float = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);"); - node_shader_write_frag(kong, "dist = length(pa - ba * h);"); - } + node_shader_add_constant(kong, "VP: float4x4", "_view_proj_matrix"); + node_shader_add_constant(kong, "camera_up: float3", "_camera_up"); + node_shader_add_constant(kong, "aspect_ratio: float", "_aspect_ratio_window"); + node_shader_add_constant(kong, "camera_align: float", "_brush_camera_align"); + + node_shader_write_frag(kong, "if (constants.camera_align > 0.0) {"); + node_shader_write_frag(kong, "var vp_up_y: float = (constants.VP * float4(constants.camera_up, 0.0)).y;"); + node_shader_write_frag(kong, "var ca_scale: float = (1.0 / winp.w) / (vp_up_y * constants.brush_radius);"); + node_shader_write_frag(kong, "var sa: float2 = sp.xy - constants.inp.xy;"); + node_shader_write_frag(kong, "sa.x *= constants.aspect_ratio;"); + node_shader_write_frag(kong, "sa = sa * ca_scale;"); + // Capsule + node_shader_write_frag(kong, "var sb: float2 = constants.inplast.xy - constants.inp.xy;"); + node_shader_write_frag(kong, "sb.x *= constants.aspect_ratio;"); + node_shader_write_frag(kong, "sb = sb * ca_scale;"); + node_shader_write_frag(kong, "var sh: float = clamp(dot(sa, sb) / dot(sb, sb), 0.0, 1.0);"); + node_shader_write_frag(kong, "dist = length(sa - sb * sh) * 2.0 * constants.brush_radius;"); + node_shader_write_frag(kong, "}"); + + node_shader_write_frag(kong, "else {"); + // Capsule + node_shader_write_frag(kong, "var h: float = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);"); + node_shader_write_frag(kong, "dist = length(pa - ba * h);"); + node_shader_write_frag(kong, "}"); node_shader_write_frag(kong, "if (dist > constants.brush_radius) { discard; }"); diff --git a/paint/sources/render/make_paint.c b/paint/sources/render/make_paint.c index 0fb46e42..e0e6de82 100644 --- a/paint/sources/render/make_paint.c +++ b/paint/sources/render/make_paint.c @@ -421,6 +421,9 @@ node_shader_context_t *make_paint_run(material_t *data, material_context_t *matc node_shader_add_function(kong, str_octahedron_wrap); node_shader_add_texture(kong, "gbuffer0", NULL); node_shader_add_constant(kong, "camera_right: float3", "_camera_right"); + node_shader_add_constant(kong, "camera_up: float3", "_camera_up"); + node_shader_add_constant(kong, "camera_align: float", "_brush_camera_align"); + node_shader_add_constant(kong, "VP: float4x4", "_view_proj_matrix"); node_shader_write_frag(kong, "var mn0: float2 = sample_lod(gbuffer0, sampler_linear, constants.inp.xy, 0.0).rg;"); node_shader_write_frag(kong, "var mn: float3;"); node_shader_write_frag(kong, "mn.z = 1.0 - abs(mn0.x) - abs(mn0.y);"); @@ -432,7 +435,16 @@ node_shader_context_t *make_paint_run(material_t *data, material_context_t *matc node_shader_write_frag(kong, "var mt: float3 = normalize(mr - mn * dot(mr, mn));"); node_shader_write_frag(kong, "var mb: float3 = cross(mt, mn);"); node_shader_write_frag(kong, "var pa_mask_3d: float3 = input.wposition - winp.xyz;"); - node_shader_write_frag(kong, "var pa_mask: float2 = float2(dot(pa_mask_3d, mt), dot(pa_mask_3d, mb));"); + node_shader_write_frag(kong, "var pa_mask: float2;"); + node_shader_write_frag(kong, "if (constants.camera_align > 0.0) {"); + node_shader_write_frag(kong, "var mvp_up_y: float = (constants.VP * float4(constants.camera_up, 0.0)).y;"); + node_shader_write_frag(kong, "var msa: float2 = sp.xy - constants.inp.xy;"); + node_shader_write_frag(kong, "msa.x *= constants.aspect_ratio;"); + node_shader_write_frag(kong, "pa_mask = msa * (2.0 / (mvp_up_y * winp.w));"); + node_shader_write_frag(kong, "}"); + node_shader_write_frag(kong, "else {"); + node_shader_write_frag(kong, "pa_mask = float2(dot(pa_mask_3d, mt), dot(pa_mask_3d, mb));"); + node_shader_write_frag(kong, "}"); if (g_context->brush_directional) { node_shader_add_constant(kong, "brush_direction: float3", "_brush_direction"); node_shader_write_frag(kong, "if (constants.brush_direction.z == 0.0) { discard; }"); diff --git a/paint/sources/render/make_sculpt.c b/paint/sources/render/make_sculpt.c index 5e6a88e8..2f276022 100644 --- a/paint/sources/render/make_sculpt.c +++ b/paint/sources/render/make_sculpt.c @@ -354,7 +354,7 @@ node_shader_context_t *sculpt_make_sculpt_run(material_t *data, material_context node_shader_add_constant(kong, "aspect_ratio: float", "_aspect_ratio_window"); node_shader_add_constant(kong, "camera_right: float3", "_camera_right"); node_shader_add_constant(kong, "camera_up: float3", "_camera_up"); - node_shader_add_constant(kong, "camera_align: float", "_decal_camera_align"); + node_shader_add_constant(kong, "camera_align: float", "_brush_camera_align"); node_shader_write_attrib_frag(kong, "var uvsp: float2 = float2(0.0, 0.0);"); diff --git a/paint/sources/render/make_texcoord.c b/paint/sources/render/make_texcoord.c index 684772f4..1e1b4443 100644 --- a/paint/sources/render/make_texcoord.c +++ b/paint/sources/render/make_texcoord.c @@ -42,7 +42,7 @@ void make_texcoord_run(node_shader_t *kong) { node_shader_add_constant(kong, "VP: float4x4", "_view_proj_matrix"); node_shader_add_constant(kong, "camera_right: float3", "_camera_right"); node_shader_add_constant(kong, "camera_up: float3", "_camera_up"); - node_shader_add_constant(kong, "camera_align: float", "_decal_camera_align"); + node_shader_add_constant(kong, "camera_align: float", "_brush_camera_align"); node_shader_write_attrib_frag(kong, "if (constants.camera_align > 0.0) {"); node_shader_write_attrib_frag(kong, "var ca_depth: float = sample_lod(gbufferD, sampler_linear, constants.decal_mask.xy, 0.0).r;"); diff --git a/paint/sources/render/render_path_paint.c b/paint/sources/render/render_path_paint.c index ae829d10..9276eefc 100644 --- a/paint/sources/render/render_path_paint.c +++ b/paint/sources/render/render_path_paint.c @@ -659,6 +659,9 @@ void render_path_paint_draw_cursor(f32 mx, f32 my, f32 radius, f32 tint_r, f32 t vec4_t right = vec4_norm(camera_object_right_world(scene_camera)); gpu_set_float3(pipes_cursor_camera_right, right.x, right.y, right.z); gpu_set_float3(pipes_cursor_tint, tint_r, tint_g, tint_b); + vec4_t up = vec4_norm(camera_object_up_world(scene_camera)); + gpu_set_float3(pipes_cursor_camera_up, up.x, up.y, up.z); + gpu_set_float(pipes_cursor_camera_align, context_is_brush_camera_align() ? 1.0f : 0.0f); gpu_set_mat4(pipes_cursor_vp, scene_camera->vp); mat4_t inv_vp = mat4_inv(scene_camera->vp); gpu_set_mat4(pipes_cursor_inv_vp, inv_vp); @@ -699,7 +702,7 @@ void render_path_paint_draw_cursor_decal(f32 mx, f32 my, f32 radius, f32 opacity gpu_set_float3(pipes_cursor_decal_camera_right, right.x, right.y, right.z); vec4_t up = vec4_norm(camera_object_up_world(scene_camera)); gpu_set_float3(pipes_cursor_decal_camera_up, up.x, up.y, up.z); - gpu_set_float(pipes_cursor_decal_camera_align, context_is_decal_camera_align() ? 1.0f : 0.0f); + gpu_set_float(pipes_cursor_decal_camera_align, context_is_brush_camera_align() ? 1.0f : 0.0f); f32 opacity = g_context->brush_opacity * brush_nodes_opacity * opacity_scale; gpu_set_float(pipes_cursor_decal_opacity, opacity); f32 angle = (g_context->brush_angle + brush_nodes_angle) * (math_pi() / 180.0); diff --git a/paint/sources/types.h b/paint/sources/types.h index 689feea6..095bb6d8 100644 --- a/paint/sources/types.h +++ b/paint/sources/types.h @@ -300,7 +300,7 @@ typedef struct context { bool decal_preview; f32 decal_x; f32 decal_y; - bool decal_camera_align; + bool brush_camera_align; bool select_active; // Select tool bool select_dragging; f32 select_start_x; diff --git a/paint/sources/uniforms.c b/paint/sources/uniforms.c index 44b46dcf..da202dfa 100644 --- a/paint/sources/uniforms.c +++ b/paint/sources/uniforms.c @@ -131,8 +131,8 @@ f32 uniforms_ext_f32_link(object_t *object, material_data_t *mat, char *link) { vec4_t sc = mat4_get_scale(g_context->layer->decal_mat); return sc.z * 0.5; } - else if (string_equals(link, "_decal_camera_align")) { - return context_is_decal_camera_align() ? 1.0f : 0.0f; + else if (string_equals(link, "_brush_camera_align")) { + return context_is_brush_camera_align() ? 1.0f : 0.0f; } else if (string_equals(link, "_picker_opacity")) { return g_context->picked_color->opacity;