зеркало из https://github.com/mozilla/Spoke.git
Added support for MOZ_lightmap
This commit is contained in:
Родитель
05fec755b2
Коммит
f489cbbf80
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче