*/}}

ourshader.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  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"
  20. "#define WORKGROUP_SIZE 32\n";
  21. const char OUR_SHADER_VERSION_320ES[]="#version 320 es\n"
  22. "#define OUR_GLES\n#define WORKGROUP_SIZE 16\n";
  23. const char OUR_SHADER_COMMON[]=R"(
  24. #ifdef OUR_GLES
  25. vec4 cunpack(uint d){
  26. return vec4(float(d&0xFFu)/255.,float((d>>8u)&0xFFu)/255.,float((d>>16u)&0xFFu)/255.,float((d>>24u)&0xFFu)/255.);
  27. }
  28. uvec4 cpack(vec4 c){
  29. uint v= uint(uint(c.r*255.) | (uint(c.g*255.)<<8u) | (uint(c.b*255.)<<16u) | (uint(c.a*255.)<<24u));
  30. return uvec4(v,v,v,v);
  31. }
  32. #define OurImageLoad(img, p) \
  33. (cunpack(imageLoad(img,p).x))
  34. #define OurImageStore(img, p, color) \
  35. imageStore(img,p,cpack(color))
  36. #else
  37. #define OurImageLoad(img, p) \
  38. (vec4(imageLoad(img,p))/65535.)
  39. #define OurImageStore(img, p, color) \
  40. imageStore(img,p,uvec4(vec4(color)*65535.))
  41. #endif
  42. )";
  43. const char OUR_CANVAS_SHADER[]=R"(
  44. layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
  45. #ifdef OUR_GLES
  46. precision highp uimage2D;
  47. precision highp float;
  48. precision highp int;
  49. layout(r32ui, binding = 0) uniform uimage2D img;
  50. layout(r32ui, binding = 1) coherent uniform uimage2D smudge_buckets;
  51. #define OUR_FLT_EPS (1.0/255.0f)
  52. #else
  53. layout(rgba16ui, binding = 0) uniform uimage2D img;
  54. layout(rgba16ui, binding = 1) coherent uniform uimage2D smudge_buckets;
  55. #define OUR_FLT_EPS (1e-4)
  56. #endif
  57. uniform int uCanvasType;
  58. uniform int uCanvasRandom;
  59. uniform float uCanvasFactor;
  60. uniform ivec2 uImageOffset;
  61. uniform ivec2 uBrushCorner;
  62. uniform vec2 uBrushCenter;
  63. uniform float uBrushSize;
  64. uniform float uBrushHardness;
  65. uniform float uBrushSmudge;
  66. uniform float uBrushSlender;
  67. uniform float uBrushAngle;
  68. uniform vec2 uBrushDirection;
  69. uniform float uBrushForce;
  70. uniform float uBrushGunkyness;
  71. uniform float uBrushRecentness;
  72. uniform vec4 uBrushColor;
  73. uniform vec4 uBackgroundColor;
  74. uniform int uBrushErasing;
  75. uniform int uBrushMix;
  76. #ifdef OUR_GLES
  77. uniform int uBrushRoutineSelectionES;
  78. uniform int uMixRoutineSelectionES;
  79. #endif
  80. #ifdef OUR_CANVAS_MODE_PIGMENT
  81. #with OUR_PIGMENT_COMMON
  82. layout(std140) uniform BrushPigmentBlock{
  83. PigmentData p;
  84. }uBrushPigment;
  85. #endif
  86. #with OUR_SHADER_COMMON
  87. const vec4 p1_22=vec4(1.0/2.2,1.0/2.2,1.0/2.2,1.0/2.2);
  88. const vec4 p22=vec4(2.2,2.2,2.2,2.2);
  89. const float WGM_EPSILON=0.001f;
  90. const float T_MATRIX_SMALL[30] = float[30](0.026595621243689,0.049779426257903,0.022449850859496,-0.218453689278271
  91. ,-0.256894883201278,0.445881722194840,0.772365886289756,0.194498761382537
  92. ,0.014038157587820,0.007687264480513
  93. ,-0.032601672674412,-0.061021043498478,-0.052490001018404
  94. ,0.206659098273522,0.572496335158169,0.317837248815438,-0.021216624031211
  95. ,-0.019387668756117,-0.001521339050858,-0.000835181622534
  96. ,0.339475473216284,0.635401374177222,0.771520797089589,0.113222640692379
  97. ,-0.055251113343776,-0.048222578468680,-0.012966666339586
  98. ,-0.001523814504223,-0.000094718948810,-0.000051604594741);
  99. const float spectral_r_small[10] = float[10](0.009281362787953,0.009732627042016,0.011254252737167,0.015105578649573
  100. ,0.024797924177217,0.083622585502406,0.977865045723212,1.000000000000000
  101. ,0.999961046144372,0.999999992756822);
  102. const float spectral_g_small[10] = float[10](0.002854127435775,0.003917589679914,0.012132151699187,0.748259205918013
  103. ,1.000000000000000,0.865695937531795,0.037477469241101,0.022816789725717
  104. ,0.021747419446456,0.021384940572308);
  105. const float spectral_b_small[10] = float[10](0.537052150373386,0.546646402401469,0.575501819073983,0.258778829633924
  106. ,0.041709923751716,0.012662638828324,0.007485593127390,0.006766900622462
  107. ,0.006699764779016,0.006676219883241);
  108. void rgb_to_spectral (vec3 rgb, out float spectral_[10]) {
  109. float offset = 1.0 - WGM_EPSILON;
  110. float r = rgb.r * offset + WGM_EPSILON;
  111. float g = rgb.g * offset + WGM_EPSILON;
  112. float b = rgb.b * offset + WGM_EPSILON;
  113. 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;}
  114. 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;}
  115. 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;}
  116. for (int i=0; i<10; i++) {spectral_[i] = spec_r[i] + spec_g[i] + spec_b[i];}
  117. }
  118. vec3 spectral_to_rgb (float spectral[10]) {
  119. float offset = 1.0 - WGM_EPSILON;
  120. // We need this tmp. array to allow auto vectorization. <-- How about on GPU?
  121. float tmp[3] = float[3](0.,0.,0.);
  122. for (int i=0; i<10; i++) {
  123. tmp[0] += T_MATRIX_SMALL[i] * spectral[i];
  124. tmp[1] += T_MATRIX_SMALL[10+i] * spectral[i];
  125. tmp[2] += T_MATRIX_SMALL[20+i] * spectral[i];
  126. }
  127. vec3 rgb_;
  128. for (int i=0; i<3; i++) {rgb_[i] = clamp((tmp[i] - WGM_EPSILON) / offset, 0.0f, 1.0f);}
  129. return rgb_;
  130. }
  131. vec2 hash( vec2 p ){
  132. p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) );
  133. return -1.0 + 2.0*fract(sin(p)*43758.5453123);
  134. }
  135. float rand(vec2 co){
  136. return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
  137. }
  138. float noise(in vec2 p){ // from iq
  139. const float K1 = 0.366025404; // (sqrt(3)-1)/2;
  140. const float K2 = 0.211324865; // (3-sqrt(3))/6;
  141. vec2 i = floor( p + (p.x+p.y)*K1 );
  142. vec2 a = p - i + (i.x+i.y)*K2;
  143. float m = step(a.y,a.x);
  144. vec2 o = vec2(m,1.0-m);
  145. vec2 b = a - o + K2;
  146. vec2 c = a - 1.0 + 2.0*K2;
  147. vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
  148. vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
  149. return dot( n, vec3(70.0) );
  150. }
  151. #define HEIGHT_STRAND(x,y) abs(fract(x)-.5)<.48? \
  152. (.4+.2*sin(3.14*(y+ceil(x))))* \
  153. ((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
  154. #define PATTERN_CANVAS(x,y) \
  155. (max(HEIGHT_STRAND((x),(y)),HEIGHT_STRAND(-(y),(x))))
  156. float HEIGHT_CANVAS(float x,float y){
  157. if(uCanvasType == 1){
  158. return PATTERN_CANVAS(x,y);
  159. }else if(uCanvasType == 2){
  160. vec2 uv=vec2(x,y); float f; uv*=0.1; // from iq
  161. f = 0.2*noise( uv ); uv*=5.;
  162. f += 0.6*noise( uv ); uv*=3.;
  163. f += 0.5*noise( uv );
  164. f = 0.55 + 0.55*f;
  165. return pow(f,0.5);
  166. }
  167. return 1.;
  168. }
  169. float SampleCanvas(vec2 U, vec2 dir,float rfac, float force, float gunky){
  170. if(uCanvasType==0 || abs(gunky)<1.e-2){ return rfac; }
  171. U+=vec2(uImageOffset); U/=20.3; U.x=U.x+rand(U)/10.; U.y=U.y+rand(U)/10.;
  172. 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.;
  173. U.x+=noise(_uv)*2.1; _uv = m*_uv; U.x+=noise(_uv)*0.71;
  174. _uv.y+=365.404;
  175. U.y+=noise(_uv)*1.9; _uv = m*_uv; U.y+=noise(_uv)*0.83;
  176. float d=0.1;
  177. float h=HEIGHT_CANVAS(U.x,U.y);
  178. float hr=HEIGHT_CANVAS(U.x+d,U.y);
  179. float hu=HEIGHT_CANVAS(U.x,U.y+d);
  180. 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);
  181. float useforce=force*rfac;
  182. float scrape=dot(normalize(vz),vec3(-normalize(dir).xy,0))*mix(0.3,1.,useforce);
  183. float top=h-(1.-pow(useforce,1.5)*2.); float tophard=smoothstep(0.4,0.6,top);
  184. float fac=(gunky>=0.)?mix(mix(1.,top,gunky),tophard,gunky):mix(1.,1.-h,-gunky*0.8);
  185. fac=max(fac,scrape*clamp(gunky,0.,1.));
  186. fac=clamp(fac,0.,1.);
  187. fac*=rfac;
  188. return mix(rfac,fac,uCanvasFactor);
  189. }
  190. #ifndef OUR_GLES
  191. subroutine vec4 MixRoutines(vec4 a, vec4 b, float fac_a);
  192. #endif
  193. #ifndef OUR_GLES
  194. subroutine(MixRoutines)
  195. #endif
  196. vec4 DoMixNormal(vec4 a, vec4 b, float fac_a){
  197. return mix(a,b,1.0f-fac_a);
  198. }
  199. #ifndef OUR_GLES
  200. subroutine(MixRoutines)
  201. #endif
  202. vec4 DoMixSpectral(vec4 a, vec4 b, float fac_a){
  203. vec4 result = vec4(0,0,0,0);
  204. result.a=mix(a.a,b.a,1.0f-fac_a);
  205. float spec_a[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); rgb_to_spectral(a.rgb, spec_a);
  206. float spec_b[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.); rgb_to_spectral(b.rgb, spec_b);
  207. float spectralmix[10] = float[10](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.);
  208. for (int i=0; i < 10; i++) { spectralmix[i] = pow(spec_a[i], fac_a) * pow(spec_b[i], 1.0f-fac_a); }
  209. result.rgb=spectral_to_rgb(spectralmix);
  210. return result;
  211. }
  212. #ifdef OUR_GLES
  213. vec4 uMixRoutineSelection(vec4 a, vec4 b, float fac_a){
  214. if(uMixRoutineSelectionES==0){ return DoMixNormal(a,b,fac_a); }
  215. else{ return DoMixSpectral(a,b,fac_a); }
  216. }
  217. #else
  218. subroutine uniform MixRoutines uMixRoutineSelection;
  219. #endif
  220. vec4 spectral_mix(vec4 a, vec4 b, float fac_a){
  221. return uMixRoutineSelection(a,b,fac_a);
  222. }
  223. vec4 spectral_mix_always(vec4 colora, vec4 colorb, float fac){
  224. #ifndef OUR_STRAIGHT_ALPHA
  225. vec4 ca=(colora.a==0.0f)?colora:vec4(colora.rgb/colora.a,colora.a);
  226. vec4 cb=(colorb.a==0.0f)?colorb:vec4(colorb.rgb/colorb.a,colorb.a);
  227. #else
  228. vec4 ca=colora; vec4 cb=colorb;
  229. #endif
  230. float af=colora.a*(1.0f-fac);
  231. float aa=af/(af+fac*colorb.a+0.000001);
  232. vec4 result=spectral_mix(ca,cb,aa);
  233. result.a=mix(colora.a,colorb.a,fac);
  234. #ifndef OUR_STRAIGHT_ALPHA
  235. result = vec4(result.rgb*result.a,result.a);
  236. #endif
  237. return result;
  238. }
  239. float atan2(in float y, in float x){
  240. bool s = (abs(x) > abs(y)); return mix(3.1415926535/2.0 - atan(x,y), atan(y,x), s);
  241. }
  242. vec2 rotate(vec2 v, float angle) {
  243. float s = sin(angle); float c = cos(angle);
  244. return mat2(c,-s,s,c) * v;
  245. }
  246. float brightness(vec4 color) {
  247. return color.r*0.2126+color.b*0.7152+color.g*0.0722;
  248. }
  249. vec4 mix_over(vec4 colora, vec4 colorb){
  250. #ifndef OUR_STRAIGHT_ALPHA
  251. vec4 a=(colora.a==0.0f)?colora:vec4(colora.rgb/colora.a,colora.a);
  252. vec4 b=(colorb.a==0.0f)?colorb:vec4(colorb.rgb/colorb.a,colorb.a);
  253. #else
  254. vec4 a=colora; vec4 b=colorb;
  255. #endif
  256. vec4 m=vec4(0,0,0,0); float aa=colora.a/(colora.a+(1.0f-colora.a)*colorb.a+OUR_FLT_EPS);
  257. m=spectral_mix(a,b,aa);
  258. m.a=colora.a+colorb.a*(1.0f-colora.a);
  259. #ifndef OUR_STRAIGHT_ALPHA
  260. m=vec4(m.rgb*m.a,m.a);
  261. #endif
  262. return m;
  263. }
  264. int dab(float d, vec2 fpx, vec4 color, float size, float hardness, float smudge, vec4 smudge_color, vec4 last_color, out vec4 final){
  265. vec4 cc=color;
  266. float fac=1.0f-pow(d/size,1.0f+1.0f/(1.0f-hardness+OUR_FLT_EPS));
  267. float canvas=SampleCanvas(fpx,uBrushDirection,fac,uBrushForce,uBrushGunkyness);
  268. cc.a=color.a*canvas*(1.0f-smudge);
  269. #ifndef OUR_STRAIGHT_ALPHA
  270. cc.rgb=cc.rgb*cc.a;
  271. #endif
  272. float erasing=float(uBrushErasing);
  273. cc=cc*(1.0f-erasing);
  274. // this looks better than the one commented out below
  275. vec4 c2=spectral_mix_always(last_color,smudge_color,smudge*fac*color.a*canvas);
  276. c2=mix_over(cc,c2);
  277. //vec4 c2=mix_over(cc,last_color);
  278. //c2=spectral_mix_always(c2,smudge_color,smudge*fac*color.a*canvas);
  279. c2=spectral_mix_always(c2,c2*(1.0f-fac*color.a),erasing*canvas);
  280. final=c2;
  281. return 1;
  282. }
  283. #ifndef saturate
  284. #define saturate(v) clamp(v, 0., 1.)
  285. #endif
  286. const float HCV_EPSILON = 1e-10;
  287. const float HCY_EPSILON = 1e-10;
  288. vec3 hue_to_rgb(float hue){
  289. float R = abs(hue * 6. - 3.) - 1.;
  290. float G = 2. - abs(hue * 6. - 2.);
  291. float B = 2. - abs(hue * 6. - 4.);
  292. return saturate(vec3(R,G,B));
  293. }
  294. vec3 hcy_to_rgb(vec3 hcy){
  295. const vec3 HCYwts = vec3(0.299, 0.587, 0.114);
  296. vec3 RGB = hue_to_rgb(hcy.x);
  297. float Z = dot(RGB, HCYwts);
  298. if (hcy.z < Z) { hcy.y *= hcy.z / Z; }
  299. else if (Z < 1.) { hcy.y *= (1. - hcy.z) / (1. - Z); }
  300. return (RGB - Z) * hcy.y + hcy.z;
  301. }
  302. vec3 rgb_to_hcv(vec3 rgb){
  303. // Based on work by Sam Hocevar and Emil Persson
  304. vec4 P = (rgb.g < rgb.b) ? vec4(rgb.bg, -1.0, 2.0/3.0) : vec4(rgb.gb, 0.0, -1.0/3.0);
  305. vec4 Q = (rgb.r < P.x) ? vec4(P.xyw, rgb.r) : vec4(rgb.r, P.yzx);
  306. float C = Q.x - min(Q.w, Q.y);
  307. float H = abs((Q.w - Q.y) / (6. * C + HCV_EPSILON) + Q.z);
  308. return vec3(H, C, Q.x);
  309. }
  310. vec3 rgb_to_hcy(vec3 rgb){
  311. const vec3 HCYwts = vec3(0.299, 0.587, 0.114);
  312. // Corrected by David Schaeffer
  313. vec3 HCV = rgb_to_hcv(rgb);
  314. float Y = dot(rgb, HCYwts);
  315. float Z = dot(hue_to_rgb(HCV.x), HCYwts);
  316. if (Y < Z) { HCV.y *= Z / (HCY_EPSILON + Y); }
  317. else { HCV.y *= (1. - Z) / (HCY_EPSILON + 1. - Y); }
  318. return vec3(HCV.x, HCV.y, Y);
  319. }
  320. #ifndef OUR_GLES
  321. subroutine void BrushRoutines();
  322. #endif
  323. #ifdef OUR_CANVAS_MODE_RGB
  324. #ifndef OUR_GLES
  325. subroutine(BrushRoutines)
  326. #endif
  327. void DoDabs(){
  328. ivec2 px = ivec2(gl_GlobalInvocationID.xy)+uBrushCorner;
  329. if(px.x<0||px.y<0||px.x>1024||px.y>1024) return;
  330. vec2 fpx=vec2(px),origfpx=fpx;
  331. fpx=uBrushCenter+rotate(fpx-uBrushCenter,uBrushAngle);
  332. fpx.x=uBrushCenter.x+(fpx.x-uBrushCenter.x)*(1.+uBrushSlender);
  333. float dd=distance(fpx,uBrushCenter); if(dd>uBrushSize) return;
  334. vec4 dabc=OurImageLoad(img, px);
  335. vec4 smudgec=pow(spectral_mix_always(pow(OurImageLoad(smudge_buckets,ivec2(1,0)),p1_22),pow(OurImageLoad(smudge_buckets,ivec2(0,0)),p1_22),uBrushRecentness),p22);
  336. vec4 final_color;
  337. dab(dd,origfpx,uBrushColor,uBrushSize,uBrushHardness,uBrushSmudge,smudgec,dabc,final_color);
  338. if(final_color.a>0.){
  339. if(uBrushMix==0){ dabc=final_color; }
  340. else if(uBrushMix==1){ dabc.rgb=final_color.rgb/final_color.a*dabc.a;}
  341. 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); }
  342. else if(uBrushMix==3){ dabc.rgb=dabc.rgb+final_color.rgb*0.01;dabc.a=dabc.a*0.99+final_color.a*0.01; }
  343. OurImageStore(img, px, dabc);
  344. }
  345. }
  346. #ifndef OUR_GLES
  347. subroutine(BrushRoutines)
  348. #endif
  349. void DoSample(){
  350. ivec2 p=ivec2(gl_GlobalInvocationID.xy);
  351. int DoSample=1; vec4 color;
  352. if(p.y==0){
  353. vec2 sp=round(vec2(sin(float(p.x)),cos(float(p.x)))*uBrushSize);
  354. ivec2 px=ivec2(sp)+uBrushCorner; if(px.x<0||px.y<0||px.x>=1024||px.y>=1024){ DoSample=0; }
  355. if(DoSample!=0){
  356. 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)); }
  357. color=OurImageLoad(img, px);
  358. OurImageStore(smudge_buckets,ivec2(p.x+128,0),color);
  359. }
  360. }else{DoSample=0;}
  361. memoryBarrier();barrier(); if(DoSample==0) return;
  362. if(uBrushErasing==0 || p.x!=0) return;
  363. color=vec4(0.,0.,0.,0.); for(int i=0;i<WORKGROUP_SIZE;i++){ color=color+OurImageLoad(smudge_buckets, ivec2(i+128,0)); }
  364. color=spectral_mix_always(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));
  365. OurImageStore(smudge_buckets,ivec2(1,0),uBrushErasing==2?color:oldcolor);
  366. OurImageStore(smudge_buckets,ivec2(0,0),color);
  367. }
  368. #endif // canvas mode rgb
  369. )"
  370. R"(
  371. #ifdef OUR_CANVAS_MODE_PIGMENT //========================================================================================
  372. int dab_pigment(float d, vec2 fpx, PigmentData color, float size, float hardness,
  373. float smudge, PigmentData smudge_color, PigmentData last_color, out PigmentData final){
  374. PigmentData cc=(uBrushErasing!=0)?PIGMENT_BLANK:color;
  375. float erasing=float(uBrushErasing);
  376. float fac=1.0f-safepow(d/size,1.0f+1.0f/(1.0f-hardness+OUR_FLT_EPS));
  377. float canvas=SampleCanvas(fpx,uBrushDirection,fac,uBrushForce,uBrushGunkyness);
  378. if(uBrushErasing!=0){
  379. PigmentData smudged_color=PigmentMix(last_color,smudge_color,smudge*fac*canvas);
  380. final=PigmentMix(smudged_color,PIGMENT_BLANK,erasing*canvas*fac);
  381. }else{
  382. cc.a[15]=color.a[15]*canvas*fac*(1.-smudge);
  383. cc.r[15]=color.r[15]*canvas*fac*(1.-smudge);
  384. PigmentData smudged_color=PigmentMix(last_color,smudge_color,smudge*fac*canvas);
  385. PigmentData added_color=PigmentOver(cc,smudged_color);
  386. final=added_color;
  387. }
  388. return 1;
  389. }
  390. #ifndef OUR_GLES
  391. subroutine(BrushRoutines)
  392. #endif
  393. void DoDabs(){
  394. ivec2 px = ivec2(gl_GlobalInvocationID.xy)*2+uBrushCorner; px/=2; px*=2;
  395. if(px.x<0||px.y<0||px.x>=1024||px.y>=1024) return; vec2 fpx=vec2(px),origfpx=fpx;
  396. fpx=uBrushCenter+rotate(fpx-uBrushCenter,uBrushAngle);
  397. fpx.x=uBrushCenter.x+(fpx.x-uBrushCenter.x)*(1.+uBrushSlender);
  398. float dd=distance(fpx,uBrushCenter); if(dd>uBrushSize) return;
  399. PigmentData dabc; GetImgPixel(img, px, dabc);
  400. PigmentData sm_old; ivec2 oldvec=ivec2(2,0); GetImgPixel(smudge_buckets,oldvec,sm_old);
  401. PigmentData sm_new; ivec2 newvec=ivec2(0,0); GetImgPixel(smudge_buckets,newvec,sm_new);
  402. PigmentData smudgec=PigmentMix(sm_old,sm_new,uBrushRecentness);
  403. PigmentData final_color;
  404. dab_pigment(dd,origfpx,uBrushPigment.p,uBrushSize,uBrushHardness,uBrushSmudge,smudgec,dabc,final_color);
  405. if(final_color.a[15]>0. || final_color.r[15]>0.){
  406. WriteImgPixel(img, px, final_color);
  407. }
  408. }
  409. #ifndef OUR_GLES
  410. subroutine(BrushRoutines)
  411. #endif
  412. void DoSample(){
  413. ivec2 p=ivec2(gl_GlobalInvocationID.xy);
  414. int DoSample=1; ivec2 corner=ivec2(uBrushCenter);
  415. if(p.y==0){
  416. vec2 sp=round(vec2(sin(float(p.x)),cos(float(p.x)))*(uBrushSize+2.));
  417. ivec2 px=ivec2(sp)+corner; px/=2; px*=2; if(px.x<0||px.y<0||px.x>=1024||px.y>=1024){ DoSample=0; }
  418. if(DoSample!=0){
  419. PigmentData dabc; GetImgPixel(img, px, dabc);
  420. WriteImgPixel(smudge_buckets,ivec2(p.x*2+128,0),dabc);
  421. }
  422. }else{DoSample=0;}
  423. memoryBarrier();barrier(); if(DoSample==0) return;
  424. if(uBrushErasing==0 || p.x!=0) return;
  425. PigmentData color=PIGMENT_BLANK; for(int i=0;i<WORKGROUP_SIZE;i++){
  426. PigmentData dabc; GetImgPixel(smudge_buckets, ivec2(i*2+128,0), dabc); color=PigmentMix(color,dabc,1.0/(float(i)+1.));
  427. }
  428. PigmentData oldcolor; GetImgPixel(smudge_buckets, ivec2(0,0), oldcolor);
  429. //PigmentMultiply(color,2./WORKGROUP_SIZE);
  430. WriteImgPixel(smudge_buckets,ivec2(2,0),uBrushErasing==2?color:oldcolor);
  431. WriteImgPixel(smudge_buckets,ivec2(0,0),color);
  432. }
  433. #endif // canvas mode pigment
  434. #ifdef OUR_GLES
  435. void uBrushRoutineSelection(){
  436. if(uBrushRoutineSelectionES==0){ DoDabs(); }
  437. else{ DoSample(); }
  438. }
  439. #else
  440. subroutine uniform BrushRoutines uBrushRoutineSelection;
  441. #endif
  442. void main() {
  443. uBrushRoutineSelection();
  444. }
  445. )";
  446. const char OUR_COMPOSITION_SHADER[] = R"(
  447. layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
  448. #ifdef OUR_GLES
  449. precision highp uimage2D;
  450. precision highp float;
  451. precision highp int;
  452. layout(r32ui, binding = 0) uniform uimage2D top;
  453. layout(r32ui, binding = 1) uniform uimage2D bottom;
  454. #else
  455. layout(rgba16ui, binding = 0) uniform uimage2D top;
  456. layout(rgba16ui, binding = 1) uniform uimage2D bottom;
  457. #endif
  458. uniform int uBlendMode;
  459. uniform float uAlphaTop;
  460. uniform float uAlphaBottom;
  461. #with OUR_SHADER_COMMON
  462. vec4 mix_over(vec4 colora, vec4 colorb){
  463. #ifdef OUR_STRAIGHT_ALPHA
  464. colora=vec4(colora.rgb*colora.a,colora.a);
  465. colorb=vec4(colorb.rgb*colorb.a,colorb.a);
  466. #endif
  467. colora=colora*uAlphaTop/uAlphaBottom;
  468. vec4 c; c.a=colora.a+colorb.a*(1.0f-colora.a);
  469. c.rgb=(colora.rgb+colorb.rgb*(1.0f-colora.a));
  470. #ifdef OUR_STRAIGHT_ALPHA
  471. c=(c.a!=0.)?vec4(c.rgb/c.a,c.a):vec4(0.,0.,0.,0.);
  472. #endif
  473. return c;
  474. }
  475. vec4 add_over(vec4 colora, vec4 colorb){
  476. #ifdef OUR_STRAIGHT_ALPHA
  477. colora=vec4(colora.rgb*colora.a,colora.a);
  478. colorb=vec4(colorb.rgb*colorb.a,colorb.a);
  479. #endif
  480. colora=colora*uAlphaTop/uAlphaBottom;
  481. vec4 result=colora+colorb; result.a=clamp(result.a,0.,1.);
  482. #ifdef OUR_STRAIGHT_ALPHA
  483. result=result.a!=0.?vec4(result.rgb/result.a,result.a):vec4(0.,0.,0.,0.);
  484. #endif
  485. return result;
  486. }
  487. void main() {
  488. ivec2 px=ivec2(gl_GlobalInvocationID.xy);
  489. vec4 c1=OurImageLoad(top,px); vec4 c2=OurImageLoad(bottom,px);
  490. vec4 c=(uBlendMode==0)?mix_over(c1,c2):add_over(c1,c2);
  491. OurImageStore(bottom,px,c);
  492. OurImageStore(top,px,vec4(1.));
  493. }
  494. )";
  495. const char OUR_PIGMENT_COMMON[]=R"(
  496. #define POW_EPS (1.0e-9)
  497. #define USE_SAFE_POW 1
  498. #if USE_SAFE_POW
  499. float safepow(float a, float b){
  500. return pow(max(a,POW_EPS),b);
  501. }
  502. #else
  503. #define safepow pow
  504. #endif
  505. #define OUR_SPECTRAL_SLICES 14
  506. struct PigmentData{ float r[16]; float a[16]; };
  507. const PigmentData PIGMENT_BLANK=
  508. PigmentData(float[16](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.),float[16](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.));
  509. const PigmentData PIGMENT_WHITE=
  510. PigmentData(float[16](1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.),float[16](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.));
  511. const PigmentData PIGMENT_BLACK=
  512. PigmentData(float[16](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,1.),float[16](0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.));
  513. #ifdef OUR_GLES
  514. #define PixType uint
  515. #define PREC_FIX (0.0/15.)
  516. #define fetchpix(tex,uv,level) texelFetch(tex,uv,level).x
  517. #define loadpix(tex,uv) imageLoad(tex,uv).x
  518. #define packpix(c) uvec4(c)
  519. #define l8f(a) (float((uint(a)&0x0fu)>>0)/15.)
  520. #define h8f(a) (float((uint(a)&0xf0u)>>4)/15.)
  521. #define lh16f(a) (float(a)/255.)
  522. #define fl16(l,h) (clamp((uint((l+PREC_FIX)*15.)),0u,15u)|(clamp((uint((h+PREC_FIX)*15.)),0u,15u)<<4))
  523. #define fl16w(a) (uint(a*255.))
  524. uvec4 pixunpack(PixType c_){
  525. return uvec4((uint(c_)&0xffu),(uint(c_>>8)&0xffu),(uint(c_>>16)&0xffu),(uint(c_>>24)&0xffu));
  526. }
  527. PixType pixpack(uvec4 c){
  528. return uint(((c[0])&0xffu)|(((c[1])&0xffu)<<8)|(((c[2])&0xffu)<<16)|(((c[3])&0xffu)<<24));
  529. }
  530. void setRL(PixType c_, inout PigmentData p){
  531. uvec4 c=pixunpack(c_);
  532. p.r[0]=l8f(c[0]); p.r[1]=h8f(c[0]); p.r[2]=l8f(c[1]); p.r[3]=h8f(c[1]);
  533. p.r[4]=l8f(c[2]); p.r[5]=h8f(c[2]); p.r[6]=l8f(c[3]); p.r[7]=h8f(c[3]);
  534. }
  535. void setRH(PixType c_, inout PigmentData p){
  536. uvec4 c=pixunpack(c_);
  537. p.r[8]= l8f(c[0]); p.r[9] =h8f(c[0]); p.r[10]=l8f(c[1]); p.r[11]=h8f(c[1]);
  538. p.r[12]=l8f(c[2]); p.r[13]=h8f(c[2]); p.r[14]=0.; p.r[15]=lh16f(c[3]); //p.r[14]=l8f(c[3]); p.r[15]=h8f(c[3]);
  539. }
  540. void setAL(PixType c_, inout PigmentData p){
  541. uvec4 c=pixunpack(c_);
  542. p.a[0]=l8f(c[0]); p.a[1]=h8f(c[0]); p.a[2]=l8f(c[1]); p.a[3]=h8f(c[1]);
  543. p.a[4]=l8f(c[2]); p.a[5]=h8f(c[2]); p.a[6]=l8f(c[3]); p.a[7]=h8f(c[3]);
  544. }
  545. void setAH(PixType c_, inout PigmentData p){
  546. uvec4 c=pixunpack(c_);
  547. p.a[8]= l8f(c[0]); p.a[9] =h8f(c[0]); p.a[10]=l8f(c[1]); p.a[11]=h8f(c[1]);
  548. p.a[12]=l8f(c[2]); p.a[13]=h8f(c[2]); p.a[14]=0.; p.a[15]=lh16f(c[3]); //p.a[14]=l8f(c[3]); p.a[15]=h8f(c[3]);
  549. }
  550. PixType getRL(PigmentData p){ uvec4 c;
  551. c[0]=fl16(p.r[0],p.r[1]); c[1]=fl16(p.r[2],p.r[3]);
  552. c[2]=fl16(p.r[4],p.r[5]); c[3]=fl16(p.r[6],p.r[7]); return pixpack(c);
  553. }
  554. PixType getRH(PigmentData p){ uvec4 c;
  555. c[0]=fl16(p.r[8],p.r[9]); c[1]=fl16(p.r[10],p.r[11]);
  556. c[2]=fl16(p.r[12],p.r[13]); c[3]=fl16w(p.r[15]); //c[3]=fl16(p.r[14],p.r[15]);
  557. return pixpack(c);
  558. }
  559. PixType getAL(PigmentData p){ uvec4 c;
  560. c[0]=fl16(p.a[0],p.a[1]); c[1]=fl16(p.a[2],p.a[3]);
  561. c[2]=fl16(p.a[4],p.a[5]); c[3]=fl16(p.a[6],p.a[7]); return pixpack(c);
  562. }
  563. PixType getAH(PigmentData p){ uvec4 c;
  564. c[0]=fl16(p.a[8],p.a[9]); c[1]=fl16(p.a[10],p.a[11]);
  565. c[2]=fl16(p.a[12],p.a[13]); c[3]=fl16w(p.a[15]); //c[3]=fl16(p.a[14],p.a[15]);
  566. return pixpack(c);
  567. }
  568. PixType PixelAvg2(PixType a_, PixType b_){
  569. uvec4 a=pixunpack(a_); uvec4 b=pixunpack(b_);
  570. uvec4 r;
  571. r[0]=(((a[0]&0xffu)+(b[0]&0xffu))/2u)|((((a[0]&0xff00u)+(b[0]&0xff00u))/2u)&0xff00u);
  572. r[1]=(((a[1]&0xffu)+(b[1]&0xffu))/2u)|((((a[1]&0xff00u)+(b[1]&0xff00u))/2u)&0xff00u);
  573. r[2]=(((a[2]&0xffu)+(b[2]&0xffu))/2u)|((((a[2]&0xff00u)+(b[2]&0xff00u))/2u)&0xff00u);
  574. r[3]=(((a[3]&0xffu)+(b[3]&0xffu))/2u)|((((a[3]&0xff00u)+(b[3]&0xff00u))/2u)&0xff00u);
  575. return pixpack(r);
  576. }
  577. PixType PixelAvg2H(PixType a_, PixType b_){
  578. uvec4 a=pixunpack(a_); uvec4 b=pixunpack(b_);
  579. uvec4 r;
  580. r[0]=(((a[0]&0xffu)+(b[0]&0xffu))/2u)|((((a[0]&0xff00u)+(b[0]&0xff00u))/2u)&0xff00u);
  581. r[1]=(((a[1]&0xffu)+(b[1]&0xffu))/2u)|((((a[1]&0xff00u)+(b[1]&0xff00u))/2u)&0xff00u);
  582. r[2]=(((a[2]&0xffu)+(b[2]&0xffu))/2u)|((((a[2]&0xff00u)+(b[2]&0xff00u))/2u)&0xff00u);
  583. r[3]=(a[3]+b[3])/2u;
  584. return pixpack(r);
  585. }
  586. PixType PixelAvg4(PixType a_, PixType b_, PixType c_, PixType d_){
  587. uvec4 a=pixunpack(a_); uvec4 b=pixunpack(b_);
  588. uvec4 c=pixunpack(c_); uvec4 d=pixunpack(d_);
  589. uvec4 r;
  590. r[0]=(((a[0]&0xffu)+(b[0]&0xffu)+(c[0]&0xffu)+(d[0]&0xffu))/4u)|((((a[0]&0xff00u)+(b[0]&0xff00u)+(c[0]&0xff00u)+(d[0]&0xff00u))/4u)&0xff00u);
  591. r[1]=(((a[1]&0xffu)+(b[1]&0xffu)+(c[1]&0xffu)+(d[1]&0xffu))/4u)|((((a[1]&0xff00u)+(b[1]&0xff00u)+(c[1]&0xff00u)+(d[1]&0xff00u))/4u)&0xff00u);
  592. r[2]=(((a[2]&0xffu)+(b[2]&0xffu)+(c[2]&0xffu)+(d[2]&0xffu))/4u)|((((a[2]&0xff00u)+(b[2]&0xff00u)+(c[2]&0xff00u)+(d[2]&0xff00u))/4u)&0xff00u);
  593. r[3]=(((a[3]&0xffu)+(b[3]&0xffu)+(c[3]&0xffu)+(d[3]&0xffu))/4u)|((((a[3]&0xff00u)+(b[3]&0xff00u)+(c[3]&0xff00u)+(d[3]&0xff00u))/4u)&0xff00u);
  594. return pixpack(r);
  595. }
  596. PixType PixelAvg4H(PixType a_, PixType b_, PixType c_, PixType d_){
  597. uvec4 a=pixunpack(a_); uvec4 b=pixunpack(b_);
  598. uvec4 c=pixunpack(c_); uvec4 d=pixunpack(d_);
  599. uvec4 r;
  600. r[0]=(((a[0]&0xffu)+(b[0]&0xffu)+(c[0]&0xffu)+(d[0]&0xffu))/4u)|((((a[0]&0xff00u)+(b[0]&0xff00u)+(c[0]&0xff00u)+(d[0]&0xff00u))/4u)&0xff00u);
  601. r[1]=(((a[1]&0xffu)+(b[1]&0xffu)+(c[1]&0xffu)+(d[1]&0xffu))/4u)|((((a[1]&0xff00u)+(b[1]&0xff00u)+(c[1]&0xff00u)+(d[1]&0xff00u))/4u)&0xff00u);
  602. r[2]=(((a[2]&0xffu)+(b[2]&0xffu)+(c[2]&0xffu)+(d[2]&0xffu))/4u)|((((a[2]&0xff00u)+(b[2]&0xff00u)+(c[2]&0xff00u)+(d[2]&0xff00u))/4u)&0xff00u);
  603. r[3]=(a[3]+b[3]+c[3]+d[3])/4u;
  604. return pixpack(r);
  605. }
  606. #else // gles / desktop gl
  607. #define PixType uvec4
  608. #define PREC_FIX (0.25/255.)
  609. #define fetchpix texelFetch
  610. #define packpix(c) c
  611. #define loadpix imageLoad
  612. #define l8f(a) (float(((a)&0x00ffu)>>0)/255.)
  613. #define h8f(a) (float(((a)&0xff00u)>>8)/255.)
  614. #define lh16f(a) (float(a)/65535.)
  615. #define fl16(l,h) (clamp((uint((l+PREC_FIX)*255.)),0u,255u)|(clamp((uint((h+PREC_FIX)*255.)),0u,255u)<<8))
  616. #define fl16w(a) (uint(a*65535.))
  617. void setRL(uvec4 c, inout PigmentData p){
  618. p.r[0]=l8f(c[0]); p.r[1]=h8f(c[0]); p.r[2]=l8f(c[1]); p.r[3]=h8f(c[1]);
  619. p.r[4]=l8f(c[2]); p.r[5]=h8f(c[2]); p.r[6]=l8f(c[3]); p.r[7]=h8f(c[3]);
  620. }
  621. void setRH(uvec4 c, inout PigmentData p){
  622. p.r[8]= l8f(c[0]); p.r[9] =h8f(c[0]); p.r[10]=l8f(c[1]); p.r[11]=h8f(c[1]);
  623. p.r[12]=l8f(c[2]); p.r[13]=h8f(c[2]); p.r[14]=0.; p.r[15]=lh16f(c[3]); //p.r[14]=l8f(c[3]); p.r[15]=h8f(c[3]);
  624. }
  625. void setAL(uvec4 c, inout PigmentData p){
  626. p.a[0]=l8f(c[0]); p.a[1]=h8f(c[0]); p.a[2]=l8f(c[1]); p.a[3]=h8f(c[1]);
  627. p.a[4]=l8f(c[2]); p.a[5]=h8f(c[2]); p.a[6]=l8f(c[3]); p.a[7]=h8f(c[3]);
  628. }
  629. void setAH(uvec4 c, inout PigmentData p){
  630. p.a[8]= l8f(c[0]); p.a[9] =h8f(c[0]); p.a[10]=l8f(c[1]); p.a[11]=h8f(c[1]);
  631. p.a[12]=l8f(c[2]); p.a[13]=h8f(c[2]); p.a[14]=0.; p.a[15]=lh16f(c[3]); //p.a[14]=l8f(c[3]); p.a[15]=h8f(c[3]);
  632. }
  633. uvec4 getRL(PigmentData p){ uvec4 c;
  634. c[0]=fl16(p.r[0],p.r[1]); c[1]=fl16(p.r[2],p.r[3]);
  635. c[2]=fl16(p.r[4],p.r[5]); c[3]=fl16(p.r[6],p.r[7]); return c;
  636. }
  637. uvec4 getRH(PigmentData p){ uvec4 c;
  638. c[0]=fl16(p.r[8],p.r[9]); c[1]=fl16(p.r[10],p.r[11]);
  639. c[2]=fl16(p.r[12],p.r[13]); c[3]=fl16w(p.r[15]); //c[3]=fl16(p.r[14],p.r[15]);
  640. return c;
  641. }
  642. uvec4 getAL(PigmentData p){ uvec4 c;
  643. c[0]=fl16(p.a[0],p.a[1]); c[1]=fl16(p.a[2],p.a[3]);
  644. c[2]=fl16(p.a[4],p.a[5]); c[3]=fl16(p.a[6],p.a[7]); return c;
  645. }
  646. uvec4 getAH(PigmentData p){ uvec4 c;
  647. c[0]=fl16(p.a[8],p.a[9]); c[1]=fl16(p.a[10],p.a[11]);
  648. c[2]=fl16(p.a[12],p.a[13]); c[3]=fl16w(p.a[15]); //c[3]=fl16(p.a[14],p.a[15]);
  649. return c;
  650. }
  651. PixType PixelAvg2(PixType a, PixType b){
  652. PixType r;
  653. r[0]=(((a[0]&0xffu)+(b[0]&0xffu))/2u)|((((a[0]&0xff00u)+(b[0]&0xff00u))/2u)&0xff00u);
  654. r[1]=(((a[1]&0xffu)+(b[1]&0xffu))/2u)|((((a[1]&0xff00u)+(b[1]&0xff00u))/2u)&0xff00u);
  655. r[2]=(((a[2]&0xffu)+(b[2]&0xffu))/2u)|((((a[2]&0xff00u)+(b[2]&0xff00u))/2u)&0xff00u);
  656. r[3]=(((a[3]&0xffu)+(b[3]&0xffu))/2u)|((((a[3]&0xff00u)+(b[3]&0xff00u))/2u)&0xff00u);
  657. return r;
  658. }
  659. PixType PixelAvg2H(PixType a, PixType b){
  660. PixType r;
  661. r[0]=(((a[0]&0xffu)+(b[0]&0xffu))/2u)|((((a[0]&0xff00u)+(b[0]&0xff00u))/2u)&0xff00u);
  662. r[1]=(((a[1]&0xffu)+(b[1]&0xffu))/2u)|((((a[1]&0xff00u)+(b[1]&0xff00u))/2u)&0xff00u);
  663. r[2]=(((a[2]&0xffu)+(b[2]&0xffu))/2u)|((((a[2]&0xff00u)+(b[2]&0xff00u))/2u)&0xff00u);
  664. r[3]=(a[3]+b[3])/2u;
  665. return r;
  666. }
  667. PixType PixelAvg4(PixType a, PixType b, PixType c, PixType d){
  668. uvec4 r;
  669. r[0]=(((a[0]&0xffu)+(b[0]&0xffu)+(c[0]&0xffu)+(d[0]&0xffu))/4u)|((((a[0]&0xff00u)+(b[0]&0xff00u)+(c[0]&0xff00u)+(d[0]&0xff00u))/4u)&0xff00u);
  670. r[1]=(((a[1]&0xffu)+(b[1]&0xffu)+(c[1]&0xffu)+(d[1]&0xffu))/4u)|((((a[1]&0xff00u)+(b[1]&0xff00u)+(c[1]&0xff00u)+(d[1]&0xff00u))/4u)&0xff00u);
  671. r[2]=(((a[2]&0xffu)+(b[2]&0xffu)+(c[2]&0xffu)+(d[2]&0xffu))/4u)|((((a[2]&0xff00u)+(b[2]&0xff00u)+(c[2]&0xff00u)+(d[2]&0xff00u))/4u)&0xff00u);
  672. r[3]=(((a[3]&0xffu)+(b[3]&0xffu)+(c[3]&0xffu)+(d[3]&0xffu))/4u)|((((a[3]&0xff00u)+(b[3]&0xff00u)+(c[3]&0xff00u)+(d[3]&0xff00u))/4u)&0xff00u);
  673. return r;
  674. }
  675. PixType PixelAvg4H(PixType a, PixType b, PixType c, PixType d){
  676. uvec4 r;
  677. r[0]=(((a[0]&0xffu)+(b[0]&0xffu)+(c[0]&0xffu)+(d[0]&0xffu))/4u)|((((a[0]&0xff00u)+(b[0]&0xff00u)+(c[0]&0xff00u)+(d[0]&0xff00u))/4u)&0xff00u);
  678. r[1]=(((a[1]&0xffu)+(b[1]&0xffu)+(c[1]&0xffu)+(d[1]&0xffu))/4u)|((((a[1]&0xff00u)+(b[1]&0xff00u)+(c[1]&0xff00u)+(d[1]&0xff00u))/4u)&0xff00u);
  679. r[2]=(((a[2]&0xffu)+(b[2]&0xffu)+(c[2]&0xffu)+(d[2]&0xffu))/4u)|((((a[2]&0xff00u)+(b[2]&0xff00u)+(c[2]&0xff00u)+(d[2]&0xff00u))/4u)&0xff00u);
  680. r[3]=(a[3]+b[3]+c[3]+d[3])/4u;
  681. return r;
  682. }
  683. #endif // desktop gl
  684. PixType GetSubPixelH2(highp usampler2D tex, ivec2 uv, int offset){
  685. if(uv.x>=textureSize(tex,0).x-offset) return fetchpix(tex,ivec2(uv.x-offset,uv.y),0);
  686. if(uv.x<=offset) return fetchpix(tex,ivec2(uv.x+offset,uv.y),0);
  687. PixType a=fetchpix(tex,ivec2(uv.x-offset,uv.y),0);
  688. PixType b=fetchpix(tex,ivec2(uv.x+offset,uv.y),0);
  689. return PixelAvg2(a,b);
  690. }
  691. PixType GetSubPixelH2H(highp usampler2D tex, ivec2 uv, int offset){
  692. if(uv.x>=textureSize(tex,0).x-offset) return fetchpix(tex,ivec2(uv.x-offset,uv.y),0);
  693. if(uv.x<=offset) return fetchpix(tex,ivec2(uv.x+offset,uv.y),0);
  694. PixType a=fetchpix(tex,ivec2(uv.x-offset,uv.y),0);
  695. PixType b=fetchpix(tex,ivec2(uv.x+offset,uv.y),0);
  696. return PixelAvg2H(a,b);
  697. }
  698. PixType GetSubPixelV2(highp usampler2D tex, ivec2 uv, int offset){
  699. if(uv.y>=textureSize(tex,0).y-offset) return fetchpix(tex,ivec2(uv.x,uv.y-offset),0);
  700. if(uv.y<=offset) return fetchpix(tex,ivec2(uv.x,uv.y+offset),0);
  701. PixType a=fetchpix(tex,ivec2(uv.x,uv.y-offset),0);
  702. PixType b=fetchpix(tex,ivec2(uv.x,uv.y+offset),0);
  703. return PixelAvg2(a,b);
  704. }
  705. PixType GetSubPixelV2H(highp usampler2D tex, ivec2 uv, int offset){
  706. if(uv.y>=textureSize(tex,0).y-offset) return fetchpix(tex,ivec2(uv.x,uv.y-offset),0);
  707. if(uv.y<=offset) return fetchpix(tex,ivec2(uv.x,uv.y+offset),0);
  708. PixType a=fetchpix(tex,ivec2(uv.x,uv.y-offset),0);
  709. PixType b=fetchpix(tex,ivec2(uv.x,uv.y+offset),0);
  710. return PixelAvg2H(a,b);
  711. }
  712. PixType GetSubPixelX4(highp usampler2D tex, ivec2 uv, int offset){
  713. if(uv.x>=textureSize(tex,0).x-offset) return GetSubPixelV2(tex,ivec2(uv.x-offset,uv.y),offset);
  714. if(uv.y>=textureSize(tex,0).y-offset) return GetSubPixelH2(tex,ivec2(uv.x,uv.y-offset),offset);
  715. if(uv.x<=offset) return GetSubPixelV2(tex,ivec2(uv.x+offset,uv.y),offset);
  716. if(uv.y<=offset) return GetSubPixelH2(tex,ivec2(uv.x,uv.y+offset),offset);
  717. PixType a=fetchpix(tex,ivec2(uv.x-offset,uv.y-offset),0);
  718. PixType b=fetchpix(tex,ivec2(uv.x-offset,uv.y+offset),0);
  719. PixType c=fetchpix(tex,ivec2(uv.x+offset,uv.y-offset),0);
  720. PixType d=fetchpix(tex,ivec2(uv.x+offset,uv.y+offset),0);
  721. return PixelAvg4(a,b,c,d);
  722. }
  723. PixType GetSubPixelX4H(highp usampler2D tex, ivec2 uv, int offset){
  724. if(uv.x>=textureSize(tex,0).x-offset) return GetSubPixelV2(tex,ivec2(uv.x-offset,uv.y),offset);
  725. if(uv.y>=textureSize(tex,0).y-offset) return GetSubPixelH2(tex,ivec2(uv.x,uv.y-offset),offset);
  726. if(uv.x<=offset) return GetSubPixelV2(tex,ivec2(uv.x+offset,uv.y),offset);
  727. if(uv.y<=offset) return GetSubPixelH2(tex,ivec2(uv.x,uv.y+offset),offset);
  728. PixType a=fetchpix(tex,ivec2(uv.x-offset,uv.y-offset),0);
  729. PixType b=fetchpix(tex,ivec2(uv.x-offset,uv.y+offset),0);
  730. PixType c=fetchpix(tex,ivec2(uv.x+offset,uv.y-offset),0);
  731. PixType d=fetchpix(tex,ivec2(uv.x+offset,uv.y+offset),0);
  732. return PixelAvg4H(a,b,c,d);
  733. }
  734. PigmentData GetPixelDebayer(highp usampler2D tex, ivec2 uv, int offset){
  735. PixType c[4]; int s=(uv.x%2)*2+uv.y%2;
  736. if(s==0){
  737. c[0]=fetchpix(tex,uv,0);
  738. c[1]=GetSubPixelV2H(tex,uv,offset);
  739. c[2]=GetSubPixelH2(tex,uv,offset);
  740. c[3]=GetSubPixelX4H(tex,uv,offset);
  741. }else if(s==1){
  742. c[0]=GetSubPixelV2(tex,uv,offset);
  743. c[1]=fetchpix(tex,uv,0);
  744. c[2]=GetSubPixelX4(tex,uv,offset);
  745. c[3]=GetSubPixelH2H(tex,uv,offset);
  746. }else if(s==2){
  747. c[0]=GetSubPixelH2(tex,uv,offset);
  748. c[1]=GetSubPixelX4H(tex,uv,offset);
  749. c[2]=fetchpix(tex,uv,0);
  750. c[3]=GetSubPixelV2H(tex,uv,offset);
  751. }else{
  752. c[0]=GetSubPixelX4(tex,uv,offset);
  753. c[1]=GetSubPixelH2H(tex,uv,offset);
  754. c[2]=GetSubPixelV2(tex,uv,offset);
  755. c[3]=fetchpix(tex,uv,0);
  756. }
  757. PigmentData p;
  758. setRL(c[0],p); setRH(c[1],p); setAL(c[2],p); setAH(c[3],p);
  759. return p;
  760. }
  761. const uvec4 DB[4]=uvec4[4](uvec4(0,1,2,3),uvec4(1,0,3,2),uvec4(2,3,0,1),uvec4(3,2,1,0));
  762. PigmentData GetPixelQuick(highp usampler2D tex, ivec2 uv){
  763. PixType c[4];
  764. c[0]=fetchpix(tex,uv,0);
  765. c[1]=fetchpix(tex,ivec2(uv.x,uv.y+1),0);
  766. c[2]=fetchpix(tex,ivec2(uv.x+1,uv.y),0);
  767. c[3]=fetchpix(tex,ivec2(uv.x+1,uv.y+1),0);
  768. int s=uv.x%2*2+uv.y%2;
  769. PigmentData p;
  770. setRL(c[DB[s][0]],p); setRH(c[DB[s][1]],p); setAL(c[DB[s][2]],p); setAH(c[DB[s][3]],p);
  771. return p;
  772. }
  773. PigmentData GetPixel(highp usampler2D tex, ivec2 uv){
  774. PixType c0=fetchpix(tex,uv,0);
  775. PixType c1=fetchpix(tex,ivec2(uv.x,uv.y+1),0);
  776. PixType c2=fetchpix(tex,ivec2(uv.x+1,uv.y),0);
  777. PixType c3=fetchpix(tex,ivec2(uv.x+1,uv.y+1),0);
  778. PigmentData p;
  779. setRL(c0,p); setRH(c1,p); setAL(c2,p); setAH(c3,p);
  780. return p;
  781. }
  782. PixType PackPixel(PigmentData p, int choose){
  783. switch(choose){
  784. case 0: return getRL(p); case 1: return getRH(p);
  785. case 2: return getAL(p); case 3: return getAH(p);
  786. default: return PixType(0u);
  787. }
  788. }
  789. void PigmentMixSlices(float a[16], inout float b[16], float factor){
  790. if(factor==1.) return; if(factor==0.){ for(int i=0;i<16;i++){b[i]=a[i];} return; }
  791. float fac=(1.0f-factor)*a[15]; float fac1=factor*b[15]; if(fac+fac1==0.){ return; }
  792. float scale=1.0/(fac+fac1); b[15]=mix(a[15],b[15],factor); fac*=scale; fac1*=scale;
  793. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  794. b[i]=safepow(a[i],fac)*safepow(b[i],fac1);
  795. }
  796. }
  797. void PigmentMixSlicesInverted(float a[16], inout float b[16], float factor){
  798. if(factor==1.) return; if(factor==0.){ for(int i=0;i<16;i++){b[i]=a[i];} return; }
  799. float fac=(1.0f-factor)*a[15]; float fac1=factor*b[15]; if(fac+fac1==0.){ return; }
  800. float scale=1.0/(fac+fac1); b[15]=mix(a[15],b[15],factor); fac*=scale; fac1*=scale;
  801. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  802. b[i]=1.-safepow(1.-a[i],fac)*safepow(1.-b[i],fac1);
  803. }
  804. }
  805. void PigmentOverSlices(float a[16], inout float b[16]){
  806. float fac=a[15]; float fac1=(1.0f-fac)*b[15]; if(fac==0.) return;
  807. float scale=1.0/(fac+fac1); b[15]=fac1+fac; fac*=scale; fac1*=scale;
  808. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  809. b[i]=safepow(a[i],fac)*safepow(b[i],fac1);
  810. }
  811. }
  812. void PigmentOverSlicesInverted(float a[16], inout float b[16]){
  813. float fac=a[15]; float fac1=(1.0f-fac)*b[15]; if(fac==0.) return;
  814. float scale=1.0/(fac+fac1); b[15]=fac1+fac; fac*=scale; fac1*=scale;
  815. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  816. b[i]=1.-safepow((1.-a[i]),fac)*safepow((1.-b[i]),fac1);
  817. }
  818. }
  819. void PigmentMultiplySlicesInverted(float a[16], inout float b[16], float factor){
  820. float fac=a[15]*factor; float fac1=b[15]; if(fac==0.) return;
  821. b[15]=1.-(1.-fac1)*(1.-fac);
  822. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  823. float pre=1.-b[i]*fac1; float mult=pre*(1.-a[i]*fac);
  824. b[i]=(1.-mult)/b[15];
  825. //b[i]=1.-(1.-a[i]*fac)*(1.-b[i]);
  826. }
  827. }
  828. PigmentData PigmentMix(PigmentData p0, PigmentData p1, float factor){
  829. PigmentData result=p1;
  830. PigmentMixSlicesInverted(p0.a,result.a,factor);
  831. PigmentMixSlices(p0.r,result.r,factor);
  832. return result;
  833. }
  834. PigmentData PigmentOver(PigmentData p0, PigmentData p1){
  835. PigmentData result=p1; float mfac=1.0;//p0.r[15];
  836. float rfac=p0.r[15]; result.a[15]=mix(result.a[15],0.,rfac*rfac);
  837. PigmentOverSlices(p0.r,result.r);
  838. PigmentMultiplySlicesInverted(p0.a,result.a,mfac);
  839. return result;
  840. }
  841. void PigmentAdd(inout PigmentData p, PigmentData on_top){
  842. for(int i=0;i<16;i++){ p.r[i]+=on_top.r[i]; p.a[i]+=on_top.a[i]; }
  843. }
  844. void PigmentMultiply(inout PigmentData p, float a){
  845. for(int i=0;i<15;i++){ p.r[i]*=a; p.a[i]*=a; }
  846. }
  847. PigmentData PigmentInterpolate(PigmentData p0, PigmentData p1, float fac){
  848. 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;
  849. }
  850. vec3 XYZ2sRGB(vec3 xyz){
  851. mat3 mat=mat3(vec3(3.2404542,-1.5371385,-0.4985314),
  852. vec3(-0.9692660,1.8760108,0.0415560),
  853. vec3(0.0556434,-0.2040259,1.0572252));
  854. return xyz*mat;
  855. }
  856. float srgb_transfer_function(float a){
  857. return .0031308f >= a ? 12.92f * a : 1.055f * pow(a, .4166666666666667f) - .055f;
  858. }
  859. vec3 to_log_srgb(vec3 color){
  860. return vec3(srgb_transfer_function(color.r),srgb_transfer_function(color.g),srgb_transfer_function(color.b));
  861. }
  862. float PigmentCMF[3][14]=float[3][14](
  863. float[14](0.0343533436363636,0.220925140909091,0.328355822727273,0.2018815,0.0360974655,0.0285879281818182,0.215876535454545,0.525338609090909,0.906198259090909,1.13085586363636,0.895278031818182,0.435115186363636,0.138809882272727,0.0324976972727273),
  864. float[14](0.00359930259090909,0.0236005122727273,0.0565472954545455,0.114833071818182,0.236568031818182,0.535090640909091,0.876579286363636,0.992233536363636,0.923666477272727,0.708120895454545,0.419073681818182,0.178679336363636,0.0541232845454545,0.0124627878181818),
  865. float[14](0.171746535909091,1.15671911363636,1.84186645454545,1.32759531363636,0.488183445454546,0.12631411,0.0225265765,0.00293351760909091,0.000351412640909091,4.70501886363636E-05,3.51041136363636E-06,0.,0.,0.)
  866. );
  867. const float PigmentCMFNormalize=5.13517814086364;
  868. vec3 Spectral2XYZ(float spec[OUR_SPECTRAL_SLICES]){
  869. vec3 xyz=vec3(0.,0.,0.);
  870. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  871. xyz[0]+=spec[i]*PigmentCMF[0][i];
  872. xyz[1]+=spec[i]*PigmentCMF[1][i];
  873. xyz[2]+=spec[i]*PigmentCMF[2][i];
  874. }
  875. vec3 XYZ;
  876. XYZ[0]=xyz[0]/PigmentCMFNormalize;
  877. XYZ[1]=xyz[1]/PigmentCMFNormalize;
  878. XYZ[2]=xyz[2]/PigmentCMFNormalize;
  879. return XYZ;
  880. }
  881. vec3 PigmentToRGB(PigmentData pd, PigmentData light){
  882. float slices[OUR_SPECTRAL_SLICES];
  883. for(int i=0;i<OUR_SPECTRAL_SLICES;i++){
  884. if(pd.a[15]!=0.0){ // apparently intel iGPUs need this
  885. float absfac=1.0f-pd.a[i]*pow(pd.a[15],1.); if(absfac<0.)absfac=0.; slices[i]=pd.r[i]*absfac;
  886. }else{
  887. slices[i]=pd.r[i];
  888. }
  889. slices[i]*=light.r[i];
  890. }
  891. vec3 xyz=Spectral2XYZ(slices); vec3 rgb=XYZ2sRGB(xyz); return rgb;
  892. }
  893. #define GetImgPixel(tex, uv, p) \
  894. { \
  895. PixType c0=loadpix(tex,uv); \
  896. PixType c1=loadpix(tex,ivec2(uv.x,uv.y+1)); \
  897. PixType c2=loadpix(tex,ivec2(uv.x+1,uv.y)); \
  898. PixType c3=loadpix(tex,ivec2(uv.x+1,uv.y+1)); \
  899. setRL(c0,p); setRH(c1,p); setAL(c2,p); setAH(c3,p); \
  900. }
  901. #define WriteImgPixel(tex, uv, p) \
  902. { \
  903. PixType c0=getRL(p); PixType c1=getRH(p); PixType c2=getAL(p); PixType c3=getAH(p); \
  904. imageStore(tex,uv,packpix(c0)); \
  905. imageStore(tex,ivec2(uv.x,uv.y+1),packpix(c1)); \
  906. imageStore(tex,ivec2(uv.x+1,uv.y),packpix(c2)); \
  907. imageStore(tex,ivec2(uv.x+1,uv.y+1),packpix(c3)); \
  908. }
  909. )";
  910. const char OUR_PIGMENT_TEXTURE_MIX_SHADER[]=R"(
  911. #ifndef OUR_GLES
  912. #extension GL_ARB_shading_language_420pack : enable // uniform sampler binding
  913. #endif
  914. precision highp float;
  915. precision highp int;
  916. layout (binding=2) uniform highp usampler2D TexColorUI0;
  917. layout (binding=5) uniform highp usampler2D TexColorUI1;
  918. uniform float MixingTop;
  919. in vec2 fUV;
  920. layout(location = 0) out uvec4 outColor;
  921. #with OUR_PIGMENT_COMMON
  922. void main(){
  923. ivec2 iuv=ivec2(ivec2(fUV*512.)*2);
  924. ivec2 iuvscr=ivec2(gl_FragCoord.xy); int xof=iuvscr.x%2; int yof=iuvscr.y%2; iuvscr.x-=xof; iuvscr.y-=yof;
  925. PigmentData p0 = GetPixel(TexColorUI0,iuv);
  926. PigmentData p1 = GetPixel(TexColorUI1,iuvscr);
  927. p0.r[15]*=MixingTop; p0.a[15]*=MixingTop;
  928. PigmentData result = PigmentOver(p0,p1);
  929. int choose = xof*2+yof;
  930. uvec4 pixel = packpix(PackPixel(result,choose));
  931. outColor=pixel;
  932. }
  933. )";
  934. const char OUR_PIGMENT_COMPOSITION_SHADER[] = R"(
  935. layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
  936. #ifdef OUR_GLES
  937. precision highp uimage2D;
  938. precision highp float;
  939. precision highp int;
  940. layout(r32ui, binding = 0) uniform uimage2D top;
  941. layout(r32ui, binding = 1) uniform uimage2D bottom;
  942. #else
  943. layout(rgba16ui, binding = 0) uniform uimage2D top;
  944. layout(rgba16ui, binding = 1) uniform uimage2D bottom;
  945. #endif
  946. uniform float uAlphaTop;
  947. uniform float uAlphaBottom;
  948. #with OUR_PIGMENT_COMMON
  949. void main() {
  950. ivec2 px=ivec2(gl_GlobalInvocationID.xy)*2;
  951. PigmentData p0=PIGMENT_BLANK; GetImgPixel(top, px, p0);
  952. PigmentData p1=PIGMENT_BLANK; GetImgPixel(bottom, px, p1);
  953. float afac=uAlphaTop/uAlphaBottom;
  954. if(afac==0.){ return; }
  955. p0.r[15]*=afac; p0.a[15]*=afac;
  956. PigmentData result=PigmentOver(p0,p1);
  957. WriteImgPixel(bottom,px,result);
  958. }
  959. )";
  960. const char OUR_PIGMENT_TEXTURE_DISPLAY_SHADER[]=R"(
  961. #ifndef OUR_GLES
  962. #extension GL_ARB_shading_language_420pack : enable // uniform sampler binding
  963. #endif
  964. precision highp float;
  965. precision highp int;
  966. layout (binding=2) uniform highp usampler2D TexColorUI;
  967. uniform float texture_scale;
  968. uniform int display_mode;
  969. uniform ivec2 frag_offset;
  970. in vec2 fUV;
  971. layout(location = 0) out vec4 outColor;
  972. #with OUR_PIGMENT_COMMON
  973. layout(std140) uniform CanvasPigmentBlock{
  974. PigmentData light;
  975. PigmentData paper;
  976. }uCanvasPigment;
  977. void main(){
  978. ivec2 iuv=ivec2(gl_FragCoord.xy)+frag_offset;
  979. //ivec2(fUV*vec2(display_size)); //int xof=iuv.x%2; int yof=iuv.y%2; iuv.x-=xof; iuv.y-=yof;
  980. int offset=int(texture_scale/2.)*2+1;
  981. PigmentData p0;
  982. if(display_mode==0){
  983. p0=GetPixelQuick(TexColorUI,iuv);
  984. }else if(display_mode==1){
  985. p0=GetPixelDebayer(TexColorUI,iuv,offset);
  986. }else if(display_mode==2){
  987. p0=GetPixelQuick(TexColorUI,iuv*2);
  988. }else if(display_mode==3){
  989. p0=GetPixelDebayer(TexColorUI,iuv*2+ivec2(0,0),offset);
  990. PigmentData p1=GetPixelDebayer(TexColorUI,iuv*2+ivec2(0,1),offset);
  991. PigmentData p2=GetPixelDebayer(TexColorUI,iuv*2+ivec2(1,1),offset);
  992. PigmentData p3=GetPixelDebayer(TexColorUI,iuv*2+ivec2(1,0),offset);
  993. p0=PigmentMix(PigmentMix(p0,p1,0.5),PigmentMix(p2,p3,0.5),0.5);
  994. }
  995. PigmentData final = PigmentOver(p0,uCanvasPigment.paper);
  996. vec3 pixel = to_log_srgb(PigmentToRGB(final,uCanvasPigment.light));
  997. outColor=vec4(pixel,1.0);
  998. }
  999. )";