href portal wip
This commit is contained in:
parent
2953be9cd6
commit
21ffc80e07
8 changed files with 482 additions and 213 deletions
139
dist/xrfragment.aframe.js
vendored
139
dist/xrfragment.aframe.js
vendored
|
|
@ -605,9 +605,18 @@ xrfragment.init = function(opts){
|
||||||
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
|
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
|
||||||
xrfragment.Parser.debug = xrfragment.debug
|
xrfragment.Parser.debug = xrfragment.debug
|
||||||
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
||||||
|
xrfragment.patchRenderer(opts.renderer)
|
||||||
return xrfragment
|
return xrfragment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xrfragment.patchRenderer = function(renderer){
|
||||||
|
renderer.render = ((render) => function(scene,camera){
|
||||||
|
if( xrfragment.getLastModel() && xrfragment.getLastModel().render )
|
||||||
|
xrfragment.getLastModel().render(scene,camera)
|
||||||
|
render(scene,camera)
|
||||||
|
})(renderer.render.bind(renderer))
|
||||||
|
}
|
||||||
|
|
||||||
xrfragment.patchLoader = function(loader){
|
xrfragment.patchLoader = function(loader){
|
||||||
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
||||||
load.call( this,
|
load.call( this,
|
||||||
|
|
@ -678,60 +687,53 @@ xrfragment.xrf.env = function(v, opts){
|
||||||
}
|
}
|
||||||
xrfragment.xrf.href = function(v, opts){
|
xrfragment.xrf.href = function(v, opts){
|
||||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||||
return
|
|
||||||
|
|
||||||
// Create a shader material that treats the texture as an equirectangular map
|
let size = 5
|
||||||
mesh.texture = mesh.material.map // backup texture
|
let texture = mesh.material.map
|
||||||
const equirectShader = THREE.ShaderLib[ 'equirect' ];
|
|
||||||
const equirectMaterial = new THREE.ShaderMaterial( {
|
/*
|
||||||
uniforms: THREE.UniformsUtils.merge([
|
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
THREE.UniformsLib.equirect,
|
mesh.material = new THREE.MeshStandardMaterial( {
|
||||||
equirectShader.uniforms,
|
envMap: texture,
|
||||||
]),
|
roughness: 0.0,
|
||||||
vertexShader: equirectShader.vertexShader,
|
metalness: 1,
|
||||||
fragmentShader: equirectShader.fragmentShader,
|
side: THREE.DoubleSide,
|
||||||
side: THREE.DoubleSide //THREE.FrontSide //THREE.DoubleSide //THREE.BackSide
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
|
mesh.material = new THREE.ShaderMaterial( {
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
uniforms: {
|
||||||
|
pano: { value: texture }
|
||||||
|
},
|
||||||
|
vertexShader: `
|
||||||
|
vec3 portalPosition;
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
varying float vDistanceToCenter;
|
||||||
|
varying float vDistance;
|
||||||
|
void main() {
|
||||||
|
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
|
||||||
|
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
||||||
|
vDistance = length(portalPosition - cameraPosition);
|
||||||
|
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
fragmentShader: `
|
||||||
|
#define RECIPROCAL_PI2 0.15915494
|
||||||
|
uniform sampler2D pano;
|
||||||
|
varying float vDistanceToCenter;
|
||||||
|
varying float vDistance;
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
void main() {
|
||||||
|
vec3 direction = normalize(vWorldPosition - cameraPosition);
|
||||||
|
vec2 sampleUV;
|
||||||
|
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
|
||||||
|
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;
|
||||||
|
gl_FragColor = texture2D(pano, sampleUV);
|
||||||
|
}
|
||||||
|
`
|
||||||
});
|
});
|
||||||
equirectMaterial.uniforms[ 'tEquirect' ].value = mesh.texture
|
|
||||||
// Define the tEquirectInvProjection uniform
|
|
||||||
equirectMaterial.uniforms.tEquirectInvProjection = {
|
|
||||||
value: new THREE.Matrix4(),
|
|
||||||
};
|
|
||||||
// Assign the new material to the mesh
|
|
||||||
mesh.material = equirectMaterial;
|
|
||||||
console.dir(mesh.material)
|
|
||||||
mesh.texture.wrapS = THREE.RepeatWrapping;
|
|
||||||
|
|
||||||
// patch custom model renderloop
|
|
||||||
model.render = ((render) => (scene,camera) => {
|
|
||||||
|
|
||||||
// Store the original projection matrix of the camera
|
|
||||||
const originalProjectionMatrix = camera.projectionMatrix.clone();
|
|
||||||
// Calculate the current camera view matrix
|
|
||||||
const aspectRatio = mesh.texture.image.width / mesh.texture.image.height;
|
|
||||||
camera.projectionMatrix.makePerspective(camera.fov, aspectRatio, camera.near, camera.far);
|
|
||||||
|
|
||||||
const viewMatrix = camera.matrixWorldInverse;
|
|
||||||
const worldMatrix = mesh.matrixWorld;
|
|
||||||
|
|
||||||
const equirectInvProjection = new THREE.Matrix4();
|
|
||||||
equirectInvProjection.copy(camera.projectionMatrix).multiply(viewMatrix).invert();
|
|
||||||
|
|
||||||
// Update the equirectangular material's tEquirect uniform
|
|
||||||
equirectMaterial.uniforms.tEquirect.value = mesh.texture;
|
|
||||||
equirectMaterial.uniforms.tEquirectInvProjection.value.copy(
|
|
||||||
equirectInvProjection
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset the camera projection matrix
|
|
||||||
camera.projectionMatrix.copy(originalProjectionMatrix);
|
|
||||||
|
|
||||||
|
|
||||||
render(scene,camera)
|
|
||||||
|
|
||||||
})(model.render)
|
|
||||||
|
|
||||||
console.dir(mesh)
|
|
||||||
}
|
}
|
||||||
xrfragment.xrf.pos = function(v, opts){
|
xrfragment.xrf.pos = function(v, opts){
|
||||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||||
|
|
@ -818,3 +820,36 @@ window.AFRAME.registerComponent('xrf', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AFRAME.registerComponent('gltf-to-entity', {
|
||||||
|
schema: {
|
||||||
|
from: {default: '', type: 'selector'},
|
||||||
|
name: {default: ''},
|
||||||
|
duplicate: {type:'boolean'}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function () {
|
||||||
|
var el = this.el;
|
||||||
|
var data = this.data;
|
||||||
|
|
||||||
|
data.from.addEventListener('model-loaded', evt => {
|
||||||
|
var model;
|
||||||
|
var subset;
|
||||||
|
model = evt.detail.model;
|
||||||
|
console.dir(this.data.from)
|
||||||
|
subset = model.getObjectByName(data.name);
|
||||||
|
if (!subset){
|
||||||
|
console.error("Sub-object", data.name, "not found in #"+data.from.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( !this.data.duplicate ) subset.parent.remove(subset)
|
||||||
|
let clone = subset.clone()
|
||||||
|
////subset.updateMatrixWorld();
|
||||||
|
el.object3D.position.setFromMatrixPosition(data.from.object3D.matrixWorld);
|
||||||
|
el.object3D.quaternion.setFromRotationMatrix(data.from.object3D.matrixWorld);
|
||||||
|
|
||||||
|
el.setObject3D('mesh', clone );
|
||||||
|
el.emit('model-loaded', el.getObject3D('mesh'));
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
106
dist/xrfragment.three.js
vendored
106
dist/xrfragment.three.js
vendored
|
|
@ -605,9 +605,18 @@ xrfragment.init = function(opts){
|
||||||
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
|
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
|
||||||
xrfragment.Parser.debug = xrfragment.debug
|
xrfragment.Parser.debug = xrfragment.debug
|
||||||
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
||||||
|
xrfragment.patchRenderer(opts.renderer)
|
||||||
return xrfragment
|
return xrfragment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xrfragment.patchRenderer = function(renderer){
|
||||||
|
renderer.render = ((render) => function(scene,camera){
|
||||||
|
if( xrfragment.getLastModel() && xrfragment.getLastModel().render )
|
||||||
|
xrfragment.getLastModel().render(scene,camera)
|
||||||
|
render(scene,camera)
|
||||||
|
})(renderer.render.bind(renderer))
|
||||||
|
}
|
||||||
|
|
||||||
xrfragment.patchLoader = function(loader){
|
xrfragment.patchLoader = function(loader){
|
||||||
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
||||||
load.call( this,
|
load.call( this,
|
||||||
|
|
@ -678,60 +687,53 @@ xrfragment.xrf.env = function(v, opts){
|
||||||
}
|
}
|
||||||
xrfragment.xrf.href = function(v, opts){
|
xrfragment.xrf.href = function(v, opts){
|
||||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||||
return
|
|
||||||
|
|
||||||
// Create a shader material that treats the texture as an equirectangular map
|
let size = 5
|
||||||
mesh.texture = mesh.material.map // backup texture
|
let texture = mesh.material.map
|
||||||
const equirectShader = THREE.ShaderLib[ 'equirect' ];
|
|
||||||
const equirectMaterial = new THREE.ShaderMaterial( {
|
/*
|
||||||
uniforms: THREE.UniformsUtils.merge([
|
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
THREE.UniformsLib.equirect,
|
mesh.material = new THREE.MeshStandardMaterial( {
|
||||||
equirectShader.uniforms,
|
envMap: texture,
|
||||||
]),
|
roughness: 0.0,
|
||||||
vertexShader: equirectShader.vertexShader,
|
metalness: 1,
|
||||||
fragmentShader: equirectShader.fragmentShader,
|
side: THREE.DoubleSide,
|
||||||
side: THREE.DoubleSide //THREE.FrontSide //THREE.DoubleSide //THREE.BackSide
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
|
mesh.material = new THREE.ShaderMaterial( {
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
uniforms: {
|
||||||
|
pano: { value: texture }
|
||||||
|
},
|
||||||
|
vertexShader: `
|
||||||
|
vec3 portalPosition;
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
varying float vDistanceToCenter;
|
||||||
|
varying float vDistance;
|
||||||
|
void main() {
|
||||||
|
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
|
||||||
|
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
||||||
|
vDistance = length(portalPosition - cameraPosition);
|
||||||
|
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
fragmentShader: `
|
||||||
|
#define RECIPROCAL_PI2 0.15915494
|
||||||
|
uniform sampler2D pano;
|
||||||
|
varying float vDistanceToCenter;
|
||||||
|
varying float vDistance;
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
void main() {
|
||||||
|
vec3 direction = normalize(vWorldPosition - cameraPosition);
|
||||||
|
vec2 sampleUV;
|
||||||
|
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
|
||||||
|
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;
|
||||||
|
gl_FragColor = texture2D(pano, sampleUV);
|
||||||
|
}
|
||||||
|
`
|
||||||
});
|
});
|
||||||
equirectMaterial.uniforms[ 'tEquirect' ].value = mesh.texture
|
|
||||||
// Define the tEquirectInvProjection uniform
|
|
||||||
equirectMaterial.uniforms.tEquirectInvProjection = {
|
|
||||||
value: new THREE.Matrix4(),
|
|
||||||
};
|
|
||||||
// Assign the new material to the mesh
|
|
||||||
mesh.material = equirectMaterial;
|
|
||||||
console.dir(mesh.material)
|
|
||||||
mesh.texture.wrapS = THREE.RepeatWrapping;
|
|
||||||
|
|
||||||
// patch custom model renderloop
|
|
||||||
model.render = ((render) => (scene,camera) => {
|
|
||||||
|
|
||||||
// Store the original projection matrix of the camera
|
|
||||||
const originalProjectionMatrix = camera.projectionMatrix.clone();
|
|
||||||
// Calculate the current camera view matrix
|
|
||||||
const aspectRatio = mesh.texture.image.width / mesh.texture.image.height;
|
|
||||||
camera.projectionMatrix.makePerspective(camera.fov, aspectRatio, camera.near, camera.far);
|
|
||||||
|
|
||||||
const viewMatrix = camera.matrixWorldInverse;
|
|
||||||
const worldMatrix = mesh.matrixWorld;
|
|
||||||
|
|
||||||
const equirectInvProjection = new THREE.Matrix4();
|
|
||||||
equirectInvProjection.copy(camera.projectionMatrix).multiply(viewMatrix).invert();
|
|
||||||
|
|
||||||
// Update the equirectangular material's tEquirect uniform
|
|
||||||
equirectMaterial.uniforms.tEquirect.value = mesh.texture;
|
|
||||||
equirectMaterial.uniforms.tEquirectInvProjection.value.copy(
|
|
||||||
equirectInvProjection
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset the camera projection matrix
|
|
||||||
camera.projectionMatrix.copy(originalProjectionMatrix);
|
|
||||||
|
|
||||||
|
|
||||||
render(scene,camera)
|
|
||||||
|
|
||||||
})(model.render)
|
|
||||||
|
|
||||||
console.dir(mesh)
|
|
||||||
}
|
}
|
||||||
xrfragment.xrf.pos = function(v, opts){
|
xrfragment.xrf.pos = function(v, opts){
|
||||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@
|
||||||
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
|
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
|
||||||
<script async src="./../../assets/alpine.min.js"></script>
|
<script async src="./../../assets/alpine.min.js"></script>
|
||||||
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
|
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/aframe-blink-controls/dist/aframe-blink-controls.min.js"></script>
|
||||||
<script src="./../../../dist/xrfragment.aframe.js"></script>
|
<script src="./../../../dist/xrfragment.aframe.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="overlay" x-data="{ urls: ['#pos=0,4,15&rot=0,360,0'] }">
|
<div id="overlay" x-data="{ urls: ['#pos=0,1.6,15&rot=0,360,0'] }">
|
||||||
<img src="./../../assets/logo.png" class="logo"/>
|
<img src="./../../assets/logo.png" class="logo"/>
|
||||||
<input type="submit" value="load 3D asset"></input>
|
<input type="submit" value="load 3D asset"></input>
|
||||||
<input type="text" id="uri" list="urls" value="#pos=0,4,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
|
<input type="text" id="uri" list="urls" value="#pos=0,1.6,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
|
||||||
<datalist id="urls" >
|
<datalist id="urls" >
|
||||||
<template x-for="url in urls">
|
<template x-for="url in urls">
|
||||||
<option x-bind:value="url" selected></option>
|
<option x-bind:value="url" selected></option>
|
||||||
|
|
@ -26,10 +27,15 @@
|
||||||
<a id="model" target="_blank" href="">⬇️ model</a>
|
<a id="model" target="_blank" href="">⬇️ model</a>
|
||||||
<textarea style="display:none"></textarea>
|
<textarea style="display:none"></textarea>
|
||||||
<a-scene>
|
<a-scene>
|
||||||
<a-entity xrf gltf-model="./../../assets/example3.gltf"/>
|
<a-entity id="model" xrf gltf-model="./../../assets/example3.gltf" />
|
||||||
<a-entity xrf position="0 4 15">
|
<a-entity id="floor" gltf-to-entity="from: #model; name: floor" />
|
||||||
<a-entity camera look-controls wasd-controls></a-entity>
|
|
||||||
|
<a-entity xrf id="player">
|
||||||
|
<a-entity camera position="0 1.6 15" look-controls wasd-controls></a-entity>
|
||||||
|
<a-entity id="left-hand" oculus-touch-controls="hand: left" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
|
||||||
|
<a-entity id="right-hand" oculus-touch-controls="hand: right" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
</a-scene>
|
</a-scene>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -9,10 +9,10 @@
|
||||||
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
|
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="overlay" x-data="{ urls: ['#pos=0,4,15','#pos=0,4,15&rot=0,360,0'] }">
|
<div id="overlay" x-data="{ urls: ['#pos=0,1.6,15','#pos=0,1.6,15&rot=0,360,0'] }">
|
||||||
<img src="./../../assets/logo.png" class="logo"/>
|
<img src="./../../assets/logo.png" class="logo"/>
|
||||||
<input type="submit" value="load 3D asset"></input>
|
<input type="submit" value="load 3D asset"></input>
|
||||||
<input type="text" id="uri" list="urls" value="#pos=0,4,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
|
<input type="text" id="uri" list="urls" value="#pos=0,1.6,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
|
||||||
<datalist id="urls" >
|
<datalist id="urls" >
|
||||||
<template x-for="url in urls">
|
<template x-for="url in urls">
|
||||||
<option x-bind:value="url" selected></option>
|
<option x-bind:value="url" selected></option>
|
||||||
|
|
@ -268,8 +268,6 @@
|
||||||
//torus.rotation.x = time * 0.4;
|
//torus.rotation.x = time * 0.4;
|
||||||
//torus.rotation.y = time;
|
//torus.rotation.y = time;
|
||||||
|
|
||||||
if( XRF.getLastModel() ) XRF.getLastModel().render(scene,camera)
|
|
||||||
|
|
||||||
//controls.update()
|
//controls.update()
|
||||||
renderer.render( scene, camera );
|
renderer.render( scene, camera );
|
||||||
stats.update();
|
stats.update();
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,36 @@ window.AFRAME.registerComponent('xrf', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AFRAME.registerComponent('gltf-to-entity', {
|
||||||
|
schema: {
|
||||||
|
from: {default: '', type: 'selector'},
|
||||||
|
name: {default: ''},
|
||||||
|
duplicate: {type:'boolean'}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function () {
|
||||||
|
var el = this.el;
|
||||||
|
var data = this.data;
|
||||||
|
|
||||||
|
data.from.addEventListener('model-loaded', evt => {
|
||||||
|
var model;
|
||||||
|
var subset;
|
||||||
|
model = evt.detail.model;
|
||||||
|
console.dir(this.data.from)
|
||||||
|
subset = model.getObjectByName(data.name);
|
||||||
|
if (!subset){
|
||||||
|
console.error("Sub-object", data.name, "not found in #"+data.from.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( !this.data.duplicate ) subset.parent.remove(subset)
|
||||||
|
let clone = subset.clone()
|
||||||
|
////subset.updateMatrixWorld();
|
||||||
|
el.object3D.position.setFromMatrixPosition(data.from.object3D.matrixWorld);
|
||||||
|
el.object3D.quaternion.setFromRotationMatrix(data.from.object3D.matrixWorld);
|
||||||
|
|
||||||
|
el.setObject3D('mesh', clone );
|
||||||
|
el.emit('model-loaded', el.getObject3D('mesh'));
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,18 @@ xrfragment.init = function(opts){
|
||||||
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
|
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
|
||||||
xrfragment.Parser.debug = xrfragment.debug
|
xrfragment.Parser.debug = xrfragment.debug
|
||||||
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
||||||
|
xrfragment.patchRenderer(opts.renderer)
|
||||||
return xrfragment
|
return xrfragment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xrfragment.patchRenderer = function(renderer){
|
||||||
|
renderer.render = ((render) => function(scene,camera){
|
||||||
|
if( xrfragment.getLastModel() && xrfragment.getLastModel().render )
|
||||||
|
xrfragment.getLastModel().render(scene,camera)
|
||||||
|
render(scene,camera)
|
||||||
|
})(renderer.render.bind(renderer))
|
||||||
|
}
|
||||||
|
|
||||||
xrfragment.patchLoader = function(loader){
|
xrfragment.patchLoader = function(loader){
|
||||||
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
||||||
load.call( this,
|
load.call( this,
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,50 @@
|
||||||
xrfragment.xrf.href = function(v, opts){
|
xrfragment.xrf.href = function(v, opts){
|
||||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||||
return
|
|
||||||
|
|
||||||
// Create a shader material that treats the texture as an equirectangular map
|
let size = 5
|
||||||
mesh.texture = mesh.material.map // backup texture
|
let texture = mesh.material.map
|
||||||
const equirectShader = THREE.ShaderLib[ 'equirect' ];
|
|
||||||
const equirectMaterial = new THREE.ShaderMaterial( {
|
|
||||||
uniforms: THREE.UniformsUtils.merge([
|
|
||||||
THREE.UniformsLib.equirect,
|
|
||||||
equirectShader.uniforms,
|
|
||||||
]),
|
|
||||||
vertexShader: equirectShader.vertexShader,
|
|
||||||
fragmentShader: equirectShader.fragmentShader,
|
|
||||||
side: THREE.DoubleSide //THREE.FrontSide //THREE.DoubleSide //THREE.BackSide
|
|
||||||
} );
|
|
||||||
equirectMaterial.uniforms[ 'tEquirect' ].value = mesh.texture
|
|
||||||
// Define the tEquirectInvProjection uniform
|
|
||||||
equirectMaterial.uniforms.tEquirectInvProjection = {
|
|
||||||
value: new THREE.Matrix4(),
|
|
||||||
};
|
|
||||||
// Assign the new material to the mesh
|
|
||||||
mesh.material = equirectMaterial;
|
|
||||||
console.dir(mesh.material)
|
|
||||||
mesh.texture.wrapS = THREE.RepeatWrapping;
|
|
||||||
|
|
||||||
// patch custom model renderloop
|
/*
|
||||||
model.render = ((render) => (scene,camera) => {
|
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
|
mesh.material = new THREE.MeshStandardMaterial( {
|
||||||
|
envMap: texture,
|
||||||
|
roughness: 0.0,
|
||||||
|
metalness: 1,
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
// Store the original projection matrix of the camera
|
mesh.material = new THREE.ShaderMaterial( {
|
||||||
const originalProjectionMatrix = camera.projectionMatrix.clone();
|
side: THREE.DoubleSide,
|
||||||
// Calculate the current camera view matrix
|
uniforms: {
|
||||||
const aspectRatio = mesh.texture.image.width / mesh.texture.image.height;
|
pano: { value: texture }
|
||||||
camera.projectionMatrix.makePerspective(camera.fov, aspectRatio, camera.near, camera.far);
|
},
|
||||||
|
vertexShader: `
|
||||||
const viewMatrix = camera.matrixWorldInverse;
|
vec3 portalPosition;
|
||||||
const worldMatrix = mesh.matrixWorld;
|
varying vec3 vWorldPosition;
|
||||||
|
varying float vDistanceToCenter;
|
||||||
const equirectInvProjection = new THREE.Matrix4();
|
varying float vDistance;
|
||||||
equirectInvProjection.copy(camera.projectionMatrix).multiply(viewMatrix).invert();
|
void main() {
|
||||||
|
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
|
||||||
// Update the equirectangular material's tEquirect uniform
|
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
||||||
equirectMaterial.uniforms.tEquirect.value = mesh.texture;
|
vDistance = length(portalPosition - cameraPosition);
|
||||||
equirectMaterial.uniforms.tEquirectInvProjection.value.copy(
|
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
||||||
equirectInvProjection
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||||
);
|
}
|
||||||
|
`,
|
||||||
// Reset the camera projection matrix
|
fragmentShader: `
|
||||||
camera.projectionMatrix.copy(originalProjectionMatrix);
|
#define RECIPROCAL_PI2 0.15915494
|
||||||
|
uniform sampler2D pano;
|
||||||
|
varying float vDistanceToCenter;
|
||||||
render(scene,camera)
|
varying float vDistance;
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
})(model.render)
|
void main() {
|
||||||
|
vec3 direction = normalize(vWorldPosition - cameraPosition);
|
||||||
console.dir(mesh)
|
vec2 sampleUV;
|
||||||
|
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
|
||||||
|
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;
|
||||||
|
gl_FragColor = texture2D(pano, sampleUV);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue