Skip to content

Instantly share code, notes, and snippets.

@Pan-Maciek
Created May 3, 2017 14:13
Show Gist options
  • Save Pan-Maciek/e5a6d4b65f941b425586b306f5b62cee to your computer and use it in GitHub Desktop.
Save Pan-Maciek/e5a6d4b65f941b425586b306f5b62cee to your computer and use it in GitHub Desktop.
const __size__ = {
vec2: 2,
vec3: 3,
vec4: 4,
mat3: 9,
mat4: 16
}
const typeSize = (type) => __size__[type]
/**
* @param {WebGLRenderingContext} gl
*/
export const glUtils = gl => {
class Attribute {
constructor(program, name, type) {
this.name = name
this.size = typeSize(type)
this.type = type
this.__buffer__ = gl.createBuffer()
this.__location__ = gl.getAttribLocation(program, name)
this.length = 0
gl.enableVertexAttribArray(this.__location__)
}
set(value) {
gl.bindBuffer(gl.ARRAY_BUFFER, this.__buffer__)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(value), gl.STATIC_DRAW)
gl.vertexAttribPointer(this.__location__, this.size, gl.FLOAT, false, 0, 0)
this.length = value.length / this.size
}
}
class Uniform {
constructor(program, name, type) {
this.name = name
this.size = typeSize(type)
this.type = type
this.__location__ = gl.getUniformLocation(program, name)
this.__uniform__ = gl.getUniform(program, this.__location__)
}
set(value) {
switch (this.size) {
case 1:
gl.uniform1fv(this.__location__, value)
break
case 2:
gl.uniform2fv(this.__location__, value)
break
case 3:
gl.uniform3fv(this.__location__, value)
break
case 4:
if (this.type[0] === 'm')
gl.uniformMatrix2fv(this.___location__, false, value)
else
gl.uniform4fv(this.__location__, value)
break
case 9:
gl.uniformMatrix3fv(this.___location__, false, value)
break
case 16:
gl.uniformMatrix4fv(this.__location__, false, value)
break
}
}
}
/** Finds attributes and uniforms and appends them to program.
*
* @param {WebGLProgram} program
* @param {String} source
*/
const appendAU = (program, source) => {
const regex = /^(attribute|uniform)\s+(\w+)\s+(\w+)\s*;/gm
let temp
while (temp = regex.exec(source)) {
const [, type, varType, name] = temp
if (program[name]) continue
switch (type) {
case 'attribute':
program[name] = new Attribute(program, name, varType)
break
case 'uniform':
program[name] = new Uniform(program, name, varType)
break
}
}
}
const createShader = (type, source) => {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(`An error occurred while compiling the shaders: ${gl.getShaderInfoLog(shader)}`)
gl.deleteShader(shader)
return null
}
shader.source = source
return shader
}
return {
createFragmentShader(source) {
return createShader(gl.FRAGMENT_SHADER, source)
},
createVertexShader(source) {
return createShader(gl.VERTEX_SHADER, source)
},
createProgram(vertex, fragment) {
const program = gl.createProgram()
gl.attachShader(program, vertex)
gl.attachShader(program, fragment)
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(`Failed to link program: ${gl.getProgramInfoLog(program)}`)
gl.deleteProgram(program)
gl.deleteShader(fragment)
gl.deleteShader(vertex)
return null
}
gl.validateProgram(program)
if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
console.error(`Failed to link program: ${gl.getProgramInfoLog(program)}`)
gl.deleteProgram(program)
gl.deleteShader(fragment)
gl.deleteShader(vertex)
return null
}
const fullSource = vertex.source + fragment.source
appendAU(program, fullSource)
return program
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment