diff --git a/shaders/README.md b/shaders/README.md new file mode 100644 index 00000000..e3b29dd7 --- /dev/null +++ b/shaders/README.md @@ -0,0 +1,19 @@ +All game shaders are placed in this directory. + +Only `.vert` and `.frag` files are loaded; all other extensions are ignored. + +Shader language used: GLSL ES2. + +Usage: +```js +import getShader from './shaders'; +const shader = getShader('shaderName'); +console.log(shader); +// { vertex: '...', fragment: '...' } +``` + +References: + * https://www.khronos.org/files/opengles_shading_language.pdf + * https://www.khronos.org/opengl/wiki/Shader + * https://www.khronos.org/opengl/wiki/Vertex_Shader + * https://www.khronos.org/opengl/wiki/Fragment_Shader diff --git a/shaders/index.js b/shaders/index.js new file mode 100644 index 00000000..66529a25 --- /dev/null +++ b/shaders/index.js @@ -0,0 +1,70 @@ +import fs from 'fs'; + +// All loaded shaders are stored here. +const shader = {}; +// Amount of files that need to be loaded / skipped. +let shadersToLoad = null; +// If true, all shaders have been loaded. +let discoveryComplete = false; +// Used as keys in `shader`. +const term = { + vert: 'vertexShader', + frag: 'fragmentShader', +} + +// Counts the amount of shaders loaded. Calls 'onComplete' if loaded shader +// count equals initial total count. +function checkAllComplete (onComplete) { + if (!--shadersToLoad) { + discoveryComplete = true; + onComplete(); + } +} + +function discoverShaders(onComplete=()=>{}) { + if (discoveryComplete) { + return onComplete(); + } + fs.readdir('./shaders', (error, files) => { + if (error) { + discoveryComplete = true; + console.error('Could not read shader directory.'); + return onComplete(); + } + + shadersToLoad = files.length; + for (let i = 0, len = files.length; i < len; i++) { + const file = files[i]; + if (!file.includes('.vert') && !file.includes('.frag')) { + // We currently support .vert and .frag. This also weeds out .js. + checkAllComplete(onComplete); + continue; + } + + fs.readFile('./shaders/' + file, (error, data) => { + if (error) { + console.error(`Could not read shader '${file}':`, error); + return checkAllComplete(onComplete); + } + + const baseName = file.replace(/\.[^/.]+$/, ''); + const shaderType = term[file.split('.').pop()]; + + if (!shader[baseName]) { + shader[baseName] = {}; + } + shader[baseName][shaderType] = data.toString(); + checkAllComplete(onComplete); + }); + } + }); +} + +function getShader(name) { + return shader[name]; +} + +export { + discoverShaders, + getShader, +}