Added support for MOZ_lightmap

This commit is contained in:
Robert Long 2020-04-15 15:45:30 -07:00
Родитель 05fec755b2
Коммит f489cbbf80
3 изменённых файлов: 105 добавлений и 71 удалений

Просмотреть файл

@ -21,7 +21,6 @@ import {
BufferAttribute,
BufferGeometry,
ClampToEdgeWrapping,
Color,
DefaultLoadingManager,
DoubleSide,
FileLoader,
@ -65,13 +64,13 @@ import {
TextureLoader,
TriangleFanDrawMode,
TriangleStripDrawMode,
Vector2,
VectorKeyframeTrack,
VertexColors,
sRGBEncoding
} from "three";
import { MaterialsUnlitLoaderExtension } from "./extensions/loader/MaterialsUnlitLoaderExtension";
import { LightmapLoaderExtension } from "./extensions/loader/LightmapLoaderExtension";
/* CONSTANTS */
@ -300,6 +299,7 @@ class GLTFLoader {
this.hooks = {};
this.registerExtension(MaterialsUnlitLoaderExtension);
this.registerExtension(LightmapLoaderExtension);
}
registerExtension(Extension, options = {}) {
@ -326,7 +326,7 @@ class GLTFLoader {
hooks.push({ test, callback });
}
async runHook(hookName, ...args) {
async runFirstHook(hookName, ...args) {
const hooks = this.hooks[hookName];
if (hooks) {
@ -340,6 +340,22 @@ class GLTFLoader {
return undefined;
}
async runAllHooks(hookName, ...args) {
const hooks = this.hooks[hookName];
const matchedHooks = [];
if (hooks) {
for (const { test, callback } of hooks) {
if (test(...args)) {
matchedHooks.push(callback(...args));
}
}
}
return Promise.all(matchedHooks);
}
async loadRoot() {
// Tells the LoadingManager to track an extra item, which resolves after
// the model is fully loaded. This means the count of items loaded will
@ -1094,7 +1110,7 @@ class GLTFLoader {
const material = originalMaterials[i];
let mesh = await this.runHook("createPrimitive", meshDef, primitive, geometry, material);
let mesh = await this.runFirstHook("createPrimitive", meshDef, primitive, geometry, material);
if (!mesh) {
if (
@ -1416,18 +1432,14 @@ class GLTFLoader {
const { json } = await this.getDependency("root");
const materialDef = json.materials[materialIndex];
let materialParams = await this.runHook("gatherMaterialParams", materialDef);
if (!materialParams) {
materialParams = await this.gatherStandardMaterialParams(materialDef);
}
let material = await this.runHook("createMaterial", materialDef, materialParams);
let material = await this.runFirstHook("createMaterial", materialDef);
if (!material) {
material = new MeshStandardMaterial(materialParams);
material = await this.createStandardMaterial(materialDef);
}
await this.runAllHooks("setMaterialParams", material, materialDef);
if (materialDef.name !== undefined) material.name = materialDef.name;
this.assignExtrasToUserData(material, materialDef);
@ -1437,8 +1449,8 @@ class GLTFLoader {
return material;
}
async gatherStandardMaterialParams(materialDef) {
const materialParams = {};
async createStandardMaterial(materialDef) {
const material = new MeshStandardMaterial();
const pending = [];
@ -1447,93 +1459,78 @@ class GLTFLoader {
const metallicRoughness = materialDef.pbrMetallicRoughness || {};
materialParams.color = new Color(1.0, 1.0, 1.0);
materialParams.opacity = 1.0;
material.color.set(1.0, 1.0, 1.0);
material.opacity = 1.0;
const alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
if (Array.isArray(metallicRoughness.baseColorFactor)) {
const array = metallicRoughness.baseColorFactor;
materialParams.color.fromArray(array);
materialParams.opacity = array[3];
material.color.fromArray(array);
material.opacity = array[3];
}
if (metallicRoughness.baseColorTexture !== undefined) {
const format = alphaMode === ALPHA_MODES.OPAQUE ? RGBFormat : RGBAFormat;
pending.push(this.assignTexture(materialParams, "map", metallicRoughness.baseColorTexture, sRGBEncoding, format));
pending.push(this.assignTexture(material, "map", metallicRoughness.baseColorTexture, sRGBEncoding, format));
}
materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
materialParams.roughness =
metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
material.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
material.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
if (metallicRoughness.metallicRoughnessTexture !== undefined) {
pending.push(
this.assignTexture(
materialParams,
"metalnessMap",
metallicRoughness.metallicRoughnessTexture,
undefined,
RGBFormat
)
this.assignTexture(material, "metalnessMap", metallicRoughness.metallicRoughnessTexture, undefined, RGBFormat)
);
pending.push(
this.assignTexture(
materialParams,
"roughnessMap",
metallicRoughness.metallicRoughnessTexture,
undefined,
RGBFormat
)
this.assignTexture(material, "roughnessMap", metallicRoughness.metallicRoughnessTexture, undefined, RGBFormat)
);
}
if (materialDef.doubleSided === true) {
materialParams.side = DoubleSide;
material.side = DoubleSide;
}
if (alphaMode === ALPHA_MODES.BLEND) {
materialParams.transparent = true;
material.transparent = true;
} else {
materialParams.transparent = false;
material.transparent = false;
if (alphaMode === ALPHA_MODES.MASK) {
materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
}
}
if (materialDef.normalTexture !== undefined) {
pending.push(this.assignTexture(materialParams, "normalMap", materialDef.normalTexture, undefined, RGBFormat));
pending.push(this.assignTexture(material, "normalMap", materialDef.normalTexture, undefined, RGBFormat));
materialParams.normalScale = new Vector2(1, 1);
material.normalScale.set(1, 1);
if (materialDef.normalTexture.scale !== undefined) {
materialParams.normalScale.set(materialDef.normalTexture.scale, materialDef.normalTexture.scale);
material.normalScale.set(materialDef.normalTexture.scale, materialDef.normalTexture.scale);
}
}
if (materialDef.occlusionTexture !== undefined) {
pending.push(this.assignTexture(materialParams, "aoMap", materialDef.occlusionTexture, undefined, RGBFormat));
pending.push(this.assignTexture(material, "aoMap", materialDef.occlusionTexture, undefined, RGBFormat));
if (materialDef.occlusionTexture.strength !== undefined) {
materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
material.aoMapIntensity = materialDef.occlusionTexture.strength;
}
}
if (materialDef.emissiveFactor !== undefined) {
materialParams.emissive = new Color().fromArray(materialDef.emissiveFactor);
material.emissive.fromArray(materialDef.emissiveFactor);
}
if (materialDef.emissiveTexture !== undefined) {
pending.push(
this.assignTexture(materialParams, "emissiveMap", materialDef.emissiveTexture, sRGBEncoding, RGBFormat)
);
pending.push(this.assignTexture(material, "emissiveMap", materialDef.emissiveTexture, sRGBEncoding, RGBFormat));
}
await Promise.all(pending);
return materialParams;
return material;
}
/**
@ -1716,13 +1713,13 @@ class GLTFLoader {
/**
* Asynchronously assigns a texture to the given material parameters.
* @param {Object} materialParams
* @param {Object} material
* @param {string} mapName
* @param {Object} mapDef
* @param {PixelFormat} format
* @return {Promise}
*/
async assignTexture(materialParams, mapName, mapDef, overrideEncoding, overrideFormat) {
async assignTexture(material, mapName, mapDef, overrideEncoding, overrideFormat) {
const texture = await this.getDependency("texture", mapDef.index);
if (!texture.isCompressedTexture && overrideFormat) {
@ -1733,7 +1730,7 @@ class GLTFLoader {
texture.encoding = overrideEncoding;
}
materialParams[mapName] = texture;
material[mapName] = texture;
}
/**

Просмотреть файл

@ -0,0 +1,31 @@
import { sRGBEncoding, RGBFormat } from "three";
import { LoaderExtension } from "./LoaderExtension";
function getLightmap(materialDef) {
return materialDef.extensions && materialDef.extensions[LightmapLoaderExtension.extensionName];
}
function shouldSetMaterialParams(_material, materialDef) {
return getLightmap(materialDef);
}
export class LightmapLoaderExtension extends LoaderExtension {
static extensionName = "MOZ_lightmap";
extensionNames = [LightmapLoaderExtension.extensionName];
onLoad() {
if (this.loader.usesExtension(LightmapLoaderExtension.extensionName)) {
this.loader.addHook("setMaterialParams", shouldSetMaterialParams, this.setMaterialParams);
}
}
setMaterialParams = async (material, materialDef) => {
const lightmap = getLightmap(materialDef);
if (lightmap) {
console.log("set lightmap", lightmap);
await this.loader.assignTexture(material, "lightMap", lightmap, sRGBEncoding, RGBFormat);
}
};
}

Просмотреть файл

@ -1,11 +1,19 @@
import { Color, DoubleSide, MeshBasicMaterial, sRGBEncoding, RGBFormat, RGBAFormat } from "three";
import { DoubleSide, MeshBasicMaterial, sRGBEncoding, RGBFormat, RGBAFormat } from "three";
import { ALPHA_MODES } from "../../GLTFLoader";
import { LoaderExtension } from "./LoaderExtension";
export function getUnlitMaterial(materialDef) {
function getUnlitMaterial(materialDef) {
return materialDef.extensions && materialDef.extensions[MaterialsUnlitLoaderExtension.extensionName];
}
function shouldCreateMaterial(materialDef) {
return getUnlitMaterial(materialDef);
}
function shouldSetMaterialParams(_material, materialDef) {
return getUnlitMaterial(materialDef);
}
export class MaterialsUnlitLoaderExtension extends LoaderExtension {
static extensionName = "KHR_materials_unlit";
@ -13,18 +21,18 @@ export class MaterialsUnlitLoaderExtension extends LoaderExtension {
onLoad() {
if (this.loader.usesExtension(MaterialsUnlitLoaderExtension.extensionName)) {
this.loader.addHook("gatherMaterialParams", getUnlitMaterial, this.gatherMaterialParams);
this.loader.addHook("createMaterial", getUnlitMaterial, this.createMaterial);
this.loader.addHook("createMaterial", shouldCreateMaterial, this.createMaterial);
this.loader.addHook("setMaterialParams", shouldSetMaterialParams, this.setMaterialParams);
}
}
gatherMaterialParams = async materialDef => {
const materialParams = {};
createMaterial = async () => new MeshBasicMaterial();
setMaterialParams = async (material, materialDef) => {
const pending = [];
materialParams.color = new Color(1.0, 1.0, 1.0);
materialParams.opacity = 1.0;
material.color.set(0xffffff);
material.opacity = 1.0;
const alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
@ -34,36 +42,34 @@ export class MaterialsUnlitLoaderExtension extends LoaderExtension {
if (Array.isArray(metallicRoughness.baseColorFactor)) {
const array = metallicRoughness.baseColorFactor;
materialParams.color.fromArray(array);
materialParams.opacity = array[3];
material.color.fromArray(array);
material.opacity = array[3];
}
if (metallicRoughness.baseColorTexture !== undefined) {
const format = alphaMode === ALPHA_MODES.OPAQUE ? RGBFormat : RGBAFormat;
pending.push(
this.loader.assignTexture(materialParams, "map", metallicRoughness.baseColorTexture, sRGBEncoding, format)
this.loader.assignTexture(material, "map", metallicRoughness.baseColorTexture, sRGBEncoding, format)
);
}
}
if (materialDef.doubleSided === true) {
materialParams.side = DoubleSide;
material.side = DoubleSide;
}
if (alphaMode === ALPHA_MODES.BLEND) {
materialParams.transparent = true;
material.transparent = true;
} else {
materialParams.transparent = false;
material.transparent = false;
if (alphaMode === ALPHA_MODES.MASK) {
materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
}
}
await Promise.all(pending);
return materialParams;
console.log("unlit material", material, materialDef);
};
createMaterial = async (materialDef, materialParams) => new MeshBasicMaterial(materialParams);
}