href portal wip
This commit is contained in:
parent
2953be9cd6
commit
21ffc80e07
8 changed files with 482 additions and 213 deletions
137
dist/xrfragment.aframe.js
vendored
137
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.)
|
||||
xrfragment.Parser.debug = xrfragment.debug
|
||||
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
||||
xrfragment.patchRenderer(opts.renderer)
|
||||
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){
|
||||
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
||||
load.call( this,
|
||||
|
|
@ -678,60 +687,53 @@ xrfragment.xrf.env = function(v, opts){
|
|||
}
|
||||
xrfragment.xrf.href = function(v, opts){
|
||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||
return
|
||||
|
||||
// Create a shader material that treats the texture as an equirectangular map
|
||||
mesh.texture = mesh.material.map // backup texture
|
||||
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;
|
||||
let size = 5
|
||||
let texture = mesh.material.map
|
||||
|
||||
// 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
|
||||
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)
|
||||
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);
|
||||
}
|
||||
`
|
||||
});
|
||||
}
|
||||
xrfragment.xrf.pos = function(v, 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'));
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
104
dist/xrfragment.three.js
vendored
104
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.)
|
||||
xrfragment.Parser.debug = xrfragment.debug
|
||||
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
||||
xrfragment.patchRenderer(opts.renderer)
|
||||
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){
|
||||
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
||||
load.call( this,
|
||||
|
|
@ -678,60 +687,53 @@ xrfragment.xrf.env = function(v, opts){
|
|||
}
|
||||
xrfragment.xrf.href = function(v, opts){
|
||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||
return
|
||||
|
||||
// Create a shader material that treats the texture as an equirectangular map
|
||||
mesh.texture = mesh.material.map // backup texture
|
||||
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;
|
||||
let size = 5
|
||||
let texture = mesh.material.map
|
||||
|
||||
// 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
|
||||
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)
|
||||
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);
|
||||
}
|
||||
`
|
||||
});
|
||||
}
|
||||
xrfragment.xrf.pos = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@
|
|||
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
|
||||
<script async src="./../../assets/alpine.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>
|
||||
</head>
|
||||
<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"/>
|
||||
<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" >
|
||||
<template x-for="url in urls">
|
||||
<option x-bind:value="url" selected></option>
|
||||
|
|
@ -26,10 +27,15 @@
|
|||
<a id="model" target="_blank" href="">⬇️ model</a>
|
||||
<textarea style="display:none"></textarea>
|
||||
<a-scene>
|
||||
<a-entity xrf gltf-model="./../../assets/example3.gltf"/>
|
||||
<a-entity xrf position="0 4 15">
|
||||
<a-entity camera look-controls wasd-controls></a-entity>
|
||||
<a-entity id="model" xrf gltf-model="./../../assets/example3.gltf" />
|
||||
<a-entity id="floor" gltf-to-entity="from: #model; name: floor" />
|
||||
|
||||
<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-scene>
|
||||
|
||||
<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"/>
|
||||
</head>
|
||||
<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"/>
|
||||
<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" >
|
||||
<template x-for="url in urls">
|
||||
<option x-bind:value="url" selected></option>
|
||||
|
|
@ -268,8 +268,6 @@
|
|||
//torus.rotation.x = time * 0.4;
|
||||
//torus.rotation.y = time;
|
||||
|
||||
if( XRF.getLastModel() ) XRF.getLastModel().render(scene,camera)
|
||||
|
||||
//controls.update()
|
||||
renderer.render( scene, camera );
|
||||
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.)
|
||||
xrfragment.Parser.debug = xrfragment.debug
|
||||
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
|
||||
xrfragment.patchRenderer(opts.renderer)
|
||||
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){
|
||||
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
|
||||
load.call( this,
|
||||
|
|
|
|||
|
|
@ -1,57 +1,50 @@
|
|||
xrfragment.xrf.href = function(v, opts){
|
||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||
return
|
||||
|
||||
// Create a shader material that treats the texture as an equirectangular map
|
||||
mesh.texture = mesh.material.map // backup texture
|
||||
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;
|
||||
let size = 5
|
||||
let texture = mesh.material.map
|
||||
|
||||
// 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
|
||||
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)
|
||||
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);
|
||||
}
|
||||
`
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue