Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDR Lightmaps & Environment Settings System #4538

Merged
merged 7 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/assets/stylesheets/hub.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,11 @@ a-entity {
vertical-align: -0.125em;
height: 1em;
}

// Dat GUI
.dg select {
color: black;
}
.dg input {
line-height: normal;
}
5 changes: 0 additions & 5 deletions src/components/camera-tool.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,6 @@ AFRAME.registerComponent("camera-tool", {
const width = 0.28;
const geometry = new THREE.PlaneBufferGeometry(width, width / this.camera.aspect);

const environmentMapComponent = this.el.sceneEl.components["environment-map"];
if (environmentMapComponent) {
environmentMapComponent.applyEnvironmentMap(this.el.object3D);
}

this.screen = new THREE.Mesh(geometry, material);
this.screen.rotation.set(0, Math.PI, 0);
this.screen.position.set(0, 0, -0.042);
Expand Down
25 changes: 0 additions & 25 deletions src/components/environment-map.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { forEachMaterial } from "../utils/material-utils";
import cubeMapPosX from "../assets/images/cubemap/posx.jpg";
import cubeMapNegX from "../assets/images/cubemap/negx.jpg";
import cubeMapPosY from "../assets/images/cubemap/posy.jpg";
Expand All @@ -14,27 +13,3 @@ export async function createDefaultEnvironmentMap() {
texture.format = THREE.RGBFormat;
return texture;
}

AFRAME.registerComponent("environment-map", {
init() {
this.environmentMap = null;

this.updateEnvironmentMap = this.updateEnvironmentMap.bind(this);
},

updateEnvironmentMap(environmentMap) {
this.environmentMap = environmentMap;
this.applyEnvironmentMap(this.el.object3D);
},

applyEnvironmentMap(object3D) {
object3D.traverse(object => {
forEachMaterial(object, material => {
if (material.isMeshStandardMaterial) {
material.envMap = this.environmentMap;
material.needsUpdate = true;
}
});
});
}
});
109 changes: 102 additions & 7 deletions src/components/gltf-model-plus.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MeshBVH, acceleratedRaycast } from "three-mesh-bvh";
import { disposeNode, cloneObject3D } from "../utils/three-utils";
import HubsTextureLoader from "../loaders/HubsTextureLoader";
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";

THREE.Mesh.prototype.raycast = acceleratedRaycast;

Expand Down Expand Up @@ -398,6 +399,21 @@ class GLTFHubsPlugin {
node.extras.gltfIndex = i;
}
}

function hookDef(defType, hookName) {
return Promise.all(
parser.json[defType].map((_def, idx) => {
return Promise.all(
parser._invokeAll(function(ext) {
return ext[hookName] && ext[hookName](idx);
})
);
})
);
}

// TODO decide if thse should get put into the GLTF loader itself
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: typo

Suggested change
// TODO decide if thse should get put into the GLTF loader itself
// TODO decide if these should get put into the GLTF loader itself

return Promise.all([hookDef("scenes", "extendScene"), hookDef("nodes", "extendNode")]);
}

afterRoot(gltf) {
Expand Down Expand Up @@ -431,6 +447,59 @@ class GLTFHubsPlugin {
}
}

class GLTFHubsComponentsExtension {
constructor(parser) {
this.parser = parser;
this.name = "MOZ_hubs_components";
}

_markDefs() {
// TODO hack to keep hubs component data in userData. Remove once we handle all component stuff in a plugin
delete this.parser.extensions.MOZ_hubs_components;
}

extendScene(sceneIdx) {
const ext = this.parser.json.scenes[sceneIdx]?.extensions?.MOZ_hubs_components;
console.log("extendceneParams", ext, sceneIdx, this.parser.json.scenes[sceneIdx]);
if (ext) return this.resolveComponentLinks(ext);
}

extendNode(nodeIdx) {
const ext = this.parser.json.nodes[nodeIdx]?.extensions?.MOZ_hubs_components;
if (ext) return this.resolveComponentLinks(ext);
}

resolveComponentLinks(ext) {
console.log("resolveComponentLinks", ext);

const deps = [];

for (const componentName in ext) {
const props = ext[componentName];
for (const propName in props) {
const value = props[propName];
const type = value?.__mhc_link_type;
if (type && value.index !== undefined) {
console.log("Loading link", value);
deps.push(
this.parser.getDependency(type, value.index).then(loadedDep => {
console.log(`${type} loaded`, loadedDep);
props[propName] = loadedDep;
// TODO figure out if this is sane
if (type === "texture") {
loadedDep.flipY = true;
}
console.log(props);
})
);
}
}
}

return Promise.all(deps);
}
}

class GLTFHubsLightMapExtension {
constructor(parser) {
this.parser = parser;
Expand Down Expand Up @@ -501,6 +570,36 @@ class GLTFHubsTextureBasisExtension {
}
}

class GLTFMozTextureRGBE {
constructor(parser, loader) {
this.parser = parser;
this.loader = loader;
this.name = "MOZ_texture_rgbe";
}

loadTexture(textureIndex) {
const parser = this.parser;
const json = parser.json;
const textureDef = json.textures[textureIndex];

if (!textureDef.extensions || !textureDef.extensions[this.name]) {
return null;
}

const extensionDef = textureDef.extensions[this.name];
const source = json.images[extensionDef.source];
return parser.loadTextureImage(textureIndex, source, this.loader).then(t => {
// TODO pretty severe artifacting when using mipmaps, disable for now
if (t.minFilter == THREE.NearestMipmapNearestFilter || t.minFilter == THREE.NearestMipmapLinearFilter) {
t.minFilter = THREE.NearestFilter;
} else if (t.minFilter == THREE.LinearMipmapNearestFilter || t.minFilter == THREE.LinearMipmapLinearFilter) {
t.minFilter = THREE.LinearFilter;
}
return t;
});
}
}

export async function loadGLTF(src, contentType, onProgress, jsonPreprocessor) {
let gltfUrl = src;
let fileMap;
Expand All @@ -514,9 +613,11 @@ export async function loadGLTF(src, contentType, onProgress, jsonPreprocessor) {
loadingManager.setURLModifier(getCustomGLTFParserURLResolver(gltfUrl));
const gltfLoader = new THREE.GLTFLoader(loadingManager);
gltfLoader
.register(parser => new GLTFHubsComponentsExtension(parser))
.register(parser => new GLTFHubsPlugin(parser, jsonPreprocessor))
.register(parser => new GLTFHubsLightMapExtension(parser))
.register(parser => new GLTFHubsTextureBasisExtension(parser));
.register(parser => new GLTFHubsTextureBasisExtension(parser))
.register(parser => new GLTFMozTextureRGBE(parser, new RGBELoader().setDataType(THREE.HalfFloatType)));

// TODO some models are loaded before the renderer exists. This is likely things like the camera tool and loading cube.
// They don't currently use KTX textures but if they did this would be an issue. Fixing this is hard but is part of
Expand Down Expand Up @@ -701,12 +802,6 @@ AFRAME.registerComponent("gltf-model-plus", {
if (el) rewires.push(() => (o.el = el));
});

const environmentMapComponent = this.el.sceneEl.components["environment-map"];

if (environmentMapComponent) {
environmentMapComponent.applyEnvironmentMap(object3DToSet);
}

if (lastSrc) {
gltfCache.release(lastSrc);
}
Expand Down
10 changes: 0 additions & 10 deletions src/components/media-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { waitForDOMContentLoaded } from "../utils/async-utils";

import { SHAPE } from "three-ammo/constants";

let loadingObjectEnvMap;
let loadingObject;

waitForDOMContentLoaded().then(() => {
Expand Down Expand Up @@ -192,15 +191,6 @@ AFRAME.registerComponent("media-loader", {
this.updateScale(true, false);

if (useFancyLoader) {
const environmentMapComponent = this.el.sceneEl.components["environment-map"];
if (environmentMapComponent) {
const currentEnivronmentMap = environmentMapComponent.environmentMap;
if (loadingObjectEnvMap !== currentEnivronmentMap) {
environmentMapComponent.applyEnvironmentMap(mesh);
loadingObjectEnvMap = currentEnivronmentMap;
}
}

this.loaderMixer = new THREE.AnimationMixer(mesh);

this.loadingClip = this.loaderMixer.clipAction(mesh.animations[0]);
Expand Down
1 change: 0 additions & 1 deletion src/components/scene-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import "./floaty-object";
import "./super-spawner";
import "./water";
import "./simple-water";
import "./environment-map";
import "./trigger-volume";
import "./video-pause-state";
import "./particle-emitter";
Expand Down
10 changes: 3 additions & 7 deletions src/components/skybox.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,12 +430,6 @@ AFRAME.registerComponent("skybox", {
init() {
this.sky = new Sky();
this.el.setObject3D("mesh", this.sky);

this.updateEnvironmentMap = this.updateEnvironmentMap.bind(this);
// HACK: Render environment map on next frame to avoid bug where the render target texture is black.
// This is likely due to the custom elements attached callback being synchronous on Chrome but not Firefox.
// Added timeout due to additional case where texture is black in Firefox.
requestAnimationFrame(() => setTimeout(this.updateEnvironmentMap));
},

update(oldData) {
Expand Down Expand Up @@ -478,7 +472,8 @@ AFRAME.registerComponent("skybox", {
this.sky.matrixNeedsUpdate = true;
}

this.updateEnvironmentMap();
// TODO do we care about updating enviornment map after scene load?
// this.updateEnvironmentMap();
},

updateEnvironmentMap() {
Expand All @@ -491,6 +486,7 @@ AFRAME.registerComponent("skybox", {
const envMap = this.sky.generateEnvironmentMap(renderer);
environmentMapComponent.updateEnvironmentMap(envMap);
} else if (quality === "medium") {
// TODO this still needs to be accounted for
// This extra ambient light is here to normalize lighting with the MeshStandardMaterial.
// Without it, objects are significantly darker in brighter environments.
// It's kept to a low value to not wash out objects in very dark environments.
Expand Down
5 changes: 0 additions & 5 deletions src/components/tools/networked-drawing.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,6 @@ AFRAME.registerComponent("networked-drawing", {

this.el.setObject3D("mesh", this.drawing);

const environmentMapComponent = this.el.sceneEl.components["environment-map"];
if (environmentMapComponent) {
environmentMapComponent.applyEnvironmentMap(this.drawing);
}

this.prevIdx = Object.assign({}, this.sharedBuffer.idx);
this.idx = Object.assign({}, this.sharedBuffer.idx);
this.vertexCount = 0; //number of vertices added for current line (used for line deletion).
Expand Down
6 changes: 0 additions & 6 deletions src/components/tools/pen-laser.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ AFRAME.registerComponent("pen-laser", {
this.laserTip.scale.setScalar(0.01);
this.laserTip.matrixNeedsUpdate = true;

const environmentMapComponent = this.el.sceneEl.components["environment-map"];
if (environmentMapComponent) {
environmentMapComponent.applyEnvironmentMap(this.laser);
environmentMapComponent.applyEnvironmentMap(this.laserTip);
}

//prevents the line from being a raycast target for the cursor
this.laser.raycast = function() {};

Expand Down
5 changes: 0 additions & 5 deletions src/components/tools/pen.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,6 @@ AFRAME.registerComponent("pen", {

this.el.setObject3D("mesh", this.penTip);

const environmentMapComponent = this.el.sceneEl.components["environment-map"];
if (environmentMapComponent) {
environmentMapComponent.applyEnvironmentMap(this.el.parentEl.object3D);
}

this.penLaserAttributesUpdated = false;
this.penLaserAttributes = {
color: "#FF0033",
Expand Down
33 changes: 30 additions & 3 deletions src/gltf-component-mappings.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,12 @@ AFRAME.GLTFModelPlus.registerComponent(
enterComponentMapping = getSanitizedComponentMapping(enterComponent, enterProperty, publicComponents);
leaveComponentMapping = getSanitizedComponentMapping(leaveComponent, leaveProperty, publicComponents);

targetEntity = indexToEntityMap[target];
// indexToEntityMap should be considered depredcated. These references are now resovled by the GLTFHubsComponentExtension
if (typeof target === "number") {
targetEntity = indexToEntityMap[target];
} else {
targetEntity = target?.el;
}

if (!targetEntity) {
throw new Error(`Couldn't find target entity with index: ${target}.`);
Expand Down Expand Up @@ -434,7 +439,12 @@ AFRAME.GLTFModelPlus.registerComponent(

let srcEl;
if (srcNode !== undefined) {
srcEl = indexToEntityMap[srcNode];
// indexToEntityMap should be considered depredcated. These references are now resovled by the GLTFHubsComponentExtension
if (typeof srcNode === "number") {
srcEl = indexToEntityMap[srcNode];
} else {
srcEl = srcNode?.el;
}
if (!srcEl) {
console.warn(
`Error inflating gltf component "video-texture-srcEl": Couldn't find srcEl entity with index ${srcNode}`
Expand Down Expand Up @@ -462,7 +472,12 @@ AFRAME.GLTFModelPlus.registerComponent(

let srcEl;
if (srcNode !== undefined) {
srcEl = indexToEntityMap[srcNode];
// indexToEntityMap should be considered depredcated. These references are now resovled by the GLTFHubsComponentExtension
if (typeof srcNode === "number") {
srcEl = indexToEntityMap[srcNode];
} else {
srcEl = srcNode?.el;
}
if (!srcEl) {
console.warn(
`Error inflating gltf component ${componentName}: Couldn't find srcEl entity with index ${srcNode}`
Expand Down Expand Up @@ -514,3 +529,15 @@ AFRAME.GLTFModelPlus.registerComponent(
AFRAME.GLTFModelPlus.registerComponent("audio-zone", "audio-zone", (el, componentName, componentData) => {
el.setAttribute(componentName, { ...componentData });
});

AFRAME.GLTFModelPlus.registerComponent(
"environment-settings",
"environment-settings",
(el, componentName, componentData) => {
// TODO a bit silly to be storing this as an aframe component. Use a glboal store of some sort
el.setAttribute(componentName, {
...componentData,
backgroundColor: new THREE.Color(componentData.backgroundColor)
});
}
);
1 change: 0 additions & 1 deletion src/hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
freeze-controller
personal-space-bubble="debug: false;"
rotate-selected-object
environment-map
light="defaultLightsEnabled: false"
>
<a-assets>
Expand Down
Loading