Javascript 为什么我的three.js场景中的聚光灯仍以摄影机透视图为中心,而仅在Android的Chrome上?
我目前正在使用AngularJS和Three.js尝试开发一个VR应用程序的小示例。我已经根据用户代理是否是移动设备定义了控件。这是一个狡猾的方法,但它只是一个例子。OrbitControl用于非移动设备,DeviceOrientationControl用于其他设备Javascript 为什么我的three.js场景中的聚光灯仍以摄影机透视图为中心,而仅在Android的Chrome上?,javascript,android,google-chrome,three.js,Javascript,Android,Google Chrome,Three.js,我目前正在使用AngularJS和Three.js尝试开发一个VR应用程序的小示例。我已经根据用户代理是否是移动设备定义了控件。这是一个狡猾的方法,但它只是一个例子。OrbitControl用于非移动设备,DeviceOrientationControl用于其他设备 var controls = new THREE.OrbitControls(camera, game.renderer.domElement); controls.noPan = true; controls.noZoom =
var controls = new THREE.OrbitControls(camera, game.renderer.domElement);
controls.noPan = true;
controls.noZoom = true;
controls.target.set(
camera.position.x,
camera.position.y,
camera.position.z
);
// Really dodgy method of checking if we're on mobile or not
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
controls = new THREE.DeviceOrientationControls(camera, true);
controls.connect();
controls.update();
}
return controls;
我还创建了一些实际显示的对象
this.camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.001, 1000);
this.camera.position.set(0, 15, 0);
this.textGeometry = new THREE.TextGeometry("Hello World", { size: 5, height: 1 });
this.textMesh = new THREE.Mesh(this.textGeometry, new THREE.MeshBasicMaterial({
color: 0xFF0000, opacity: 1
}));
this.textMesh.position.set(-20, 0, -20);
this.light = new THREE.SpotLight(0x999999, 3, 300);
this.light.position.set(50, 50, 50);
this.floorGeometry = new THREE.PlaneBufferGeometry(1000, 1000);
this.floorTexture = THREE.ImageUtils.loadTexture('img/textures/wood.jpg');
this.floorTexture.wrapS = THREE.RepeatWrapping;
this.floorTexture.wrapT = THREE.RepeatWrapping;
this.floorTexture.repeat = new THREE.Vector2(50, 50);
this.floorTexture.anisotropy = this.game.renderer.getMaxAnisotropy();
this.floorMaterial = new THREE.MeshPhongMaterial({
color: 0xffffff,
specular: 0xffffff,
shininess: 20,
shading: THREE.FlatShading,
map: this.floorTexture
});
this.floor = new THREE.Mesh(this.floorGeometry, this.floorMaterial);
this.floor.rotation.x = -Math.PI / 2;
this.scene.add(this.textMesh);
this.scene.add(this.light);
this.scene.add(this.floor);
this.scene.add(this.camera);
这在Chrome for OSX、Safari for OSX和Safari on iPad(包括适当的设备方向控制)上运行良好
在Chrome for Android上运行应用程序时会出现问题。添加到场景中的聚光灯将始终指向与摄影机相同的方向。以下是在Android上运行的应用程序的屏幕截图:
在我尝试使用的所有其他浏览器上,灯光都正确定位在(50,50,50),并保持静止。在上面的示例中,光被呈现在相机的中间,并且在移动或旋转时继续跟随相机。实际的方向控制工作得很好
事实上,这只发生在一个浏览器中,这真的让我头疼,因为演示需要在Chrome for Android上运行
谢谢
更新:已经尝试了许多不同的解决方案,从不同的控制方法到不同类型的照明,但都没有效果。照你的话说,它在chrome桌面上运行良好,但问题只在于android, 您可以尝试在android中以桌面模式运行chrome。就像你可以为chrome做“请求桌面站点”一样。 看看这是否有帮助。
我在我的Moto G第1代(高通Snapdragon 400)上看到了问题,但在我的Project Tango平板电脑(nVidia Tegra K1)上没有看到,因此这可能是GPU驱动程序错误或某些硬件上不支持的功能 我能够编写一个简单的可重复测试用例,并使用它来确定计算在我的两个平台之间的分歧。事实证明,它发生在Three.js GLSL片段着色器(从Three.js脚本中提取)的这一部分中,导致了差异(我添加的注释): 这段代码确定了片段的法线。您的材质设置导致启用“平面着色”块。显然,对衍生函数
dFdx()
和dFdy()
的调用(由GL_OES_标准_衍生函数扩展提供给WebGL)产生了不一致的结果。这表明扩展的实现不正确,或者平台不支持扩展,从而导致问题。支持这一假设,特别指出高通公司的硬件:
许多设备公开了OES_标准_的衍生产品,但已经损坏
it的实现
简单的解决方法是避免平面着色代码路径。您的floorMaterial
包含以下参数:
shading: THREE.FlatShading,
删除这一行将默认为平滑着色(或者您可以显式地将该值更改为THREE.SmoothShading
)。您的网格已经提供了顶点法线,因此这应该可以正常工作
我试图克隆你的测试站点,并评论说,在我的Moto G上,有一行看起来更好。我还创建了两个四边形,一个带有平滑着色(左),一个带有平面着色(右)。四边形应该看起来是彼此的反射,但如果平台的平面着色器存在问题,则不会出现这种情况。能否发布渲染器的完整代码?我们更容易复制和测试当光线是相机的子对象时应该发生的情况。在你的情况下,它不是,所以你也不必将相机添加到场景中。我在网上放了一个小例子,在我的移动设备上检查这一点。。。但我并不完全相信我有生殖能力。有限的相机自由度加上大的镜面反射高光,使它很难看到。如果其他人想查看,示例如下:。很抱歉更新太晚。下面可以找到导致问题的代码版本。当在我的Android设备上打开时,灯光将跟随相机并指向它的方向。无法在我的任何设备上复制,因此它似乎非常具体。也许下面的新答案有帮助..请求网站的桌面版本仍然与移动版本存在相同的问题。
shading: THREE.FlatShading,