UNPKG

mdx-m3-viewer

Version:

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

165 lines (129 loc) 4.95 kB
import Reference from '../../../parsers/m3/reference'; import Layer from '../../../parsers/m3/layer'; import Texture from '../../texture'; import ShaderProgram from '../../gl/program'; import TextureMapper from '../../texturemapper'; import M3StandardMaterial from './standardmaterial'; import M3Model from './model'; const layerTypeToTextureUnit = { diffuse: 1, decal: 2, specular: 3, gloss: 4, emissive: 5, emissive2: 6, evio: 7, evioMask: 8, alphaMask: 9, alphaMask2: 10, normal: 11, heightMap: 12, lightMap: 13, ao: 14, }; /** * An M3 layer. */ export default class M3Layer { model: M3Model; active: number = 0; layer: Layer | null = null; gl: WebGLRenderingContext; uniformMap: { map: string; enabled: string; op: string; channels: string; teamColorMode: string; invert: string; clampResult: string; uvCoordinate: string; }; source: string = ''; texture: Texture | null = null; flags: number = 0; colorChannels: number = 0; type: string = ''; op: number = 0; uvCoordinate: number = 0; textureUnit: number = 0; invert: number = 0; clampResult: number = 0; teamColorMode: number = 0; constructor(material: M3StandardMaterial, layerReference: Reference | null, type: string, op: number) { let model = material.model; this.model = model; this.gl = material.gl; let uniform = 'u_' + type; let settings = uniform + 'LayerSettings.'; this.uniformMap = { map: uniform + 'Map', enabled: settings + 'enabled', op: settings + 'op', channels: settings + 'channels', teamColorMode: settings + 'teamColorMode', invert: settings + 'invert', clampResult: settings + 'clampResult', uvCoordinate: settings + 'uvCoordinate', }; // Since Gloss doesn't exist in all versions if (layerReference) { let layer = layerReference.get(); this.layer = layer; let pathSolver = model.pathSolver; let source = layer.imagePath.getAll().join('').replace('\0', '').toLowerCase(); if (source.length) { this.source = source; this.texture = <Texture>model.viewer.load(source, pathSolver); this.active = 1; let uvSource = layer.uvSource; let flags = layer.flags; this.flags = flags; this.colorChannels = layer.colorChannelSetting; this.model = model; this.type = type; this.op = op; let uvCoordinate = 0; if (uvSource === 1) { uvCoordinate = 1; } else if (uvSource === 9) { uvCoordinate = 2; } else if (uvSource === 10) { uvCoordinate = 3; } this.uvCoordinate = uvCoordinate; this.textureUnit = layerTypeToTextureUnit[type]; this.invert = flags & 0x10; this.clampResult = flags & 0x20; // I am not sure if the emissive team color mode is even used, since so far combineColors takes care of it. if (type === 'diffuse') { this.teamColorMode = 1; } } } } bind(shader: ShaderProgram, textureMapper: TextureMapper) { let gl = this.gl; let uniformMap = this.uniformMap; let uniforms = shader.uniforms; let active = this.active; gl.uniform1f(uniforms[uniformMap.enabled], active); if (active) { let texture = this.texture; let textureUnit = this.textureUnit; gl.uniform1i(uniforms[uniformMap.map], textureUnit); this.model.viewer.webgl.bindTexture(textureMapper.get(texture) || texture, textureUnit); gl.uniform1f(uniforms[uniformMap.op], this.op); gl.uniform1f(uniforms[uniformMap.channels], this.colorChannels); gl.uniform1f(uniforms[uniformMap.teamColorMode], this.teamColorMode); // Alpha is probably unknown12. Can this be confirmed? // Many of these flags seem to be incorrect // gl.setParameter(uniform + 'multAddAlpha', [this.model.getValue(this.rgbMultiply, sequence, frame), this.model.getValue(this.rgbAdd, sequence, frame), 0]); // gl.setParameter(uniform + 'useAlphaFactor', 0); gl.uniform1f(uniforms[uniformMap.invert], this.invert); // gl.setParameter(uniform + 'multColor', 0); // gl.setParameter(uniform + 'addColor', 0); gl.uniform1f(uniforms[uniformMap.clampResult], this.clampResult); // gl.setParameter(uniform + 'useConstantColor', this.flags && 0x400); // gl.setParameter(uniform + 'constantColor', this.model.getValue(this.color, sequence, frame)); // gl.setParameter(settings + 'uvSource', this.uvSource); gl.uniform1f(uniforms[uniformMap.uvCoordinate], this.uvCoordinate); } } unbind(shader: ShaderProgram) { if (this.active) { this.gl.uniform1f(shader.uniforms[this.uniformMap.enabled], 0); } } }