¿Por qué el foco en mi escena de tres.js sigue centrado en la perspectiva de la cámara, pero sólo en Chrome para Android?
Actualmente utilizo AngularJS y Three.js para tratar de desarrollar un pequeño ejemplo de una aplicación VR. He definido controles basados en si el agente de usuario es un dispositivo móvil o no. Es un método desagradable, pero es sólo un ejemplo. OrbitControls se utilizan en dispositivos no móviles y DeviceOrientationControls se utilizan de otra manera.
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;
También he creado algunos objetos para mostrar realmente.
- Obtenga coordenadas de Hardware GPS
- ¿Puedo usar javax.script en el desarrollo de Android y si es así, cómo?
- Módulo cordova / exec / proxy no encontrado usando Cordova phonegap
- Error de aplicación Es un directorio (file: ///#android_asset/www/index.html)
- PhoneGap deviceready evento no disparar
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);
Esto funciona bien en Chrome para OSX, Safari para OSX y Safari en iPad (incluidos los controles de orientación del dispositivo, según corresponda).
El problema se produce al ejecutar la aplicación en Chrome para Android. El proyector que se ha añadido a la escena será constantemente apuntado en la misma dirección que la cámara. Aquí hay una captura de pantalla de la aplicación que se ejecuta en Android:
En todos los demás navegadores que he intentado utilizar, la luz se posiciona correctamente (50, 50, 50) y permanece estática. En el ejemplo anterior, la luz se está representando en el centro de la cámara y continúa siguiendo la cámara cuando se mueve o gira. Los controles de orientación reales funcionan bien.
El hecho de que esto sólo suceda en un navegador realmente me da dolores de cabeza, ya que la demo necesita ejecutarse en Chrome para Android.
Gracias.
Actualización: Han estado intentando muchas soluciones diferentes de diferentes métodos de control a diferentes tipos de iluminación en vano.
- Tipo de entrada = número no es posible insertar números negativos en el teléfono móvil
- Realizar una llamada desde ListView (OnitemClick)
- Jquery keyup no funciona en Android
- Funciones de JavaScript de Android Calling en WebView
- Android equivalente de la "Añadir a la pantalla de inicio" del iPhone?
- Práctica recomendada para la autorización / acción de Facebook en dispositivos móviles sin complementos
- Android - JavaScript: el evento touchstart no se activa hasta que se amplía o se desplaza por la página
- JavaScript: Detectar pellizco para aplicar zoom cuando 'usuario-escalable' está establecido en sí
Veo el problema en mi primera generación de Moto G (Qualcomm Snapdragon 400), pero no en mi tablet Project Tango (nVidia Tegra K1), por lo que es probable que se trate de un error de controlador de GPU o de una característica no admitida en cierto hardware.
Fui capaz de escribir un caso de prueba repetible simple y utilizarlo para determinar dónde el cálculo divergió entre mis dos plataformas. Resultó que sucedió en esta porción del shader de fragmentos GLSL de Three.js (extraído del script Three.js) que causa la discrepancia (comentarios añadidos por mí):
#ifndef FLAT_SHADED // Smooth shaded - use the interpolated normal. vec3 normal = normalize( vNormal ); #ifdef DOUBLE_SIDED normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) ); #endif #else // Flat shaded - generate the normal by taking the cross // product of derivatives that lie tangent to the surface. // This is the code that produces inconsistent results on // some mobile GPUs. vec3 fdx = dFdx( vViewPosition ); vec3 fdy = dFdy( vViewPosition ); vec3 normal = normalize( cross( fdx, fdy ) ); #endif
Esta sección de código determina lo normal en un fragmento. Su configuración de material resulta en habilitar el bloque FLAT_SHADED
. Aparentemente las llamadas a las funciones derivadas dFdx()
y dFdy()
, que son proporcionadas por la extensión GL_OES_standard_derivatives a WebGL, están produciendo resultados inconsistentes. Esto sugiere que la extensión se implementa incorrectamente o no se admite en las plataformas que causan problemas. Este error de Mozilla apoya esta hipótesis, señalando específicamente hardware Qualcomm:
Una serie de dispositivos exponen OES_standard_derivatives, pero han roto implementaciones de la misma
La solución sencilla es evitar la ruta de código de sombreado plano. Su floorMaterial
contiene el parámetro:
shading: THREE.FlatShading,
La eliminación de esta línea única predeterminará el sombreado suave (o puede cambiar explícitamente el valor a THREE.SmoothShading
). Su malla ya proporciona vértices normales, por lo que esto debería funcionar.
He intentado clonar tu sitio de prueba y comentar que una línea me parece mucho mejor en mi Moto G. También he creado este jsfiddle que muestra dos quads, uno con sombreado suave (izquierda) y otro con sombreado plano (derecha). Los quads deben aparecer como reflejos entre sí, pero no si la plataforma tiene problemas con el sombreado plano.
Pasando por tus palabras que funciona bien en el escritorio de cromo, pero el problema es sólo con Android, puede intentar ejecutar cromado en el modo de escritorio en android. Al igual que usted puede hacer "solicitud de sitio de escritorio" para el cromo. Ver si esto ayuda. ¿Cómo funciona la opción "Solicitar sitio de escritorio" de Chrome?
- ¿Cómo puedo hacer que mi diseño se mueva horizontal y verticalmente?
- Creación de servicios de fondo para Bluetooth de baja energía en Android