使用 WebVR 进行眼睛分离
Eye separation using WebVR
我正在尝试使用 Three.js 创建一个 WebVR 环境。我从 Cinema4D 中导出了一些场景,并使用 Three.js 的 Colladaloader 加载它们。现在我想在我的 Google Cardboard 中尝试这个环境,但我当然需要为我的双眼设置分屏。
我使用了 npm 模块 three-stereo-effect to achieve the VR effect, but it's overlapping when using it in a cardboard. I looked it up and saw that a lot of WebVR examples had a rounded rectangle for each eye (example of what I mean), not a straight rectangle, I thought I needed to find matrices to fix that (When looking at the examples of this repository)。不过后来下载了一个VR隧道赛车游戏,看到用的是直角矩形,视觉还不错。
现在我认为我的立体效果的 eyeSeparation 不正确,我看到有人在 StereoEffect 模块上使用了 属性 eyeSeparation 并尝试了一下,但我认为我不应该只是猜测值...
我在寻找解决方案的道路上是否正确?还是我看错了方向,为什么我的 3D 场景在使用 Cardboard 时视觉效果不佳?
这是我正在试验的代码。
import {sets} from './data/';
import * as THREE from 'three';
import threeOrbitControls from 'three-orbit-controls';
import ColladaLoader from 'three-collada-loader';
import threeStereoEffect from 'three-stereo-effect';
import {BufferLoader} from './modules/sound';
import {SpawnObject} from './modules/render';
const OrbitControls = threeOrbitControls(THREE);
const StereoEffect = threeStereoEffect(THREE);
let scene, camera, renderer;
let audioCtx, bufferLoader;
const notes = [];
let stereoEffect = null;
const init = () => {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
audioCtx = new AudioContext();
bufferLoader = new BufferLoader(audioCtx);
bufferLoader.load(sets.drums)
.then(data => spawnObject(data));
initEnvironment();
};
const spawnObject = data => {
for (let i = 0;i < 5;i ++) {
const bol = new SpawnObject(`object.dae`, audioCtx, data[0], scene, false);
notes.push(bol);
}
// console.log(notes);
};
const initEnvironment = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight,
1, 10000
);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
stereoEffect = new StereoEffect(renderer);
// stereoEffect.eyeSeparation = 1;
stereoEffect.setSize(window.innerWidth, window.innerHeight);
console.log(stereoEffect);
document.querySelector(`main`).appendChild(renderer.domElement);
camera.position.set(0, 0, 2);
camera.lookAt(scene.position);
new OrbitControls(camera);
//LIGHTS
const light = new THREE.PointLight(0xFFFFFF);
light.position.set(0, 0, 9);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
light.shadow.camera.near = 10;
light.shadow.camera.far = 100;
scene.add(light);
// const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
// hemiLight.color.setHSL(0.6, 1, 0.6);
// hemiLight.groundColor.setHSL(0.095, 1, 0.75);
// hemiLight.position.set(0, 500, 0);
// scene.add(hemiLight);
//
// const dirLight = new THREE.DirectionalLight(0xffffff, 1);
// dirLight.color.setHSL(0.1, 1, 0.95);
// dirLight.position.set(- 1, 1.75, 1);
// dirLight.position.multiplyScalar(50);
// scene.add(dirLight);
// dirLight.castShadow = true;
//FLOOR
const matFloor = new THREE.MeshPhongMaterial();
const geoFloor = new THREE.BoxGeometry(2000, 1, 2000);
const mshFloor = new THREE.Mesh(geoFloor, matFloor);
matFloor.color.set(0x212E39);
mshFloor.receiveShadow = true;
mshFloor.position.set(0, - 1, 0);
scene.add(mshFloor);
//ENVIRONMENT
const loader = new ColladaLoader();
loader.load(`../assets/environment.dae`, collada => {
collada.scene.traverse(child => {
child.castShadow = true;
child.receiveShadow = true;
});
scene.add(collada.scene);
render();
});
};
const render = () => {
// stereoEffect.render(scene, camera);
// effect.render(scene, camera);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setClearColor(0xdddddd, 1);
stereoEffect.render(scene, camera);
requestAnimationFrame(render);
};
init();
2.1.1 Binocular Disparity
Binocular disparity is the positional difference between the two retinal projections of a given point in space. This positional difference results from the fact that the two eyes are laterally separated and therefore see the world from the two slightly different vantage points. For the average person the mean lateral separation also known as the interocular is 65mm. Most of the population has an eye separation within ±10mm of the average interocular.
看起来,通过与不同脸型的朋友进行一些测试,您会发现设备和使用它的人的 eyeSeparation
值的平均值令人满意。然后我还会提供一些设置面板,允许 eyeSeparation
的一些不同设置供用户选择,如果他们发现他们的立体体验存在差异或重叠。通常我认为这可以通过将键盘连接到同一系统来拨入立体声对齐来完成,但你在硬纸板中,因此用户可能需要反复试验才能正确完成。
我正在尝试使用 Three.js 创建一个 WebVR 环境。我从 Cinema4D 中导出了一些场景,并使用 Three.js 的 Colladaloader 加载它们。现在我想在我的 Google Cardboard 中尝试这个环境,但我当然需要为我的双眼设置分屏。
我使用了 npm 模块 three-stereo-effect to achieve the VR effect, but it's overlapping when using it in a cardboard. I looked it up and saw that a lot of WebVR examples had a rounded rectangle for each eye (example of what I mean), not a straight rectangle, I thought I needed to find matrices to fix that (When looking at the examples of this repository)。不过后来下载了一个VR隧道赛车游戏,看到用的是直角矩形,视觉还不错。
现在我认为我的立体效果的 eyeSeparation 不正确,我看到有人在 StereoEffect 模块上使用了 属性 eyeSeparation 并尝试了一下,但我认为我不应该只是猜测值...
我在寻找解决方案的道路上是否正确?还是我看错了方向,为什么我的 3D 场景在使用 Cardboard 时视觉效果不佳?
这是我正在试验的代码。
import {sets} from './data/';
import * as THREE from 'three';
import threeOrbitControls from 'three-orbit-controls';
import ColladaLoader from 'three-collada-loader';
import threeStereoEffect from 'three-stereo-effect';
import {BufferLoader} from './modules/sound';
import {SpawnObject} from './modules/render';
const OrbitControls = threeOrbitControls(THREE);
const StereoEffect = threeStereoEffect(THREE);
let scene, camera, renderer;
let audioCtx, bufferLoader;
const notes = [];
let stereoEffect = null;
const init = () => {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
audioCtx = new AudioContext();
bufferLoader = new BufferLoader(audioCtx);
bufferLoader.load(sets.drums)
.then(data => spawnObject(data));
initEnvironment();
};
const spawnObject = data => {
for (let i = 0;i < 5;i ++) {
const bol = new SpawnObject(`object.dae`, audioCtx, data[0], scene, false);
notes.push(bol);
}
// console.log(notes);
};
const initEnvironment = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight,
1, 10000
);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
stereoEffect = new StereoEffect(renderer);
// stereoEffect.eyeSeparation = 1;
stereoEffect.setSize(window.innerWidth, window.innerHeight);
console.log(stereoEffect);
document.querySelector(`main`).appendChild(renderer.domElement);
camera.position.set(0, 0, 2);
camera.lookAt(scene.position);
new OrbitControls(camera);
//LIGHTS
const light = new THREE.PointLight(0xFFFFFF);
light.position.set(0, 0, 9);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
light.shadow.camera.near = 10;
light.shadow.camera.far = 100;
scene.add(light);
// const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
// hemiLight.color.setHSL(0.6, 1, 0.6);
// hemiLight.groundColor.setHSL(0.095, 1, 0.75);
// hemiLight.position.set(0, 500, 0);
// scene.add(hemiLight);
//
// const dirLight = new THREE.DirectionalLight(0xffffff, 1);
// dirLight.color.setHSL(0.1, 1, 0.95);
// dirLight.position.set(- 1, 1.75, 1);
// dirLight.position.multiplyScalar(50);
// scene.add(dirLight);
// dirLight.castShadow = true;
//FLOOR
const matFloor = new THREE.MeshPhongMaterial();
const geoFloor = new THREE.BoxGeometry(2000, 1, 2000);
const mshFloor = new THREE.Mesh(geoFloor, matFloor);
matFloor.color.set(0x212E39);
mshFloor.receiveShadow = true;
mshFloor.position.set(0, - 1, 0);
scene.add(mshFloor);
//ENVIRONMENT
const loader = new ColladaLoader();
loader.load(`../assets/environment.dae`, collada => {
collada.scene.traverse(child => {
child.castShadow = true;
child.receiveShadow = true;
});
scene.add(collada.scene);
render();
});
};
const render = () => {
// stereoEffect.render(scene, camera);
// effect.render(scene, camera);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setClearColor(0xdddddd, 1);
stereoEffect.render(scene, camera);
requestAnimationFrame(render);
};
init();
2.1.1 Binocular Disparity
Binocular disparity is the positional difference between the two retinal projections of a given point in space. This positional difference results from the fact that the two eyes are laterally separated and therefore see the world from the two slightly different vantage points. For the average person the mean lateral separation also known as the interocular is 65mm. Most of the population has an eye separation within ±10mm of the average interocular.
看起来,通过与不同脸型的朋友进行一些测试,您会发现设备和使用它的人的 eyeSeparation
值的平均值令人满意。然后我还会提供一些设置面板,允许 eyeSeparation
的一些不同设置供用户选择,如果他们发现他们的立体体验存在差异或重叠。通常我认为这可以通过将键盘连接到同一系统来拨入立体声对齐来完成,但你在硬纸板中,因此用户可能需要反复试验才能正确完成。