gl.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * gl.js
  3. * Keep all webgl boilerplate over here
  4. */
  5. // Vertex shader program
  6. const vsSource = `precision mediump float;
  7. attribute vec4 position;
  8. attribute vec2 texcoord;
  9. uniform mat4 projection;
  10. varying vec2 texcoord_f;
  11. void main() {
  12. texcoord_f = texcoord;
  13. gl_Position = projection * position;
  14. }
  15. `;
  16. const fsSource = `precision mediump float;
  17. varying vec2 texcoord_f;
  18. uniform vec2 dim;
  19. uniform vec2 rseed;
  20. uniform sampler2D sampler;
  21. uniform bool enabled;
  22. vec3 rgb2hsv(vec3 c)
  23. {
  24. vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
  25. vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
  26. vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
  27. float d = q.x - min(q.w, q.y);
  28. float e = 1.0e-10;
  29. return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
  30. }
  31. vec3 hsv2rgb(vec3 c)
  32. {
  33. vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
  34. vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
  35. return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
  36. }
  37. vec3 interpolate(vec4 from, vec4 to, float amt) {
  38. vec3 from_hsv = rgb2hsv(from.xyz);
  39. vec3 to_hsv = rgb2hsv(to.xyz);
  40. vec3 final;
  41. final.x = mix(from_hsv.x, to_hsv.x, amt);
  42. final.y = mix(from_hsv.y, to_hsv.y, amt);
  43. final.z = mix(from_hsv.z, to_hsv.z, amt);
  44. return hsv2rgb(final);
  45. }
  46. float rand(vec2 co)
  47. {
  48. co = co * rseed * dim * 10.;
  49. float a = 12.9898;
  50. float b = 78.233;
  51. float c = 43758.5453;
  52. float dt= dot(co.xy ,vec2(a,b));
  53. float sn= mod(dt,3.14);
  54. return fract(sin(sn) * c);
  55. }
  56. ivec2 decideOutcome(ivec2 texel, vec2 dim) {
  57. vec4 outcome = vec4(0., 0., 0., 0.);
  58. // u d l r
  59. float r = rand(texcoord_f);
  60. int which = int(r * 5.0);
  61. ivec2 t = texel;
  62. if(which == 0) {
  63. // center
  64. t = texel;
  65. }
  66. else if(which == 1) {
  67. // up
  68. if(texel.y < 1) {
  69. // down instead
  70. t = ivec2(texel.x, texel.y + 1);
  71. } else {
  72. t = ivec2(texel.x, texel.y - 1);
  73. }
  74. }
  75. else if(which == 2) {
  76. // right
  77. if(texel.x > int(dim.x)-2) {
  78. // left instead
  79. t = ivec2(texel.x - 1, texel.y);
  80. } else {
  81. t = ivec2(texel.x + 1, texel.y);
  82. }
  83. }
  84. else if(which == 3) {
  85. // down
  86. if(texel.y > int(dim.y)-2) {
  87. // up instead
  88. t = ivec2(texel.x, texel.y - 1);
  89. } else {
  90. t = ivec2(texel.x, texel.y + 1);
  91. }
  92. }
  93. else if(which == 4) {
  94. // left
  95. if(texel.x < 1) {
  96. // right instead
  97. t = ivec2(texel.x + 1, texel.y);
  98. } else {
  99. t = ivec2(texel.x - 1, texel.y);
  100. }
  101. }
  102. return t;
  103. }
  104. void main() {
  105. if (enabled) {
  106. ivec2 texel = ivec2(texcoord_f * dim);
  107. ivec2 outcome = decideOutcome(texel, dim);
  108. gl_FragColor = vec4(interpolate(texture2D(sampler, texcoord_f), texture2D(sampler, (vec2(outcome)+0.5)/dim), 0.999), 1.0);
  109. }
  110. else {
  111. gl_FragColor = texture2D(sampler, texcoord_f);
  112. }
  113. }
  114. `;
  115. /*
  116. * Combine vertex&fragment source into compiled shader program
  117. */
  118. function initShader(gl, vsSource, fsSource) {
  119. const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vsSource);
  120. const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fsSource);
  121. // Create the shader program
  122. const shaderProgram = gl.createProgram();
  123. gl.attachShader(shaderProgram, vertexShader);
  124. gl.attachShader(shaderProgram, fragmentShader);
  125. gl.linkProgram(shaderProgram);
  126. // If creating the shader program failed, alert
  127. if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
  128. alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
  129. return null;
  130. }
  131. return shaderProgram;
  132. }
  133. /*
  134. * Compile individual shader
  135. */
  136. function compileShader(gl, type, source) {
  137. const shader = gl.createShader(type);
  138. gl.shaderSource(shader, source);
  139. gl.compileShader(shader);
  140. if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  141. alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
  142. gl.deleteShader(shader);
  143. return null;
  144. }
  145. return shader;
  146. }
  147. function initBuffers(gl) {
  148. const positionBuffer = gl.createBuffer();
  149. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  150. const positions = [
  151. 1.0, 1.0,
  152. -1.0, 1.0,
  153. 1.0, -1.0,
  154. -1.0, -1.0,
  155. ];
  156. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
  157. const textureBuffer = gl.createBuffer();
  158. gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
  159. const tex = [
  160. 0.0, 0.0,
  161. 1.0, 0.0,
  162. 1.0, 1.0,
  163. 0.0, 1.0,
  164. ];
  165. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(tex), gl.STATIC_DRAW);
  166. return {
  167. position: positionBuffer,
  168. texcoords: textureBuffer,
  169. };
  170. }