{"id":13576938,"url":"https://github.com/xemantic/shader-web-background","last_synced_at":"2025-04-13T08:21:01.631Z","repository":{"id":50710020,"uuid":"305628411","full_name":"xemantic/shader-web-background","owner":"xemantic","description":"Displays GLSL fragment shaders as a website background. Supports offscreen buffers and floating point textures on almost any browser and hardware. Compatible with Shadertoy.","archived":false,"fork":false,"pushed_at":"2023-06-06T23:19:04.000Z","size":3475,"stargazers_count":235,"open_issues_count":4,"forks_count":30,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-27T00:11:05.466Z","etag":null,"topics":["background","closure-compiler","design","fragment-shaders","framework","glsl","glsl-shaders","javascript","javascript-framework","javascript-library","library","shaders","shadertoy","shadertoy-compatibility","web","web-design","web-development","webgl","webgl2"],"latest_commit_sha":null,"homepage":"https://xemantic.github.io/shader-web-background/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xemantic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":["xemantic"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://www.buymeacoffee.com/kazik"]}},"created_at":"2020-10-20T07:40:58.000Z","updated_at":"2025-03-13T04:00:27.000Z","dependencies_parsed_at":"2024-03-17T04:41:19.017Z","dependency_job_id":"69d4c324-bd45-483f-83fa-e1d7d4663e0c","html_url":"https://github.com/xemantic/shader-web-background","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xemantic%2Fshader-web-background","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xemantic%2Fshader-web-background/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xemantic%2Fshader-web-background/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xemantic%2Fshader-web-background/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xemantic","download_url":"https://codeload.github.com/xemantic/shader-web-background/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248681598,"owners_count":21144715,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["background","closure-compiler","design","fragment-shaders","framework","glsl","glsl-shaders","javascript","javascript-framework","javascript-library","library","shaders","shadertoy","shadertoy-compatibility","web","web-design","web-development","webgl","webgl2"],"created_at":"2024-08-01T15:01:16.050Z","updated_at":"2025-04-13T08:21:01.607Z","avatar_url":"https://github.com/xemantic.png","language":"JavaScript","funding_links":["https://github.com/sponsors/xemantic","https://www.buymeacoffee.com/kazik","https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20tea\u0026emoji="],"categories":["JavaScript"],"sub_categories":[],"readme":"# shader-web-background\n\n_Displays GLSL fragment shaders as a website background. Supports Shadertoy shaders,\nmultipass - ping-pong offscreen buffers, feedback loops, floating-point textures.\nEither with WebGL 1 or 2, will try to run wherever it's technically possible._\n\n**Website/Demo:** :fireworks: https://xemantic.github.io/shader-web-background :sparkler:\n\n:grey_question::rainbow::angel::construction_worker: To ask questions go to [xemantic discord server](https://discord.gg/vQktqqN2Vn) :coffee::tea::strawberry::space_invader:\n\n![shader-web-background logo](https://xemantic.github.io/shader-web-background/media/shader-web-backgroung.jpg)\n\nI designed this library to use complex fragment shaders as part of my web design and development\nprocess. This is the tool which finally lets me embrace the web browser as a creative coding\nenvironment. If you are familiar with GLSL, then it might help you publish your work on\nweb as well. If you are coming from a web development background,\nthen you might want to learn a bit more about shaders first, for example from\n[The Book of Shaders](https://thebookofshaders.com/). I hope that examples presented\nin this documentation are self-explanatory. If you find it useful, then\n\n[:heart: Sponsor xemantic on GitHub](https://github.com/sponsors/xemantic) or\n![Buy me a tea](https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20tea\u0026emoji=🍵\u0026slug=kazik\u0026button_colour=BD5FFF\u0026font_colour=ffffff\u0026font_family=Cookie\u0026outline_colour=000000\u0026coffee_colour=FFDD00)\nhttps://www.buymeacoffee.com/kazik\n\n\n_Kazik (morisil) Pogoda_\n\nhttps://xemantic.com/\n\n---\n\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**\n\n- [Features](#features)\n- [Adding shader-web-background to your projects](#adding-shader-web-background-to-your-projects)\n  - [Step 1 - Add library to your project](#step-1---add-library-to-your-project)\n    - [Option A - Embedded minified library directly in HTML](#option-a---embedded-minified-library-directly-in-html)\n    - [Option B - Reference the minified library](#option-b---reference-the-minified-library)\n    - [Option C - Download distribution](#option-c---download-distribution)\n  - [Step 2 - Add your fragment shaders](#step-2---add-your-fragment-shaders)\n  - [Step 3 - Start shading](#step-3---start-shading)\n  - [Step 4 - Specify fallback styles](#step-4---specify-fallback-styles)\n- [shader-web-background API](#shader-web-background-api)\n- [Configuring shading](#configuring-shading)\n  - [Adding shader uniforms](#adding-shader-uniforms)\n    - [About uniforms](#about-uniforms)\n    - [Textures as uniforms](#textures-as-uniforms)\n  - [Initializing shader texture](#initializing-shader-texture)\n  - [Complex config example](#complex-config-example)\n  - [Handling errors](#handling-errors)\n- [Shader GLSL version](#shader-glsl-version)\n- [Adding mouse support](#adding-mouse-support)\n- [Adding textures](#adding-textures)\n- [Shadertoy support](#shadertoy-support)\n  - [What to do with Shadertoy \"Common\" tab?](#what-to-do-with-shadertoy-common-tab)\n  - [What to do with `texture` function?](#what-to-do-with-texture-function)\n  - [Handling Shadertoy texture parameters](#handling-shadertoy-texture-parameters)\n  - [How to handle \"Multipass\" Shadertoy shaders?](#how-to-handle-multipass-shadertoy-shaders)\n- [Own vertex shader](#own-vertex-shader)\n- [General tips](#general-tips)\n- [Building](#building)\n- [Contributing](#contributing)\n  - [Code conventions](#code-conventions)\n  - [Adding your project to the list of project using this library](#adding-your-project-to-the-list-of-project-using-this-library)\n- [Tools and dependencies](#tools-and-dependencies)\n- [TODO](#todo)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Features\n\n* **simplicity**: it is just rendering canvas background as fragment shader.\n* **speed**: designed to be embedded in HTML and start rendering before other page resources\n  are downloaded.\n* **extensibility**: adding own interaction and controls is trivial.\n* **convenience**: straightforward [API](API.md), specific errors will inform you about mistakes\n  which are otherwise hard to debug.\n* **minimal footprint**: transpiled from JavaScript to JavaScript with\n  [Google Closure Compiler].\n* **pixel feedback loops**: preserving movement in time on offscreen buffers with floating–point precision.\n* **[Shadertoy support](#shadertoy-support)**: including multipass shaders\n* **cross browser / cross device**: on Chrome, Safari, Firefox or Edge, either with WebGL 1 or 2,\n  on Linux, Windows, Mac, iPhone or Samsung phone — it will use optimal strategy to squeeze out what's possible from the browser and the hardware.\n\n## Adding shader-web-background to your projects\n\n**TL;DR:**\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"utf-8\"\u003e\n  \u003ctitle\u003eMinimal shader\u003c/title\u003e\n  \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n  \u003cmeta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"\u003e\n  \u003cscript src=\"https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js\"\u003e\u003c/script\u003e\n  \u003cscript type=\"x-shader/x-fragment\" id=\"image\"\u003e\n    precision highp float;\n\n    uniform float iTime;\n\n    void main() {\n      gl_FragColor = vec4(\n        mod(gl_FragCoord.x / 256., 1.),\n        mod((gl_FragCoord.x + gl_FragCoord.y - iTime * 40.) / 256. , 1.),\n        mod(gl_FragCoord.y / 256., 1.),\n        1.\n      );\n    }\n  \u003c/script\u003e\n  \u003cscript\u003e\n    shaderWebBackground.shade({\n      shaders: {\n        image: {\n          uniforms: {\n            iTime: (gl, loc) =\u003e gl.uniform1f(loc, performance.now() / 1000)\n          }\n        }\n      }\n    });\n  \u003c/script\u003e\n  \u003cstyle\u003e\n    .shader-web-background-fallback {\n      background: url(\"https://placekitten.com/666/666\");\n      background-position: center;\n      background-size: cover;\n      background-attachment: fixed;\n    }\n  \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003ch1\u003eshader-web-background minimal example\u003c/h1\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n:information_source: If you prefer to learn by example, here is the list of demos displayed\nwith their highlighted source code:\n\nhttps://xemantic.github.io/shader-web-background/#demo\n\nThere are several ways of adjusting this library to your needs:\n\n\n### Step 1 - Add library to your project\n\n#### Option A - Embedded minified library directly in HTML\n\nIf you want your shaders to start rendering before any other resources are loaded,\nthen go for this method. Just take the contents of:\n\nhttps://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js\n\nand put it as `\u003cscript\u003e` in the `\u003chead\u003e` of your HTML file.\n\nSee [minimal demo](demo/minimal.html) for reference\n([live version](https://xemantic.github.io/shader-web-background/demo/minimal.html)). \n\n\n#### Option B - Reference the minified library\n\nAdd this code to the `\u003chead\u003e` of your HTML:\n\n```html\n\u003cscript src=\"https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js\"\u003e\u003c/script\u003e\n```\n\n\n#### Option C - Download distribution\n\nIn the future I will publish `shader-web-background` to npm. For now you can just\ndownload the latest minified distribution together with source map and sources.\n\n\n### Step 2 - Add your fragment shaders\n\nYou will need at least one fragment shader defined like this:\n\n```html\n\u003cscript type=\"x-shader/x-fragment\" id=\"image\"\u003e\n  precision highp float;\n\n  void main() {\n    // ...\n  }\n\u003c/script\u003e\n``` \n\nPut it in the `\u003chead\u003e` of your HTML. The `type` should be `x-shader/x-fragment` and\nthe `id` attribute is arbitrary. \n\n:warning: Note: Remember to give unique `id` to each of your shaders if you are\ndefining more of them.\n\n### Step 3 - Start shading\n\n```javascript\n\u003cscript\u003e\n  shaderWebBackground.shade({\n    shaders: {\n      image: {}\n    }\n  });\n\u003c/script\u003e\n```\n\n:warning: Note: the shader name `image` should match the one defined as\nshader source `id` attribute. \n\n\n### Step 4 - Specify fallback styles\n\n:information_source: This step is not necessary, however adding it will improve\nthe experience for the small amount of users who still cannot\nrun shaders on their devices.\n\nDefine fallback CSS style, for example a static screenshot of your shader frame: \n\n```html\n\u003cstyle\u003e\n  .shader-web-background-fallback {\n    background: url(\"https://placekitten.com/666/666\");\n    background-position: center;\n    background-size: cover;\n    background-attachment: fixed;    \n  }\n\u003c/style\u003e\n```\nThe `shader-web-background-fallback` CSS class is applied to HTML document root and\nthe canvas.\n\n:warning: Note that in case of any errors the default canvas will not be attached\nto HTML document at all. In case of shading a canvas which is already attached\nto HTML, it might be tempting to provide a fallback canvas background based on the\n`shader-web-background-fallback` CSS class, however it might not work on some browsers.\nCustom error handler might be needed for cross compatibility.\n\nSee [Handling errors](#handling-errors) section for details.\n\n\n## shader-web-background API\n\nSee the full [shader-web-background API](API.md) \n\n\n## Configuring shading\n\nThe [configuration object](API.md#config) passed to the\n[shaderWebBackground.shade(config)](API.md#shaderwebbackgroundshadeconfig)\ncall in the example above will result in a minimal rendering pipeline consisting of one fragment\nshader named `image`. A new static\n`\u003ccanvas id=\"shader-web-background\"\u003e` element covering the whole viewport\nwill be added to the page with `z-index: -9999`, to be displayed behind other page elements.\n\n:information_source: Note: the default `\u003ccanvas\u003e` element will be attached to document\n`\u003cbody\u003e` only when the whole DOM tree is constructed. Also the actual rendering\nof shader frames will not happen until the page is fully loaded, even though shaders\nare compiled immediately.\n\n\n### Adding shader uniforms\n\n#### About uniforms\n\nUniforms provide shaders with the input from the world outside GPU.\nDescribing this mechanism is out of scope of this documentation.\nI decided not to build abstraction over this part of WebGL, because it is\nalready quite concise. See [WebGLRenderingContext.uniform] documentation.\n\nLet's assume that you want to provide your shader with a time value measured\nin seconds since the moment the page was loaded. First define a uniform in the\n`image` shader:\n\n```glsl\nuniform float iTime;\n```\n\nThe `iTime` name is arbitrary, but it should match with what you\nspecify in the configuration:\n\n```javascript\nshaderWebBackground.shade({\n  shaders: {\n    image: {\n      uniforms: {\n        iTime: (gl, loc) =\u003e gl.uniform1f(loc, performance.now() / 1000)\n      }\n    }\n  }\n});\n```\n\nThe `(gl, loc) =\u003e gl.uniform1f(loc, performance.now() / 1000)` function will\nbe invoked before rendering each shader frame. If you are not familiar with\n[JavaScript arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions),\nit's an equivalent of:\n\n```javascript\nfunction(gl, loc) {\n  gl.uniform1f(loc, performance.now() / 1000)\n}\n```\n\n:information_source: Check documentation of the standard JavaScript [performance.now()]\nfunction which returns the number of milliseconds since the page was loaded.\nDividing it by `1000` will result in floating-point value measured in seconds.\n\n:warning: During development check the console often. If you will forget to configure\na uniform declared in the shader, then exception will be thrown (See\n[error-no-configuration-of-shader-uniform](src/test/html/errors/error-no-configuration-of-shader-uniform.html)\ntest case). Also if you configure a uniform which does not exist in the shader, \nthen a warning will pop up on console (see\n[error-unnecessary-uniform-configured](src/test/html/errors/error-unnecessary-uniform-configured.html) \ntest case).\n\nSummary: you can use this mechanism to adapt any API as an input of your shaders.\nCheck project [demos](https://xemantic.github.io/shader-web-background/#demo) for\nexamples how to integrate input like:\n\n* mouse (fullscreen augmentation of the pointer)\n* scrolling position (parallax scrolling effect)\n* device orientation (fullscreen reaction to device tilting)\n* externally computed coefficients controlling the animation\n\n#### Textures as uniforms\n\nThe declaration of \"texture\" uniform uses `sampler2D` type:\n\n```glsl\nuniform sampler2D iWebCam;\n```\n\n:information_source: The uniform name is arbitrary. For example [Shadertoy] is\nbinding textures under name `iChannel0`, `iChannel1`, etc. and this is the convention\nused mostly in this documentation.\n\nSuch a uniform can be set with:\n\n```javascript\nshaderWebBackground.shade({\n  onInit: (ctx) =\u003e {\n    ctx.iWebCam = initializeTexture(ctx.gl);\n  },\n  shaders: {\n    image: {\n      uniforms: {\n        iWebCam: (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.iWebCam);\n      }\n    }\n  }\n});\n```\n\n:information_source: the _texture_ passed as a second argument\nto [ctx.texture](API.md#context-texture) can be either an instance of [WebGLTexture] or\na reference to the buffer of another shader in the pipeline. Check \n[Complex config example](#complex-config-example) section and\n[API - Context: buffers](API.md#context-buffers).\n\nSee [Adding textures](#adding-textures) section for details on how to load a texture from\nan image.\n\n\n### Initializing shader texture\n\nAll the shaders, except for the last one in the pipeline, will have associated textures to\nrender to. By default these textures are initialized as RGBA `HALF_FLOAT` (16bit) floating-point\nwith linear interpolation and are clamped to the edge. The texture initialization can be\ncustomized. See [API - Shader: texture](API.md#shader-texture) documentation for details. \n\n:warning: Note: the default settings will work on all the platforms while customization\ncan easily break the compatibility, especially on older iOS devices. Consult the API\nfor remedies.\n\n\n### Complex config example\n\nHere is a comprehensive example of a [configuration object](API.md#config) with\ncomments. It is using [Shadertoy] conventions for naming buffers and uniforms\nbut keep in mind that the naming is arbitrary and might be adjusted to the needs\nof your project.\n\n```javascript\n// mouse coordinates taken from from the mousemove event expressed in \"CSS pixels\"\nvar mouseX;\nvar mouseY;\n\ndocument.addEventListener(\"mousemove\", (event) =\u003e {\n   mouseX = event.clientX;\n   mouseY = event.clientY;\n});\n\nshaderWebBackground.shade({\n  // supplied canvas to use for shading\n  canvas: document.getElementById(\"my-canvas\"),\n  // called only once before the first run\n  onInit: (ctx) =\u003e {\n    // we can center the mouse even before any \"mousemove\" event occurs\n    // note, we are \n    mouseX = ctx.cssWidth / 2;\n    mouseY = ctx.cssHeight / 2;\n    // for convenience you can store your attributes on context\n    ctx.iFrame = 0;\n  },\n  onResize: (width, height, ctx) =\u003e {\n    ctx.iMinDimension = Math.min(width, height);\n  },                 \n  onBeforeFrame: (ctx) =\u003e {\n    ctx.shaderMouseX = ctx.toShaderX(mouseX);\n    ctx.shaderMouseY = ctx.toShaderY(mouseY);\n  },\n  shaders: {\n    // the first buffer to be rendered in the pipeline\n    BufferA: {\n      // uniform setters, attribute names should match with those defined in the shader\n      uniforms: {\n        // uniform value calculated in place\n        iTime: (gl, loc) =\u003e gl.uniform1f(loc, performance.now() / 1000),\n        // uniform values taken from context\n        iFrame: (gl, loc) =\u003e gl.uniform1i(loc, ctx.iFrame),\n        iMinDimension: (gl, loc, ctx) =\u003e gl.uniform1f(loc, ctx.iMinDimension),\n        iResolution: (gl, loc, ctx) =\u003e gl.uniform2f(loc, ctx.width, ctx.height),\n        iMouse: (gl, loc, ctx) =\u003e gl.uniform2f(loc, ctx.shaderMouseX, ctx.shaderMouseY),        \n        // inputing the previous output of itself - feedback loop \n        iChannel0: (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.buffers.BufferA)\n        // ... more uniforms\n      }\n    },\n    // ... more shaders\n    BufferD: {\n      // optional custom initializer of buffer's texture                   \n      texture: (gl, ctx) =\u003e {\n        // initializing floating-point texture in custom way for WebGL 1 and 2        \n        ctx.initHalfFloatRGBATexture(ctx.width, ctx.height);\n        // standard WebGL texture parameters\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);        \n      },    \n      uniforms: {\n        iChanel0: (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.buffers.BufferA)\n        // ... more uniforms\n      }\n    },\n    // the last shader will render to screen\n    Image: {\n      uniforms: {\n        iChanel0: (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.buffers.BufferD)\n        // ... more uniforms\n      }\n    }    \n  },\n  onAfterFrame: (ctx) =\u003e {\n    ctx.iFrame++;\n  },\n  // custom error handler\n  onError: (error, canvas) =\u003e {\n    canvas.remove();\n    console.error(error);\n    document.documentElement.classList.add(\"my-fallback\");\n  }\n});\n```\n\nThe API is intended to be self explanatory. Check [API specification](API.md) for details.\nThere are several shaders defined in the example above. They will be processed in sequence\ncalled `Multipass` in [Shadertoy] nomenclature. The last of defined shaders will render to screen.\nThe output of previous shaders, including feedback loop of the previous frame rendered by the same\nshader, can be easily passed to uniforms.\n\n\n### Handling errors\n\nSeveral validations are being performed on supplied configuration to avoid common problems\nwhich are usually hard to debug otherwise. The [src/test/html/errors/](src/test/html/errors)\nfolder contains all the error test cases which can be also checked on\nthe\n[live demo of error handling](https://xemantic.github.io/shader-web-background/src/test/html/errors/).\n\nAll the errors and warnings will be visible on console.\n\nSee:\n\n * [API - Config: onError](API.md#config-onerror)\n * [API - shaderWebBackground.ConfigError](API.md#shaderwebbackgroundconfigerror)\n * [API - shaderWebBackground.GlError](API.md#shaderwebbackgroundglerror)\n\n\n## Shader GLSL version\n\n:warning: This library relays on WebGL 1 as a common denominator, therefore even if it will use\nWebGL 2 whenever it is supported in runtime, the shader code should be still compatible with\n[GLSL ES 1.00](https://www.khronos.org/registry/OpenGL/specs/es/2.0/GLSL_ES_Specification_1.00.pdf)\n\n\n## Adding mouse support\n\n```javascript\n// mouse coordinates taken from from the mousemove event\nvar mouseX;\nvar mouseY;\n\ndocument.addEventListener(\"mousemove\", (event) =\u003e {\n   mouseX = event.clientX;\n   mouseY = event.clientY;\n});\n\n// mouse coordinates relative to the shader, you can also store them on the context\nvar shaderMouseX;\nvar shaderMouseY;\n\nshaderWebBackground.shade({\n  onInit: (ctx) =\u003e {\n    // screen center\n    mouseX = ctx.cssWidth / 2;\n    mouseY = ctx.cssHeight / 2;\n  },\n  onBeforeFrame: (ctx) =\u003e {\n    shaderMouseX = ctx.toShaderX(mouseX);\n    shaderMouseY = ctx.toShaderY(mouseY);\n  },\n  shaders: {\n    image: {\n      uniforms: {\n        iMouse: (gl, loc) =\u003e gl.uniform2f(loc, shaderMouseX, shaderMouseY)\n      }\n    }\n  }\n});\n```\n\n:information_source: Note: initial mouse coordinates are provided in `onInit` function\nbecause the first `mousemove` event can happen long after the shader is started. Shader\ncoordinates start at the bottom-left corner of the canvas and are aligned with the middle\nof the pixel - `(0.5, 0.5)`.\n\nAPI reference:\n\n * [Context: cssWidth](API.md#context-csswidth)\n * [Context: cssHeight](API.md#context-cssheight)\n * [Context: toShaderX](API.md#context-toshaderx)\n * [Context: toShaderY](API.md#context-toshadery)\n\nDemos:\n\n * [mouse](https://xemantic.github.io/shader-web-background/demo/mouse.html)\n * [mouse normalized](https://xemantic.github.io/shader-web-background/demo/mouse-normalized.html)\n\n## Adding textures\n\n:warning: Working with textures locally will be limited by the same security mechanisms which\nprevent them from being loaded from a different domain\n([explanation](https://webglfundamentals.org/webgl/lessons/webgl-cors-permission.html)). For\nlocal testing you might want to start local HTTP server. E.g.: `python -m http.server 8000` if\nit doesn't work on your latest ubuntu than run `sudo apt install python-is-python3` first.\n\nSee [texture: Blue Marble to Flat Earth mapping](https://xemantic.github.io/shader-web-background/demo/texture-blue-marble-to-flat-earth.html)\ndemo\n\nTextures can be set in the same way buffers are set as uniforms, but first we need to load them.\nFor example by defining custom Promise which can be reused:\n\n```javascript\nconst loadImage = (src) =\u003e new Promise((resolve, reject) =\u003e {\n  let img = new Image();\n  img.onload = () =\u003e resolve(img);\n  img.onerror = () =\u003e {\n    reject(new Error(\"Failed to load image from: \" + src));\n  }\n  img.src = src;\n});\n```\n\nThe `onInit` function is quite a convenient place for calling `loadPicture`:\n\n```javascript\nshaderWebBackground.shade({\n  onInit: (ctx) =\u003e {\n    loadImage(\"texture.jpg\")\n      .then(image =\u003e {\n        const gl = ctx.gl;\n        const texture = gl.createTexture();\n        gl.bindTexture(gl.TEXTURE_2D, texture);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n        gl.bindTexture(gl.TEXTURE_2D, null);\n        ctx.iTexture = texture;\n      });\n  },\n  shaders: {\n    image: {\n      uniforms: {\n        iTexture:    (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.iTexture)\n      }\n    }\n  }\n});\n```\n\n\n## Shadertoy support\n\nThis library can utilize [Shadertoy] code with minimal effort - a simple shader wrapping:\n\n```html\n\u003cscript type=\"x-shader/x-fragment\" id=\"Image\"\u003e\n  precision highp float;\n\n  uniform vec2  iResolution;\n  uniform float iTime;\n  // ... other needed uniforms\n \n  // -- Paste your Shadertoy code here:\n  // ...\n  // -- End of Shadertoy code\n    \n    \n  void main() {\n    mainImage(gl_FragColor, gl_FragCoord.xy);\n  }\n\u003c/script\u003e\n```\n\nThe `id` attribute of the `\u003cscript\u003e` is set to reflect [Shadertoy] tab called `Image`.\nMost shaders will use at least these 2 uniforms, and it's easy to provide their\nvalues in the configuration:\n\n```javascript\nshaderWebBackground.shade({\n  shaders: {\n    Image: {\n      uniforms: {\n        iResolution: (gl, loc, ctx) =\u003e gl.uniform2f(loc, ctx.width, ctx.height),\n        iTime:       (gl, loc) =\u003e gl.uniform1f(loc, performance.now() / 1000),\n      }\n    }\n  }\n});\n```\n\nShadertoy demos:\n\n * [minimal shadertoy demo](https://xemantic.github.io/shader-web-background/demo/shadertoy-default.html).\n * [Warping - procedural 2 by Inigo Quilez](https://xemantic.github.io/shader-web-background/demo/shadertoy-warping-procedural-2.html)\n * [Reaction Diffusion - 2 Pass by Shane](https://xemantic.github.io/shader-web-background/demo/shadertoy-reaction-diffusion-2-pass.html)\n\n\n### What to do with Shadertoy \"Common\" tab?\n\nThere is no automated solution for that. You will have to copy the `Common` part directly\ninto your shaders, just above the other [Shadertoy] code.\n\n\n### What to do with `texture` function?\n\nIn [Shadertoy] textures are accessed with the `texture` function while in WebGL 1 it is \n`texture2D`. Here is a simple workaround to be added before the original code:\n\n```glsl\n#define texture texture2D\n```\n\n\n### Handling Shadertoy texture parameters\n\nIn [Shadertoy] each \"Channel\" binding a texture can have separate sampler parameters\nlike interpolation or wrapping. This functionality cannot be easily ported to WebGL 1,\nbut most shaders relaying on these features can be adjusted with code-based workarounds.\nFor example if the texture is supposed to be repeated, then something like this might be\na functional replacement of the `texture` function in a given shader:\n\n```glsl\nvec4 repeatedTexture(in sampler2D channel, in vec2 uv) {\n  return texture2D(channel, mod(uv, 1.));\n}\n```\n\n:warning: Mipmaps are not supported.\n\nSee also [API - Shader: texture](API.md#shader-texture).\n\n\n### How to handle \"Multipass\" Shadertoy shaders?\n\nYou can name your shaders according to [Shadertoy] buffer names:\n\n* `BufferA`\n* `BufferB`\n* `BufferC`\n* `BufferD`\n* `Image`\n\nAnd then wire them together:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n  \u003ctitle\u003eMultipass Shadertoy shader\u003c/title\u003e\n  \u003cscript type=\"x-shader/x-fragment\" id=\"BufferA\"\u003e\n    precision highp float;\n    \n    uniform sampler2D iChannel0;\n\n    // ... the code of BufferA tab with the uniforms and wrapping as above\n  \u003c/script\u003e\n  \u003cscript type=\"x-shader/x-fragment\" id=\"Image\"\u003e\n    precision highp float;\n    \n    uniform sampler2D iChannel0;\n\n    // ... the code of Image tab with the uniforms and wrapping as above\n  \u003c/script\u003e\n  \u003cscript\u003e\n    // ... your prefer method of loading shader-web-background as described above\n  \u003c/script\u003e\n  \u003cscript\u003e\n    shaderWebBackground.shade({\n      shaders: {\n        BufferA: {\n          uniforms: {\n            iChannel0: (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.buffers.BufferA)\n          }\n        },\n        Image: {\n          uniforms: {\n            iChannel0: (gl, loc, ctx) =\u003e ctx.texture(loc, ctx.buffers.BufferA)\n          }\n        }\n      }\n    });\n  \u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Own vertex shader\n\nIt's possible to alter default vertex shader for each fragment shader by providing\nthe following script in the `\u003chead\u003e`:\n\n```javascript\n\u003cscript type=\"x-shader/x-vertex\" id=\"shaderIdVertex\"\u003e\n  attribute vec2 V;\n  varying vec2 uv;\n\n  void main(){\n    gl_Position=vec4(V,0,1);\n  }\n\u003c/script\u003e\n\u003cscript type=\"x-shader/x-fragment\" id=\"shaderId\"\u003e\n  // ...\n  varying vec2 uv;\n  // ...\n\u003c/script\u003e\n```\n\n:information_source: Note: the script `type` is set to `x-shader/x-vertex` and the\n`id` attribute is prepended with `Vertex` suffix. The vertex attribute should be named\n`V`.\n\n:information_source: Note: `varying vec2 uv` can be specified to be shared between vertex\nand fragment shaders (not added by default).\n\n\n## General tips\n\n* set the html background color to the dominant color of your shader to avoid flickering\n  on page load\n\n\n## Building\n\n```console\ngit clone https://github.com/xemantic/shader-web-background.git\ncd shader-web-background\n./gradlew compileJs\n```\n\nIt will trigger Google Closure Compiler which will check sources using type information\nand transpile them into minified JavaScript files:\n\n * [dist/shader-web-background.min.js](dist/shader-web-background.min.js)\n * [dist/shader-web-background.min.js.map](dist/shader-web-background.min.js.map)\n\n\n## Contributing\n\n### Code conventions\n\nThis project has been developed using\n[IntelliJ IDEA](https://www.jetbrains.com/idea/) with\n[google-java-format](https://plugins.jetbrains.com/plugin/8527-google-java-format)\nplugin enabled. The most noticeable element of this style are 2 spaces\ninstead of 4 for rendering tabs. \n\n\n### Adding your project to the list of project using this library\n\nEither:\n\n * fork this repo\n * open [index.html](index.html) and scroll to `\u003csection id=\"projects-using-shader-web-background\"\u003e`\n * add your project to the list\n * create pull-request\n\nOr [send me](https://xemantic.com/) a link with description.\n\n\n## Tools and dependencies\n\n * [gradle](https://gradle.org/) as a build system\n * [Kotlin](https://kotlinlang.org/) for scripting the build\n * [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API)\n   for [OpenGL](https://www.opengl.org/) based rendering\n * [Google Closure Compiler] for verifying JavaScript and minimizing it\n * [highlight.js](https://highlightjs.org/) (minimal modification - \n   [GLSL in HTML script support](lib/highlight/LOCAL_CHANGES.md)) for presenting the code in demo\n   folder\n * [screenfull.js](https://github.com/sindresorhus/screenfull.js/) for cross-browser fullscreen\n   support in library demo\n * [NoSleep.js](https://richtr.github.io/NoSleep.js/) for preventing sleep and screen dimming\n   in fullscreen mode demo\n * [BrowserStack](https://www.browserstack.com/) for testing the library on variety of\n   physical mobile and tablet devices\n\n\n## TODO\n\n * remove h1 on iphone as an alternative to real fullscreen\n * add an option to install as a home app on android and iOS\n\n\n[Shadertoy]:                     https://www.shadertoy.com/\n[performance.now()]:             https://developer.mozilla.org/en-US/docs/Web/API/Performance/now\n[Google Closure Compiler]:       https://github.com/google/closure-compiler\n[WebGLTexture]:                  https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture\n[WebGLRenderingContext.uniform]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniform\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxemantic%2Fshader-web-background","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxemantic%2Fshader-web-background","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxemantic%2Fshader-web-background/lists"}