diff --git a/PanoPainter.vcxproj b/PanoPainter.vcxproj index 2f9c14a..2186c19 100644 --- a/PanoPainter.vcxproj +++ b/PanoPainter.vcxproj @@ -404,6 +404,37 @@ Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PanoPainter.vcxproj.filters b/PanoPainter.vcxproj.filters index 308fe48..eb3cb0a 100644 --- a/PanoPainter.vcxproj.filters +++ b/PanoPainter.vcxproj.filters @@ -52,6 +52,12 @@ {7b4f5b47-7a8b-4e4c-9e82-399bb5047ffc} + + {b55fb692-a845-4ef2-9b0e-5b2dd8bd125f} + + + {a2cacb13-2854-44ee-9511-6cb8ac587428} + @@ -543,4 +549,93 @@ extras + + + shaders + + + shaders\include + + + shaders\include + + + shaders\include + + + shaders\include + + + shaders\include + + + shaders\include + + + shaders\include + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + + shaders + + \ No newline at end of file diff --git a/data/layout.xml b/data/layout.xml index e8f59e5..c948d72 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -164,7 +164,7 @@ - + @@ -309,7 +309,7 @@ - + @@ -355,7 +355,7 @@ - + diff --git a/data/shaders/atlas.glsl b/data/shaders/atlas.glsl new file mode 100644 index 0000000..26951a5 --- /dev/null +++ b/data/shaders/atlas.glsl @@ -0,0 +1,21 @@ +[[vertex]] +uniform mat4 mvp; +uniform vec2 tof; +uniform vec2 tsz; +in vec2 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = tof + uvs * tsz; + gl_Position = mvp * vec4(pos, 0.0, 1.0); +}; + +[[fragment]] +uniform sampler2D tex; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + frag = texture(tex, uv); +}; diff --git a/data/shaders/bake-uv.glsl b/data/shaders/bake-uv.glsl new file mode 100644 index 0000000..e3d0593 --- /dev/null +++ b/data/shaders/bake-uv.glsl @@ -0,0 +1,27 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec3 nor; +in vec2 uvs; +out vec3 n; +out vec3 p; +void main() +{ + n = nor; + p = vec3(mvp * pos); + gl_Position = vec4(uvs * 2.0 - 1.0, 0.0, 1.0); +} + +[[fragment]] +uniform int mode; +in highp vec3 n; +in highp vec3 p; +out highp vec3 frag; +void main() +{ + switch(mode) + { + case 0: frag = normalize(n); break; + case 1: frag = p; break; + } +} diff --git a/data/shaders/checkerboard.glsl b/data/shaders/checkerboard.glsl new file mode 100644 index 0000000..9d5089f --- /dev/null +++ b/data/shaders/checkerboard.glsl @@ -0,0 +1,24 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +} + +[[fragment]] +uniform bool colorize; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + const mediump vec4 c1 = vec4(1.0, 1.0, 1.0, 1.0); + const mediump vec4 c2 = vec4(0.9, 0.9, 0.9, 1.0); + mediump vec2 c = floor(fract(uv * 10.0) * 2.0); + mediump float alpha = mix(c.x, 1.0 - c.x, c.y); + if (colorize) frag = mix(c1, c2, alpha) * vec4(fract(uv.x * 5.0), uv.y, 1.0, 1.0); + else frag = mix(c1, c2, alpha); +} diff --git a/data/shaders/color-hue.glsl b/data/shaders/color-hue.glsl new file mode 100644 index 0000000..8bce283 --- /dev/null +++ b/data/shaders/color-hue.glsl @@ -0,0 +1,22 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec3 uv; +void main() +{ + gl_Position = mvp * pos; + uv = vec3(uvs, pos.w); +}; + +[[fragment]] +#include "include/hsv.glsl" +uniform mediump vec4 col; +uniform bool dir; // 0:horizontal, 1:vertical +in mediump vec3 uv; +out mediump vec4 frag; +void main() +{ + frag = vec4(hsv2rgb(vec3(dir?uv.y:uv.x, 1.0, 1.0)), 1.0); +}; + diff --git a/data/shaders/color-quad.glsl b/data/shaders/color-quad.glsl new file mode 100644 index 0000000..2f4ea7d --- /dev/null +++ b/data/shaders/color-quad.glsl @@ -0,0 +1,20 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec3 uv; +void main() +{ + gl_Position = mvp * pos; + uv = vec3(uvs, pos.w); +}; + +[[fragment]] +#include "include/hsv.glsl" +uniform mediump vec4 col; // HSV +in mediump vec3 uv; +out mediump vec4 frag; +void main() +{ + frag = vec4(hsv2rgb(vec3(col.x, uv.x, 1.0 - uv.y)), 1.0); +}; diff --git a/data/shaders/color-tri.glsl b/data/shaders/color-tri.glsl new file mode 100644 index 0000000..febc8a8 --- /dev/null +++ b/data/shaders/color-tri.glsl @@ -0,0 +1,21 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec3 uv; +void main() +{ + gl_Position = mvp * pos; + uv = vec3(uvs, pos.w); +}; + +[[fragment]] +#include "include/hsv.glsl" +uniform mediump vec4 col; // in HSV +in mediump vec3 uv; +out mediump vec4 frag; +void main() +{ + mediump float sat = tan(atan(uv.y, uv.x)) * 0.5 + 0.5; + frag = vec4(hsv2rgb(vec3(col.r, sat, uv.x)), 1.0); +}; diff --git a/data/shaders/color.glsl b/data/shaders/color.glsl new file mode 100644 index 0000000..1934e6b --- /dev/null +++ b/data/shaders/color.glsl @@ -0,0 +1,16 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +void main() +{ + gl_Position = mvp * pos; + gl_PointSize = 5.0; +}; + +[[fragment]] +uniform mediump vec4 col; +out mediump vec4 frag; +void main() +{ + frag = col; +}; diff --git a/data/shaders/comp-draw.glsl b/data/shaders/comp-draw.glsl new file mode 100644 index 0000000..db9e5eb --- /dev/null +++ b/data/shaders/comp-draw.glsl @@ -0,0 +1,74 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +#include "include/blur.glsl" +#include "include/blend.glsl" +#include "include/blend-stroke.glsl" +#include "include/color.glsl" + +uniform sampler2D tex; +uniform sampler2D tex_stroke; +uniform sampler2D tex_mask; +uniform mediump float alpha; +uniform mediump float stroke_alpha; +uniform mediump int blend_mode; +uniform mediump vec2 resolution; +uniform bool lock; +uniform bool mask; + +uniform bool use_dual; +uniform sampler2D tex_dual; +uniform mediump float dual_alpha; +uniform mediump int dual_blend_mode; + +uniform bool use_pattern; +uniform sampler2D tex_pattern; +uniform mediump vec2 pattern_scale; +uniform mediump float pattern_bright; +uniform mediump float pattern_contr; +uniform mediump float pattern_depth; +uniform mediump vec2 pattern_offset; +uniform mediump bool pattern_invert; +uniform mediump int patt_blend_mode; + +in mediump vec2 uv; +out mediump vec4 frag; + +void main() +{ + mediump vec4 base = texture(tex, uv); + mediump vec4 stroke = texture(tex_stroke, uv); + if (use_pattern) + { + mediump vec2 rscale = resolution / vec2(512.0); + mediump float patt = texture(tex_pattern, uv * (0.5 / pattern_scale) * rscale + pattern_offset).r; + if (pattern_invert) + patt = 1.0 - patt; + //" patt = patt * pattern_alpha + (1.0 - pattern_alpha); + if (pattern_bright != 0.5) + patt = brightness1(patt, 1.0 - pattern_bright); + if (pattern_contr != 0.5) + patt = contrast1(patt, pattern_contr); + //" mediump float pa = (1.0 - patt) * pow(pattern_depth, 0.25) + (stroke.a * pattern_depth * 10.0); + mediump float pa = pow((1.0 - patt), max(1.0, (1.0 - pattern_depth) * 10.0)) * pow(pattern_depth, 0.25) + (stroke.a * pattern_depth * 5.0); + stroke.a = mix(pa * stroke.a, stroke.a, 0.0); + } + if (use_dual) + { + mediump vec4 dual = texture(tex_dual, uv); + stroke.a = blend_stroke(stroke.a, dual.a * dual_alpha, dual_blend_mode); + } + stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv).r : stroke.a * stroke_alpha; + if (!lock && base.a == 0.0) { frag = stroke * vec4(1.0, 1.0, 1.0, alpha); return; } + mediump vec4 blended = blend(base, stroke, blend_mode); + frag = vec4(blended.rgb, (lock ? base.a : blended.a) * alpha); +}; diff --git a/data/shaders/comp-erase.glsl b/data/shaders/comp-erase.glsl new file mode 100644 index 0000000..a0835dd --- /dev/null +++ b/data/shaders/comp-erase.glsl @@ -0,0 +1,29 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +#include "include/blur.glsl" +uniform sampler2D tex; +uniform sampler2D tex_stroke; +uniform sampler2D tex_mask; +uniform mediump float alpha; +uniform mediump float stroke_alpha; +uniform mediump vec2 resolution; +uniform bool mask; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + mediump vec4 base = texture(tex, uv); + mediump vec4 stroke = texture(tex_stroke, uv); + stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv).r : stroke.a * stroke_alpha; + frag = vec4(base.rgb, clamp((base.a - stroke.a) * alpha, 0.0, 1.0)); +}; diff --git a/data/shaders/equirect.glsl b/data/shaders/equirect.glsl new file mode 100644 index 0000000..994e24d --- /dev/null +++ b/data/shaders/equirect.glsl @@ -0,0 +1,29 @@ +[[vertex]] +#define PI 3.1415926535897932384626433832795 +#define TWO_PI 6.283185307179586476925286766559 +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = (vec2(1.0) - uvs + vec2(0.25,0.0)) * vec2(TWO_PI, PI); + gl_Position = mvp * vec4(pos.xyz, 1.0); +} + +[[fragment]] +uniform samplerCube tex; +in highp vec2 uv; +out mediump vec4 frag; +void main() +{ + highp float anglex = uv.x; + highp float angley = uv.y; + highp float sx = sin(anglex); + highp float cx = cos(anglex); + highp vec3 dir = vec3(0.0, 0.0, 0.0); + dir.x = sin(angley) * cx; + dir.y = cos(angley); + dir.z = sin(angley) * sx; + frag = texture(tex, dir); +} diff --git a/data/shaders/font.glsl b/data/shaders/font.glsl new file mode 100644 index 0000000..f95c801 --- /dev/null +++ b/data/shaders/font.glsl @@ -0,0 +1,22 @@ +[[vertex]] +uniform mat4 mvp; +in vec2 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos, 0.0, 1.0); +}; + +[[fragment]] +uniform mediump sampler2D tex; +uniform mediump vec4 col; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + mediump float a = texture(tex, uv).r; + frag = vec4(col.rgb, a); +}; + diff --git a/data/shaders/include/blend-stroke.glsl b/data/shaders/include/blend-stroke.glsl new file mode 100644 index 0000000..dd581f8 --- /dev/null +++ b/data/shaders/include/blend-stroke.glsl @@ -0,0 +1,9 @@ +mediump float blend_stroke(mediump float base, mediump float stroke, int mode) +{ + if (mode == 0) /* normal */ return (base + stroke) * 0.5; + else if (mode == 1) /* multiply */ return base * stroke; + else if (mode == 2) /* screen */ return 1.0-(1.0-base)*(1.0-stroke); + else if (mode == 3) /* color-dodge */ return base/(1.0-stroke); + else if (mode == 4) /* overlay */ return mix(2.0*base*stroke, 1.0-2.0*(1.0-base)*(1.0-stroke), floor(base*2.0)); + else return 1.0; +} diff --git a/data/shaders/include/blend.glsl b/data/shaders/include/blend.glsl new file mode 100644 index 0000000..09a4a6f --- /dev/null +++ b/data/shaders/include/blend.glsl @@ -0,0 +1,20 @@ +mediump vec3 blend_normal(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot) +{ return mix(base.rgb, stroke.rgb, stroke.a/alpha_tot); } +mediump vec3 blend_multiply(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot) +{ return mix(stroke.rgb, mix(base.rgb, base.rgb*stroke.rgb, stroke.a/alpha_tot), base.a/alpha_tot); } +mediump vec3 blend_screen(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot) +{ return mix(stroke.rgb, mix(base.rgb, 1.0-(1.0-base.rgb)*(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); } +mediump vec3 blend_colorDodge(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot) +{ return mix(stroke.rgb, mix(base.rgb, base.rgb/(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); } +mediump vec3 blend_overlay(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot) +{ return mix(stroke.rgb, mix(base.rgb, mix(2.0*base.rgb*stroke.rgb, 1.0-2.0*(1.0-base.rgb)*(1.0-stroke.rgb), floor(base.rgb*2.0)), stroke.a/alpha_tot), base.a/alpha_tot); } +mediump vec4 blend(mediump vec4 base, mediump vec4 stroke, int mode) { + mediump float contribution = (1.0 - base.a) * stroke.a; + mediump float alpha_tot = base.a + contribution; + if (mode == 0) return vec4(blend_normal(base, stroke, alpha_tot), alpha_tot); + else if (mode == 1) return vec4(blend_multiply(base, stroke, alpha_tot), alpha_tot); + else if (mode == 2) return vec4(blend_screen(base, stroke, alpha_tot), alpha_tot); + else if (mode == 3) return vec4(blend_colorDodge(base, stroke, alpha_tot), alpha_tot); + else if (mode == 4) return vec4(blend_overlay(base, stroke, alpha_tot), alpha_tot); + else return vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/data/shaders/include/blur.glsl b/data/shaders/include/blur.glsl new file mode 100644 index 0000000..c6f098d --- /dev/null +++ b/data/shaders/include/blur.glsl @@ -0,0 +1,13 @@ +mediump vec4 blur(sampler2D t, mediump vec2 uv) +{ + mediump vec4 sum = texture(t, uv); + sum += textureOffset(t, uv, ivec2(-1, -1)); + sum += textureOffset(t, uv, ivec2(-1, 0)); + sum += textureOffset(t, uv, ivec2(-1, 1)); + sum += textureOffset(t, uv, ivec2( 0, -1)); + sum += textureOffset(t, uv, ivec2( 0, 1)); + sum += textureOffset(t, uv, ivec2( 1, -1)); + sum += textureOffset(t, uv, ivec2( 1, 0)); + sum += textureOffset(t, uv, ivec2( 1, 1)); + return sum / vec4(9.0); +} diff --git a/data/shaders/include/color.glsl b/data/shaders/include/color.glsl new file mode 100644 index 0000000..1d91f10 --- /dev/null +++ b/data/shaders/include/color.glsl @@ -0,0 +1,20 @@ +mediump vec3 brightness3(mediump vec3 c, mediump float val) +{ + return clamp(c + vec3(val * 2.0 - 1.0), vec3(0), vec3(1)); +} +mediump vec3 contrast3(mediump vec3 c, mediump float val) +{ + val = val * 2.0 - 1.0; + mediump float factor = ((259.0 / 255.0) * (val + 1.0)) / (1.0 * ((259.0 / 255.0) - val)); + return clamp(factor * (c - 0.5) + 0.5, vec3(0), vec3(1)); +} +mediump float brightness1(mediump float c, mediump float val) +{ + return clamp(c + (val * 2.0 - 1.0), 0.0, 1.0); +} +mediump float contrast1(mediump float c, mediump float val) +{ + val = val * 2.0 - 1.0; + mediump float factor = ((259.0 / 255.0) * (val + 1.0)) / (1.0 * ((259.0 / 255.0) - val)); + return clamp(factor * (c - 0.5) + 0.5, 0.0, 1.0); +} diff --git a/data/shaders/include/ext-fb-fetch.glsl b/data/shaders/include/ext-fb-fetch.glsl new file mode 100644 index 0000000..72401de --- /dev/null +++ b/data/shaders/include/ext-fb-fetch.glsl @@ -0,0 +1,5 @@ +#if defined(GL_EXT_shader_framebuffer_fetch) + #extension GL_EXT_shader_framebuffer_fetch : enable +#elif defined(GL_ARM_shader_framebuffer_fetch) + #extension GL_ARM_shader_framebuffer_fetch : enable +#endif diff --git a/data/shaders/include/hsv.glsl b/data/shaders/include/hsv.glsl new file mode 100644 index 0000000..7100be9 --- /dev/null +++ b/data/shaders/include/hsv.glsl @@ -0,0 +1,15 @@ +mediump vec3 rgb2hsv(mediump vec3 c) +{ + mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + mediump vec4 p = mix(vec4(c.bg, k.wz), vec4(c.gb, k.xy), step(c.b, c.g)); + mediump vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + mediump float d = q.x - min(q.w, q.y); + mediump float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} +mediump vec3 hsv2rgb(mediump vec3 c) +{ + mediump vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + mediump vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} diff --git a/data/shaders/include/rand.glsl b/data/shaders/include/rand.glsl new file mode 100644 index 0000000..5f7caa8 --- /dev/null +++ b/data/shaders/include/rand.glsl @@ -0,0 +1,10 @@ +// http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ +highp float rand(mediump vec2 co) +{ + highp float a = 12.9898; + highp float b = 78.233; + highp float c = 43758.5453; + highp float dt= dot(co.xy, vec2(a,b)); + highp float sn= mod(dt, 3.14); + return fract(sin(sn) * c); +} diff --git a/data/shaders/lambert.glsl b/data/shaders/lambert.glsl new file mode 100644 index 0000000..26c2302 --- /dev/null +++ b/data/shaders/lambert.glsl @@ -0,0 +1,23 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec3 nor; +in vec2 uvs; +out vec3 n; +void main() +{ + n = nor; + gl_Position = mvp * pos; +} + +[[fragment]] +uniform mediump vec3 light_dir; +uniform mediump float ambient; +in mediump vec3 n; +out mediump vec4 frag; +void main() +{ + mediump float d = max(0.0, dot(normalize(n), light_dir)); + frag = vec4(vec3(d) + ambient, 1.0); + //frag = vec4(normalize(n) * 0.5 + 0.5, 1.0); +} diff --git a/data/shaders/lightmap.glsl b/data/shaders/lightmap.glsl new file mode 100644 index 0000000..f6be00f --- /dev/null +++ b/data/shaders/lightmap.glsl @@ -0,0 +1,27 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec3 nor; +in vec2 uvs; +out vec3 n; +out vec2 uv; +void main() +{ + n = nor; + uv = uvs; + gl_Position = mvp * pos; +} + +[[fragment]] +uniform mediump sampler2D tex; +uniform mediump vec3 light_dir; +uniform mediump float ambient; +in mediump vec3 n; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + mediump float d = max(0.0, dot(normalize(n), normalize(light_dir))); + mediump vec4 c = texture(tex, uv); + frag = vec4(c.rgb * d + ambient, 1.0); +} diff --git a/data/shaders/stroke-instanced.glsl b/data/shaders/stroke-instanced.glsl new file mode 100644 index 0000000..b3b1977 --- /dev/null +++ b/data/shaders/stroke-instanced.glsl @@ -0,0 +1,31 @@ +[[vertex]] +in vec4 pos; +in vec2 uvs; +in mat4 a_mvp; +in float a_flow; +out vec3 uv; +out float alpha; +void main() +{ + uv = vec3(uvs, pos.w); + alpha = a_flow; + gl_Position = a_mvp * vec4(pos.xyz, 1.0); +} + +[[fragment]] +uniform mediump sampler2D tex; +uniform mediump sampler2D tex_pattern; +uniform mediump vec4 col; +uniform mediump vec2 resolution; +uniform mediump vec2 pattern_offset; +uniform mediump float pattern_alpha; +in mediump float alpha; +in mediump vec3 uv; +out mediump vec4 frag; +void main() +{ + mediump vec2 uv2 = gl_FragCoord.st / resolution; + mediump float pattern = 1.0 - (texture(tex_pattern, (uv2+pattern_offset)).r * 0.9) * pattern_alpha; + mediump float a = (1.0 - texture(tex, uv.xy).r) * alpha * pattern; + frag = vec4(col.rgb, a); +} diff --git a/data/shaders/stroke-preview.glsl b/data/shaders/stroke-preview.glsl new file mode 100644 index 0000000..c118caf --- /dev/null +++ b/data/shaders/stroke-preview.glsl @@ -0,0 +1,31 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +uniform sampler2D tex; +uniform mediump vec4 col; +in mediump vec2 uv; +out mediump vec4 frag; +void main() { + mediump float stroke = 1.0 - texture(tex, uv).r; + int zero_count = 0; + if (textureOffset(tex, uv, ivec2(-1, -1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(-1, 0)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(-1, +1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2( 0, -1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2( 0, 0)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2( 0, +1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(+1, -1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(+1, 0)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(+1, +1)).r > 0.99) zero_count++; + mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0; + frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f)); +}; diff --git a/data/shaders/stroke.glsl b/data/shaders/stroke.glsl new file mode 100644 index 0000000..6fc8dd5 --- /dev/null +++ b/data/shaders/stroke.glsl @@ -0,0 +1,93 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +in vec2 uvs2; +out vec2 uv; +out vec2 uv_2; +out float q; +void main() +{ + uv = uvs; + uv_2 = uvs2; + q = pos.w; + gl_Position = mvp * vec4(pos.xy, 0.0, 1.0); +}; + +[[fragment]] +#include "include/ext-fb-fetch.glsl" +#include "include/rand.glsl" +#include "include/color.glsl" + +uniform mediump sampler2D tex; +uniform mediump sampler2D tex_bg; +uniform mediump sampler2D tex_mix; +uniform mediump vec4 col; +uniform mediump vec2 resolution; +uniform mediump float alpha; +uniform mediump float noise; +uniform mediump float mix_alpha; +uniform mediump float wet; + +uniform bool use_pattern; +uniform mediump sampler2D tex_pattern; +uniform mediump vec2 pattern_scale; +uniform mediump float pattern_bright; +uniform mediump float pattern_contr; +uniform mediump float pattern_depth; +uniform mediump vec2 pattern_offset; +uniform mediump bool pattern_invert; + +in mediump vec2 uv; +in mediump vec2 uv_2; +in mediump float q; +#if defined(GL_EXT_shader_framebuffer_fetch) + inout mediump vec4 frag; +#else + out mediump vec4 frag; +#endif + +void main() +{ + mediump vec2 uv2 = gl_FragCoord.st / resolution; + mediump float brush_alpha = ( 1.0 - texture(tex, uv/q).r ) * alpha; + mediump vec4 fg = vec4(col.rgb, brush_alpha); + if (use_pattern) + { + mediump vec2 rscale = resolution / vec2(512.0); + mediump float patt = texture(tex_pattern, uv2 * (0.5 / pattern_scale) * rscale + pattern_offset).r; + if (pattern_invert) + patt = 1.0 - patt; + patt = patt * pattern_depth + (1.0 - pattern_depth); + if (pattern_bright != 0.5) + patt = brightness1(patt, 1.0 - pattern_bright); + if (pattern_contr != 0.5) + patt = contrast1(patt, pattern_contr); + fg.a = mix(fg.a, fg.a * patt, pattern_depth); + } + +#if defined(GL_EXT_shader_framebuffer_fetch) + mediump vec4 bg = frag; +#elif defined(GL_ARM_shader_framebuffer_fetch) + mediump vec4 bg = gl_LastFragColorARM; +#else + mediump vec4 bg = texture(tex_bg, uv2); +#endif + + fg.a *= 1.0-rand(uv2+uv)*noise; + if (fg.a == 0.0) discard; + if (mix_alpha > 0.0) + { + mediump vec2 uv_mix = uv_2 / q; + if (uv_mix.x < 0.0 || uv_mix.x > 1.0 || uv_mix.y < 0.0 || uv_mix.y > 1.0) discard; + mediump vec4 mbg = texture(tex_mix, uv_mix); + fg.rgb = mix(fg.rgb, mbg.rgb, mix_alpha * mbg.a); + } + mediump float contribution = (1.0 - bg.a) * fg.a; + mediump float alpha_tot = bg.a + contribution; + mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot); + mediump vec4 frag_wet = vec4(rgb, max(bg.a, fg.a * 1.2)); + mediump vec4 frag_dry = vec4(rgb, alpha_tot); + frag = mix(frag_dry, frag_wet, wet); +}; + diff --git a/data/shaders/texture-alpha-sep.glsl b/data/shaders/texture-alpha-sep.glsl new file mode 100644 index 0000000..c43638f --- /dev/null +++ b/data/shaders/texture-alpha-sep.glsl @@ -0,0 +1,28 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +uniform sampler2D tex; +uniform sampler2D tex_alpha; +uniform sampler2D tex_bg; +uniform mediump float alpha; +uniform bool highlight; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + mediump vec3 rgb = texture(tex, uv).rgb; + mediump float a = texture(tex_alpha, uv).a; + mediump vec4 c = vec4(rgb, a); + frag = highlight ? + vec4(clamp(vec3(0.3) + c.rgb, vec3(0.0), vec3(1.0)), c.a) : + texture(tex, uv) * vec4(1.0, 1.0, 1.0, alpha); +}; diff --git a/data/shaders/texture-alpha.glsl b/data/shaders/texture-alpha.glsl new file mode 100644 index 0000000..938c182 --- /dev/null +++ b/data/shaders/texture-alpha.glsl @@ -0,0 +1,24 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +uniform sampler2D tex; +uniform mediump float alpha; +uniform bool highlight; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + mediump vec4 c = texture(tex, uv); + frag = highlight ? + vec4(clamp(vec3(0.3) + c.rgb, vec3(0.0), vec3(1.0)), c.a) : + c * vec4(1.0, 1.0, 1.0, alpha); +}; diff --git a/data/shaders/texture-blend.glsl b/data/shaders/texture-blend.glsl new file mode 100644 index 0000000..df3fe63 --- /dev/null +++ b/data/shaders/texture-blend.glsl @@ -0,0 +1,38 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +#include "include/ext-fb-fetch.glsl" +#include "include/blend.glsl" +uniform sampler2D tex; +uniform sampler2D tex_alpha; +uniform sampler2D tex_bg; +uniform mediump float alpha; +uniform int blend_mode; +in mediump vec2 uv; +#if defined(GL_EXT_shader_framebuffer_fetch) + inout highp vec4 frag; +#else + out mediump vec4 frag; +#endif +void main() { +#if defined(GL_EXT_shader_framebuffer_fetch) + highp vec4 bg = frag; +#elif defined(GL_ARM_shader_framebuffer_fetch) + highp vec4 bg = gl_LastFragColorARM; +#else + mediump vec4 bg = texture(tex_bg, uv); +#endif + mediump vec4 fg = vec4(texture(tex, uv).rgb, texture(tex_alpha, uv).a); + if (fg.a == 0.0) { frag = bg; return; } + mediump vec4 blended = blend(bg, fg, blend_mode); + frag = vec4(blended.rgb, blended.a * alpha); +}; diff --git a/data/shaders/texture.glsl b/data/shaders/texture.glsl new file mode 100644 index 0000000..c1360ae --- /dev/null +++ b/data/shaders/texture.glsl @@ -0,0 +1,19 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +uniform sampler2D tex; +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + frag = texture(tex, uv); +}; diff --git a/data/shaders/uvs.glsl b/data/shaders/uvs.glsl new file mode 100644 index 0000000..7e4eebe --- /dev/null +++ b/data/shaders/uvs.glsl @@ -0,0 +1,18 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec2 uvs; +out vec2 uv; +void main() +{ + uv = uvs; + gl_Position = mvp * vec4(pos.xyz, 1.0); +}; + +[[fragment]] +in mediump vec2 uv; +out mediump vec4 frag; +void main() +{ + frag = vec4(uv, 0.0, 1.0); +}; diff --git a/data/shaders/vertex-color.glsl b/data/shaders/vertex-color.glsl new file mode 100644 index 0000000..b166c30 --- /dev/null +++ b/data/shaders/vertex-color.glsl @@ -0,0 +1,19 @@ +[[vertex]] +uniform mat4 mvp; +in vec4 pos; +in vec4 col; +out vec4 c; +void main() +{ + c = col; + gl_Position = mvp * pos; + gl_PointSize = 5.0; +}; + +[[fragment]] +in mediump vec4 c; +out mediump vec4 frag; +void main() +{ + frag = c; +}; diff --git a/src/abr.cpp b/src/abr.cpp index 004911f..b6285bf 100644 --- a/src/abr.cpp +++ b/src/abr.cpp @@ -149,7 +149,7 @@ std::vector> ABR::compute_brushes(const std::string& path auto patt_uid = wstr2str(patt->value("Idnt")); b->m_pattern_path = path + "/patterns/" + patt_uid + ".png"; //b->m_brush_thumb_path = path + "/patterns/thumbs/" + patt_uid + ".png"; - b->m_pattern_opacity = p->value("textureDepth") * 0.01f; + b->m_pattern_depth = p->value("textureDepth") * 0.01f; } ret.push_back(b); } diff --git a/src/app_shaders.cpp b/src/app_shaders.cpp index 20482b0..67d6a8a 100644 --- a/src/app_shaders.cpp +++ b/src/app_shaders.cpp @@ -2,673 +2,8 @@ #include "app.h" #include "shader.h" -#define SHADER_FUNCTION_BLUR \ - "mediump vec4 blur(sampler2D t, mediump vec2 uv){\n"\ - " mediump vec4 sum = texture(t, uv);\n"\ - " sum += textureOffset(t, uv, ivec2(-1, -1));\n"\ - " sum += textureOffset(t, uv, ivec2(-1, 0));\n"\ - " sum += textureOffset(t, uv, ivec2(-1, 1));\n"\ - " sum += textureOffset(t, uv, ivec2( 0, -1));\n"\ - " sum += textureOffset(t, uv, ivec2( 0, 1));\n"\ - " sum += textureOffset(t, uv, ivec2( 1, -1));\n"\ - " sum += textureOffset(t, uv, ivec2( 1, 0));\n"\ - " sum += textureOffset(t, uv, ivec2( 1, 1));\n"\ - " return sum / vec4(9.0);\n"\ - "}\n" - -#define SHADER_FUNCTION_BLEND \ - "mediump vec3 blend_normal(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot)"\ - "{ return mix(base.rgb, stroke.rgb, stroke.a/alpha_tot); }\n"\ - "mediump vec3 blend_multiply(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot)"\ - "{ return mix(stroke.rgb, mix(base.rgb, base.rgb*stroke.rgb, stroke.a/alpha_tot), base.a/alpha_tot); }\n"\ - "mediump vec3 blend_screen(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot)"\ - "{ return mix(stroke.rgb, mix(base.rgb, 1.0-(1.0-base.rgb)*(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); }\n"\ - "mediump vec3 blend_colorDodge(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot)"\ - "{ return mix(stroke.rgb, mix(base.rgb, base.rgb/(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); }\n"\ - "mediump vec3 blend_overlay(mediump vec4 base, mediump vec4 stroke, mediump float alpha_tot)"\ - "{ return mix(stroke.rgb, mix(base.rgb, mix(2.0*base.rgb*stroke.rgb, 1.0-2.0*(1.0-base.rgb)*(1.0-stroke.rgb), floor(base.rgb*2.0)), stroke.a/alpha_tot), base.a/alpha_tot); }\n"\ - "mediump vec4 blend(mediump vec4 base, mediump vec4 stroke, int mode) {\n"\ - " mediump float contribution = (1.0 - base.a) * stroke.a;\n"\ - " mediump float alpha_tot = base.a + contribution;\n"\ - " if (mode == 0) return vec4(blend_normal(base, stroke, alpha_tot), alpha_tot);\n"\ - " else if (mode == 1) return vec4(blend_multiply(base, stroke, alpha_tot), alpha_tot);\n"\ - " else if (mode == 2) return vec4(blend_screen(base, stroke, alpha_tot), alpha_tot);\n"\ - " else if (mode == 3) return vec4(blend_colorDodge(base, stroke, alpha_tot), alpha_tot);\n"\ - " else if (mode == 4) return vec4(blend_overlay(base, stroke, alpha_tot), alpha_tot);\n"\ - " else return vec4(1.0, 0.0, 0.0, 1.0);\n"\ - "}\n" - -#define SHADER_FUNCTION_BLEND_STROKE \ - "mediump float blend_stroke(mediump float base, mediump float stroke, int mode) {\n"\ - " if (mode == 0) return (base + stroke) * 0.5;\n"\ - " else if (mode == 1) return base * stroke;\n"\ - " else if (mode == 2) return 1.0-(1.0-base)*(1.0-stroke);\n"\ - " else if (mode == 3) return base/(1.0-stroke);\n"\ - " else if (mode == 4) return mix(2.0*base*stroke, 1.0-2.0*(1.0-base)*(1.0-stroke), floor(base*2.0));\n"\ - " else return 1.0;\n"\ - "}\n" - -#define SHADER_FUNCTION_HSV \ - "mediump vec3 rgb2hsv(mediump vec3 c) {\n"\ - " mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"\ - " mediump vec4 p = mix(vec4(c.bg, k.wz), vec4(c.gb, k.xy), step(c.b, c.g));\n"\ - " mediump vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"\ - " mediump float d = q.x - min(q.w, q.y);\n"\ - " mediump float e = 1.0e-10;\n"\ - " return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"\ - "}\n"\ - "mediump vec3 hsv2rgb(mediump vec3 c) {\n"\ - " mediump vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"\ - " mediump vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"\ - " return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"\ - "}\n" - -#define SHADER_FUNCTION_COLOR \ - "mediump vec3 brightness3(mediump vec3 c, mediump float val) {\n"\ - " return clamp(c + vec3(val * 2.0 - 1.0), vec3(0), vec3(1));\n"\ - "}\n"\ - "mediump vec3 contrast3(mediump vec3 c, mediump float val) {\n"\ - " val = val * 2.0 - 1.0;\n"\ - " mediump float factor = ((259.0 / 255.0) * (val + 1.0)) / (1.0 * ((259.0 / 255.0) - val));\n"\ - " return clamp(factor * (c - 0.5) + 0.5, vec3(0), vec3(1));\n"\ - "}\n"\ - "mediump float brightness1(mediump float c, mediump float val) {\n"\ - " return clamp(c + (val * 2.0 - 1.0), 0.0, 1.0);\n"\ - "}\n"\ - "mediump float contrast1(mediump float c, mediump float val) {\n"\ - " val = val * 2.0 - 1.0;\n"\ - " mediump float factor = ((259.0 / 255.0) * (val + 1.0)) / (1.0 * ((259.0 / 255.0) - val));\n"\ - " return clamp(factor * (c - 0.5) + 0.5, 0.0, 1.0);\n"\ - "}\n" - -// http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ -#define SHADER_FUNCTION_RAND \ - "highp float rand(mediump vec2 co)\n"\ - "{\n"\ - " highp float a = 12.9898;\n"\ - " highp float b = 78.233;\n"\ - " highp float c = 43758.5453;\n"\ - " highp float dt= dot(co.xy, vec2(a,b));\n"\ - " highp float sn= mod(dt, 3.14);\n"\ - " return fract(sin(sn) * c);\n"\ - "}\n" - -#define SHADER_EXT_FB_FETCH \ - "#if defined(GL_EXT_shader_framebuffer_fetch)\n"\ - " #extension GL_EXT_shader_framebuffer_fetch : enable\n"\ - "#elif defined(GL_ARM_shader_framebuffer_fetch)\n"\ - " #extension GL_ARM_shader_framebuffer_fetch : enable\n"\ - "#endif\n" - void App::initShaders() { - static const char* shader_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec2 uvs;\n" - "out vec2 uv;\n" - "void main() {\n" - " uv = uvs;\n" - " gl_Position = mvp * vec4(pos.xyz, 1.0);\n" - "}\n"; - static const char* shader_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " frag = texture(tex, uv);\n" - "}\n"; - static const char* shader_blend_f = - SHADER_VERSION - SHADER_EXT_FB_FETCH - "uniform sampler2D tex;\n" - "uniform sampler2D tex_alpha;\n" - "uniform sampler2D tex_bg;\n" - "uniform mediump float alpha;\n" - "uniform int blend_mode;\n" - "in mediump vec2 uv;\n" - "#if defined(GL_EXT_shader_framebuffer_fetch)\n" - " inout highp vec4 frag;\n" - "#else\n" - " out mediump vec4 frag;\n" - "#endif\n" - SHADER_FUNCTION_BLEND - "void main() {\n" - "#if defined(GL_EXT_shader_framebuffer_fetch)\n" - " highp vec4 bg = frag;\n" - "#elif defined(GL_ARM_shader_framebuffer_fetch)\n" - " highp vec4 bg = gl_LastFragColorARM;\n" - "#else\n" - " mediump vec4 bg = texture(tex_bg, uv);\n" - "#endif\n" - " mediump vec4 fg = vec4(texture(tex, uv).rgb, texture(tex_alpha, uv).a);\n" - " if (fg.a == 0.0) { frag = bg; return; }\n" - " mediump vec4 blended = blend(bg, fg, blend_mode);\n" - " frag = vec4(blended.rgb, blended.a * alpha);\n" - "}\n"; - static const char* shader_uv_f = - SHADER_VERSION - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " frag = vec4(uv, 0.0, 1.0);\n" - "}\n"; - // TEXTURE ALPHA - static const char* shader_alpha_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "uniform mediump float alpha;\n" - "uniform bool highlight;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump vec4 c = texture(tex, uv);\n" - " frag = highlight ? \n" - " vec4(clamp(vec3(0.3) + c.rgb, vec3(0.0), vec3(1.0)), c.a) : \n" - " c * vec4(1.0, 1.0, 1.0, alpha);\n" - "}\n"; - // TEXTURE ALPHA SEPARATED - static const char* shader_alpha_sep_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "uniform sampler2D tex_alpha;\n" - "uniform sampler2D tex_bg;\n" - "uniform mediump float alpha;\n" - "uniform bool highlight;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump vec3 rgb = texture(tex, uv).rgb;\n" - " mediump float a = texture(tex_alpha, uv).a;\n" - " mediump vec4 c = vec4(rgb, a);\n" - " frag = highlight ? \n" - " vec4(clamp(vec3(0.3) + c.rgb, vec3(0.0), vec3(1.0)), c.a) : \n" - " texture(tex, uv) * vec4(1.0, 1.0, 1.0, alpha);\n" - "}\n"; - // STROKE PREVIEW - static const char* shader_stroke_preview_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "uniform mediump vec4 col;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump float stroke = 1.0 - texture(tex, uv).r;\n" - " int zero_count = 0;\n" - " if (textureOffset(tex, uv, ivec2(-1, -1)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2(-1, 0)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2(-1, +1)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2( 0, -1)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2( 0, 0)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2( 0, +1)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2(+1, -1)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2(+1, 0)).r > 0.99) zero_count++;\n" - " if (textureOffset(tex, uv, ivec2(+1, +1)).r > 0.99) zero_count++;\n" - " mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0;\n" - " frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f));\n" - "}\n"; - // TEXTURE COMP ERASE - static const char* shader_comp_erase_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "uniform sampler2D tex_stroke;\n" - "uniform sampler2D tex_mask;\n" - "uniform mediump float alpha;\n" - "uniform mediump float stroke_alpha;\n" - "uniform mediump vec2 resolution;\n" - "uniform bool mask;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - SHADER_FUNCTION_BLUR - "void main() {\n" - " mediump vec4 base = texture(tex, uv);\n" - " mediump vec4 stroke = texture(tex_stroke, uv);\n" - " stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv).r : stroke.a * stroke_alpha;\n" - " frag = vec4(base.rgb, clamp((base.a - stroke.a) * alpha, 0.0, 1.0));\n" - "}\n"; - // TEXTURE COMP DRAW - static const char* shader_comp_draw_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "uniform sampler2D tex_stroke;\n" - "uniform sampler2D tex_mask;\n" - "uniform mediump float alpha;\n" - "uniform mediump float stroke_alpha;\n" - "uniform mediump int blend_mode;\n" - "uniform mediump vec2 resolution;\n" - "uniform bool lock;\n" - "uniform bool mask;\n" - - "uniform bool use_dual;\n" - "uniform sampler2D tex_dual;\n" - "uniform mediump float dual_alpha;\n" - "uniform mediump int dual_blend_mode;\n" - - "uniform bool use_pattern;\n" - "uniform sampler2D tex_pattern;\n" - "uniform mediump float pattern_alpha;\n" - "uniform mediump vec2 pattern_scale;\n" - "uniform mediump float pattern_bright;\n" - "uniform mediump float pattern_contr;\n" - "uniform mediump vec2 pattern_offset;\n" - "uniform mediump bool pattern_invert;\n" - - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - SHADER_FUNCTION_BLUR - SHADER_FUNCTION_BLEND - SHADER_FUNCTION_BLEND_STROKE - SHADER_FUNCTION_COLOR - "void main() {\n" - " mediump vec4 base = texture(tex, uv);\n" - " mediump vec4 stroke = texture(tex_stroke, uv);\n" - " if (use_pattern){\n" - " mediump vec2 rscale = resolution / vec2(512.0);\n" - " mediump float patt = texture(tex_pattern, uv * (0.5 / pattern_scale) * rscale + pattern_offset).r;\n" - " if (pattern_invert)\n" - " patt = 1.0 - patt;\n" - " if (pattern_bright != 0.5)\n" - " patt = brightness1(patt, 1.0 - pattern_bright);\n" - " if (pattern_contr != 0.5)\n" - " patt = contrast1(patt, pattern_contr);\n" - " stroke.a = mix(stroke.a, stroke.a * patt, pattern_alpha);\n" - " }\n" - " if (use_dual){\n" - " mediump vec4 dual = texture(tex_dual, uv);\n" - " stroke.a = blend_stroke(stroke.a, dual.a * dual_alpha, dual_blend_mode);\n" - " }\n" - " stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv).r : stroke.a * stroke_alpha;\n" - " if (!lock && base.a == 0.0) { frag = stroke * vec4(1.0, 1.0, 1.0, alpha); return; }\n" - " mediump vec4 blended = blend(base, stroke, blend_mode);\n" - " frag = vec4(blended.rgb, (lock ? base.a : blended.a) * alpha);\n" - "}\n"; - - // TEXTURE ATLAS - static const char* shader_atlas_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "uniform vec2 tof;\n" - "uniform vec2 tsz;\n" - "in vec2 pos;\n" - "in vec2 uvs;\n" - "out vec2 uv;\n" - "void main() {\n" - " uv = tof + uvs * tsz;\n" - " gl_Position = mvp * vec4(pos, 0.0, 1.0);\n" - "}\n"; - static const char* shader_atlas_f = - SHADER_VERSION - "uniform sampler2D tex;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " frag = texture(tex, uv);\n" - "}\n"; - - // SOLID COLOR - static const char* shader_color_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "void main() {\n" - " gl_Position = mvp * pos;\n" - " gl_PointSize = 5.0;\n" - "}\n"; - static const char* shader_color_f = - SHADER_VERSION - "uniform mediump vec4 col;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " frag = col;\n" - "}\n"; - - // COLOR QUAD - static const char* shader_color_quad_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec2 uvs;\n" - "out vec3 uv;\n" - "void main() {\n" - " gl_Position = mvp * pos;\n" - " uv = vec3(uvs, pos.w);\n" - "}\n"; - static const char* shader_color_quad_f = - SHADER_VERSION - "uniform mediump vec4 col; // HSV\n" - "in mediump vec3 uv;\n" - "out mediump vec4 frag;\n" - SHADER_FUNCTION_HSV - "void main() {\n" - " frag = vec4(hsv2rgb(vec3(col.x, uv.x, 1.0 - uv.y)), 1.0);\n" - "}\n"; - // COLOR TRI - static const char* shader_color_tri_f = - SHADER_VERSION - "uniform mediump vec4 col;\n" // in HSV - "in mediump vec3 uv;\n" - "out mediump vec4 frag;\n" - SHADER_FUNCTION_HSV - "void main() {\n" - " mediump float sat = tan(atan(uv.y, uv.x)) * 0.5 + 0.5;\n" - " frag = vec4(hsv2rgb(vec3(col.r, sat, uv.x)), 1.0);\n" - "}\n"; - - // HUE - static const char* shader_color_hue_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec2 uvs;\n" - "out vec3 uv;\n" - "void main() {\n" - " gl_Position = mvp * pos;\n" - " uv = vec3(uvs, pos.w);\n" - "}\n"; - static const char* shader_color_hue_f = - SHADER_VERSION - "uniform mediump vec4 col;\n" - "uniform bool dir;\n" // 0:horizontal, 1:vertical - "in mediump vec3 uv;\n" - "out mediump vec4 frag;\n" - SHADER_FUNCTION_HSV - "void main() {\n" - " frag = vec4(hsv2rgb(vec3(dir?uv.y:uv.x, 1.0, 1.0)), 1.0);\n" - "}\n"; - - // FONT - static const char* shader_font_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec2 pos;\n" - "in vec2 uvs;\n" - "out vec2 uv;\n" - "void main() {\n" - " uv = uvs;\n" - " gl_Position = mvp * vec4(pos, 0.0, 1.0);\n" - "}\n"; - static const char* shader_font_f = - SHADER_VERSION - "uniform mediump sampler2D tex;\n" - "uniform mediump vec4 col;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump float a = texture(tex, uv).r;\n" - " frag = vec4(col.rgb, a);\n" - "}\n"; - - // STROKE - static const char* shader_stroke_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec2 uvs;\n" - "in vec2 uvs2;\n" - "out vec2 uv;\n" - "out vec2 uv_2;\n" - "out float q;\n" - "void main() {\n" - " uv = uvs;\n" - " uv_2 = uvs2;\n" - " q = pos.w;\n" - " gl_Position = mvp * vec4(pos.xy, 0.0, 1.0);\n" - "}\n"; - static const char* shader_stroke_f = - SHADER_VERSION - SHADER_EXT_FB_FETCH - "uniform mediump sampler2D tex;\n" - "uniform mediump sampler2D tex_bg;\n" - "uniform mediump sampler2D tex_mix;\n" - "uniform mediump vec4 col;\n" - "uniform mediump vec2 resolution;\n" - "uniform mediump float alpha;\n" - "uniform mediump float noise;\n" - "uniform mediump float mix_alpha;\n" - "uniform mediump float wet;\n" - - "uniform bool use_pattern;\n" - "uniform mediump sampler2D tex_pattern;\n" - "uniform mediump float pattern_alpha;\n" - "uniform mediump vec2 pattern_scale;\n" - "uniform mediump float pattern_bright;\n" - "uniform mediump float pattern_contr;\n" - "uniform mediump vec2 pattern_offset;\n" - "uniform mediump bool pattern_invert;\n" - - "in mediump vec2 uv;\n" - "in mediump vec2 uv_2;\n" - "in mediump float q;\n" - "#if defined(GL_EXT_shader_framebuffer_fetch)\n" - " inout mediump vec4 frag;\n" - "#else\n" - " out mediump vec4 frag;\n" - "#endif\n" - SHADER_FUNCTION_RAND - SHADER_FUNCTION_COLOR - "void main() {\n" - " mediump vec2 uv2 = gl_FragCoord.st / resolution;\n" - " mediump float brush_alpha = ( 1.0 - texture(tex, uv/q).r ) * alpha;\n" - " mediump vec4 fg = vec4(col.rgb, brush_alpha);\n" - " if (use_pattern){\n" - " mediump vec2 rscale = resolution / vec2(512.0);\n" - " mediump float patt = texture(tex_pattern, uv2 * (0.5 / pattern_scale) * rscale + pattern_offset).r;\n" - " if (pattern_invert)\n" - " patt = 1.0 - patt;\n" - " if (pattern_bright != 0.5)\n" - " patt = brightness1(patt, 1.0 - pattern_bright);\n" - " if (pattern_contr != 0.5)\n" - " patt = contrast1(patt, pattern_contr);\n" - " fg.a = mix(fg.a, fg.a * patt, pattern_alpha);\n" - " }\n" - "#if defined(GL_EXT_shader_framebuffer_fetch)\n" - " mediump vec4 bg = frag;\n" - "#elif defined(GL_ARM_shader_framebuffer_fetch)\n" - " mediump vec4 bg = gl_LastFragColorARM;\n" - "#else\n" - " mediump vec4 bg = texture(tex_bg, uv2);\n" - "#endif\n" - " fg.a *= 1.0-rand(uv2+uv)*noise;\n" - " if (fg.a == 0.0) discard;\n" - " if (mix_alpha > 0.0){\n" - " mediump vec2 uv_mix = uv_2 / q;\n" - " if (uv_mix.x < 0.0 || uv_mix.x > 1.0 || uv_mix.y < 0.0 || uv_mix.y > 1.0) discard;\n" - " mediump vec4 mbg = texture(tex_mix, uv_mix);\n" - " fg.rgb = mix(fg.rgb, mbg.rgb, mix_alpha * mbg.a);\n" - " }\n" - " mediump float contribution = (1.0 - bg.a) * fg.a;\n" - " mediump float alpha_tot = bg.a + contribution;\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_dry = vec4(rgb, alpha_tot);\n" - " frag = mix(frag_dry, frag_wet, wet);\n" - "}\n"; - - static const char* shader_checkerboard_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec2 uvs;\n" - "out vec2 uv;\n" - "void main() {\n" - " uv = uvs;\n" - " gl_Position = mvp * vec4(pos.xyz, 1.0);\n" - "}\n"; - static const char* shader_checkerboard_f = - SHADER_VERSION - "uniform bool colorize;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " const mediump vec4 c1 = vec4(1.0, 1.0, 1.0, 1.0);\n" - " const mediump vec4 c2 = vec4(0.9, 0.9, 0.9, 1.0);\n" - " mediump vec2 c = floor(fract(uv * 10.0) * 2.0);\n" - " mediump float alpha = mix(c.x, 1.0 - c.x, c.y);\n" - " if (colorize) frag = mix(c1, c2, alpha) * vec4(fract(uv.x * 5.0), uv.y, 1.0, 1.0);\n" - " else frag = mix(c1, c2, alpha);\n" - "}\n"; - - static const char* shader_equirect_v = - SHADER_VERSION - "#define PI 3.1415926535897932384626433832795\n" - "#define TWO_PI 6.283185307179586476925286766559\n" - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec2 uvs;\n" - "out vec2 uv;\n" - "void main() {\n" - " uv = (vec2(1.0) - uvs + vec2(0.25,0.0)) * vec2(TWO_PI, PI);\n" - " gl_Position = mvp * vec4(pos.xyz, 1.0);\n" - "}\n"; - static const char* shader_equirect_f = - SHADER_VERSION - "uniform samplerCube tex;\n" - "in highp vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " highp float anglex = uv.x;\n" - " highp float angley = uv.y;\n" - " highp float sx = sin(anglex);\n" - " highp float cx = cos(anglex);\n" - " highp vec3 dir = vec3(0.0, 0.0, 0.0);\n" - " dir.x = sin(angley) * cx;\n" - " dir.y = cos(angley);\n" - " dir.z = sin(angley) * sx;\n" - " frag = texture(tex, dir);\n" - "}\n"; - - // STROKE - INSTANCED - static const char* shader_stroke_inst_v = - SHADER_VERSION - "in vec4 pos;\n" - "in vec2 uvs;\n" - "in mat4 a_mvp;\n" - "in float a_flow;\n" - "out vec3 uv;\n" - "out float alpha;\n" - "void main() {\n" - " uv = vec3(uvs, pos.w);\n" - " alpha = a_flow;\n" - " gl_Position = a_mvp * vec4(pos.xyz, 1.0);\n" - "}\n"; - static const char* shader_stroke_inst_f = - SHADER_VERSION - "uniform mediump sampler2D tex;\n" - "uniform mediump sampler2D tex_pattern;\n" - "uniform mediump vec4 col;\n" - "uniform mediump vec2 resolution;\n" - "uniform mediump vec2 pattern_offset;\n" - "uniform mediump float pattern_alpha;\n" - "in mediump float alpha;\n" - "in mediump vec3 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump vec2 uv2 = gl_FragCoord.st / resolution;\n" - " mediump float pattern = 1.0 - (texture(tex_pattern, (uv2+pattern_offset)).r * 0.9) * pattern_alpha;\n" - " mediump float a = (1.0 - texture(tex, uv.xy).r) * alpha * pattern;\n" - " frag = vec4(col.rgb, a);\n" - "}\n"; - - // VERTEX COLOR - static const char* shader_vertcol_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec4 col;\n" - "out vec4 c;\n" - "void main() {\n" - " c = col;\n" - " gl_Position = mvp * pos;\n" - " gl_PointSize = 5.0;\n" - "}\n"; - static const char* shader_vertcol_f = - SHADER_VERSION - "in mediump vec4 c;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " frag = c;\n" - "}\n"; - - // LAMBERT - static const char* shader_lambert_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec3 nor;\n" - "in vec2 uvs;\n" - "out vec3 n;\n" - "void main() {\n" - " n = nor;\n" - " gl_Position = mvp * pos;\n" - "}\n"; - static const char* shader_lambert_f = - SHADER_VERSION - "uniform mediump vec3 light_dir;\n" - "uniform mediump float ambient;\n" - "in mediump vec3 n;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump float d = max(0.0, dot(normalize(n), light_dir));\n" - " frag = vec4(vec3(d) + ambient, 1.0);\n" - //" frag = vec4(normalize(n) * 0.5 + 0.5, 1.0);\n" - "}\n"; - - // LAMBERT LIGHTMAP - static const char* shader_lambert_lightmap_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec3 nor;\n" - "in vec2 uvs;\n" - "out vec3 n;\n" - "out vec2 uv;\n" - "void main() {\n" - " n = nor;\n" - " uv = uvs;\n" - " gl_Position = mvp * pos;\n" - "}\n"; - static const char* shader_lambert_lightmap_f = - SHADER_VERSION - "uniform mediump sampler2D tex;\n" - "uniform mediump vec3 light_dir;\n" - "uniform mediump float ambient;\n" - "in mediump vec3 n;\n" - "in mediump vec2 uv;\n" - "out mediump vec4 frag;\n" - "void main() {\n" - " mediump float d = max(0.0, dot(normalize(n), normalize(light_dir)));\n" - " mediump vec4 c = texture(tex, uv);\n" - " frag = vec4(c.rgb * d + ambient, 1.0);\n" - "}\n"; - - // BAKE UVS - static const char* shader_bakeuv_v = - SHADER_VERSION - "uniform mat4 mvp;\n" - "in vec4 pos;\n" - "in vec3 nor;\n" - "in vec2 uvs;\n" - "out vec3 n;\n" - "out vec3 p;\n" - "void main() {\n" - " n = nor;\n" - " p = vec3(mvp * pos);\n" - " gl_Position = vec4(uvs * 2.0 - 1.0, 0.0, 1.0);\n" - "}\n"; - static const char* shader_bakeuv_f = - SHADER_VERSION - "uniform int mode;\n" - "in highp vec3 n;\n" - "in highp vec3 p;\n" - "out highp vec3 frag;\n" - "void main() {\n" - " switch(mode) {\n" - " case 0: frag = normalize(n); break;\n" - " case 1: frag = p; break;\n" - " }\n" - "}\n"; GLint n_exts; glGetIntegerv(GL_NUM_EXTENSIONS, &n_exts); @@ -684,49 +19,49 @@ void App::initShaders() LOG("Shader Extension shader_framebuffer_fetch: %s", ShaderManager::ext_framebuffer_fetch ? "enabled" : "disabled"); LOG("initializing shaders"); - if (!ShaderManager::create(kShader::Texture, shader_v, shader_f)) + if (!ShaderManager::load(kShader::Texture, "data/shaders/texture.glsl")) LOG("Failed to create shader Texture"); - if (!ShaderManager::create(kShader::TextureAlpha, shader_v, shader_alpha_f)) + if (!ShaderManager::load(kShader::TextureAlpha, "data/shaders/texture-alpha.glsl")) LOG("Failed to create shader TextureAlpha"); - if (!ShaderManager::create(kShader::TextureAlphaSep, shader_v, shader_alpha_sep_f)) + if (!ShaderManager::load(kShader::TextureAlphaSep, "data/shaders/texture-alpha-sep.glsl")) LOG("Failed to create shader TextureAlphaSep"); - if (!ShaderManager::create(kShader::TextureBlend, shader_v, shader_blend_f)) + if (!ShaderManager::load(kShader::TextureBlend, "data/shaders/texture-blend.glsl")) LOG("Failed to create shader TextureBlend"); - if (!ShaderManager::create(kShader::StrokePreview, shader_v, shader_stroke_preview_f)) + if (!ShaderManager::load(kShader::StrokePreview, "data/shaders/stroke-preview.glsl")) LOG("Failed to create shader StrokePreview"); - if (!ShaderManager::create(kShader::CompErase, shader_v, shader_comp_erase_f)) + if (!ShaderManager::load(kShader::CompErase, "data/shaders/comp-erase.glsl")) LOG("Failed to create shader CompErase"); - if (!ShaderManager::create(kShader::CompDraw, shader_v, shader_comp_draw_f)) + if (!ShaderManager::load(kShader::CompDraw, "data/shaders/comp-draw.glsl")) LOG("Failed to create shader CompDraw"); - if (!ShaderManager::create(kShader::Color, shader_color_v, shader_color_f)) + if (!ShaderManager::load(kShader::Color, "data/shaders/color.glsl")) LOG("Failed to create shader Color"); - if (!ShaderManager::create(kShader::ColorQuad, shader_color_quad_v, shader_color_quad_f)) + if (!ShaderManager::load(kShader::ColorQuad, "data/shaders/color-quad.glsl")) LOG("Failed to create shader ColorQuad"); - if (!ShaderManager::create(kShader::ColorTri, shader_color_quad_v, shader_color_tri_f)) + if (!ShaderManager::load(kShader::ColorTri, "data/shaders/color-tri.glsl")) LOG("Failed to create shader ColorTri"); - if (!ShaderManager::create(kShader::ColorHue, shader_color_hue_v, shader_color_hue_f)) + if (!ShaderManager::load(kShader::ColorHue, "data/shaders/color-hue.glsl")) LOG("Failed to create shader ColorHue"); - if (!ShaderManager::create(kShader::UVs, shader_v, shader_uv_f)) + if (!ShaderManager::load(kShader::UVs, "data/shaders/uvs.glsl")) LOG("Failed to create shader UVs"); - if (!ShaderManager::create(kShader::Font, shader_font_v, shader_font_f)) + if (!ShaderManager::load(kShader::Font, "data/shaders/font.glsl")) LOG("Failed to create shader Font"); - if (!ShaderManager::create(kShader::Atlas, shader_atlas_v, shader_atlas_f)) + if (!ShaderManager::load(kShader::Atlas, "data/shaders/atlas.glsl")) LOG("Failed to create shader Atlas"); - if (!ShaderManager::create(kShader::Stroke, shader_stroke_v, shader_stroke_f)) + if (!ShaderManager::load(kShader::Stroke, "data/shaders/stroke.glsl")) LOG("Failed to create shader Stroke"); - if (!ShaderManager::create(kShader::Checkerboard, shader_checkerboard_v, shader_checkerboard_f)) + if (!ShaderManager::load(kShader::Checkerboard, "data/shaders/checkerboard.glsl")) LOG("Failed to create shader Checkerboard"); - if (!ShaderManager::create(kShader::Equirect, shader_equirect_v, shader_equirect_f)) + if (!ShaderManager::load(kShader::Equirect, "data/shaders/equirect.glsl")) LOG("Failed to create shader Equirect"); - if (!ShaderManager::create(kShader::BrushStroke, shader_stroke_inst_v, shader_stroke_inst_f)) + if (!ShaderManager::load(kShader::BrushStroke, "data/shaders/stroke-instanced.glsl")) LOG("Failed to create shader BrushStroke"); - if (!ShaderManager::create(kShader::VertexColor, shader_vertcol_v, shader_vertcol_f)) + if (!ShaderManager::load(kShader::VertexColor, "data/shaders/vertex-color.glsl")) LOG("Failed to create shader VertexColor"); - if (!ShaderManager::create(kShader::Lambert, shader_lambert_v, shader_lambert_f)) + if (!ShaderManager::load(kShader::Lambert, "data/shaders/lambert.glsl")) LOG("Failed to create shader Lambert"); - if (!ShaderManager::create(kShader::LambertLightmap, shader_lambert_lightmap_v, shader_lambert_lightmap_f)) + if (!ShaderManager::load(kShader::LambertLightmap, "data/shaders/lightmap.glsl")) LOG("Failed to create shader LambertLightmap"); - if (!ShaderManager::create(kShader::BakeUV, shader_bakeuv_v, shader_bakeuv_f)) + if (!ShaderManager::load(kShader::BakeUV, "data/shaders/bake-uv.glsl")) LOG("Failed to create shader BakeUV"); LOG("shaders initialized"); } diff --git a/src/app_vr.cpp b/src/app_vr.cpp index 4ef6408..c8276b8 100644 --- a/src/app_vr.cpp +++ b/src/app_vr.cpp @@ -100,7 +100,6 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat ShaderManager::u_vec2(kShaderUniform::Resolution, canvas->m_canvas->m_size); ShaderManager::u_int(kShaderUniform::TexPattern, 3); ShaderManager::u_float(kShaderUniform::StrokeAlpha, b->m_tip_opacity); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_layers[layer_index].m_opacity); ShaderManager::u_int(kShaderUniform::Lock, canvas->m_canvas->m_layers[layer_index].m_alpha_locked); ShaderManager::u_int(kShaderUniform::Mask, canvas->m_canvas->m_smask_active); @@ -112,6 +111,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); + ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); ShaderManager::u_vec2(kShaderUniform::PatternOffset, Canvas::I->m_pattern_offset); glActiveTexture(GL_TEXTURE0); diff --git a/src/brush.h b/src/brush.h index 1fe1ef3..ec6e6d2 100644 --- a/src/brush.h +++ b/src/brush.h @@ -30,7 +30,6 @@ public: float m_tip_angle = 0; float m_tip_angle_delay = 0; float m_tip_mix = 0; - float m_pattern_opacity = 1.f; float m_tip_wet = 0; float m_tip_noise = 0; float m_tip_hue = 0; @@ -78,6 +77,7 @@ public: float m_pattern_brightness = 0.5f; float m_pattern_contrast = 0.5f; bool m_pattern_rand_offset = false; + float m_pattern_depth = 1.f; bool load_tip(const std::string& path, const std::string& thumb); bool load_dual(const std::string& path, const std::string& thumb); diff --git a/src/canvas.cpp b/src/canvas.cpp index 244ebdb..c389c32 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -249,7 +249,6 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz) ShaderManager::u_vec2(kShaderUniform::Resolution, m_size); ShaderManager::u_int(kShaderUniform::TexPattern, 3); ShaderManager::u_float(kShaderUniform::StrokeAlpha, b->m_tip_opacity); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_float(kShaderUniform::Alpha, 1); ShaderManager::u_int(kShaderUniform::Lock, false/*m_layers[layer_index].m_alpha_locked*/); ShaderManager::u_int(kShaderUniform::Mask, false/*m_smask_active*/); @@ -496,11 +495,11 @@ void Canvas::stroke_draw() ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer //ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height }); - ShaderManager::u_float(kShaderUniform::PatternAlpha, brush->m_pattern_opacity); ShaderManager::u_vec2(kShaderUniform::PatternScale, patt_scale); ShaderManager::u_float(kShaderUniform::PatternInvert, brush->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, brush->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, brush->m_pattern_contrast); + ShaderManager::u_float(kShaderUniform::PatternDepth, brush->m_pattern_depth); ShaderManager::u_vec2(kShaderUniform::PatternOffset, m_pattern_offset); ShaderManager::u_int(kShaderUniform::UsePattern, brush->m_pattern_enabled && brush->m_pattern_eachsample); ShaderManager::u_float(kShaderUniform::MixAlpha, brush->m_tip_mix); @@ -799,7 +798,6 @@ void Canvas::stroke_commit() ShaderManager::u_int(kShaderUniform::TexPattern, 4); ShaderManager::u_vec2(kShaderUniform::Resolution, m_size); ShaderManager::u_float(kShaderUniform::StrokeAlpha, b->m_tip_opacity); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_float(kShaderUniform::Alpha, 1); ShaderManager::u_int(kShaderUniform::Mask, m_smask_active); ShaderManager::u_int(kShaderUniform::BlendMode, b->m_blend_mode); @@ -811,6 +809,7 @@ void Canvas::stroke_commit() ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); + ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); ShaderManager::u_vec2(kShaderUniform::PatternOffset, m_pattern_offset); ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity); diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 18e6af5..9770250 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -216,7 +216,6 @@ void NodeCanvas::draw() ShaderManager::u_vec2(kShaderUniform::Resolution, Canvas::I->m_size); ShaderManager::u_int(kShaderUniform::TexPattern, 4); ShaderManager::u_float(kShaderUniform::StrokeAlpha, b->m_tip_opacity); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity); ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[layer_index].m_alpha_locked); ShaderManager::u_int(kShaderUniform::Mask, m_canvas->m_smask_active); @@ -229,6 +228,7 @@ void NodeCanvas::draw() ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); + ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); ShaderManager::u_vec2(kShaderUniform::PatternOffset, Canvas::I->m_pattern_offset); ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity); diff --git a/src/node_checkbox.cpp b/src/node_checkbox.cpp index d13bb58..25031f8 100644 --- a/src/node_checkbox.cpp +++ b/src/node_checkbox.cpp @@ -108,6 +108,14 @@ void NodeCheckBox::set_icon(const std::string& icon_path) update_icon(); } +void NodeCheckBox::set_value(bool checked, bool trigger_event) +{ + this->checked = checked; + update_icon(); + if (trigger_event && on_value_changed) + on_value_changed(this, checked); +} + void NodeCheckBox::update_icon() { if (m_icon_path.empty()) diff --git a/src/node_checkbox.h b/src/node_checkbox.h index 9b45b88..8991170 100644 --- a/src/node_checkbox.h +++ b/src/node_checkbox.h @@ -20,6 +20,6 @@ public: virtual void draw() override; virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override; void set_icon(const std::string& icon_path); - void set_value(bool checked) { this->checked = checked; update_icon(); } + void set_value(bool checked, bool trigger_event = false); void update_icon(); }; diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index ceb4d4b..ee21bfa 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -538,79 +538,80 @@ bool NodePanelBrushPreset::save() fwrite(&h, sizeof(h), 1, fp); for (int ci = 0; ci < m_container->m_children.size(); ci++) { - auto b = static_cast(m_container->get_child_at(ci)); + auto bpi = static_cast(m_container->get_child_at(ci)); + auto& b = bpi->m_brush; item_t i; - i.m_name_len = b->m_brush->m_name.size(); - i.m_brush_path_len = b->m_brush->m_brush_path.size(); - i.m_brush_thumb_path_len = b->m_brush->m_brush_thumb_path.size(); - i.m_dual_path_len = b->m_brush->m_brush_path.size(); - i.m_dual_thumb_path_len = b->m_brush->m_brush_thumb_path.size(); - i.m_stencil_path_len = b->m_brush->m_pattern_path.size(); - i.m_stencil_thumb_path_len = b->m_brush->m_texture_thumb_path.size(); - i.m_tip_color = b->m_brush->m_tip_color; - i.m_tip_size = b->m_brush->m_tip_size; - i.m_tip_spacing = b->m_brush->m_tip_spacing; - i.m_tip_flow = b->m_brush->m_tip_flow; - i.m_tip_opacity = b->m_brush->m_tip_opacity; - i.m_tip_angle = b->m_brush->m_tip_angle; - i.m_tip_angle_delay = b->m_brush->m_tip_angle_delay; - i.m_tip_mix = b->m_brush->m_tip_mix; - i.m_pattern_opacity = b->m_brush->m_pattern_opacity; - i.m_tip_wet = b->m_brush->m_tip_wet; - i.m_tip_noise = b->m_brush->m_tip_noise; - i.m_tip_hue = b->m_brush->m_tip_hue; - i.m_tip_sat = b->m_brush->m_tip_sat; - i.m_tip_val = b->m_brush->m_tip_val; - i.m_tip_angle_follow = b->m_brush->m_tip_angle_follow; - i.m_tip_flow_pressure = b->m_brush->m_tip_flow_pressure; - i.m_tip_size_pressure = b->m_brush->m_tip_size_pressure; - i.m_jitter_scale = b->m_brush->m_jitter_scale; - i.m_jitter_angle = b->m_brush->m_jitter_angle; - i.m_jitter_spread = b->m_brush->m_jitter_spread; - i.m_jitter_flow = b->m_brush->m_jitter_flow; - i.m_jitter_hue = b->m_brush->m_jitter_hue; - i.m_jitter_sat = b->m_brush->m_jitter_sat; - i.m_jitter_val = b->m_brush->m_jitter_val; - i.m_blend_mode = b->m_brush->m_blend_mode; + i.m_name_len = b->m_name.size(); + i.m_brush_path_len = b->m_brush_path.size(); + i.m_brush_thumb_path_len = b->m_brush_thumb_path.size(); + i.m_dual_path_len = b->m_brush_path.size(); + i.m_dual_thumb_path_len = b->m_brush_thumb_path.size(); + i.m_stencil_path_len = b->m_pattern_path.size(); + i.m_stencil_thumb_path_len = b->m_texture_thumb_path.size(); + i.m_tip_color = b->m_tip_color; + i.m_tip_size = b->m_tip_size; + i.m_tip_spacing = b->m_tip_spacing; + i.m_tip_flow = b->m_tip_flow; + i.m_tip_opacity = b->m_tip_opacity; + i.m_tip_angle = b->m_tip_angle; + i.m_tip_angle_delay = b->m_tip_angle_delay; + i.m_tip_mix = b->m_tip_mix; + i.m_tip_wet = b->m_tip_wet; + i.m_tip_noise = b->m_tip_noise; + i.m_tip_hue = b->m_tip_hue; + i.m_tip_sat = b->m_tip_sat; + i.m_tip_val = b->m_tip_val; + i.m_tip_angle_follow = b->m_tip_angle_follow; + i.m_tip_flow_pressure = b->m_tip_flow_pressure; + i.m_tip_size_pressure = b->m_tip_size_pressure; + i.m_jitter_scale = b->m_jitter_scale; + i.m_jitter_angle = b->m_jitter_angle; + i.m_jitter_spread = b->m_jitter_spread; + i.m_jitter_flow = b->m_jitter_flow; + i.m_jitter_hue = b->m_jitter_hue; + i.m_jitter_sat = b->m_jitter_sat; + i.m_jitter_val = b->m_jitter_val; + i.m_blend_mode = b->m_blend_mode; - i.m_tip_invert = b->m_brush->m_tip_invert; - i.m_tip_flipx = b->m_brush->m_tip_flipx; - i.m_tip_flipy = b->m_brush->m_tip_flipy; - i.m_pattern_enabled = b->m_brush->m_pattern_enabled; - i.m_dual_enabled = b->m_brush->m_dual_enabled; - i.m_dual_blend_mode = b->m_brush->m_dual_blend_mode; - i.m_dual_randflip = b->m_brush->m_dual_randflip; - i.m_dual_size = b->m_brush->m_dual_size; - i.m_dual_spacing = b->m_brush->m_dual_spacing; - i.m_dual_scatter = b->m_brush->m_dual_scatter; - i.m_dual_scatter_axis = b->m_brush->m_dual_scatter_axis; - i.m_dual_invert = b->m_brush->m_dual_invert; - i.m_dual_flipx = b->m_brush->m_dual_flipx; - i.m_dual_flipy = b->m_brush->m_dual_flipy; - i.m_tip_randflipx = b->m_brush->m_tip_randflipx; - i.m_tip_randflipy = b->m_brush->m_tip_randflipy; - i.m_tip_aspect = b->m_brush->m_tip_aspect; - i.m_dual_flow = b->m_brush->m_dual_flow; - i.m_dual_opacity = b->m_brush->m_dual_opacity; - i.m_dual_rotate = b->m_brush->m_dual_rotate; + i.m_tip_invert = b->m_tip_invert; + i.m_tip_flipx = b->m_tip_flipx; + i.m_tip_flipy = b->m_tip_flipy; + i.m_pattern_enabled = b->m_pattern_enabled; + i.m_dual_enabled = b->m_dual_enabled; + i.m_dual_blend_mode = b->m_dual_blend_mode; + i.m_dual_randflip = b->m_dual_randflip; + i.m_dual_size = b->m_dual_size; + i.m_dual_spacing = b->m_dual_spacing; + i.m_dual_scatter = b->m_dual_scatter; + i.m_dual_scatter_axis = b->m_dual_scatter_axis; + i.m_dual_invert = b->m_dual_invert; + i.m_dual_flipx = b->m_dual_flipx; + i.m_dual_flipy = b->m_dual_flipy; + i.m_tip_randflipx = b->m_tip_randflipx; + i.m_tip_randflipy = b->m_tip_randflipy; + i.m_tip_aspect = b->m_tip_aspect; + i.m_dual_flow = b->m_dual_flow; + i.m_dual_opacity = b->m_dual_opacity; + i.m_dual_rotate = b->m_dual_rotate; - i.m_pattern_eachsample = b->m_brush->m_pattern_eachsample; - i.m_pattern_invert = b->m_brush->m_pattern_invert; - i.m_pattern_flipx = b->m_brush->m_pattern_flipx; - i.m_pattern_flipy = b->m_brush->m_pattern_flipy; - i.m_pattern_scale = b->m_brush->m_pattern_scale; - i.m_pattern_brightness = b->m_brush->m_pattern_brightness; - i.m_pattern_contrast = b->m_brush->m_pattern_contrast; - i.m_pattern_rand_offset = b->m_brush->m_pattern_rand_offset; + i.m_pattern_eachsample = b->m_pattern_eachsample; + i.m_pattern_invert = b->m_pattern_invert; + i.m_pattern_flipx = b->m_pattern_flipx; + i.m_pattern_flipy = b->m_pattern_flipy; + i.m_pattern_scale = b->m_pattern_scale; + i.m_pattern_brightness = b->m_pattern_brightness; + i.m_pattern_contrast = b->m_pattern_contrast; + i.m_pattern_rand_offset = b->m_pattern_rand_offset; + i.m_pattern_depth = b->m_pattern_depth; fwrite(&i, sizeof(i), 1, fp); - fwrite(b->m_brush->m_name.c_str(), 1, b->m_brush->m_name.size(), fp); - fwrite(b->m_brush->m_brush_path.c_str(), 1, b->m_brush->m_brush_path.size(), fp); - fwrite(b->m_brush->m_brush_thumb_path.c_str(), 1, b->m_brush->m_brush_thumb_path.size(), fp); - fwrite(b->m_brush->m_dual_path.c_str(), 1, b->m_brush->m_brush_path.size(), fp); - fwrite(b->m_brush->m_dual_thumb_path.c_str(), 1, b->m_brush->m_brush_thumb_path.size(), fp); - fwrite(b->m_brush->m_pattern_path.c_str(), 1, b->m_brush->m_pattern_path.size(), fp); - fwrite(b->m_brush->m_texture_thumb_path.c_str(), 1, b->m_brush->m_texture_thumb_path.size(), fp); + fwrite(b->m_name.c_str(), 1, b->m_name.size(), fp); + fwrite(b->m_brush_path.c_str(), 1, b->m_brush_path.size(), fp); + fwrite(b->m_brush_thumb_path.c_str(), 1, b->m_brush_thumb_path.size(), fp); + fwrite(b->m_dual_path.c_str(), 1, b->m_brush_path.size(), fp); + fwrite(b->m_dual_thumb_path.c_str(), 1, b->m_brush_thumb_path.size(), fp); + fwrite(b->m_pattern_path.c_str(), 1, b->m_pattern_path.size(), fp); + fwrite(b->m_texture_thumb_path.c_str(), 1, b->m_texture_thumb_path.size(), fp); } fclose(fp); return true; @@ -651,7 +652,6 @@ bool NodePanelBrushPreset::restore() b->m_tip_angle = i.m_tip_angle; b->m_tip_angle_delay = i.m_tip_angle_delay; b->m_tip_mix = i.m_tip_mix; - b->m_pattern_opacity = i.m_pattern_opacity; b->m_tip_wet = i.m_tip_wet; b->m_tip_noise = i.m_tip_noise; b->m_tip_hue = i.m_tip_hue; @@ -696,6 +696,7 @@ bool NodePanelBrushPreset::restore() b->m_pattern_brightness = i.m_pattern_brightness; b->m_pattern_contrast = i.m_pattern_contrast; b->m_pattern_rand_offset = i.m_pattern_rand_offset; + b->m_pattern_depth = i.m_pattern_depth; b->m_name.resize(i.m_name_len); b->m_brush_path.resize(i.m_brush_path_len); diff --git a/src/node_panel_brush.h b/src/node_panel_brush.h index 06a5a85..b5713bf 100644 --- a/src/node_panel_brush.h +++ b/src/node_panel_brush.h @@ -111,7 +111,6 @@ class NodePanelBrushPreset : public Node float m_tip_angle = 0; float m_tip_angle_delay = 0; float m_tip_mix = 0; - float m_pattern_opacity = 0; float m_tip_wet = 0; float m_tip_noise = 0; float m_tip_hue = 0; @@ -158,6 +157,7 @@ class NodePanelBrushPreset : public Node float m_pattern_brightness = 0.5f; float m_pattern_contrast = 0.5f; bool m_pattern_rand_offset = false; + float m_pattern_depth = 1.f; }; public: std::function& brush)> on_brush_changed; diff --git a/src/node_panel_stroke.cpp b/src/node_panel_stroke.cpp index c3ed845..a967e56 100644 --- a/src/node_panel_stroke.cpp +++ b/src/node_panel_stroke.cpp @@ -31,7 +31,6 @@ void NodePanelStroke::update_controls() m_tip_opacity->m_value.x = b->m_tip_opacity; m_tip_angle->m_value.x = b->m_tip_angle; m_tip_angle_delay->m_value.x = b->m_tip_angle_delay; - m_pattern_opacity->m_value.x = b->m_pattern_opacity; m_tip_wet->m_value.x = b->m_tip_wet; m_tip_noise->m_value.x = b->m_tip_noise; m_jitter_scale->m_value.x = b->m_jitter_scale; @@ -74,6 +73,7 @@ void NodePanelStroke::update_controls() m_pattern_scale->m_value.x = b->m_pattern_scale; m_pattern_brightness->m_value.x = b->m_pattern_brightness; m_pattern_contrast->m_value.x = b->m_pattern_contrast; + m_pattern_depth->m_value.x = b->m_pattern_depth; m_blend_mode->set_index(b->m_blend_mode); m_dual_blend_mode->set_index(b->m_dual_blend_mode); @@ -285,6 +285,7 @@ void NodePanelStroke::init_controls() }; m_pattern_popup->on_brush_changed = [this](Node*, int index) { + m_pattern_enabled->set_value(true, true); if (on_pattern_changed) on_pattern_changed(this, m_pattern_popup->get_texture_path(index), m_pattern_popup->get_thumb_path(index)); m_pattern_thumb->set_image(m_pattern_popup->get_thumb_path(index)); @@ -308,7 +309,6 @@ void NodePanelStroke::init_controls() init_slider(m_tip_angle, "tip-angle", &Brush::m_tip_angle); init_slider(m_tip_angle_delay, "tip-angle-delay", &Brush::m_tip_angle_delay); init_slider(m_tip_mix, "tip-mix", &Brush::m_tip_mix); - init_slider(m_pattern_opacity, "pattern-opacity", &Brush::m_pattern_opacity); init_slider(m_tip_wet, "tip-wet", &Brush::m_tip_wet); init_slider(m_tip_noise, "tip-noise", &Brush::m_tip_noise); init_slider(m_tip_hue, "tip-hue", &Brush::m_tip_hue); @@ -355,6 +355,7 @@ void NodePanelStroke::init_controls() init_slider(m_pattern_scale, "pattern-scale", &Brush::m_pattern_scale); init_slider(m_pattern_brightness, "pattern-brightness", &Brush::m_pattern_brightness); init_slider(m_pattern_contrast, "pattern-contrast", &Brush::m_pattern_contrast); + init_slider(m_pattern_depth, "pattern-depth", &Brush::m_pattern_depth); auto curve_cubic = [](float v) { return glm::pow(v, 3.f); }; auto curve_quad = [](float v) { return glm::pow(v, 2.f); }; diff --git a/src/node_panel_stroke.h b/src/node_panel_stroke.h index 528fbbf..02d8bb4 100644 --- a/src/node_panel_stroke.h +++ b/src/node_panel_stroke.h @@ -21,7 +21,6 @@ public: NodeSliderH* m_tip_angle; NodeSliderH* m_tip_angle_delay; NodeSliderH* m_tip_mix; - NodeSliderH* m_pattern_opacity; NodeSliderH* m_tip_wet; NodeSliderH* m_tip_noise; NodeSliderH* m_tip_hue; @@ -78,6 +77,7 @@ public: NodeSliderH* m_pattern_scale; NodeSliderH* m_pattern_brightness; NodeSliderH* m_pattern_contrast; + NodeSliderH* m_pattern_depth; std::shared_ptr m_brush_popup; std::shared_ptr m_pattern_popup; diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index ed982dc..594653b 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -82,7 +82,6 @@ void NodeStrokePreview::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2 ShaderManager::u_int(kShaderUniform::TexPattern, 4); ShaderManager::u_vec2(kShaderUniform::Resolution, m_size); ShaderManager::u_float(kShaderUniform::StrokeAlpha, b->m_tip_opacity); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_float(kShaderUniform::Alpha, 1); ShaderManager::u_int(kShaderUniform::Lock, false); ShaderManager::u_int(kShaderUniform::Mask, false); @@ -95,7 +94,8 @@ void NodeStrokePreview::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2 ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); - ShaderManager::u_vec2(kShaderUniform::PatternOffset, glm::vec2(b->m_pattern_rand_offset ? 0.5f: 0.0f)); + ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); + ShaderManager::u_vec2(kShaderUniform::PatternOffset, glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f)); ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity); m_sampler_linear.bind(0); @@ -297,11 +297,11 @@ void NodeStrokePreview::draw_stroke() ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer //ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer ShaderManager::u_vec2(kShaderUniform::Resolution, size); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_vec2(kShaderUniform::PatternScale, patt_scale); ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); + ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); ShaderManager::u_vec2(kShaderUniform::PatternOffset, glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f)); ShaderManager::u_int(kShaderUniform::UsePattern, b->m_pattern_enabled && b->m_pattern_eachsample); ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj); @@ -393,7 +393,6 @@ void NodeStrokePreview::draw_stroke() ShaderManager::u_int(kShaderUniform::TexPattern, 4); ShaderManager::u_vec2(kShaderUniform::Resolution, size); ShaderManager::u_float(kShaderUniform::StrokeAlpha, b->m_tip_opacity); - ShaderManager::u_float(kShaderUniform::PatternAlpha, b->m_pattern_opacity); ShaderManager::u_float(kShaderUniform::Alpha, 1); ShaderManager::u_int(kShaderUniform::Mask, false); ShaderManager::u_int(kShaderUniform::BlendMode, b->m_blend_mode); @@ -405,6 +404,7 @@ void NodeStrokePreview::draw_stroke() ShaderManager::u_float(kShaderUniform::PatternInvert, b->m_pattern_invert); ShaderManager::u_float(kShaderUniform::PatternBright, b->m_pattern_brightness); ShaderManager::u_float(kShaderUniform::PatternContrast, b->m_pattern_contrast); + ShaderManager::u_float(kShaderUniform::PatternDepth, b->m_pattern_depth); ShaderManager::u_vec2(kShaderUniform::PatternOffset, glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f)); ShaderManager::u_float(kShaderUniform::DualAlpha, b->m_dual_opacity); diff --git a/src/shader.cpp b/src/shader.cpp index 5a0cbff..53b0bd9 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -1,11 +1,122 @@ #include "pch.h" #include "log.h" #include "shader.h" +#include "asset.h" std::map ShaderManager::m_shaders; Shader* ShaderManager::m_current; bool ShaderManager::ext_framebuffer_fetch = false; +std::string Shader::read(const std::string& path) +{ + Asset a; + std::string ret; + if (a.open(path.c_str())) + { + std::regex reg_include(R"!(#include "([^"]+)")!"); + std::string data((char*)a.read_all(), a.m_len); + + // split path + std::string name, base, ext; + std::regex reg_path(R"((.*)[\\/]([^\\/]+)\.(\w+)$)"); + std::smatch m; + if (std::regex_search(path, m, reg_path)) + { + base = m[1].str(); + name = m[2].str(); + ext = m[3].str(); + } + + for (const auto& l : split(data, '\n')) + { + std::smatch m; + if (std::regex_search(l, m, reg_include)) + { + std::string inc = base + "/" + m[1].str(); + if (Asset::exist(inc.c_str())) + { + std::string subdata = read(inc); + ret.append(subdata + "\n"); + } + } + else + { + ret.append(l + "\n"); + } + } + } + return ret; +} + +void Shader::parse_error(const char* msg, const char* code) +{ + auto code_lines = split(code, '\n'); + auto error_lines = split(msg, '\n'); + std::smatch m; + std::regex r(R"(\((\d+)\))"); + for (const auto& line : error_lines) + { + LOG("%s", line.c_str()); + if (std::regex_search(line, m, r)) + { + int ln = std::stoi(m[1].str()); + if (ln < code_lines.size()) + { + int n = 2; + int s = std::max(ln - n, 1); + int e = std::min((int)code_lines.size() - 1, ln + n); + for (int i = s; i < e; i++) + { + LOG("- line %02d: %s", i, code_lines[i - 1].c_str()); + } + } + } + } +} + +bool Shader::load(const std::string& path) +{ + std::string data = read(path); + if (data.empty()) return false; + + std::map> sections; + std::shared_ptr current_section = nullptr; + std::regex reg_section(R"!(\[\[(.*)\]\])!"); + for (const auto& l : split(data, '\n')) + { + std::smatch m; + if (std::regex_search(l, m, reg_section)) + { + std::string section_name = m[1].str(); + if (!sections[section_name]) + sections[section_name] = std::make_shared(); + current_section = sections[section_name]; + } + else + { + // create an un-named section + if (!current_section) + current_section = sections[""] = std::make_shared(); + current_section->append(l + "\n"); + } + } + + if (sections.find("vertex") != sections.end() && sections.find("fragment") != sections.end()) + { + *sections["vertex"] = SHADER_VERSION + *sections["vertex"]; + *sections["fragment"] = SHADER_VERSION + *sections["fragment"]; + return create(sections["vertex"]->c_str(), sections["fragment"]->c_str()); + } + else + { + LOG("could not find [[vertex]] and [[fragment]] sections on %s", path.c_str()); + } + + m_path = path; + + return false; +} + bool Shader::create(const char* vertex, const char* fragment) { GLint status; @@ -24,7 +135,10 @@ bool Shader::create(const char* vertex, const char* fragment) glGetShaderiv(vs, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog); if (infolen > 0) - LOG("VERTEX SHADER:\n%s", infolog); + { + LOG("\nVERTEX SHADER:"); + parse_error(infolog, vertex); + } if (status == 0) { glDeleteShader(vs); @@ -43,7 +157,10 @@ bool Shader::create(const char* vertex, const char* fragment) glGetShaderiv(fs, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog); if (infolen > 0) - LOG("FRAGMENT SHADER:\n%s", infolog); + { + LOG("\nFRAGMENT SHADER:"); + parse_error(infolog, fragment); + } if (status == 0) { glDeleteShader(vs); @@ -159,6 +276,12 @@ GLint Shader::GetAttribLocation(const char* name) return glGetAttribLocation(prog, name); } +bool ShaderManager::load(kShader id, const std::string& path) +{ + m_shaders[id].name = id; + return m_shaders[id].load(path); +} + bool ShaderManager::create(kShader id, const char* vertex, const char* fragment) { m_shaders[id].name = id; diff --git a/src/shader.h b/src/shader.h index 95eeba8..ad47747 100644 --- a/src/shader.h +++ b/src/shader.h @@ -40,6 +40,7 @@ enum class kShaderUniform : uint16_t PatternScale = const_hash("pattern_scale"), PatternBright = const_hash("pattern_bright"), PatternContrast = const_hash("pattern_contr"), + PatternDepth = const_hash("pattern_depth"), Colorize = const_hash("colorize"), DualAlpha = const_hash("dual_alpha"), }; @@ -73,10 +74,14 @@ enum class kShader : uint16_t class Shader { + std::string m_path; std::map m_umap; GLuint prog; + std::string read(const std::string& path); public: kShader name; + void parse_error(const char* msg, const char* code); + bool load(const std::string& path); bool create(const char* vertex, const char* fragment); void use(); void u_vec4(kShaderUniform id, const glm::vec4& v); @@ -94,6 +99,7 @@ class ShaderManager static Shader* m_current; public: static bool ext_framebuffer_fetch; + static bool load(kShader id, const std::string& path); static bool create(kShader id, const char* vertex, const char* fragment); static void use(kShader id); static void use(const char* name);