Skip to content

Instantly share code, notes, and snippets.

@h4k1m0u
Last active December 18, 2022 20:21
Show Gist options
  • Save h4k1m0u/a312b9d557acf9b065ecdecc43529c33 to your computer and use it in GitHub Desktop.
Save h4k1m0u/a312b9d557acf9b065ecdecc43529c33 to your computer and use it in GitHub Desktop.

Description

Demo (using Webpack) of glslCanvas, a tool to test GLSL shaders on HTML canvas. See the Book of Shaders for a list of tutorials on GLSL.

Builtin uniforms

  • u_time: Time in seconds since shader started.
  • u_resolution: Billboard size.
  • u_mouse: Mouse position inside billboard (in px).

GLSL vars & functions

gl_FragCoord

  • Coordinates of current fragment rel. to window.
  • Origin: lower-left corner.
  • Lower-left pixel coords: (0.5, 0.5)

Step function (step()

$$ step(edge, x) = \begin{cases} 0, & x \lt edge \\ 1, & \text{otherwise} \end{cases} $$

with:

  • $x$: input variable
  • $edge$: threshold

Hermite interpolation (smoothstep())

$$ smoothstep(t_0, t_1, x) = \begin{cases} 0, & x \lt t_0 \\ 3x^2 - 2x^3, & 0 \le x \le 1 \\ 1, & x \ge t_1 \\ \end{cases} $$

with:

  • $x$: input variable
  • $t_0$ and $t_1$: thresholds
  • gives a sigmoid-shaped function

Linear interpolation (mix())

$$ mix(x, y, a) = (1 - a) x + a y $$

with:

  • $x$ and $y$: input variables
  • $a$: weight
// file: src/main.js
import fragUrl from '../shaders/shader.frag';
// load file content of fragment shader
const fragContent = await fetch(fragUrl).then(res => res.text());
// attach fragment shader to canvas
const canvas = document.getElementById('canvas');
const sandbox = new GlslCanvas(canvas);
sandbox.load(fragContent);
console.log(`Fragment shader: ${fragContent}`);
console.log('sandbox');
console.log(sandbox);
<!-- file: templates/index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GLSL-Canvas Example</title>
<script type="text/javascript" src="https://rawgit.com/patriciogonzalezvivo/glslCanvas/master/dist/GlslCanvas.js"></script>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
</html>
{
"name": "glslcanvas-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack serve"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"
}
}
// file: shaders/shader.frag
#ifdef GL_ES
precision mediump float;
#endif
/**
* Uniforms set by default by GlslCanvas:
* - u_time: Time in sec since shader started
* - u_resolution: Billboard size in px
* - u_mouse: mouse position inside billboard in px
*/
uniform float u_time;
/* Fragment shader from: https://thebookofshaders.com/03/ */
void main() {
gl_FragColor = vec4(abs(sin(u_time)), 0.0, 0.0, 1.0);
}
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: "./src/main.js",
output: {
filename: "bundle.js"
},
module: {
rules: [
// loader for vertex & fragment shaders files (replacement to file-loader)
{ test: /\.vert|\.frag$/, type: "asset/resource" },
]
},
devServer: {
open: true, // open browser automatically
},
// generate index.html including output js file
plugins: [new HtmlWebpackPlugin({
template: 'templates/index.html'
})],
// to use `await` at top of module
experiments: {
topLevelAwait: true,
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment