Created
July 14, 2019 06:48
-
-
Save sessamekesh/92a0f46f37b2cfe9aa32104495437ce7 to your computer and use it in GitHub Desktop.
Quick example about loading vertex/fragment shaders from a GLSL file (instead of inlining it)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// If you're loading the shaders from an external file, one way or | |
// another you'll have to do some asynchronous stuff. This means | |
// that you'll have to run the code to load the shader (which can | |
// potentially take awhile), and have a callback ready to start | |
// the demo once the shader source is loaded. | |
// I'll illustrate three ways to do that here, hopefully it helps! | |
// | |
// Code shared between all three methods: essentially the same code | |
// that's in the videos, except that it's wrapped inside a function | |
// that takes vertexShaderText and fragmentShaderText as parameters | |
// instead of defining them as variables at the top. | |
function runDemo(webGLContext, vertexShaderText, fragmentShaderText) { | |
// "const" is loosely the same as "var", but newer and better. | |
const vs = webGLContext.createShader(webGLContext.VERTEX_SHADER); | |
webGLContext.shaderSource(vs, vertexShaderText); | |
// ... so on, like in the videos | |
} | |
loadShadersAndRunDemo(); | |
// Method 1: Async/Await | |
// By far the cleanest to read, but requires new-ish JavaScript features | |
// that aren't super common yet. | |
// Notice "async" before "function" - this marks the function as an | |
// asynchronous function, meaning that it will return a Promise. | |
// Read up on promises here if you aren't familiar: | |
// https://developers.google.com/web/fundamentals/primers/promises | |
async function loadShadersAndRunDemo() { | |
// "fetch" makes an HTTP request to the given address, then returns | |
// a Result object that can be parsed as text, json, or binary. | |
// We want the text result! | |
// "await" says "wait for the fetch call to finish before setting | |
// the variable and continuing execution" | |
const vertexShaderText = await fetch('vertexshader.glsl') | |
.then(result => result.text()); | |
const fragmentShaderText = await fetch('fragmentshader.glsl') | |
.then(result => result.text()); | |
runDemo(vertexShaderText, fragmentShaderText); | |
} | |
// Method 2: Promise-based. Identical to the method 1 in how the web | |
// browser actually runs the code, but not quite as new (so it'll | |
// work on more browsers, and has more demos that use it): | |
function loadShadersAndRunDemo() { | |
const vertexShaderPromise = fetch('vertexshader.glsl') | |
.then(result => result.text()); | |
const fragmentShaderPromise = fetch('fragmentshader.glsl') | |
.then(result => result.text()); | |
// Promise.all says "wait for these promises to finish, then | |
// call a function that takes the results as parameters" | |
Promise.all([vertexShaderPromise, fragmentShaderPromise]) | |
.then((vertexShaderText, fragmentShaderText) => { | |
runDemo(vertexShaderText, fragmentShaderText); | |
}); | |
} | |
// Method 3: Old, outdated, possibly familiar. This is what was common | |
// around the time I was initially learning WebGL (pre-ES6 days...) | |
// but I think even in the videos I was using newer stuff than this. | |
function loadShadersAndRunDemo() { | |
var vsxml = new XMLHttpRequest(); | |
vsxml.open('GET', 'vertexshader.glsl'); | |
vsxml.onLoad = function (vsText) { | |
var fsxml = new XMLHttpRequest(); | |
fsxml.open('GET', 'fragmentshader.glsl'); | |
fsxml.onLoad = function (fsText) { | |
runDemo(vsText, fsText); | |
}; | |
fsxml.send(); | |
}; | |
vsxml.send(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment