Three.js: Orientation CubeTexture

Créé le 25 avr. 2019  ·  31Commentaires  ·  Source: mrdoob/three.js

Dans mon application, je voudrais faire pivoter le CubeTexture qui définit l'arrière-plan de la scène et les réflexions de la carte d'environnement de 180° le long de l'axe vertical des y.
Ma rotation est définie par les spécifications VRML et X3D concernant les champs de fond.

J'ai essayé de modifier plusieurs paramètres comme les champs mapping , flipY et rotation Texture. Cependant, je n'ai pas trouvé de bon moyen de le faire.

  • Y a-t-il un moyen évident de le faire que j'ai raté?
  • Une chance de voir ça arriver dans three.js ?
  • Si je souhaite l'implémenter, quels paramètres voudriez-vous voir (par exemple Texture.flipX et CubeTexture.flipZ ) ? Seriez-vous intéressé par cette fonctionnalité ?
Enhancement

Commentaire le plus utile

Vous voulez dire pouvoir faire pivoter scene.background ? Si oui... oui, certainement intéressé.

Nous avons probablement besoin d'une nouvelle API cependant...

scene.background = new THREE.Background( cubeTexture );`
scene.background.rotation.y = Math.PI / 2;

Tous les 31 commentaires

Vous voulez dire pouvoir faire pivoter scene.background ? Si oui... oui, certainement intéressé.

Nous avons probablement besoin d'une nouvelle API cependant...

scene.background = new THREE.Background( cubeTexture );`
scene.background.rotation.y = Math.PI / 2;

J'ai du mal avec exactement ça en ce moment. Essayer d'obtenir des ombres au sol cuites pour correspondre à la direction du soleil à partir d'un cubemap.
Il semble que quelque part en cours de route, ma cubemap soit retournée à 180 degrés. Ce serait formidable si je pouvais simplement résoudre ce problème ici plutôt que de recréer mon cubemap plusieurs fois et d'essayer de comprendre où cela se passe.

@fabienrohrer Essayer

scene.rotation.y = Math.PI;

Si cela ne fonctionne pas, veuillez fournir un exemple en direct pour montrer exactement ce que vous faites.

Ah ça marche ? La caméra doit être un enfant de la scène ?

La caméra doit être un enfant de la scène ?

Je ne pense pas que cela compte.

@mrdoob c'est exactement ce dont j'ai besoin aussi :-)

@WestLangley :

La rotation de la scène globale est excessive et peut provoquer de nombreux effets secondaires dans mon application.

J'aimerais pouvoir faire pivoter l'arrière-plan uniquement, et bien sûr, les cartes d'environnement devraient fonctionner de la même manière.

Une démo en direct n'est pas possible, car l'API est manquante. Il s'agit de prendre n'importe quel exemple ayant un cubemap d'arrière-plan (comme https://threejs.org/examples/#webgl_materials_cubemap) et de pouvoir faire pivoter uniquement l'arrière-plan autour de l'axe des y. Ou plus généralement, d'appliquer n'importe quelle rotation à l'arrière-plan.

Pouvoir appliquer une matrice de rotation/un quaternion personnalisé à n'importe quel cubemap semble être la solution la plus générique pour moi.

three.js veille à ce que les réflexions matérielles soient cohérentes avec le matériau envMap , qui est défini dans le système de coordonnées de l'espace mondial. Permettre aux utilisateurs de faire pivoter l'arrière-plan de la scène entraînerait un arrière-plan incompatible avec les réflexions matérielles.

Pourquoi ne créez-vous pas la bonne carte du cube de l'espace-monde dans votre application ?

La caméra doit être un enfant de la scène ?

Je ne pense pas que cela compte.

J'ai essayé de faire scene.rotation.y ++ dans la console dans webgl_materials_standard et le pistolet tourne. Ensuite, j'ai essayé de faire scene.add( camera ) et puis si je fais scene.rotation.y ++ il fait ce que nous recherchons, mais les commandes de la caméra se dérèglent 😁

Si nous introduisons un objet THREE.Background , nous pourrions ajouter une API pour gérer cela, et dans le moteur de rendu, nous pouvons également introduire l'idée de :

var envMap = material.envMap;
if ( scene.background && scene.background.isBackground && envMap === null ) {
    envMap = scene.background.texture;
}

j'ai dit

Essayez scene.rotation.y = Math.PI; Si cela ne fonctionne pas,...

Cela signifie que cela peut ne pas fonctionner. :-)

Cela dépend du cas d'utilisation. J'ai essayé avec OrbitControls et cela a bien fonctionné.

sans rapport : l'exemple webgl_materials_standard devrait utiliser des contrôles d'orbite, de toute façon IMO.

Vous voulez dire pouvoir faire pivoter scene.background ? Si oui... oui, certainement intéressé.

Il est plus logique de le faire au niveau de la texture, sinon tout éclairage IBL ne correspondra pas à l'arrière-plan, je suppose.

Nous autorisons la rotation des textures normales, y a-t-il une raison pour laquelle nous ne voudrions pas faire la même chose pour les textures cubiques ? Est-ce trop complexe à mettre en œuvre ?

Pourquoi ne créez-vous pas la bonne carte du cube de l'espace-monde dans votre application ?

Cela prend beaucoup de temps. J'ai travaillé sur la génération de cartes de cube au cours des deux derniers jours, et apporter des modifications, puis restituer la carte de cube, me prend environ 15 à 20 minutes pour chaque modification.

Un autre cas d'utilisation potentiel intéressant pour cela est que vous pouvez changer la direction de l'éclairage environnemental en temps réel. Je combine actuellement une carte d'environnement PMREM avec une lumière directionnelle pour les ombres en temps réel, et j'utilise la carte comme skybox, ce qui donne un effet de lumière du jour assez décent.
Évidemment, il y a une limite à ce que vous pouvez faire sans changer la couleur de la carte de l'environnement, mais vous pouvez simuler au moins quelques heures de lumière du jour en faisant pivoter la carte en synchronisation avec la lumière directionnelle tout en ajustant le .envMapIntensity .

Ma préoccupation concerne aussi les performances. Actuellement, j'ai implémenté un hack sur le point de faire pivoter la texture du haut et du bas et d'échanger les autres. Il faut environ 10 ms pour faire pivoter une texture 1024x1024 en JS.

Alternativement, serait-il possible de n'avoir que deux options pour l'orientation CubeTexture, celle que vous avez actuellement et une autre (avec la rotation à 180 degrés) qui serait compatible avec l'autre standard largement utilisé dans les formats 3D (X3D, VRML, etc. .). On pourrait sans doute facilement adapter la cohérence avec des réflexions matérielles pour gérer les deux formats ?

Cela semble familier #11103

Si je devais implémenter CubeMap.rotation = matrix3 , fusionneriez-vous dans r105 ?

Ma préoccupation concerne aussi les performances. Actuellement, j'ai implémenté un hack sur le point de faire pivoter la texture du haut et du bas et d'échanger les autres. Il faut environ 10 ms pour faire pivoter une texture 1024x1024 en JS.

Et à quelle fréquence faites-vous cela dans votre application ?

@WestLangley, je viens de vous donner une réponse détaillée ici : https://github.com/mrdoob/three.js/pull/16507#discussion_r286337864

Et à quelle fréquence faites-vous cela dans votre application ?

Pas beaucoup. Une fois au chargement par client, et une fois à chaque changement de fond (cas très rare). Un DEFINE ferait également l'affaire.

Mon souci est aussi au niveau des performances... Il faut compter environ 10ms.

Et à quelle fréquence faites-vous cela dans votre application ?

Pas beaucoup. Une fois au chargement par client, et une fois à chaque changement de fond (cas très rare).

Désolé, je ne suis pas la logique de cela.

Malheureusement, @WestLangley ne veut pas fusionner ma modification sur la CubeTexture.rotation en raison de la surcharge d'exécution (une multiplication mat3 supplémentaire). Dans ce cas, je suis à court d'idées pour résoudre ce problème proprement en threejs.
Si les contributeurs de threejs ne résolvent pas ce problème, veuillez fermer ce problème.

J'attends la mise en place de cette fonctionnalité.

@FishOrBear Malheureusement, les responsables de threejs décidé de ne pas implémenter cela. Vous pouvez appliquer ce patch non fusionné dans un fork, si vous souhaitez l'avoir dans votre projet :

https://github.com/mrdoob/three.js/pull/16507

@mrdoob Peut-être pouvons-nous reconsidérer cette demande de fonctionnalité dans #18157 ?

J'utilise threejs pour créer une application similaire à AutoCAD, nous utilisons donc xy pour nous asseoir comme un avion.

La CubeTexture actuelle est un peu en conflit avec la nôtre.

BTW : Avec Babylon.js, il est au moins possible de faire pivoter une skybox autour de l'axe y :

https://www.babylonjs-playground.com/#UU7RQ #447

Le moteur prend en charge cela en transformant le vecteur de réflexion dans le shader de fragment. Donc exactement l'approche qui n'a pas été acceptée dans #16507. Code du shader de fragment Babylon.js :

https://github.com/BabylonJS/Babylon.js/blob/1c4627141f83c08fe4a7e30e2621c916b4e6c9c9/src/Shaders/ShadersInclude/reflectionFunction.fx#L114 -L117

@mrdoob Je pense que nous devrions implémenter cette fonctionnalité. Il y a une autre demande dans le forum :

https://discourse.threejs.org/t/rotate-a-scenes-background-skybox-texture/12199

Je doute qu'une seule multiplication matrice/vecteur supplémentaire par fragment affecte sensiblement les performances.

J'ai toujours le même problème dans mon application, et le hack pour le résoudre est moche et tellement coûteux... Je recommande également d'accepter cette amélioration.

J'aimerais aussi voir cette fonctionnalité ajoutée.

Il semble que le bloqueur soit une diminution potentielle des performances, mais cela devrait être facile à tester. Nous pouvons essayer de l'ajouter, et s'il y a une baisse de performance inacceptable, nous pouvons le supprimer à nouveau.

Idem ici, pourrait utiliser cette fonctionnalité au lieu de ré-implémenter mon rendu en arrière-plan :)

Je ne suis pas sûr de suivre la question des performances. Rien ne nous empêche de générer la direction du rayon directement dans le vertex shader ? Cela coûterait alors autant que n'importe quelle autre transformation modelMatrix .

Dans mon cas, je pourrais utiliser cette fonctionnalité car je rends des cubemaps capturés par des caméras et téléchargés par des utilisateurs. Les photos ne sont pas toujours correctement orientées vers le nord, elles nécessitent donc une correction manuelle après le téléchargement.

Une façon de procéder consiste à stocker la rotation en tant que variable, à l'appliquer à la scène juste avant le rendu, puis à réinitialiser la rotation des scènes à l'identité quat juste après le rendu.

Cela provoque deux mises à jour inutiles des matrices universelles de tous mes objets de scène. Cela signifie également que je ne peux effectuer aucune mise à jour de position dans onBeforeRender. Mais il maintient la scène dans un état normal sinon.

D'ailleurs (puisque personne ne l'a mentionné), il semble possible de faire une skybox "classique" qui tourne en utilisant un tableau de 6 matériaux.

quelque chose comme ça :

const urls = [
  '/assets/skybox/right.png',
  '/assets/skybox/left.png',
  '/assets/skybox/top.png',
  '/assets/skybox/bottom.png',
  '/assets/skybox/front.png',
  '/assets/skybox/back.png',
];

const materials = urls.map((url) => {
  const texture = new THREE.TextureLoader().load(url);

  return new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.BackSide,
    fog: false,
    depthWrite: false,
  });
});

const skybox = new THREE.Mesh( new THREE.BoxBufferGeometry(10000, 10000, 10000), materials );
scene.add(skybox);

skybox.rotation.y = Math.PI / 2;

Comme démontré ici : https://woodenraft.games/demos/skybox-rotation-threejs.html

@wmcmurray Vous devrez déplacer cette skybox avec la caméra pour qu'elle fonctionne correctement, et vous devrez vous assurer que la dimension de votre boîte X < Math.sqrt (0.75 * camera.far * camera.far) donc les coins s'intègre toujours dans la vue, mais cela semble plus facile que mon hack consistant à faire pivoter/annuler la rotation de la scène.

Doit-on rouvrir un PR pour ça ? Il existe deux cas d'utilisation et si nous ne voulons pas affecter les performances, nous pouvons utiliser une définition de shader :

  • Cas d'utilisation 1 : l'environnement est pré-calculé une fois et ne devrait pas avoir besoin d'être tourné dans le shader. Cela peut être fait par l'utilisateur soit sur le CPU, soit même sur le GPU s'il le souhaite.
  • Cas d'utilisation 2 : lorsqu'on travaille sur une visionneuse, il est assez courant de faire pivoter le fond en temps réel à l'aide de la souris par exemple.

Afin d'éviter que l'utilisateur avec le cas d'utilisation 1 soit affecté par la multiplication matricielle, nous pouvons peut-être simplement ajouter un indicateur comme :

renderer.dynamicBackground = true;

et compiler le shader d'arrière-plan en conséquence ?

En attendant

Comme @wmcmurray et @capnmidnight l'ont souligné, vous pouvez essentiellement

Au lieu d'utiliser MeshBasicMaterial , vous pouvez également créer directement votre propre shader étendant ShaderMaterial et échantillonner le cubemap.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

Bandit picture Bandit  ·  3Commentaires

seep picture seep  ·  3Commentaires

fuzihaofzh picture fuzihaofzh  ·  3Commentaires

filharvey picture filharvey  ·  3Commentaires

akshaysrin picture akshaysrin  ·  3Commentaires