move shaders into .glsl files and add #include feature

This commit is contained in:
2019-02-21 19:26:40 +01:00
parent 16eb9de358
commit eaab9c79e5
47 changed files with 1124 additions and 777 deletions

View File

@@ -404,6 +404,37 @@
<SubType>Designer</SubType>
</Xml>
</ItemGroup>
<ItemGroup>
<None Include="data\shaders\atlas.glsl" />
<None Include="data\shaders\bake-uv.glsl" />
<None Include="data\shaders\checkerboard.glsl" />
<None Include="data\shaders\color-hue.glsl" />
<None Include="data\shaders\color-quad.glsl" />
<None Include="data\shaders\color-tri.glsl" />
<None Include="data\shaders\color.glsl" />
<None Include="data\shaders\comp-draw.glsl" />
<None Include="data\shaders\comp-erase.glsl" />
<None Include="data\shaders\equirect.glsl" />
<None Include="data\shaders\font.glsl" />
<None Include="data\shaders\include\blend-stroke.glsl" />
<None Include="data\shaders\include\blend.glsl" />
<None Include="data\shaders\include\blur.glsl" />
<None Include="data\shaders\include\color.glsl" />
<None Include="data\shaders\include\ext-fb-fetch.glsl" />
<None Include="data\shaders\include\hsv.glsl" />
<None Include="data\shaders\include\rand.glsl" />
<None Include="data\shaders\lambert.glsl" />
<None Include="data\shaders\lightmap.glsl" />
<None Include="data\shaders\stroke-instanced.glsl" />
<None Include="data\shaders\stroke-preview.glsl" />
<None Include="data\shaders\stroke.glsl" />
<None Include="data\shaders\texture-alpha-sep.glsl" />
<None Include="data\shaders\texture-alpha.glsl" />
<None Include="data\shaders\texture-blend.glsl" />
<None Include="data\shaders\texture.glsl" />
<None Include="data\shaders\uvs.glsl" />
<None Include="data\shaders\vertex-color.glsl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@@ -52,6 +52,12 @@
<Filter Include="libs\fmt">
<UniqueIdentifier>{7b4f5b47-7a8b-4e4c-9e82-399bb5047ffc}</UniqueIdentifier>
</Filter>
<Filter Include="shaders">
<UniqueIdentifier>{b55fb692-a845-4ef2-9b0e-5b2dd8bd125f}</UniqueIdentifier>
</Filter>
<Filter Include="shaders\include">
<UniqueIdentifier>{a2cacb13-2854-44ee-9511-6cb8ac587428}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\app.cpp">
@@ -543,4 +549,93 @@
<Filter>extras</Filter>
</Xml>
</ItemGroup>
<ItemGroup>
<None Include="data\shaders\texture.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\include\blend-stroke.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\blur.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\color.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\ext-fb-fetch.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\hsv.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\rand.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\include\blend.glsl">
<Filter>shaders\include</Filter>
</None>
<None Include="data\shaders\comp-draw.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\comp-erase.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\equirect.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\font.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\lambert.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\lightmap.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke-instanced.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\stroke-preview.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-alpha.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-alpha-sep.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\texture-blend.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\uvs.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\vertex-color.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\atlas.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\bake-uv.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\checkerboard.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color-hue.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color-quad.glsl">
<Filter>shaders</Filter>
</None>
<None Include="data\shaders\color-tri.glsl">
<Filter>shaders</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -164,7 +164,7 @@
<node dir="col" align="center" grow="1" width="1" flood-events="1">
<!--<node height="20" pad="1" width="100%" margin="5 0 5 0"><slider-h id="tip-shade" value="1"/></node>-->
<button-custom id="preset-button" width="100%" height="40" margin="5 0 0 0" dir="row" pad="4">
<image id="preset-thumb" path="data/thumbs/Round-Hard.png" width="32" height="100%"/>
<image id="preset-thumb" width="32" height="100%"/>
<stroke-preview id="preset-preview" width="10" grow="1" height="100%"/>
</button-custom>
<node dir="row" margin="5 0 0 0">
@@ -309,7 +309,7 @@
<text text="Offset"/>
</node>
<node height="20" justify="center">
<text text="Opacity"/>
<text text="Depth"/>
</node>
<node height="20" justify="center">
<text text="Scale"/>
@@ -355,7 +355,7 @@
<text text="randomize"/>
</node>
<node height="20" pad="1" width="100%">
<slider-h id="pattern-opacity" value="1"/>
<slider-h id="pattern-depth" value="1"/>
</node>
<node height="20" pad="1" width="100%">
<slider-h id="pattern-scale" value=".25"/>

21
data/shaders/atlas.glsl Normal file
View File

@@ -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);
};

27
data/shaders/bake-uv.glsl Normal file
View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
};

View File

@@ -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);
};

View File

@@ -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);
};

16
data/shaders/color.glsl Normal file
View File

@@ -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;
};

View File

@@ -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);
};

View File

@@ -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));
};

View File

@@ -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);
}

22
data/shaders/font.glsl Normal file
View File

@@ -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);
};

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

23
data/shaders/lambert.glsl Normal file
View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
};

93
data/shaders/stroke.glsl Normal file
View File

@@ -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);
};

View File

@@ -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);
};

View File

@@ -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);
};

View File

@@ -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);
};

19
data/shaders/texture.glsl Normal file
View File

@@ -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);
};

18
data/shaders/uvs.glsl Normal file
View File

@@ -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);
};

View File

@@ -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;
};

View File

@@ -149,7 +149,7 @@ std::vector<std::shared_ptr<Brush>> ABR::compute_brushes(const std::string& path
auto patt_uid = wstr2str(patt->value<String>("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<UnitFloat>("textureDepth") * 0.01f;
b->m_pattern_depth = p->value<UnitFloat>("textureDepth") * 0.01f;
}
ret.push_back(b);
}

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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())

View File

@@ -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();
};

View File

@@ -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<NodeBrushPresetItem*>(m_container->get_child_at(ci));
auto bpi = static_cast<NodeBrushPresetItem*>(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);

View File

@@ -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<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;

View File

@@ -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); };

View File

@@ -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<NodePanelBrush> m_brush_popup;
std::shared_ptr<NodePanelBrush> m_pattern_popup;

View File

@@ -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);

View File

@@ -1,11 +1,122 @@
#include "pch.h"
#include "log.h"
#include "shader.h"
#include "asset.h"
std::map<kShader, Shader> 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<std::string, std::shared_ptr<std::string>> sections;
std::shared_ptr<std::string> 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<std::string>();
current_section = sections[section_name];
}
else
{
// create an un-named section
if (!current_section)
current_section = sections[""] = std::make_shared<std::string>();
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;

View File

@@ -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<kShaderUniform, GLuint> 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);