UNPKG

mdx-m3-viewer

Version:

A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.

127 lines (108 loc) 4.01 kB
import M3ParserStandardMaterial from '../../../parsers/m3/standardmaterial'; import ShaderProgram from '../../gl/program'; import Texture from '../../texture'; import M3Model from './model'; import M3Layer from './layer'; export const STANDARD_MATERIAL_OFFSET = 100; /** * An M3 standard material. */ export class M3StandardMaterial { model: M3Model; gl: WebGLRenderingContext; index: number; name: string; flags: number; blendMode: number; priority: number; specularity: number; specMult: number; emisMult: number; layerBlendType: number; emisBlendType: number; emisMode: number; doubleSided: number; layers: M3Layer[]; constructor(model: M3Model, index: number, material: M3ParserStandardMaterial) { this.model = model; this.gl = model.viewer.gl; this.index = index; this.name = <string>material.name.get(); this.flags = material.flags; this.blendMode = material.blendMode; this.priority = material.priority; this.specularity = material.specularity; this.specMult = material.specMult; this.emisMult = material.emisMult; this.layerBlendType = material.layerBlendType; this.emisBlendType = material.emisBlendType; this.emisMode = material.emisMode; this.doubleSided = material.flags & 0x8; this.layers = [ new M3Layer(this, 0, material.diffuseLayer, 'diffuse', 2), new M3Layer(this, 1, material.decalLayer, 'decal', 2), new M3Layer(this, 2, material.specularLayer, 'specular', 2), new M3Layer(this, 3, material.glossLayer, 'gloss', 2), new M3Layer(this, 4, material.emissiveLayer, 'emissive', material.emisBlendType), new M3Layer(this, 5, material.emissive2Layer, 'emissive2', material.emisMode), new M3Layer(this, 6, material.evioLayer, 'evio', 2), new M3Layer(this, 7, material.evioMaskLayer, 'evioMask', 2), new M3Layer(this, 8, material.alphaMaskLayer, 'alphaMask', 2), new M3Layer(this, 9, material.alphaMask2Layer, 'alphaMask2', 2), new M3Layer(this, 10, material.normalLayer, 'normal', 2), new M3Layer(this, 11, material.heightLayer, 'heightMap', 2), new M3Layer(this, 12, material.lightMapLayer, 'lightMap', 2), new M3Layer(this, 13, material.ambientOcclusionLayer, 'ao', 2), ]; } bindCommon() { const gl = this.gl; if (this.blendMode === 1) { gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE); } else if (this.blendMode === 2) { gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE); } else { gl.disable(gl.BLEND); } if (this.doubleSided) { gl.disable(gl.CULL_FACE); } else { gl.enable(gl.CULL_FACE); } // Flags somewhere? // Per layer? gl.enable(gl.DEPTH_TEST); gl.depthMask(true); } bind(shader: ShaderProgram, textureOverrides: Map<number, Texture>) { const gl = this.gl; this.bindCommon(); gl.uniform1f(shader.uniforms.u_specularity, this.specularity); gl.uniform1f(shader.uniforms.u_specMult, this.specMult); gl.uniform1f(shader.uniforms.u_emisMult, this.emisMult); gl.uniform4f(shader.uniforms.u_lightAmbient, 0.02, 0.02, 0.02, 0); const layers = this.layers; layers[0].bind(shader, textureOverrides); layers[1].bind(shader, textureOverrides); layers[2].bind(shader, textureOverrides); layers[4].bind(shader, textureOverrides); layers[5].bind(shader, textureOverrides); layers[10].bind(shader, textureOverrides); layers[12].bind(shader, textureOverrides); } unbind(shader: ShaderProgram) { const gl = this.gl; gl.disable(gl.BLEND); gl.enable(gl.CULL_FACE); const layers = this.layers; layers[0].unbind(shader); layers[1].unbind(shader); layers[2].unbind(shader); layers[4].unbind(shader); layers[5].unbind(shader); layers[10].unbind(shader); layers[12].unbind(shader); } }