mixer brush wip
This commit is contained in:
@@ -801,6 +801,7 @@
|
|||||||
<text text="#opengl #fromscratch #c++" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/>
|
<text text="#opengl #fromscratch #c++" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/>
|
||||||
</border>-->
|
</border>-->
|
||||||
</node>
|
</node>
|
||||||
|
<image-texture id="tex-debug" positioning="absolute" position="0 0" width="100" height="100"></image-texture>
|
||||||
<!--<color-picker/>-->
|
<!--<color-picker/>-->
|
||||||
</layout>
|
</layout>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -307,13 +307,14 @@ void App::initShaders()
|
|||||||
"uniform mediump sampler2D tex;\n"
|
"uniform mediump sampler2D tex;\n"
|
||||||
"uniform mediump sampler2D tex_bg;\n"
|
"uniform mediump sampler2D tex_bg;\n"
|
||||||
"uniform mediump sampler2D tex_stencil;\n"
|
"uniform mediump sampler2D tex_stencil;\n"
|
||||||
//"layout (binding=3, rgba8) uniform image2D tex_mix;\n"
|
"uniform mediump sampler2D tex_mix;\n"
|
||||||
"uniform mediump vec4 col;\n"
|
"uniform mediump vec4 col;\n"
|
||||||
"uniform mediump vec2 resolution;\n"
|
"uniform mediump vec2 resolution;\n"
|
||||||
"uniform mediump float alpha;\n"
|
"uniform mediump float alpha;\n"
|
||||||
"uniform mediump float noise;\n"
|
"uniform mediump float noise;\n"
|
||||||
"uniform mediump vec2 stencil_offset;\n"
|
"uniform mediump vec2 stencil_offset;\n"
|
||||||
"uniform mediump float stencil_alpha;\n"
|
"uniform mediump float stencil_alpha;\n"
|
||||||
|
"uniform mediump float mix_alpha;\n"
|
||||||
"uniform mediump float wet;\n"
|
"uniform mediump float wet;\n"
|
||||||
"in mediump vec2 uv;\n"
|
"in mediump vec2 uv;\n"
|
||||||
"in mediump float q;\n"
|
"in mediump float q;\n"
|
||||||
@@ -343,6 +344,7 @@ void App::initShaders()
|
|||||||
#else
|
#else
|
||||||
" mediump vec4 bg = texture(tex_bg, uv2);\n"
|
" mediump vec4 bg = texture(tex_bg, uv2);\n"
|
||||||
#endif
|
#endif
|
||||||
|
" mediump vec4 mbg = texture(tex_mix, uv/q);\n"
|
||||||
" fg.a *= 1.0-rand(uv2+uv)*noise;\n"
|
" fg.a *= 1.0-rand(uv2+uv)*noise;\n"
|
||||||
" if (fg.a == 0.0) discard;\n"
|
" if (fg.a == 0.0) discard;\n"
|
||||||
" mediump float contribution = (1.0 - bg.a) * fg.a;\n"
|
" mediump float contribution = (1.0 - bg.a) * fg.a;\n"
|
||||||
@@ -350,7 +352,7 @@ void App::initShaders()
|
|||||||
" mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n"
|
" mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n"
|
||||||
" mediump vec4 frag_wet = vec4(rgb, max(bg.a, fg.a * 1.2));\n"
|
" mediump vec4 frag_wet = vec4(rgb, max(bg.a, fg.a * 1.2));\n"
|
||||||
" mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n"
|
" mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n"
|
||||||
" frag = mix(frag_dry, frag_wet, wet);\n"
|
" frag = mix(mix(frag_dry, frag_wet, wet), mbg, mix_alpha);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
static const char* shader_checkerboard_v =
|
static const char* shader_checkerboard_v =
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public:
|
|||||||
float m_tip_flow = 0;
|
float m_tip_flow = 0;
|
||||||
float m_tip_opacity = 0;
|
float m_tip_opacity = 0;
|
||||||
float m_tip_angle = 0;
|
float m_tip_angle = 0;
|
||||||
|
float m_tip_mix = 0;
|
||||||
float m_tip_stencil = 0;
|
float m_tip_stencil = 0;
|
||||||
float m_tip_wet = 0;
|
float m_tip_wet = 0;
|
||||||
float m_tip_noise = 0;
|
float m_tip_noise = 0;
|
||||||
|
|||||||
@@ -219,6 +219,46 @@ void ui::Canvas::stroke_cancel()
|
|||||||
m_current_stroke = nullptr;
|
m_current_stroke = nullptr;
|
||||||
m_show_tmp = false;
|
m_show_tmp = false;
|
||||||
}
|
}
|
||||||
|
void ui::Canvas::stroke_draw_mix()
|
||||||
|
{
|
||||||
|
m_mixer.bindFramebuffer();
|
||||||
|
m_mixer.clear({ 0, 1, 1, 1 });
|
||||||
|
|
||||||
|
glViewport(m_vp.x, m_vp.y, m_vp.z, m_vp.w);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
m_sampler_bg.bind(0);
|
||||||
|
auto layer_index = m_current_layer_idx;
|
||||||
|
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||||
|
{
|
||||||
|
if (m_layers[layer_index].m_opacity == .0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto plane_mvp_z = m_proj * m_mv *
|
||||||
|
m_plane_transform[plane_index] *
|
||||||
|
glm::translate(glm::vec3(0, 0, -1));
|
||||||
|
{
|
||||||
|
ui::ShaderManager::use(kShader::TextureAlpha);
|
||||||
|
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
|
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index].m_opacity);
|
||||||
|
ui::ShaderManager::u_int(kShaderUniform::Highlight, false);
|
||||||
|
ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
// m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||||
|
// m_node->m_face_plane.draw_fill();
|
||||||
|
// m_layers[layer_index].m_rtt[plane_index].unbindTexture();
|
||||||
|
|
||||||
|
m_tmp[plane_index].bindTexture();
|
||||||
|
m_node->m_face_plane.draw_fill();
|
||||||
|
m_tmp[plane_index].unbindTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_sampler_bg.unbind();
|
||||||
|
m_mixer.unbindFramebuffer();
|
||||||
|
}
|
||||||
void ui::Canvas::stroke_draw()
|
void ui::Canvas::stroke_draw()
|
||||||
{
|
{
|
||||||
if (!(m_current_stroke && m_current_stroke->has_sample()))
|
if (!(m_current_stroke && m_current_stroke->has_sample()))
|
||||||
@@ -231,6 +271,8 @@ void ui::Canvas::stroke_draw()
|
|||||||
glGetIntegerv(GL_VIEWPORT, vp);
|
glGetIntegerv(GL_VIEWPORT, vp);
|
||||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||||
|
|
||||||
|
stroke_draw_mix();
|
||||||
|
|
||||||
glViewport(0, 0, m_width, m_height);
|
glViewport(0, 0, m_width, m_height);
|
||||||
|
|
||||||
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
||||||
@@ -243,11 +285,13 @@ void ui::Canvas::stroke_draw()
|
|||||||
tex.bind();
|
tex.bind();
|
||||||
m_sampler_brush.bind(0);
|
m_sampler_brush.bind(0);
|
||||||
m_sampler_bg.bind(1);
|
m_sampler_bg.bind(1);
|
||||||
m_sampler_mask.bind(2);
|
m_sampler_stencil.bind(2);
|
||||||
m_sampler_stencil.bind(3);
|
m_sampler_mix.bind(3);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
stencil.bind();
|
stencil.bind();
|
||||||
|
glActiveTexture(GL_TEXTURE3);
|
||||||
|
m_mixer.bindTexture();
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
@@ -280,10 +324,12 @@ void ui::Canvas::stroke_draw()
|
|||||||
#ifndef __IOS__
|
#ifndef __IOS__
|
||||||
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
|
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
|
||||||
#endif
|
#endif
|
||||||
ShaderManager::u_int(kShaderUniform::TexStencil, 3); // stencil
|
ShaderManager::u_int(kShaderUniform::TexStencil, 2); // stencil
|
||||||
|
ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer
|
||||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
||||||
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
||||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush.m_tip_stencil);
|
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush.m_tip_stencil);
|
||||||
|
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush.m_tip_mix);
|
||||||
ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet);
|
ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet);
|
||||||
ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise);
|
ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise);
|
||||||
for (const auto& s : samples)
|
for (const auto& s : samples)
|
||||||
@@ -360,11 +406,11 @@ void ui::Canvas::stroke_draw()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_alpha_lock)
|
// if (m_alpha_lock)
|
||||||
{
|
// {
|
||||||
glActiveTexture(GL_TEXTURE2);
|
// glActiveTexture(GL_TEXTURE2);
|
||||||
m_layers[m_current_layer_idx].m_rtt[i].unbindTexture();
|
// m_layers[m_current_layer_idx].m_rtt[i].unbindTexture();
|
||||||
}
|
// }
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
m_tex[i].unbind();
|
m_tex[i].unbind();
|
||||||
@@ -374,10 +420,15 @@ void ui::Canvas::stroke_draw()
|
|||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
stencil.unbind();
|
||||||
|
glActiveTexture(GL_TEXTURE3);
|
||||||
|
m_mixer.unbindTexture();
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
m_sampler_brush.unbind();
|
m_sampler_brush.unbind();
|
||||||
m_sampler_bg.unbind();
|
m_sampler_bg.unbind();
|
||||||
m_sampler_mask.unbind();
|
m_sampler_stencil.unbind();
|
||||||
tex.unbind();
|
tex.unbind();
|
||||||
|
|
||||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||||
@@ -803,6 +854,7 @@ bool ui::Canvas::create(int width, int height)
|
|||||||
m_sampler_bg.create(GL_NEAREST);
|
m_sampler_bg.create(GL_NEAREST);
|
||||||
m_sampler_mask.create(GL_LINEAR);
|
m_sampler_mask.create(GL_LINEAR);
|
||||||
m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);
|
m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);
|
||||||
|
m_sampler_mix.create(GL_LINEAR, GL_REPEAT);
|
||||||
m_plane.create<1>(1, 1);
|
m_plane.create<1>(1, 1);
|
||||||
m_plane_brush.create<1>(1, 1);
|
m_plane_brush.create<1>(1, 1);
|
||||||
m_mesh.create();
|
m_mesh.create();
|
||||||
|
|||||||
@@ -54,11 +54,13 @@ public:
|
|||||||
bool m_dirty_stroke = false;
|
bool m_dirty_stroke = false;
|
||||||
|
|
||||||
static Canvas* I;
|
static Canvas* I;
|
||||||
|
NodeCanvas* m_node = nullptr;
|
||||||
bool m_alpha_lock = false;
|
bool m_alpha_lock = false;
|
||||||
bool m_touch_lock = true;
|
bool m_touch_lock = true;
|
||||||
glm::mat4 m_mv{ 1 };
|
glm::mat4 m_mv{ 1 };
|
||||||
glm::mat4 m_proj{ 1 };
|
glm::mat4 m_proj{ 1 };
|
||||||
glm::vec4 m_box{ 0 };
|
glm::vec4 m_box{ 0 };
|
||||||
|
glm::vec4 m_vp{ 0 };
|
||||||
glm::vec2 m_pan{ 0 };
|
glm::vec2 m_pan{ 0 };
|
||||||
int m_width = 0;
|
int m_width = 0;
|
||||||
int m_height = 0;
|
int m_height = 0;
|
||||||
@@ -73,6 +75,7 @@ public:
|
|||||||
Layer m_smask; // selection mask
|
Layer m_smask; // selection mask
|
||||||
bool m_smask_active = false;
|
bool m_smask_active = false;
|
||||||
RTT m_tmp[6];
|
RTT m_tmp[6];
|
||||||
|
RTT m_mixer;
|
||||||
Texture2D m_brush_mix;
|
Texture2D m_brush_mix;
|
||||||
Texture2D m_tex[6];
|
Texture2D m_tex[6];
|
||||||
Texture2D m_tex2[6];
|
Texture2D m_tex2[6];
|
||||||
@@ -88,6 +91,7 @@ public:
|
|||||||
Sampler m_sampler_bg;
|
Sampler m_sampler_bg;
|
||||||
Sampler m_sampler_mask;
|
Sampler m_sampler_mask;
|
||||||
Sampler m_sampler_stencil;
|
Sampler m_sampler_stencil;
|
||||||
|
Sampler m_sampler_mix;
|
||||||
glm::vec2 m_cam_rot{ 0 };
|
glm::vec2 m_cam_rot{ 0 };
|
||||||
glm::vec3 m_cam_pos{ 0 };
|
glm::vec3 m_cam_pos{ 0 };
|
||||||
float m_cam_fov = 85;
|
float m_cam_fov = 85;
|
||||||
@@ -124,6 +128,7 @@ public:
|
|||||||
void layer_merge(int source_idx, int dest_idx);
|
void layer_merge(int source_idx, int dest_idx);
|
||||||
void stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush);
|
void stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush);
|
||||||
void stroke_update(glm::vec2 point, float pressure);
|
void stroke_update(glm::vec2 point, float pressure);
|
||||||
|
void stroke_draw_mix();
|
||||||
void stroke_draw();
|
void stroke_draw();
|
||||||
void stroke_end();
|
void stroke_end();
|
||||||
void stroke_cancel();
|
void stroke_cancel();
|
||||||
@@ -152,7 +157,6 @@ public:
|
|||||||
void inject_xmp(std::string jpg_path);
|
void inject_xmp(std::string jpg_path);
|
||||||
ui::Image thumbnail_generate(int w, int h);
|
ui::Image thumbnail_generate(int w, int h);
|
||||||
ui::Image thumbnail_read(std::string data_path);
|
ui::Image thumbnail_read(std::string data_path);
|
||||||
void preview_generate();
|
|
||||||
void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>);
|
void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>);
|
||||||
void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>, Layer& layer);
|
void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>, Layer& layer);
|
||||||
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "node_canvas.h"
|
#include "node_canvas.h"
|
||||||
|
#include "node_image_texture.h"
|
||||||
|
|
||||||
Node* NodeCanvas::clone_instantiate() const
|
Node* NodeCanvas::clone_instantiate() const
|
||||||
{
|
{
|
||||||
@@ -14,6 +15,7 @@ void NodeCanvas::init()
|
|||||||
m_canvas = std::make_unique<ui::Canvas>();
|
m_canvas = std::make_unique<ui::Canvas>();
|
||||||
m_canvas->create(CANVAS_RES, CANVAS_RES);
|
m_canvas->create(CANVAS_RES, CANVAS_RES);
|
||||||
m_canvas->m_unsaved = false;
|
m_canvas->m_unsaved = false;
|
||||||
|
m_canvas->m_node = this;
|
||||||
m_sampler.create(GL_NEAREST);
|
m_sampler.create(GL_NEAREST);
|
||||||
m_sampler_linear.create(GL_LINEAR);
|
m_sampler_linear.create(GL_LINEAR);
|
||||||
m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);
|
m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);
|
||||||
@@ -73,6 +75,7 @@ void NodeCanvas::draw()
|
|||||||
m_canvas->m_mv = camera;
|
m_canvas->m_mv = camera;
|
||||||
m_canvas->m_proj = proj;
|
m_canvas->m_proj = proj;
|
||||||
m_canvas->m_box = box;
|
m_canvas->m_box = box;
|
||||||
|
m_canvas->m_vp = c;
|
||||||
|
|
||||||
// auto plane_mvp = proj * camera * transform *
|
// auto plane_mvp = proj * camera * transform *
|
||||||
// glm::scale(glm::vec3(sz, 1));
|
// glm::scale(glm::vec3(sz, 1));
|
||||||
@@ -267,6 +270,9 @@ void NodeCanvas::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
|
|||||||
{
|
{
|
||||||
if (new_size.x > m_canvas->m_width)
|
if (new_size.x > m_canvas->m_width)
|
||||||
{
|
{
|
||||||
|
m_canvas->m_mixer.create((int)new_size.x, (int)new_size.y);
|
||||||
|
if (auto img = root()->find<NodeImageTexture>("tex-debug"))
|
||||||
|
img->tex.assign(m_canvas->m_mixer.getTextureID());
|
||||||
// m_canvas->resize((int)new_size.x, (int)new_size.y);
|
// m_canvas->resize((int)new_size.x, (int)new_size.y);
|
||||||
// m_canvas->clear();
|
// m_canvas->clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ void NodePanelStroke::init_controls()
|
|||||||
init_slider(m_tip_flow, "tip-flow", &ui::Brush::m_tip_flow);
|
init_slider(m_tip_flow, "tip-flow", &ui::Brush::m_tip_flow);
|
||||||
init_slider(m_tip_opacity, "tip-opacity", &ui::Brush::m_tip_opacity);
|
init_slider(m_tip_opacity, "tip-opacity", &ui::Brush::m_tip_opacity);
|
||||||
init_slider(m_tip_angle, "tip-angle", &ui::Brush::m_tip_angle);
|
init_slider(m_tip_angle, "tip-angle", &ui::Brush::m_tip_angle);
|
||||||
|
init_slider(m_tip_mix, "tip-mix", &ui::Brush::m_tip_mix);
|
||||||
init_slider(m_tip_stencil, "tip-stencil", &ui::Brush::m_tip_stencil);
|
init_slider(m_tip_stencil, "tip-stencil", &ui::Brush::m_tip_stencil);
|
||||||
init_slider(m_tip_wet, "tip-wet", &ui::Brush::m_tip_wet);
|
init_slider(m_tip_wet, "tip-wet", &ui::Brush::m_tip_wet);
|
||||||
init_slider(m_tip_noise, "tip-noise", &ui::Brush::m_tip_noise);
|
init_slider(m_tip_noise, "tip-noise", &ui::Brush::m_tip_noise);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public:
|
|||||||
NodeSliderH* m_tip_flow;
|
NodeSliderH* m_tip_flow;
|
||||||
NodeSliderH* m_tip_opacity;
|
NodeSliderH* m_tip_opacity;
|
||||||
NodeSliderH* m_tip_angle;
|
NodeSliderH* m_tip_angle;
|
||||||
|
NodeSliderH* m_tip_mix;
|
||||||
NodeSliderH* m_tip_stencil;
|
NodeSliderH* m_tip_stencil;
|
||||||
NodeSliderH* m_tip_wet;
|
NodeSliderH* m_tip_wet;
|
||||||
NodeSliderH* m_tip_noise;
|
NodeSliderH* m_tip_noise;
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ enum class kShaderUniform : uint16_t
|
|||||||
Tex = const_hash("tex"),
|
Tex = const_hash("tex"),
|
||||||
TexFG = const_hash("tex_fg"),
|
TexFG = const_hash("tex_fg"),
|
||||||
TexBG = const_hash("tex_bg"),
|
TexBG = const_hash("tex_bg"),
|
||||||
|
TexMix = const_hash("tex_mix"),
|
||||||
TexMask = const_hash("tex_mask"),
|
TexMask = const_hash("tex_mask"),
|
||||||
TexStroke = const_hash("tex_stroke"),
|
TexStroke = const_hash("tex_stroke"),
|
||||||
TexStencil= const_hash("tex_stencil"),
|
TexStencil = const_hash("tex_stencil"),
|
||||||
StencilOffset = const_hash("stencil_offset"),
|
StencilOffset = const_hash("stencil_offset"),
|
||||||
StencilAlpha = const_hash("stencil_alpha"),
|
StencilAlpha = const_hash("stencil_alpha"),
|
||||||
|
MixAlpha = const_hash("mix_alpha"),
|
||||||
Wet = const_hash("wet"),
|
Wet = const_hash("wet"),
|
||||||
Lock = const_hash("lock"),
|
Lock = const_hash("lock"),
|
||||||
Col = const_hash("col"),
|
Col = const_hash("col"),
|
||||||
|
|||||||
Reference in New Issue
Block a user