#pragma once #include "rtt.h" #include "shader.h" #include "texture.h" class Brush { public: Brush() = default; Brush(const Brush& brush) = default; std::string m_name; std::string m_brush_path; std::string m_brush_thumb_path; std::string m_stencil_path; std::shared_ptr m_tip_texture; std::shared_ptr m_stencil_texture; //uint16_t m_tex_id = 0; //uint16_t m_tex_stencil_id = const_hash("data/paper.jpg"); glm::vec4 m_tip_color{0, 0, 0, 1}; float m_tip_size = 0; float m_tip_spacing = 0; float m_tip_flow = 0; float m_tip_opacity = 0; float m_tip_angle = 0; float m_tip_mix = 0; float m_tip_stencil = 0; float m_tip_wet = 0; float m_tip_noise = 0; float m_tip_hue = 0; float m_tip_sat = 0; float m_tip_val = 0; bool m_tip_angle_follow = false; bool m_tip_flow_pressure = false; bool m_tip_size_pressure = false; bool m_tip_hue_pressure = false; bool m_tip_sat_pressure = false; bool m_tip_val_pressure = false; float m_jitter_scale = 0; float m_jitter_angle = 0; float m_jitter_spread = 0; float m_jitter_flow = 0; float m_jitter_hue = 0; float m_jitter_sat = 0; float m_jitter_val = 0; int m_blend_mode = 0; bool load_texture(const std::string& path, const std::string& thumb); bool load_stencil(const std::string& path); }; struct StrokeSample { glm::vec3 col = { 0, 0, 0 }; glm::vec3 pos = { 0, 0, 0 }; glm::vec3 origin = { 0, 0, 0 }; float size = 0; float flow = 0; float angle = 0; bool valid() const { return !( glm::any(glm::isnan(col)) || glm::any(glm::isnan(pos)) || glm::any(glm::isnan(origin)) ); } }; class BrushMesh { public: GLuint buffers[3]{ 0 }; GLuint vao{ 0 }; struct instance_t { glm::mat4 mvp; float flow; }; int loc_flow = 0; int loc_mvp = 0; bool create(); void draw(const std::vector& samples, const glm::mat4& proj); }; class Stroke { public: struct Keypoint { glm::vec3 pos = { 0, 0, 0 }; float pressure = 0; float dist = 0; }; struct Camera { glm::mat4 rot; float fov = 0; }; int m_layer = 0; float m_curve = 0; float m_dist = 0; float m_step = 0; float m_max_size = FLT_MAX; bool m_filter_points = true; Camera m_camera; std::shared_ptr m_brush; cbuffer m_curve_angles; cbuffer m_pressure_buff; cbuffer m_hsv_jitter; StrokeSample m_prev_sample; std::vector m_keypoints; std::vector> m_hold_points; std::vector m_samples; int m_last_kp; std::minstd_rand prng; void start(const std::shared_ptr& brush); void add_point(glm::vec3 pos, float pressure); void reset(bool clear_keypoints = false); bool has_sample(); std::vector compute_samples(); StrokeSample randomize_sample(const glm::vec3& pos, float pressure, float curve_angle); };