*/}}

ourshader.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. /*
  2. * Our Paint: A light weight GPU powered painting program.
  3. * Copyright (C) 2022-2023 Wu Yiming
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "ourpaint.h"
  19. const char OUR_SHADER_VERSION_430[]="#version 430\n#define WORKGROUP_SIZE 32";
  20. const char OUR_SHADER_VERSION_320ES[]="#version 320 es\n#define OUR_GLES\n#define WORKGROUP_SIZE 16";
  21. const char OUR_SHADER_COMMON[]=R"(
  22. #ifdef OUR_GLES
  23. vec4 cunpack(uint d){
  24. return vec4(float(d&0xFFu)/255.,float((d>>8u)&0xFFu)/255.,float((d>>16u)&0xFFu)/255.,float((d>>24u)&0xFFu)/255.);
  25. }
  26. uvec4 cpack(vec4 c){
  27. uint v= uint(uint(c.r*255.) | (uint(c.g*255.)<<8u) | (uint(c.b*255.)<<16u) | (uint(c.a*255.)<<24u));
  28. return uvec4(v,v,v,v);
  29. }
  30. #define OurImageLoad(img, p) \
  31. (cunpack(imageLoad(img,p).x))
  32. #define OurImageStore(img, p, color) \
  33. imageStore(img,p,cpack(color))
  34. #else
  35. #define OurImageLoad(img, p) \
  36. (vec4(imageLoad(img,p))/65535.)
  37. #define OurImageStore(img, p, color) \
  38. imageStore(img,p,uvec4(vec4(color)*65535.))
  39. #endif
  40. )";
  41. const char OUR_CANVAS_SHADER[]=R"(
  42. layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
  43. #ifdef OUR_GLES
  44. precision highp uimage2D;
  45. precision highp float;
  46. precision highp int;
  47. layout(r32ui, binding = 0) uniform uimage2D img;
  48. layout(r32ui, binding = 1) coherent uniform uimage2D smudge_buckets;
  49. #define OUR_FLT_EPS (1.0/255.0f)
  50. #else
  51. layout(rgba16ui, binding = 0) uniform uimage2D img;
  52. layout(rgba16ui, binding = 1) coherent uniform uimage2D smudge_buckets;
  53. #define OUR_FLT_EPS (1e-4)
  54. #endif
  55. uniform int uCanvasType;
  56. uniform int uCanvasRandom;
  57. uniform float uCanvasFactor;
  58. uniform ivec2 uImageOffset;
  59. uniform ivec2 uBrushCorner;
  60. uniform vec2 uBrushCenter;
  61. uniform float uBrushSize;
  62. uniform float uBrushHardness;
  63. uniform float uBrushSmudge;
  64. uniform float uBrushSlender;
  65. uniform float uBrushAngle;
  66. uniform vec2 uBrushDirection;
  67. uniform float uBrushForce;
  68. uniform float uBrushGunkyness;
  69. uniform float uBrushRecentness;
  70. uniform vec4 uBrushColor;
  71. uniform vec4 uBackgroundColor;
  72. uniform int uBrushErasing;
  73. uniform int uBrushMix;
  74. #ifdef OUR_GLES
  75. uniform int uBrushRoutineSelectionES;
  76. uniform int uMixRoutineSelectionES;
  77. #endif
  78. #ifdef OUR_CANVAS_MODE_PIGMENT
  79. #with OUR_PIGMENT_COMMON
  80. layout(std140) uniform BrushPigmentBlock{
  81. PigmentData p;
  82. }uBrushPigment;
  83. #endif
  84. #with OUR_SHADER_COMMON
  85. const vec4 p1_22=vec4(1.0/2.2,1.0/2.2,1.0/2.2,1.0/2.2);
  86. const vec4 p22=vec4(2.2,2.2,2.2,2.2);
  87. const float WGM_EPSILON=0.001f;
  88. const float T_MATRIX_SMALL[30] = float[30](0.026595621243689,0.049779426257903,0.022449850859496,-0.218453689278271
  89. ,-0.256894883201278,0.445881722194840,0.772365886289756,0.194498761382537
  90. ,0.014038157587820,0.007687264480513
  91. ,-0.032601672674412,-0.061021043498478,-0.052490001018404
  92. ,0.206659098273522,0.572496335158169,0.317837248815438,-0.021216624031211
  93. ,-0.019387668756117,-0.001521339050858,-0.000835181622534
  94. ,0.339475473216284,0.635401374177222,0.771520797089589,0.113222640692379
  95. ,-0.055251113343776,-0.048222578468680,-0.012966666339586
  96. ,-0.001523814504223,-0.000094718948810,-0.000051604594741);
  97. const float spectral_r_small[10] = float[10](0.009281362787953,0.009732627042016,0.011254252737167,0.015105578649573
  98. ,0.024797924177217,0.083622585502406,0.977865045723212,1.000000000000000
  99. ,0.999961046144372,0.999999992756822);
  100. const float spectral_g_small[10] = float[10](0.002854127435775,0.003917589679914,0.012132151699187,0.748259205918013
  101. ,1.000000000000000,0.865695937531795,0.037477469241101,0.022816789725717
  102. ,0.021747419446456,0.021384940572308);
  103. const float spectral_b_small[10] = float[10](0.537052150373386,0.546646402401469,0.575501819073983,0.258778829633924
  104. ,0.041709923751716,0.012662638828324,0.007485593127390,0.006766900622462
  105. ,0.006699764779016,0.006676219883241);
  106. void rgb_to_spectral (vec3 rgb, out float spectral_[10]) {
  107. float offset = 1.0 - WGM_EPSILON;
  108. float r = rgb.r * offset + WGM_EPSILON;
  109. float g = rgb.g * offset + WGM_EPSILON;
  110. float b = rgb.b * offset + WGM_EPSILON;
  111. float spec_r[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); for (int i=0; i < 10; i++) {spec_r[i] = spectral_r_small[i] * r;}
  112. float spec_g[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); for (int i=0; i < 10; i++) {spec_g[i] = spectral_g_small[i] * g;}
  113. float spec_b[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); for (int i=0; i < 10; i++) {spec_b[i] = spectral_b_small[i] * b;}
  114. for (int i=0; i<10; i++) {spectral_[i] = spec_r[i] + spec_g[i] + spec_b[i];}
  115. }
  116. vec3 spectral_to_rgb (float spectral[10]) {
  117. float offset = 1.0 - WGM_EPSILON;
  118. // We need this tmp. array to allow auto vectorization. <-- How about on GPU?
  119. float tmp[3] = float[3](0.,0.,0.);
  120. for (int i=0; i<10; i++) {
  121. tmp[0] += T_MATRIX_SMALL[i] * spectral[i];
  122. tmp[1] += T_MATRIX_SMALL[10+i] * spectral[i];
  123. tmp[2] += T_MATRIX_SMALL[20+i] * spectral[i];
  124. }
  125. vec3 rgb_;
  126. for (int i=0; i<3; i++) {rgb_[i] = clamp((tmp[i] - WGM_EPSILON) / offset, 0.0f, 1.0f);}
  127. return rgb_;
  128. }
  129. vec2 hash( vec2 p ){
  130. p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) );
  131. return -1.0 + 2.0*fract(sin(p)*43758.5453123);
  132. }
  133. float rand(vec2 co){
  134. return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
  135. }
  136. float noise(in vec2 p){ // from iq
  137. const float K1 = 0.366025404; // (sqrt(3)-1)/2;
  138. const float K2 = 0.211324865; // (3-sqrt(3))/6;
  139. vec2 i = floor( p + (p.x+p.y)*K1 );
  140. vec2 a = p - i + (i.x+i.y)*K2;
  141. float m = step(a.y,a.x);
  142. vec2 o = vec2(m,1.0-m);
  143. vec2 b = a - o + K2;
  144. vec2 c = a - 1.0 + 2.0*K2;
  145. vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
  146. vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
  147. return dot( n, vec3(70.0) );
  148. }
  149. #define HEIGHT_STRAND(x,y) abs(fract(x)-.5)<.48? \
  150. (.4+.2*sin(3.14*(y+ceil(x))))* \
  151. ((max(abs(sin(3.14*x*2.)+0.2),abs(sin(3.14*x*2.)-0.2))+2.*abs(sin(3.14*x)))/2.+0.5):0.1
  152. #define PATTERN_CANVAS(x,y) \
  153. (max(HEIGHT_STRAND((x),(y)),HEIGHT_STRAND(-(y),(x))))
  154. float HEIGHT_CANVAS(float x,float y){
  155. if(uCanvasType == 1){
  156. return PATTERN_CANVAS(x,y);
  157. }else if(uCanvasType == 2){
  158. vec2 uv=vec2(x,y); float f; uv*=0.1; // from iq
  159. f = 0.2*noise( uv ); uv*=5.;
  160. f += 0.6*noise( uv ); uv*=3.;
  161. f += 0.5*noise( uv );
  162. f = 0.55 + 0.55*f;
  163. return pow(f,0.5);
  164. }
  165. return 1.;
  166. }
  167. float SampleCanvas(vec2 U, vec2 dir,float rfac, float force, float gunky){
  168. if(uCanvasType==0 || abs(gunky)<1.e-2){ return rfac; }
  169. U+=vec2(uImageOffset); U/=20.3; U.x=U.x+rand(U)/10.; U.y=U.y+rand(U)/10.;
  170. mat2 m = mat2(1.6,1.2,-1.2,1.6); vec2 _uv=U; _uv.x+=float(uCanvasRandom%65535)/174.41; _uv.y+=float(uCanvasRandom%65535)/439.87; _uv/=500.;
  171. U.x+=noise(_uv)*2.1; _uv = m*_uv; U.x+=noise(_uv)*0.71;
  172. _uv.y+=365.404;
  173. U.y+=noise(_uv)*1.9; _uv = m*_uv; U.y+=noise(_uv)*0.83;
  174. float d=0.1;
  175. float h=HEIGHT_CANVAS(U.x,U.y);
  176. float hr=HEIGHT_CANVAS(U.x+d,U.y);
  177. float hu=HEIGHT_CANVAS(U.x,U.y+d);
  178. vec3 vx=normalize(vec3(d,0,hr)-vec3(0,0,h)),vy=normalize(vec3(0,d,hu)-vec3(0,0,h)),vz=cross(vx,vy);
  179. float useforce=force*rfac;
  180. float scrape=dot(normalize(vz),vec3(-normalize(dir).xy,0))*mix(0.3,1.,useforce);
  181. float top=h-(1.-pow(useforce,1.5)*2.); float tophard=smoothstep(0.4,0.6,top);
  182. float fac=(gunky>=0.)?mix(mix(1.,top,gunky),tophard,gunky):mix(1.,1.-h,-gunky*0.8);
  183. fac=max(fac,scrape*clamp(gunky,0.,1.));
  184. fac=clamp(fac,0.,1.);
  185. fac*=rfac;
  186. return mix(rfac,fac,uCanvasFactor);
  187. }
  188. #ifndef OUR_GLES
  189. subroutine vec4 MixRoutines(vec4 a, vec4 b, float fac_a);
  190. #endif
  191. #ifndef OUR_GLES
  192. subroutine(MixRoutines)
  193. #endif
  194. vec4 DoMixNormal(vec4 a, vec4 b, float fac_a){
  195. return mix(a,b,1.0f-fac_a);
  196. }
  197. #ifndef OUR_GLES
  198. subroutine(MixRoutines)
  199. #endif
  200. vec4 DoMixSpectral(vec4 a, vec4 b, float fac_a){
  201. vec4 result = vec4(0,0,0,0);
  202. result.a=mix(a.a,b.a,1.0f-fac_a);
  203. float spec_a[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); rgb_to_spectral(a.rgb, spec_a);
  204. float spec_b[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); rgb_to_spectral(b.rgb, spec_b);
  205. float spectralmix[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.);
  206. for (int i=0; i < 10; i++) { spectralmix[i] = pow(spec_a[i], fac_a) * pow(spec_b[i], 1.0f-fac_a); }
  207. result.rgb=spectral_to_rgb(spectralmix);
  208. return result;
  209. }
  210. #ifdef OUR_GLES
  211. vec4 uMixRoutineSelection(vec4 a, vec4 b, float fac_a){
  212. if(uMixRoutineSelectionES==0){ return DoMixNormal(a,b,fac_a); }
  213. else{ return DoMixSpectral(a,b,fac_a); }
  214. }
  215. #else
  216. subroutine uniform MixRoutines uMixRoutineSelection;
  217. #endif
  218. vec4 spectral_mix(vec4 a, vec4 b, float fac_a){
  219. return uMixRoutineSelection(a,b,fac_a);
  220. }
  221. vec4 spectral_mix_unpre(vec4 colora, vec4 colorb, float fac){
  222. vec4 ca=(colora.a==0.0f)?colora:vec4(colora.rgb/colora.a,colora.a);
  223. vec4 cb=(colorb.a==0.0f)?colorb:vec4(colorb.rgb/colorb.a,colorb.a);
  224. float af=colora.a*(1.0f-fac);
  225. float aa=af/(af+fac*colorb.a+0.000001);
  226. vec4 result=spectral_mix(ca,cb,aa);
  227. result.a=mix(colora.a,colorb.a,fac);
  228. return vec4(result.rgb*result.a,result.a);
  229. }
  230. float atan2(in float y, in float x){
  231. bool s = (abs(x) > abs(y)); return mix(3.1415926535/2.0 - atan(x,y), atan(y,x), s);
  232. }
  233. vec2 rotate(vec2 v, float angle) {
  234. float s = sin(angle); float c = cos(angle);
  235. return mat2(c,-s,s,c) * v;
  236. }
  237. float brightness(vec4 color) {
  238. return color.r*0.2126+color.b*0.7152+color.g*0.0722;
  239. }
  240. vec4 mix_over(vec4 colora, vec4 colorb){
  241. vec4 a=(colora.a==0.0f)?colora:vec4(colora.rgb/colora.a,colora.a);
  242. vec4 b=(colorb.a==0.0f)?colorb:vec4(colorb.rgb/colorb.a,colorb.a);
  243. vec4 m=vec4(0,0,0,0); float aa=colora.a/(colora.a+(1.0f-colora.a)*colorb.a+OUR_FLT_EPS);
  244. m=spectral_mix(a,b,aa);
  245. m.a=colora.a+colorb.a*(1.0f-colora.a);
  246. m=vec4(m.rgb*m.a,m.a);
  247. return m;
  248. }
  249. int dab(float d, vec2 fpx, vec4 color, float size, float hardness, float smudge, vec4 smudge_color, vec4 last_color, out vec4 final){
  250. vec4 cc=color;
  251. float fac=1.0f-pow(d/size,1.0f+1.0f/(1.0f-hardness+OUR_FLT_EPS));
  252. float canvas=SampleCanvas(fpx,uBrushDirection,fac,uBrushForce,uBrushGunkyness);
  253. cc.a=color.a*canvas*(1.0f-smudge); cc.rgb=cc.rgb*cc.a;
  254. float erasing=float(uBrushErasing);
  255. cc=cc*(1.0f-erasing);
  256. // this looks better than the one commented out below
  257. vec4 c2=spectral_mix_unpre(last_color,smudge_color,smudge*fac*color.a*canvas);
  258. c2=mix_over(cc,c2);
  259. //vec4 c2=mix_over(cc,last_color);
  260. //c2=spectral_mix_unpre(c2,smudge_color,smudge*fac*color.a*canvas);
  261. c2=spectral_mix_unpre(c2,c2*(1.0f-fac*color.a),erasing*canvas);
  262. final=c2;
  263. return 1;
  264. }
  265. #ifndef saturate
  266. #define saturate(v) clamp(v, 0., 1.)
  267. #endif
  268. const float HCV_EPSILON = 1e-10;
  269. const float HCY_EPSILON = 1e-10;
  270. vec3 hue_to_rgb(float hue){
  271. float R = abs(hue * 6. - 3.) - 1.;
  272. float G = 2. - abs(hue * 6. - 2.);
  273. float B = 2. - abs(hue * 6. - 4.);
  274. return saturate(vec3(R,G,B));
  275. }
  276. vec3 hcy_to_rgb(vec3 hcy){
  277. const vec3 HCYwts = vec3(0.299, 0.587, 0.114);
  278. vec3 RGB = hue_to_rgb(hcy.x);
  279. float Z = dot(RGB, HCYwts);
  280. if (hcy.z < Z) { hcy.y *= hcy.z / Z; }
  281. else if (Z < 1.) { hcy.y *= (1. - hcy.z) / (1. - Z); }
  282. return (RGB - Z) * hcy.y + hcy.z;
  283. }
  284. vec3 rgb_to_hcv(vec3 rgb){
  285. // Based on work by Sam Hocevar and Emil Persson
  286. vec4 P = (rgb.g < rgb.b) ? vec4(rgb.bg, -1.0, 2.0/3.0) : vec4(rgb.gb, 0.0, -1.0/3.0);
  287. vec4 Q = (rgb.r < P.x) ? vec4(P.xyw, rgb.r) : vec4(rgb.r, P.yzx);
  288. float C = Q.x - min(Q.w, Q.y);
  289. float H = abs((Q.w - Q.y) / (6. * C + HCV_EPSILON) + Q.z);
  290. return vec3(H, C, Q.x);
  291. }
  292. vec3 rgb_to_hcy(vec3 rgb){
  293. const vec3 HCYwts = vec3(0.299, 0.587, 0.114);
  294. // Corrected by David Schaeffer
  295. vec3 HCV = rgb_to_hcv(rgb);
  296. float Y = dot(rgb, HCYwts);
  297. float Z = dot(hue_to_rgb(HCV.x), HCYwts);
  298. if (Y < Z) { HCV.y *= Z / (HCY_EPSILON + Y); }
  299. else { HCV.y *= (1. - Z) / (HCY_EPSILON + 1. - Y); }
  300. return vec3(HCV.x, HCV.y, Y);
  301. }
  302. #ifndef OUR_GLES
  303. subroutine void BrushRoutines();
  304. #endif
  305. #ifdef OUR_CANVAS_MODE_RGB
  306. #ifndef OUR_GLES
  307. subroutine(BrushRoutines)
  308. #endif
  309. void DoDabs(){
  310. ivec2 px = ivec2(gl_GlobalInvocationID.xy)+uBrushCorner;
  311. if(px.x<0||px.y<0||px.x>1024||px.y>1024) return;
  312. vec2 fpx=vec2(px),origfpx=fpx;
  313. fpx=uBrushCenter+rotate(fpx-uBrushCenter,uBrushAngle);
  314. fpx.x=uBrushCenter.x+(fpx.x-uBrushCenter.x)*(1.+uBrushSlender);
  315. float dd=distance(fpx,uBrushCenter); if(dd>uBrushSize) return;
  316. vec4 dabc=OurImageLoad(img, px);
  317. vec4 smudgec=pow(spectral_mix_unpre(pow(OurImageLoad(smudge_buckets,ivec2(1,0)),p1_22),pow(OurImageLoad(smudge_buckets,ivec2(0,0)),p1_22),uBrushRecentness),p22);
  318. vec4 final_color;
  319. dab(dd,origfpx,uBrushColor,uBrushSize,uBrushHardness,uBrushSmudge,smudgec,dabc,final_color);
  320. if(final_color.a>0.){
  321. if(uBrushMix==0){ dabc=final_color; }
  322. else if(uBrushMix==1){ dabc.rgb=final_color.rgb/final_color.a*dabc.a;}
  323. else if(uBrushMix==2){ vec3 xyz=rgb_to_hcy(dabc.rgb); xyz.xy=rgb_to_hcy(final_color.rgb).xy; dabc.rgb=hcy_to_rgb(xyz); }
  324. else if(uBrushMix==3){ dabc.rgb=dabc.rgb+final_color.rgb*0.01;dabc.a=dabc.a*0.99+final_color.a*0.01; }
  325. OurImageStore(img, px, dabc);
  326. }
  327. }
  328. #ifndef OUR_GLES
  329. subroutine(BrushRoutines)
  330. #endif
  331. void DoSample(){
  332. ivec2 p=ivec2(gl_GlobalInvocationID.xy);
  333. int DoSample=1; vec4 color;
  334. if(p.y==0){
  335. vec2 sp=round(vec2(sin(float(p.x)),cos(float(p.x)))*uBrushSize);
  336. ivec2 px=ivec2(sp)+uBrushCorner; if(px.x<0||px.y<0||px.x>=1024||px.y>=1024){ DoSample=0; }
  337. if(DoSample!=0){
  338. ivec2 b=uBrushCorner; if(b.x>=0&&b.y>=0&&b.x<1024&&b.y<1024){ OurImageStore(smudge_buckets,ivec2(128+WORKGROUP_SIZE,0),OurImageLoad(img, b)); }
  339. color=OurImageLoad(img, px);
  340. OurImageStore(smudge_buckets,ivec2(p.x+128,0),color);
  341. }
  342. }else{DoSample=0;}
  343. memoryBarrier();barrier(); if(DoSample==0) return;
  344. if(uBrushErasing==0 || p.x!=0) return;
  345. color=vec4(0.,0.,0.,0.); for(int i=0;i<WORKGROUP_SIZE;i++){ color=color+OurImageLoad(smudge_buckets, ivec2(i+128,0)); }
  346. color=spectral_mix_unpre(color/vec4(WORKGROUP_SIZE),OurImageLoad(smudge_buckets, ivec2(128+WORKGROUP_SIZE,0)),0.6*(1.0f-uBrushColor.a)); vec4 oldcolor=OurImageLoad(smudge_buckets, ivec2(0,0));
  347. OurImageStore(smudge_buckets,ivec2(1,0),uBrushErasing==2?color:oldcolor);
  348. OurImageStore(smudge_buckets,ivec2(0,0),color);
  349. }
  350. #endif // canvas mode rgb
  351. #ifdef OUR_CANVAS_MODE_PIGMENT //========================================================================================
  352. #define GetImgPixel(tex, uv, p) \
  353. { \
  354. uvec4 c0=imageLoad(tex,uv); \
  355. uvec4 c1=imageLoad(tex,ivec2(uv.x,uv.y+1)); \
  356. uvec4 c2=imageLoad(tex,ivec2(uv.x+1,uv.y)); \
  357. uvec4 c3=imageLoad(tex,ivec2(uv.x+1,uv.y+1)); \
  358. setRL(c0,p); setRH(c1,p); setAL(c2,p); setAH(c3,p); \
  359. }
  360. #define WriteImgPixel(tex, uv, p) \
  361. { \
  362. uvec4 c0=getRL(p); uvec4 c1=getRH(p); uvec4 c2=getAL(p); uvec4 c3=getAH(p); \
  363. imageStore(tex,uv,c0); \
  364. imageStore(tex,ivec2(uv.x,uv.y+1),c1); \
  365. imageStore(tex,ivec2(uv.x+1,uv.y),c2); \
  366. imageStore(tex,ivec2(uv.x+1,uv.y+1),c3); \
  367. }
  368. int dab_pigment(float d, vec2 fpx, PigmentData color, float size, float hardness,
  369. float smudge, PigmentData smudge_color, PigmentData last_color, out PigmentData final){
  370. PigmentData cc=(uBrushErasing!=0)?PIGMENT_BLANK:color;
  371. float erasing=float(uBrushErasing);
  372. float fac=1.0f-pow(d/size,1.0f+1.0f/(1.0f-hardness+OUR_FLT_EPS));
  373. float canvas=SampleCanvas(fpx,uBrushDirection,fac,uBrushForce,uBrushGunkyness);
  374. if(uBrushErasing!=0){
  375. PigmentData smudged_color=PigmentMix(last_color,smudge_color,smudge*fac*canvas);
  376. final=PigmentMix(smudged_color,PIGMENT_BLANK,erasing*canvas*fac);
  377. }else{
  378. cc.a[15]=color.a[15]*canvas*fac*(1.-smudge);
  379. cc.r[15]=color.r[15]*canvas*fac*(1.-smudge);
  380. PigmentData smudged_color=PigmentMix(last_color,smudge_color,smudge*fac*canvas);
  381. PigmentData added_color=PigmentOver(cc,smudged_color);
  382. final=added_color;//PigmentInterpolate(added_color,smudged_color,smudge);
  383. }
  384. return 1;
  385. }
  386. #ifndef OUR_GLES
  387. subroutine(BrushRoutines)
  388. #endif
  389. void DoDabs(){
  390. ivec2 px = ivec2(gl_GlobalInvocationID.xy)*2+uBrushCorner; px/=2; px*=2;
  391. if(px.x<0||px.y<0||px.x>=1024||px.y>=1024) return; vec2 fpx=vec2(px),origfpx=fpx;
  392. fpx=uBrushCenter+rotate(fpx-uBrushCenter,uBrushAngle);
  393. fpx.x=uBrushCenter.x+(fpx.x-uBrushCenter.x)*(1.+uBrushSlender);
  394. float dd=distance(fpx,uBrushCenter); if(dd>uBrushSize) return;
  395. PigmentData dabc; GetImgPixel(img, px, dabc);
  396. PigmentData sm_old; ivec2 oldvec=ivec2(2,0); GetImgPixel(smudge_buckets,oldvec,sm_old);
  397. PigmentData sm_new; ivec2 newvec=ivec2(0,0); GetImgPixel(smudge_buckets,newvec,sm_new);
  398. PigmentData smudgec=PigmentMix(sm_old,sm_new,uBrushRecentness);
  399. PigmentData final_color;
  400. dab_pigment(dd,origfpx,uBrushPigment.p,uBrushSize,uBrushHardness,uBrushSmudge,smudgec,dabc,final_color);
  401. if(final_color.a[15]>0. || final_color.r[15]>0.){
  402. WriteImgPixel(img, px, final_color);
  403. }
  404. }
  405. #ifndef OUR_GLES
  406. subroutine(BrushRoutines)
  407. #endif
  408. void DoSample(){
  409. ivec2 p=ivec2(gl_GlobalInvocationID.xy);
  410. int DoSample=1; ivec2 corner=ivec2(uBrushCenter);
  411. if(p.y==0){
  412. vec2 sp=round(vec2(sin(float(p.x)),cos(float(p.x)))*(uBrushSize+2));
  413. ivec2 px=ivec2(sp)+corner; px/=2; px*=2; if(px.x<0||px.y<0||px.x>=1024||px.y>=1024){ DoSample=0; }
  414. if(DoSample!=0){
  415. PigmentData dabc; GetImgPixel(img, px, dabc);
  416. WriteImgPixel(smudge_buckets,ivec2(p.x*2+128,0),dabc);
  417. }
  418. }else{DoSample=0;}
  419. memoryBarrier();barrier(); if(DoSample==0) return;
  420. if(uBrushErasing==0 || p.x!=0) return;
  421. PigmentData color=PIGMENT_BLANK; for(int i=0;i<WORKGROUP_SIZE;i++){
  422. PigmentData dabc; GetImgPixel(smudge_buckets, ivec2(i*2+128,0), dabc); color=PigmentMix(color,dabc,1.0/float(i+1.));
  423. }
  424. PigmentData oldcolor; GetImgPixel(smudge_buckets, ivec2(0,0), oldcolor);
  425. //PigmentMultiply(color,2./WORKGROUP_SIZE);
  426. WriteImgPixel(smudge_buckets,ivec2(2,0),uBrushErasing==2?color:oldcolor);
  427. WriteImgPixel(smudge_buckets,ivec2(0,0),color);
  428. }
  429. #endif // canvas mode pigment
  430. #ifdef OUR_GLES
  431. void uBrushRoutineSelection(){
  432. if(uBrushRoutineSelectionES==0){ DoDabs(); }
  433. else{ DoSample(); }
  434. }
  435. #else
  436. subroutine uniform BrushRoutines uBrushRoutineSelection;
  437. #endif
  438. void main() {
  439. uBrushRoutineSelection();
  440. }
  441. )";
  442. const char OUR_COMPOSITION_SHADER[] = R"(
  443. layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
  444. #ifdef OUR_GLES
  445. precision highp uimage2D;
  446. precision highp float;
  447. precision highp int;
  448. layout(r32ui, binding = 0) uniform uimage2D top;
  449. layout(r32ui, binding = 1) uniform uimage2D bottom;
  450. #else
  451. layout(rgba16ui, binding = 0) uniform uimage2D top;
  452. layout(rgba16ui, binding = 1) uniform uimage2D bottom;
  453. #endif
  454. uniform int uBlendMode;
  455. uniform float uAlphaTop;
  456. uniform float uAlphaBottom;
  457. #with OUR_SHADER_COMMON
  458. vec4 mix_over(vec4 colora, vec4 colorb){
  459. colora=colora*uAlphaTop/uAlphaBottom;
  460. vec4 c; c.a=colora.a+colorb.a*(1.0f-colora.a);
  461. c.rgb=(colora.rgb+colorb.rgb*(1.0f-colora.a));
  462. return c;
  463. }
  464. vec4 add_over(vec4 colora, vec4 colorb){
  465. colora=colora*uAlphaTop/uAlphaBottom;
  466. vec4 a=colora+colorb; a.a=clamp(a.a,0.,1.); return a;
  467. }
  468. void main() {
  469. ivec2 px=ivec2(gl_GlobalInvocationID.xy);
  470. vec4 c1=OurImageLoad(top,px); vec4 c2=OurImageLoad(bottom,px);
  471. vec4 c=(uBlendMode==0)?mix_over(c1,c2):add_over(c1,c2);
  472. OurImageStore(bottom,px,c);
  473. OurImageStore(top,px,vec4(1.));
  474. }
  475. )";
  476. const char OUR_PIGMENT_COMMON[]=R"(
  477. #define POW_EPS (1e-7)
  478. #define USE_SAFE_POW 1
  479. #if USE_SAFE_POW
  480. float safepow(float a, float b){
  481. return pow(max(a,POW_EPS),b);
  482. }
  483. #else
  484. #define safepow pow
  485. #endif
  486. #define l8f(a) (float(((a)&0x00ff)>>0)/255.)
  487. #define h8f(a) (float(((a)&0xff00)>>8)/255.)
  488. #define fl16(l,h) ((uint((l)*255.))|((uint((h)*255.))<<8))
  489. #define OUR_SPECTRAL_SLICES 15
  490. struct PigmentData{ float r[16]; float a[16]; };
  491. const PigmentData PIGMENT_BLANK={{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.},{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}};
  492. const PigmentData PIGMENT_WHITE={{1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.},{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}};
  493. const PigmentData PIGMENT_BLACK={{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,1.},{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}};
  494. void setRL(uvec4 c, inout PigmentData p){
  495. p.r[0]=l8f(c[0]); p.r[1]=h8f(c[0]); p.r[2]=l8f(c[1]); p.r[3]=h8f(c[1]);
  496. p.r[4]=l8f(c[2]); p.r[5]=h8f(c[2]); p.r[6]=l8f(c[3]); p.r[7]=h8f(c[3]);
  497. }
  498. void setRH(uvec4 c, inout PigmentData p){
  499. p.r[8]= l8f(c[0]); p.r[9] =h8f(c[0]); p.r[10]=l8f(c[1]); p.r[11]=h8f(c[1]);
  500. p.r[12]=l8f(c[2]); p.r[13]=h8f(c[2]); p.r[14]=l8f(c[3]); p.r[15]=h8f(c[3]);
  501. }
  502. void setAL(uvec4 c, inout PigmentData p){
  503. p.a[0]=l8f(c[0]); p.a[1]=h8f(c[0]); p.a[2]=l8f(c[1]); p.a[3]=h8f(c[1]);
  504. p.a[4]=l8f(c[2]); p.a[5]=h8f(c[2]); p.a[6]=l8f(c[3]); p.a[7]=h8f(c[3]);
  505. }
  506. void setAH(uvec4 c, inout PigmentData p){
  507. p.a[8]= l8f(c[0]); p.a[9] =h8f(c[0]); p.a[10]=l8f(c[1]); p.a[11]=h8f(c[1]);
  508. p.a[12]=l8f(c[2]); p.a[13]=h8f(c[2]); p.a[14]=l8f(c[3]); p.a[15]=h8f(c[3]);
  509. }
  510. uvec4 getRL(PigmentData p){ uvec4 c;
  511. c[0]=fl16(p.r[0],p.r[1]); c[1]=fl16(p.r[2],p.r[3]);
  512. c[2]=fl16(p.r[4],p.r[5]); c[3]=fl16(p.r[6],p.r[7]); return c;
  513. }
  514. uvec4 getRH(PigmentData p){ uvec4 c;
  515. c[0]=fl16(p.r[8],p.r[9]); c[1]=fl16(p.r[10],p.r[11]);
  516. c[2]=fl16(p.r[12],p.r[13]); c[3]=fl16(p.r[14],p.r[15]); return c;
  517. }
  518. uvec4 getAL(PigmentData p){ uvec4 c;
  519. c[0]=fl16(p.a[0],p.a[1]); c[1]=fl16(p.a[2],p.a[3]);
  520. c[2]=fl16(p.a[4],p.a[5]); c[3]=fl16(p.a[6],p.a[7]); return c;
  521. }
  522. uvec4 getAH(PigmentData p){ uvec4 c;
  523. c[0]=fl16(p.a[8],p.a[9]); c[1]=fl16(p.a[10],p.a[11]);
  524. c[2]=fl16(p.a[12],p.a[13]); c[3]=fl16(p.a[14],p.a[15]); return c;
  525. }
  526. PigmentData GetPixel(usampler2D tex, ivec2 uv){
  527. uvec4 c0=texelFetch(tex,uv,0);
  528. uvec4 c1=texelFetch(tex,ivec2(uv.x,uv.y+1),0);
  529. uvec4 c2=texelFetch(tex,ivec2(uv.x+1,uv.y),0);
  530. uvec4 c3=texelFetch(tex,ivec2(uv.x+1,uv.y+1),0);
  531. PigmentData p;
  532. setRL(c0,p); setRH(c1,p); setAL(c2,p); setAH(c3,p);
  533. return p;
  534. }
  535. uvec4 PackPixel(PigmentData p, int choose){
  536. switch(choose){
  537. case 0: return getRL(p); case 1: return getRH(p);
  538. case 2: return getAL(p); case 3: return getAH(p);
  539. default: return uvec4(65535,0,65535,65535);
  540. }
  541. }
  542. void PigmentMixSlices(float a[16], inout float b[16], float factor){
  543. if(factor==1.) return; if(factor==0.){ for(int i=0;i<16;i++){b[i]=a[i];} return; }
  544. float fac=(1.0f-factor)*a[15]; float fac1=factor*b[15]; if(fac+fac1==0.){ return; }
  545. float scale=1.0/(fac+fac1); b[15]=mix(a[15],b[15],factor); fac*=scale; fac1*=scale;
  546. for(int i=0;i<15;i++){
  547. b[i]=safepow(a[i],fac)*safepow(b[i],fac1);
  548. }
  549. }
  550. void PigmentOverSlices(float a[16], inout float b[16]){
  551. float fac=a[15]; float fac1=(1.0f-fac)*b[15]; if(fac==0.) return;
  552. float scale=1.0/(fac+fac1); b[15]=fac1+fac; fac*=scale; fac1*=scale;
  553. for(int i=0;i<15;i++){
  554. b[i]=safepow(a[i],fac)*safepow(b[i],fac1);
  555. }
  556. }
  557. PigmentData PigmentMix(PigmentData p0, PigmentData p1, float factor){
  558. PigmentData result=p1;
  559. PigmentMixSlices(p0.a,result.a,factor);
  560. PigmentMixSlices(p0.r,result.r,factor);
  561. return result;
  562. }
  563. PigmentData PigmentOver(PigmentData p0, PigmentData p1){
  564. PigmentData result=p1;
  565. PigmentOverSlices(p0.a,result.a);
  566. PigmentOverSlices(p0.r,result.r);
  567. return result;
  568. }
  569. void PigmentAdd(inout PigmentData p, PigmentData on_top){
  570. for(int i=0;i<16;i++){ p.r[i]+=on_top.r[i]; p.a[i]+=on_top.a[i]; }
  571. }
  572. void PigmentMultiply(inout PigmentData p, float a){
  573. for(int i=0;i<15;i++){ p.r[i]*=a; p.a[i]*=a; }
  574. }
  575. PigmentData PigmentInterpolate(PigmentData p0, PigmentData p1, float fac){
  576. PigmentData a; for(int i=0;i<16;i++){ a.r[i]=mix(p0.r[i],p1.r[i],fac); a.a[i]=mix(p0.a[i],p1.a[i],fac); } return a;
  577. }
  578. vec3 XYZ2sRGB(vec3 xyz){
  579. mat3 mat=mat3(vec3(3.2404542,-1.5371385,-0.4985314),
  580. vec3(-0.9692660,1.8760108,0.0415560),
  581. vec3(0.0556434,-0.2040259,1.0572252));
  582. return xyz*mat;
  583. }
  584. float srgb_transfer_function(float a){
  585. return .0031308f >= a ? 12.92f * a : 1.055f * pow(a, .4166666666666667f) - .055f;
  586. }
  587. vec3 to_log_srgb(vec3 color){
  588. return vec3(srgb_transfer_function(color.r),srgb_transfer_function(color.g),srgb_transfer_function(color.b));
  589. }
  590. float PigmentCMF[3][16]={
  591. {0.0256137852631579,0.176998549473684,0.324992573684211,0.278209710526316,0.131263202631579,0.014745683,0.037739453368421,0.208473868421053,0.469442405263158,0.793365010526316,1.08417487894737,1.09022132105263,0.760274115789474,0.370996610526316,0.132563511052632,0.0379143815789474},
  592. {0.00273202863157895,0.0180098264736842,0.0448669426315789,0.0778269289473684,0.154425073684211,0.284083294736842,0.581026268421053,0.873226015789474,0.989738668421053,0.964781294736842,0.815827405263158,0.5850558,0.336884215789474,0.150147182631579,0.0515898715789474,0.0145470502631579},
  593. {0.127527536315789,0.914883057894737,1.77482205263158,1.653703,1.00137200526316,0.346880121052632,0.102993546315789,0.0227326414210526,0.00393168242105263,0.000625332878947368,0.000105245846315789,1.92985747368421E-05,0,0,0,0},
  594. };
  595. vec3 Spectral2XYZ(float spec[OUR_SPECTRAL_SLICES]){
  596. vec3 xyz=vec3(0.,0.,0.); float n=0.;
  597. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  598. xyz[0]+=spec[i]*PigmentCMF[0][i];
  599. xyz[1]+=spec[i]*PigmentCMF[1][i];
  600. xyz[2]+=spec[i]*PigmentCMF[2][i];
  601. n+=PigmentCMF[1][i];
  602. }
  603. vec3 XYZ;
  604. XYZ[0]=xyz[0]/n;
  605. XYZ[1]=xyz[1]/n;
  606. XYZ[2]=xyz[2]/n;
  607. return XYZ;
  608. }
  609. vec3 PigmentToRGB(PigmentData pd, PigmentData light){
  610. float slices[OUR_SPECTRAL_SLICES];
  611. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  612. float absfac=1.0f-pd.a[i]*pow(pd.a[15],2); if(absfac<0)absfac=0; slices[i]=pd.r[i]*absfac;
  613. slices[i]*= light.r[i];
  614. }
  615. vec3 xyz=Spectral2XYZ(slices); vec3 rgb=XYZ2sRGB(xyz); return rgb;
  616. }
  617. )";
  618. const char OUR_PIGMENT_TEXTURE_MIX_SHADER[]=R"(
  619. #extension GL_ARB_shading_language_420pack : enable // uniform sampler binding
  620. precision highp float;
  621. precision highp int;
  622. layout (binding=2) uniform highp usampler2D TexColorUI0;
  623. layout (binding=5) uniform highp usampler2D TexColorUI1;
  624. in vec2 fUV;
  625. layout(location = 0) out uvec4 outColor;
  626. #with OUR_PIGMENT_COMMON
  627. void main(){
  628. ivec2 iuv=ivec2(ivec2(fUV*512.)*2);
  629. ivec2 iuvscr=ivec2(gl_FragCoord.xy); int xof=iuvscr.x%2; int yof=iuvscr.y%2; iuvscr.x-=xof; iuvscr.y-=yof;
  630. PigmentData p0 = GetPixel(TexColorUI0,iuv);
  631. PigmentData p1 = GetPixel(TexColorUI1,iuvscr);
  632. PigmentData result = PigmentOver(p0,p1);
  633. int choose = xof*2+yof;
  634. uvec4 pixel = PackPixel(p0,choose);
  635. outColor=pixel;
  636. }
  637. )";
  638. const char OUR_PIGMENT_TEXTURE_DISPLAY_SHADER[]=R"(
  639. #extension GL_ARB_shading_language_420pack : enable // uniform sampler binding
  640. precision highp float;
  641. precision highp int;
  642. layout (binding=2) uniform highp usampler2D TexColorUI;
  643. uniform uvec2 display_size;
  644. in vec2 fUV;
  645. layout(location = 0) out vec4 outColor;
  646. #with OUR_PIGMENT_COMMON
  647. layout(std140) uniform CanvasPigmentBlock{
  648. PigmentData light;
  649. PigmentData paper;
  650. }uCanvasPigment;
  651. void main(){
  652. ivec2 iuv=ivec2(fUV*vec2(display_size)); int xof=iuv.x%2; int yof=iuv.y%2; iuv.x-=xof; iuv.y-=yof;
  653. PigmentData p0 = GetPixel(TexColorUI,iuv);
  654. PigmentData final = PigmentOver(p0,uCanvasPigment.paper);
  655. vec3 pixel = to_log_srgb(PigmentToRGB(final,uCanvasPigment.light));
  656. outColor=vec4(pixel,1.0);
  657. }
  658. )";