Skip to content

Instantly share code, notes, and snippets.

@x1unix
Last active October 9, 2018 14:07
Show Gist options
  • Save x1unix/fa678e15286b6258440519bb879ed667 to your computer and use it in GitHub Desktop.
Save x1unix/fa678e15286b6258440519bb879ed667 to your computer and use it in GitHub Desktop.
Easy shader fetch
function Shader(glContext, type) {
this.context = glContext;
this.type = type;
this.source = '';
this.shader = null;
this.name = '';
this.from = (url) => new Promise((resolve, reject) => {
this.name = ((i) => i.length > 0 ? i[i.length - 1] : i[0])(url.split('/'));
fetch(url)
.then(response => response.text())
.then((hlsl) => {
this.source = hlsl;
return this.build(hlsl);
})
.then((shader) => resolve(shader))
.catch(err => reject(err));
});
this.build = (hlsl) => {
return new Promise((resolve, reject) => {
this.shader = this.context.createShader(this.type);
this.context.shaderSource(this.shader, hlsl);
this.context.compileShader(this.shader);
if (!this.context.getShaderParameter(this.shader, gl.COMPILE_STATUS)) {
const err = this.context.getShaderInfoLog(this.shader);
reject(new Shader.ShaderBuildError(this, err));
return;
}
resolve(this.shader);
});
};
this.getContent = () => this.shader;
};
Shader.VERTEX = 35633;
Shader.FRAGMENT = 35632;
Shader.Vertex = (glContext) => new Shader(glContext, Shader.VERTEX);
Shader.Fragment = (glContext) => new Shader(glContext, Shader.FRAGMENT);
Shader.ShaderBuildError = function(shaderContainer, error) {
Error.call(this, error);
const errorRegex = /ERROR: ([0-9]):([0-9])/g;
this.name = 'ShaderBuildError';
this.message = `Failed to build shader '${shaderContainer.name}': ${error}`;
this.toString = function() {
const sources = shaderContainer.source.split('\n');
const parsedError = errorRegex.exec(error);
let output = ''+this.message;
if (error === null) {
return this.message;
}
const errorNum = +parsedError[1];
let errorLine = +parsedError[2];
if (!isNaN(errorLine) && (errorLine > 0)) {
errorLine--;
}
output += `\nError in '${shaderContainer.name}':\n\n`;
output += sources.map((strLine, index) =>
(index === errorLine) ? `--> ${strLine}` : ` ${strLine}`
).join('\n');
return output;
};
}
function initShaders(cb) {
// Fetch shaders
Promise.all([
Shader.Vertex(gl).from('shaders/vertex.hlsl'),
Shader.Fragment(gl).from('shaders/fragment.hlsl')
]).then((shaders) => {
// Apply shaders
var fragmentShader = shaders[1];
var vertexShader = shaders[0];
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
cb();
}).catch((err) => {
alert(err.toString())
/*
'.toString()' will display detalized error, like:
Failed to build shader 'fragment.glsl': ERROR: 0:4: 'double' : Illegal use of reserved word
ERROR: 0:4: 'double' : syntax error
Error in 'fragment.glsl':
-> precision mediump float;
void main() {
double r = 0;
double g = 0.5;
double b = 1;
double a = 1;
gl_FragColor = vec4(r, g, b, a);
}
*/
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment