PageSourceSearch

https://flypig.co.uk/shaderback.js

js flypig.co.uk collected 2026-10-02 03:29:41 UTC 10,555 bytes, 349 lines download raw bytes

1/***************************************************************************
2 * shaderback.js
3 * Shader-generated backgrounds for the web
4 * http://www.flypig.co.uk/shaderback
5 * 
6 * David Llewellyn-Jones <[email protected]>
7 * Version 0.03
8 * 29th March 2015
9 * 
10 * Copyright (c) 2015 David Llewellyn-Jones
11 * Released under the MIT license
12 * 
13***************************************************************************/
14
15/***************************************************************************
16 * To use, just add the following uncommented code to your HTML header
17 * 
18 *   <script type="text/javascript" src="shaderback.js"></script>
19 *   <script type="text/javascript">
20 *   window.onload = shaderback.loadURL("shader.txt"));
21 *   </script>
22 * 
23 * Where shader.txt is the URL of your fragment shader
24 * 
25 * You can also use loaddiv and loadtext rather than loadURL if your shader
26 * code is contained inside a script element or text variable respectively.
27 * 
28***************************************************************************/
29
30var shaderback = (function () {
31  "use strict";
32
33  var canvas;
34  var gl;
35  var shaderProgram;
36  var squareVertexPositionBuffer;
37  var squareVertexTextureCoordBuffer;
38  var pixelScale = 2.0;
39  var running = false;
40  var debug = false;
41
42  // Vertex shader code
43  var vsCode = "\n"
44    + "  precision highp float;\n"
45    + "\n"
46    + "  attribute vec3 aVertexPosition;\n"
47    + "  attribute vec2 aTextureCoord;\n"
48    + "\n"
49    + "  uniform vec3 iResolution;\n"
50    + "  varying vec2 fragCoord;\n"
51    + "\n"
52    + "  void main(void) {\n"
53    + "    fragCoord = aTextureCoord * iResolution.xy;\n"
54    + "    gl_Position = vec4(aVertexPosition, 1.0);\n"
55    + "  }\n"
56    + "\n";
57  var fsCode;
58
59  // Fragment shader head for use with ShaderToy.com shaders
60  var vsShadertoyHead = "\n"
61    + "  precision highp float;\n"
62    + "\n"
63    + "  varying vec2 fragCoord;\n"
64    + "  uniform vec3 iResolution;\n"
65    + "  uniform float iGlobalTime;\n"
66    + "  const vec2 iMouse = vec2(0.0, 0.0);\n"
67    + "\n"
68    + "  void mainImage (out vec4 fragColor, in vec2 fragCoord);\n"
69    + "\n"
70    + "  void main () {\n"
71    + "  	 mainImage(gl_FragColor, fragCoord);\n"
72    + "  	 gl_FragColor.a = 1.0;\n"
73    + "  }\n"
74    + "\n";
75
76  // Update dimensions on a resize event
77  function resize() {
78    var width = canvas.clientWidth / pixelScale;
79    var height = canvas.clientHeight / pixelScale;
80    if (canvas.width !== width || canvas.height !== height) {
81      canvas.width = width;
82      canvas.height = height;
83      canvas.style.height = window.innerHeight + "px";
84    }
85  }
86
87  // Add the canvas covering the body element background
88  function ready() {
89    var success = true;
90    var div = document.createElement('div');
91    div.innerHTML = '<canvas class="shaderback" id="shaderback" width="500px" height="500px" style="width: 100%; height: 100%; position: fixed; top: 0px; left: 0px; z-index: -1;"></canvas>';
92    var elements = div.childNodes[0];
93    document.getElementsByTagName('body')[0].appendChild(elements);
94    canvas = document.getElementById("shaderback");
95    
96    if (!canvas) {
97      success = false;
98      if (debug) {
99        alert("Canvas creation failed");
100      }
101    }
102    
103    return success;
104  }
105
106  // Initialise the OpenGL/WebGL canvas
107  function initGL(canvas) {
108    var success = true;
109    try {
110      gl = canvas.getContext("experimental-webgl");
111      gl.getExtension("OES_standard_derivatives");
112      gl.viewportWidth = canvas.width;
113      gl.viewportHeight = canvas.height;
114    } catch (ignore) {
115      if (debug) {
116        alert("No WebGL context");
117      }
118      success = false;
119    }
120
121    return success;
122  }
123
124  // Compile the shader with the give text
125  // Type should be either gl.FRAGMENT_SHADER or gl.VERTEX_SHADER
126  function compileShader(str, type) {
127    var shader = gl.createShader(type);
128
129    gl.shaderSource(shader, str);
130    gl.compileShader(shader);
131
132    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
133      if (debug) {
134        alert(gl.getShaderInfoLog(shader));
135      }
136      shader = null;
137    }
138
139    return shader;
140  }
141
142  // Compile and link the shader and setup CPU accessible GPU variables
143  function initShaders() {
144    var success = true;
145    var fragmentShader = compileShader(fsCode, gl.FRAGMENT_SHADER);
146    var vertexShader = compileShader(vsCode, gl.VERTEX_SHADER);
147
148    if (fragmentShader) {
149      shaderProgram = gl.createProgram();
150      gl.attachShader(shaderProgram, vertexShader);
151      gl.attachShader(shaderProgram, fragmentShader);
152      gl.linkProgram(shaderProgram);
153    }
154
155    if (fragmentShader && gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
156      gl.useProgram(shaderProgram);
157
158      shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
159      gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
160
161      shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
162      gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
163
164      shaderProgram.iGlobalTime = gl.getUniformLocation(shaderProgram, "iGlobalTime");
165      shaderProgram.iResolution = gl.getUniformLocation(shaderProgram, "iResolution");
166
167      shaderProgram.iScroll = gl.getUniformLocation(shaderProgram, "iScroll");
168    }
169    else {
170      if (debug) {
171        alert("Could not initialise shaders");
172      }
173      success = false;
174    }
175    
176    return success;
177  }
178
179  // Initialise the OpenGL vertex and index buffers for the fullscreen rectangle
180  function initBuffers() {
181    var success = true;
182    squareVertexPositionBuffer = gl.createBuffer();
183    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
184    var vertices = [
185      1.0,  1.0,  0.0,
186      -1.0,  1.0,  0.0,
187      1.0, -1.0,  0.0,
188      -1.0, -1.0,  0.0
189    ];
190    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
191    squareVertexPositionBuffer.itemSize = 3;
192    squareVertexPositionBuffer.numItems = 4;
193
194    squareVertexTextureCoordBuffer = gl.createBuffer();
195    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexTextureCoordBuffer);
196    var textureCoords = [
197      1.0, 1.0,
198      0.0, 1.0,
199      1.0, 0.0,
200      0.0, 0.0
201    ];
202    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
203    squareVertexTextureCoordBuffer.itemSize = 2;
204    squareVertexTextureCoordBuffer.numItems = 4;
205    
206    return success;
207  }
208
209  // Set a callback for window update events
210  window.requestAnimFrame = (function () {
211    return window.requestAnimationFrame ||
212      window.webkitRequestAnimationFrame ||
213      window.mozRequestAnimationFrame ||
214      window.oRequestAnimationFrame ||
215      window.msRequestAnimationFrame ||
216      function (callback, element) {
217        window.setTimeout(callback, 1000 / 60);
218      };
219  })();
220
221  // Render the scene, to be called every frame update
222  function drawScene() {
223    var timeNow = new Date().valueOf() / 1000.0;
224    requestAnimFrame(drawScene);
225
226    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
227    gl.uniform1f(shaderProgram.iGlobalTime, timeNow % 18000);
228
229    gl.uniform3f(shaderProgram.iResolution, canvas.clientWidth, canvas.clientHeight, 1.0);
230
231    gl.uniform2f(shaderProgram.iScroll, window.scrollX / document.body.scrollWidth, window.scrollY / document.body.scrollHeight);
232
233    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
234    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
235
236    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexTextureCoordBuffer);
237    gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, squareVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
238
239    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
240  }
241
242  // Initialise the event listerners for window resizing
243  function initEvents() {
244    window.addEventListener('resize', function(event) {
245      resize();
246    });
247    
248    return true;
249  }
250
251  // Set up the shader background
252  function start() {
253    if (!running) {
254      running = ready();
255      resize();
256      if (running) running = initGL(canvas);
257      if (running) running = initShaders();
258      if (running) running = initBuffers();
259      if (running) running = initEvents();
260      if (running) drawScene();
261    }
262    else {
263      running = initShaders();
264    }
265  }
266
267  // Get the shader text from the script tag with the given ID
268  function getShaderScript(id) {
269    var shaderScript = document.getElementById(id);
270    if (!shaderScript) {
271      return null;
272    }
273
274    var str = "";
275    var k = shaderScript.firstChild;
276    while (k) {
277      if (k.nodeType === 3) {
278        str += k.textContent;
279      }
280      k = k.nextSibling;
281    }
282    return str;
283  }
284  
285  // Set whether or not to generate alerts on errors
286  // active - true to generate alerts, false otherwise
287  function setDebug(active) {
288    debug = active;
289  }
290
291  // Load a shader from a as the page background
292  // url - URI of shader code
293  function loadURL(url) {
294    if (url) {
295      var client = new XMLHttpRequest();
296      client.open('GET', url);
297      client.overrideMimeType("text/plain; charset=x-user-defined");
298      client.onloadend = function () {
299        fsCode = client.responseText;
300        start();
301      };
302      client.send();
303    }
304  }
305
306  // Load the shader stored in a script tag as the page background
307  // id - id of the script tag containing the shader code
308  function loaddiv(id) {
309    fsCode = getShaderScript(id);
310    start();
311  }
312
313  // Load the shader with code text as the page background
314  // text - shader code
315  function loadtext(text) {
316    fsCode = text;
317    start();
318  }
319
320  // Load the ShaderToy.com shader as the page background
321  // shaderID - ShaderToy.com ID
322  function loadshadertoy(shaderID) {
323    if (shaderID) {
324      var client = new XMLHttpRequest();
325      client.open('GET', "https://www.shadertoy.com/api/v1/shaders/" + shaderID + "?key=rdHKwN");
326      client.onloadend = function () {
327      	var obj = JSON.parse (client.responseText);
328      	if (obj.Shader) {
329          fsCode = vsShadertoyHead + obj.Shader.renderpass[0].code;
330          start();
331        }
332        else if (debug) {
333          alert ("Shadertoy error: " + (obj.Error ? obj.Error : "Unknown response"));
334        }
335      };
336      client.send();
337    }
338  }
339
340  // Externally exposed functions
341  return {
342    loadURL : loadURL,
343    loaddiv : loaddiv,
344    loadtext : loadtext,
345    loadshadertoy : loadshadertoy,
346    setDebug : setDebug
347  };
348}());
349

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.