-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use cubemap with ocean and bump aframe to master
- Loading branch information
Showing
2 changed files
with
115 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,140 @@ | ||
/* global AFRAME, THREE */ | ||
if (typeof AFRAME === 'undefined') { | ||
throw new Error('Component attempted to register before AFRAME was available.'); | ||
if (typeof AFRAME === "undefined") { | ||
throw new Error( | ||
"Component attempted to register before AFRAME was available." | ||
); | ||
} | ||
|
||
/** | ||
* Cubemap component for A-Frame. | ||
* | ||
* Adapted from "Skybox and environment map in Three.js" by Roman Liutikov | ||
* https://web.archive.org/web/20160206163422/https://blog.romanliutikov.com/post/58705840698/skybox-and-environment-map-in-threejs | ||
* | ||
*/ | ||
AFRAME.registerComponent('cubemap', { | ||
AFRAME.registerComponent("cubemap", { | ||
schema: { | ||
folder: { | ||
type: 'string' | ||
type: "string", | ||
}, | ||
edgeLength: { | ||
type: 'int', | ||
default: 5000 | ||
type: "int", | ||
default: 5000, | ||
}, | ||
ext: { | ||
type: 'string', | ||
default: 'jpg' | ||
type: "string", | ||
default: "jpg", | ||
}, | ||
transparent: { | ||
type: 'boolean', | ||
default: false | ||
} | ||
}, | ||
|
||
/** | ||
* Called when component is attached and when component data changes. | ||
* Generally modifies the entity based on the data. | ||
* Called once when the component is initialized. | ||
* Used to set up initial state and instantiate variables. | ||
*/ | ||
update: function (oldData) { | ||
init: function () { | ||
// entity data | ||
var el = this.el; | ||
var data = this.data; | ||
|
||
// Path to the folder containing the 6 cubemap images | ||
var srcPath = data.folder; | ||
|
||
// Cubemap image files must follow this naming scheme | ||
// from: http://threejs.org/docs/index.html#Reference/Textures/CubeTexture | ||
var urls = [ | ||
'posx', 'negx', | ||
'posy', 'negy', | ||
'posz', 'negz' | ||
]; | ||
// Apply extension | ||
urls = urls.map(function(val) { | ||
return val + "." + data.ext; | ||
}); | ||
|
||
// Code that follows is adapted from "Skybox and environment map in Three.js" by Roman Liutikov | ||
// http://blog.romanliutikov.com/post/58705840698/skybox-and-environment-map-in-threejs | ||
const el = this.el; | ||
const data = this.data; | ||
|
||
var shader = THREE.ShaderLib['cube']; // init cube shader from built-in lib | ||
// A Cubemap can be rendered as a mesh composed of a BoxBufferGeometry and | ||
// ShaderMaterial. EdgeLength will scale the mesh | ||
this.geometry = new THREE.BoxBufferGeometry(1, 1, 1); | ||
|
||
// Create shader material | ||
var skyBoxShader = new THREE.ShaderMaterial({ | ||
// Now for the ShaderMaterial. | ||
const shader = THREE.ShaderLib["cube"]; | ||
// Note: cloning the material is necessary to prevent the cube shader's | ||
// uniforms from being mutated. If the material was not cloned, all cubemaps | ||
// in the scene would share the same uniforms (and look identical). | ||
this.material = new THREE.ShaderMaterial({ | ||
fragmentShader: shader.fragmentShader, | ||
vertexShader: shader.vertexShader, | ||
uniforms: shader.uniforms, | ||
depthWrite: false, | ||
side: THREE.BackSide, | ||
transparent: data.transparent | ||
}).clone(); | ||
// Threejs seems to have removed the 'tCube' uniform. | ||
// Workaround from: https://stackoverflow.com/a/59454999/6591491 | ||
Object.defineProperty(this.material, "envMap", { | ||
get: function () { | ||
return this.uniforms.envMap.value; | ||
}, | ||
}); | ||
// A dummy texture is needed (otherwise the shader will be invalid and spew | ||
// a million errors) | ||
this.material.uniforms["envMap"].value = new THREE.Texture(); | ||
this.loader = new THREE.CubeTextureLoader(); | ||
|
||
// Set skybox dimensions | ||
var edgeLength = data.edgeLength; | ||
var skyBoxGeometry = new THREE.CubeGeometry(edgeLength, edgeLength, edgeLength); | ||
// We can create the mesh now and update the material with a texture later on | ||
// in the update lifecycle handler. | ||
this.mesh = new THREE.Mesh(this.geometry, this.material); | ||
this.mesh.scale.set(data.edgeLength, data.edgeLength, data.edgeLength); | ||
el.setObject3D("cubemap", this.mesh); | ||
}, | ||
|
||
// Create loader, set folder path, and load cubemap textures | ||
var loader = new THREE.CubeTextureLoader(); | ||
loader.setPath(srcPath); | ||
loader.load(urls, function(texture) { | ||
// Clone ShaderMaterial (necessary for multiple cubemaps) | ||
var skyBoxMaterial = skyBoxShader.clone(); | ||
// Threejs seems to have removed the 'tCube' uniform. | ||
// Workaround from: https://stackoverflow.com/a/59454999/6591491 | ||
Object.defineProperty(skyBoxMaterial, "envMap", { | ||
get: function () { | ||
return this.uniforms.envMap.value; | ||
}, | ||
/** | ||
* Called when component is attached and when component data changes. | ||
* Generally modifies the entity based on the data. | ||
*/ | ||
update: function (oldData) { | ||
// entity data | ||
const el = this.el; | ||
const data = this.data; | ||
const rendererSystem = el.sceneEl.systems.renderer; | ||
|
||
if (data.edgeLength !== oldData.edgeLength) { | ||
// Update the size of the skybox. | ||
this.mesh.scale.set(data.edgeLength, data.edgeLength, data.edgeLength); | ||
} | ||
|
||
if (data.ext !== oldData.ext || data.folder !== oldData.folder) { | ||
// Load textures. | ||
// Path to the folder containing the 6 cubemap images | ||
const srcPath = data.folder; | ||
// Cubemap image files must follow this naming scheme | ||
// from: http://threejs.org/docs/index.html#Reference/Textures/CubeTexture | ||
var urls = ["posx", "negx", "posy", "negy", "posz", "negz"]; | ||
// Apply extension | ||
urls = urls.map(function (val) { | ||
return val + "." + data.ext; | ||
}); | ||
texture.encoding = THREE.sRGBEncoding; | ||
skyBoxMaterial.uniforms["envMap"].value = texture; // Apply cubemap textures to shader uniforms | ||
|
||
// Set entity's object3D | ||
el.setObject3D('cubemap', new THREE.Mesh(skyBoxGeometry, skyBoxMaterial)); | ||
}); | ||
// Set folder path, and load cubemap textures | ||
this.loader.setPath(srcPath); | ||
this.loader.load(urls, onTextureLoad.bind(this)); | ||
|
||
function onTextureLoad(texture) { | ||
if (srcPath !== this.data.folder) { | ||
// The texture that just finished loading no longer matches the folder | ||
// set on this component. This can happen when the user calls setAttribute() | ||
// to change folders multiple times in quick succession. | ||
texture.dispose(); | ||
return; | ||
} | ||
// Have the renderer system set texture encoding as in A-Frame core. | ||
// https://github.com/bryik/aframe-cubemap-component/issues/13#issuecomment-626238202 | ||
rendererSystem.applyColorCorrection(texture); | ||
|
||
// Apply cubemap texture to shader uniforms and dispose of the old texture. | ||
const oldTexture = this.material.uniforms["envMap"].value; | ||
this.material.uniforms["envMap"].value = texture; | ||
if (oldTexture) { | ||
oldTexture.dispose(); | ||
} | ||
|
||
// Tell the world that the cubemap texture has loaded. | ||
el.emit("cubemapLoaded"); | ||
} | ||
} | ||
}, | ||
|
||
/** | ||
* Called when a component is removed (e.g., via removeAttribute). | ||
* Generally undoes all modifications to the entity. | ||
*/ | ||
remove: function () { | ||
this.el.removeObject3D('cubemap'); | ||
} | ||
this.geometry.dispose(); | ||
this.material.uniforms["envMap"].value.dispose(); | ||
this.material.dispose(); | ||
this.el.removeObject3D("cubemap"); | ||
}, | ||
}); |