moh1456's picture
Upload 27 files
af8291a verified
import Attribute from './Attribute.js';
export default class Material {
/**
* The parent MiniGL controller.
*
* @type {MiniGL}
* @private
*/
gl;
uniformInstances = [];
/**
*
* @param {MiniGL} minigl
* @param {object} properties
*/
constructor(minigl, vertexShaders, fragments, uniforms = {}, properties = {}) {
// Add additional properties.
Object.assign(this, properties);
// Set required properties.
this.gl = minigl;
this.uniforms = uniforms;
const context = this.gl.getContext();
const prefix = `
precision highp float;
`;
this.vertexSource = `
${prefix}
attribute vec4 position;
attribute vec2 uv;
attribute vec2 uvNorm;
${this._getUniformVariableDeclarations(this.gl.commonUniforms,"vertex")}
${this._getUniformVariableDeclarations(uniforms,"vertex")}
${vertexShaders}
`;
this.Source = `
${prefix}
${this._getUniformVariableDeclarations(this.gl.commonUniforms,"fragment")}
${this._getUniformVariableDeclarations(uniforms,"fragment")}
${fragments}
`;
this.vertexShader = this._getShaderByType(context.VERTEX_SHADER, this.vertexSource);
this.fragmentShader = this._getShaderByType(context.FRAGMENT_SHADER, this.Source);
this.program = context.createProgram();
context.attachShader(this.program, this.vertexShader);
context.attachShader(this.program, this.fragmentShader);
context.linkProgram(this.program);
context.getProgramParameter(this.program, context.LINK_STATUS) || console.error(context.getProgramInfoLog(this.program));
context.useProgram(this.program);
this.attachUniforms(void 0, this.gl.commonUniforms);
this.attachUniforms(void 0, this.uniforms);
}
_getShaderByType(type, source) {
const context = this.gl.getContext();
const shader = context.createShader(type);
context.shaderSource(shader, source);
context.compileShader(shader);
if (!context.getShaderParameter(shader, context.COMPILE_STATUS)) {
console.error(context.getShaderInfoLog(shader));
}
return shader;
}
_getUniformVariableDeclarations(uniforms, type) {
return Object.entries(uniforms).map(([uniform, value]) => {
return value.getDeclaration(uniform, type);
}).join("\n");
}
attachUniforms(name, uniforms) {
if (!name) {
Object.entries(uniforms).forEach(([name, uniform]) => {
this.attachUniforms(name, uniform);
});
} else if (uniforms.type === 'array') {
uniforms.value.forEach((uniform, i) => {
this.attachUniforms(`${name}[${i}]`, uniform);
});
} else if (uniforms.type === 'struct') {
Object.entries(uniforms.value).forEach(([uniform, i]) => {
this.attachUniforms(`${name}.${uniform}`, i);
});
} else {
this.uniformInstances.push({
uniform: uniforms,
location: this.gl.getContext().getUniformLocation(this.program, name)
});
}
}
}