meta-next
Version:
150 lines (130 loc) • 3.65 kB
JavaScript
import Engine from "../Engine"
import Resource from "./Resource"
const requestTextFunc = (request) => { return request.text() }
function Attrib(name, loc) {
this.name = name
this.loc = loc
}
function Uniform(name, loc, type) {
this.name = name
this.loc = loc
this.type = type
}
class Material extends Resource
{
constructor(config)
{
super(config)
this.program = null
this.attrib = null
this.attribData = null
this.uniform = null
this.uniformData = null
this.numAttribs = 0
this.uniforms = {}
if(config) {
this.setup(config)
}
}
setup(config)
{
if(config.vertexSourcePath)
{
this.loading = true
fetch(config.vertexSourcePath)
.then(requestTextFunc)
.then((vertexSource) => {
if(config.fragmentSourcePath) {
fetch(config.vertexSourcePath)
.then(requestTextFunc)
.then((fragmentSource) => {
this.createProgram(vertexSource, fragmentSource)
})
}
else {
this.createProgram(vertexSource, config.fragmentSource)
}
})
}
else if(config.fragmentSourcePath) {
fetch(config.vertexSourcePath)
.then(requestTextFunc)
.then((fragmentSource) => {
this.createProgram(config.vertexSource, fragmentSource)
})
}
else {
this.createProgram(config.vertexSource, config.fragmentSource)
}
}
loadShader(type, source)
{
const gl = Engine.gl
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
let shaderType
switch(type) {
case gl.VERTEX_SHADER:
shaderType = "VERTEX_SHADER"
break
case gl.FRAGMENT_SHADER:
shaderType = "FRAGMENT_SHADER"
break
}
console.error(`${shaderType}: ${gl.getShaderInfoLog(shader)}`)
gl.deleteShader(shader)
return null
}
return shader
}
createProgram(vertexSource, fragmentSource)
{
const gl = Engine.gl
const vertexShader = this.loadShader(gl.VERTEX_SHADER, vertexSource)
const fragmentShader = this.loadShader(gl.FRAGMENT_SHADER, fragmentSource)
this.program = gl.createProgram()
gl.attachShader(this.program, vertexShader)
gl.attachShader(this.program, fragmentShader)
gl.linkProgram(this.program)
if(!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
console.error(`Unable to initialize the shader program: ${gl.getProgramInfoLog(this.program)}`)
gl.deleteProgram(this.program)
gl.deleteShader(vertexShader)
gl.deleteShader(fragmentShader)
return
}
this.extractAttribs()
this.extractUniforms()
this.loading = false
}
extractAttribs()
{
this.attrib = {}
this.attribData = []
const gl = Engine.gl
this.numAttribs = gl.getProgramParameter(this.program, gl.ACTIVE_ATTRIBUTES)
for(let n = 0; n < this.numAttribs; n++) {
const attrib = gl.getActiveAttrib(this.program, n)
const attribLoc = gl.getAttribLocation(this.program, attrib.name)
this.attrib[attrib.name] = attribLoc
this.attribData.push(new Attrib(attrib.name, attribLoc))
}
}
extractUniforms()
{
this.uniform = {}
this.uniformData = []
const gl = Engine.gl
const num = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
for(let n = 0; n < num; n++) {
const uniform = gl.getActiveUniform(this.program, n)
const name = uniform.name.replace("[0]", "")
const loc = gl.getUniformLocation(this.program, name)
this.uniform[name] = loc
this.uniformData.push(new Uniform(name, loc, uniform.type))
}
}
}
export default Material