Three.js: Éclairage sélectif

Créé le 10 août 2014  ·  101Commentaires  ·  Source: mrdoob/three.js

Je ne sais pas s'il s'agit déjà d'une fonctionnalité prévue ou peut-être même d'une fonctionnalité terminée, alors je vais d'abord essayer d'expliquer la tâche.

Je dois faire un éclairage sélectif pour différentes pièces. Par exemple, j'ai deux chambres. Une lumière ne doit affecter que les objets et les murs intérieurs d'une pièce. La deuxième pièce ne doit pas être affectée par cette lumière.

Actuellement, si j'ajoute une lumière à la scène, cela affecte tous les objets à sa distance. Et j'obtiens un effet étrange lorsque la lumière passe "à travers le mur" de la deuxième pièce.

Je pense donc que j'ai besoin d'une sorte de groupes ou de canaux pour l'éclairage, afin que je puisse définir les objets qui sont affectés par une source lumineuse et les objets qui sont affectés par une autre.

Je n'ai rien trouvé de tel ni dans les lumières ni dans les objets, alors j'ai pensé que cela pourrait peut-être être une bonne fonctionnalité à avoir.

Et, d'ailleurs, s'il n'est pas encore implémenté, quelle est l'approche recommandée pour résoudre de telles tâches en utilisant l'état actuel de three.js ?

Enhancement

Commentaire le plus utile

Avez-vous un lien vers un exemple de quelque chose comme ça?

ici, j'en ai fait un rien que pour vous : https://jsfiddle.net/f2Lommf5/524/

Tous les 101 commentaires

Ce que je dis, c'est d'avoir un champ channel dans THREE.Light et lightChannel champ THREE.Mesh ou quelque chose comme ça. Si ce dernier est nul alors il est affecté par toutes les sources lumineuses. Si ce dernier n'est pas nul alors il n'est affecté que les canaux lumineux de même valeur.

Ou peut-être qu'il pourrait être ajouté non pas au maillage lui-même, mais à des faces séparées de la géométrie du maillage.

On dirait que vous voulez utiliser des ombres ?

Eh bien, je pourrais réaliser quelque chose comme ça avec des ombres (et j'ai déjà essayé), mais cela donne différents effets secondaires et j'ai l'impression que c'est un hack, car je n'ai pas besoin d'éclairer certains objets puis de leur projeter une ombre . Je ne dois pas les allumer en premier lieu.

Ce dont j'ai besoin, c'est qu'une source de lumière spécifique n'affecte pas un ensemble de mailles, mais affecte l'autre ensemble.

Habituellement, je le fais en utilisant une technique comme celle-ci : Exemple de fil de discussion :

glEnable(GL_LIGHT0);
//...
glEnable(GL_LIGHTn);

// Draw the walls to room 1
DrawWalls(room[0]);

// Draw the contents of room 1
DrawContents(room[0]);

glDisable(GL_LIGHT0);
//...
glDisable(GL_LIGHTn);

// Draw the walls to room 2
DrawWalls(room[1]);

// Draw the contents of room 2
DrawContents(room[1]);

Cela ressemble donc à une caractéristique différente de celle des ombres. Ou est-ce que j'ai raté quelque chose ?

Oui... Je pense que cela peut en effet être pratique. Je ne sais pas à quoi devrait ressembler l'API pour cela.

Peut-être que la solution la plus simple pourrait être la plus efficace ici :

  1. Ajoutez un channel (ou group ) à THREE.Light
  2. Ajoutez un affectedByLightChannel (ou affectedByLightGroup ) à THREE.Mesh (Ou peut-être même à une face dans la géométrie)

Qu'en penses-tu?

Peut-être que 'affectedByLightChannel' est trop long et quelque chose comme 'lightChannel' ferait l'affaire, mais je pense que ce serait pratique : juste les numéros de canal sur la source lumineuse et les récepteurs.

Comme ça:

    light = new THREE.PointLight(0xFFF7D6, 1.0, 15)
    light.channel = 123
    testScene.add(light)

    testScene = new THREE.Scene
    geometry = new THREE.BoxGeometry(2,2,2)
    material = new THREE.MeshLambertMaterial 
        color: 0xffffff

    cube = new THREE.Mesh(geometry, material)
    cube.lightChannel = 123
    testScene.add(cube)

Si lightChannel est égal à 0, alors il est affecté par tous les canaux. Si channel est égal à 0, alors cela affecte tous les maillages.

Il serait donc entièrement rétrocompatible avec le comportement actuel.

C'est peut-être un peu trop difficile à comprendre... C'est peut-être mieux quelque chose comme ça :

cube.lightInfluences = [ light1, light2 ];

Cela me semble tout à fait bien.

C'est peut-être un peu plus difficile à utiliser dans certains cas, mais c'est évidemment plus facile à comprendre.

Qu'en est-il d'une simple propriété de masque entier pour les maillages et les lumières ?

light = new THREE.PointLight(0xFFF7D6, 1.0, 15)
light.mask = 0xffffffff; // default mask
testScene.add(light);

cube = new THREE.Mesh(geometry, material)
cube.mask = 0xffffffff; // default
testScene.add(cube);

Les objets ne sont alors éclairés par des lumières que si le ET logique de leurs masques est non nul.
Cela permettrait aux lumières d'être influencées par plus d'un canal, sans méthodes supplémentaires sur les objets.

Un masque par défaut de 0xffffffff n'affecterait pas le code existant.

Ce que @satori99 a dit.

Cependant, je pense que mask devrait être une propriété de Light et Mesh*Material , à la place. (Seulement les matériaux affectés par les lumières.)

En outre, la propriété peut également être nommée lightMask , lightChannel , ou channel .

Le problème de l'approche canal/masque est que l'utilisateur devra comprendre les opérations au niveau du bit. Un peu trop intense si on le compare au reste de l'API.

Que pouvez-vous faire avec les masques que vous ne pouvez pas faire avec l'approche matricielle ?

Je pourrais donner un exemple de la tâche avec deux pièces ci-dessus.

Le point principal de l'utilisation de l'approche par canal par rapport à l'approche par matrice est que des opérations simples telles que « déplacer la lumière1 de la pièce 1 à la pièce 2 » deviennent plus compliquées si vous utilisez des matrices.

Au lieu de simplement régler

light1.channel = 2

(auparavant, il était défini sur 1)

vous devrez trouver tous les objets de la pièce 1 qui avaient précédemment light1 dans le tableau lightInfluences, puis supprimer la lumière de leurs tableaux, puis l'ajouter à tous les objets de la pièce 2.

Même histoire avec l'opération simple comme « déplacer l'objet 1 de la pièce 1 à la pièce 2 ». Au lieu de régler son influenceChannel de 1 à 2, vous devrez rechercher toutes les lumières de cette pièce, puis les supprimer de son réseau d'influence, puis rechercher toutes les lumières de la pièce deux et les ajouter.

Ce n'est pas que cela ne peut pas être fait, c'est pourquoi j'ai dit que l'approche lightInfluences me convient parfaitement. Mais le truc du canal serait la première chose que j'implémenterais au-dessus pour moi juste pour rendre les opérations courantes aussi simples qu'une affectation.

Je pense qu'il devrait être mis en œuvre comme un masque. (Qu'il soit implémenté sur le CPU ou le GPU est un problème pour une discussion ultérieure.)

Nous pouvons montrer via des exemples comment le définir, et les utilisateurs peuvent suivre le modèle.

Si vous pensez que c'est encore trop compliqué, nous pouvons créer une API THREE.Channels pour cela.

light.channels = new THREE.Channels();
...
light.channels.clear();
light.channels.add( channel );
light.channels.remove( channel );
light.channels.all();

Mêmes méthodes pour Mesh*Material .

J'aime cette API :)
Je peux voir que cela fonctionne pour les objets et les lumières, mais comment voyez-vous cela fonctionner pour les matériaux ?

Seuls les matériaux répondent aux lumières. Cela devrait être une propriété du matériau, je pense.

Je suis d'accord avec @westlangley. Les lumières dépendent des matériaux.

Même histoire avec l'opération simple comme « déplacer l'objet 1 de la pièce 1 à la pièce 2 ».

Eh bien, c'est un problème. Channels ne serait pas basé sur des objets.

Eh bien, c'est un problème. Les canaux ne seraient pas basés sur des objets.

Mais pourquoi? Est-ce une limitation technique ?

Parce que ça invalide en quelque sorte toute l'idée de tout ça. Parce qu'il peut y avoir différents objets, qui réutilisent le même matériau, mais l'un d'eux doit être allumé et l'autre non.

Mais pourquoi? Est-ce une limitation technique ?

Non. C'est parce que les objets ne répondent pas aux lumières. Seuls les matériaux le font.

Parce qu'il peut y avoir différents objets, qui réutilisent le même matériau, mais l'un d'eux doit être allumé et l'autre non.

Vous pouvez utiliser le même matériau pour tous les objets de la scène -- juste clone le matériau pour les objets dont le matériau nécessite des valeurs uniformes différentes. Il ne devrait toujours y avoir qu'un seul programme de shader partagé par tous.

Je pense qu'il devrait être mis en œuvre comme un masque. (Qu'il soit implémenté sur le CPU ou le GPU est un problème pour une discussion ultérieure.)

Cela peut-il être géré assez facilement dans le GPU directement ?

Cela peut-il être géré assez facilement dans le GPU directement ?

Oui, vous devrez transmettre les uniformes channels supplémentaires pour les lumières et les matériaux.

Que diriez-vous d'un système de gestion des couches ? Je regrouperais les maillages en calques et appliquerais les masques à partir de là (pourrait affecter les lumières, les ombres, la visibilité, etc.), l'unité serait un bon exemple ?

Les ombres sont également un sujet connexe. Je pense qu'il devrait aussi y avoir quelque chose comme la projection sélective d'ombres. Comme 'receiveShadowFrom = ...' (et la liste des sources) au lieu de simplement 'receiveShadow = true'.

Parce que lorsque vous définissez des lumières qui n'affectent qu'une pièce spécifique (dans mon exemple), vous voudriez également immédiatement que ces lumières projettent des ombres uniquement sur les objets de cette pièce.

Les attributs des ombres devraient vraiment être sur les matériaux et non sur les objets pour les mêmes raisons que ci-dessus dans ce fil.

Les attributs des ombres devraient vraiment être sur les matériaux et non sur les objets pour les mêmes raisons que ci-dessus dans ce fil.

Oui, c'est logique !

Existe-t-il des plans pour inclure cette fonctionnalité (comme une version cible prévue pour le premier brouillon) ?

En guise de solution de contournement, pouvez-vous répondre à la plupart de vos exigences en créant une scène distincte pour chaque pièce (et ses lumières) ?

renderer.autoClear = false;
...
renderer.render( scene1, camera );
renderer.render( scene2, camera );

Hum, je vais essayer cette approche !

L'éclairage sélectif/ombres est un must pour les futures versions IMO.

GROS +9999 pour celui-ci, j'aimerais pouvoir sélectionner si un matériau projette une ombre à partir de la source lumineuse A ou de la source lumineuse B. Quelqu'un a-t-il actuellement une solution autre que deux scènes ? Cela va rendre les choses assez pénibles pour moi...

putain de merde, comment cela n'est-il toujours pas mis en œuvre? après +9999 de rohan)

Haha, je suppose que c'est un peu difficile à implémenter @tsone pouvez-vous fournir des informations sur ce commit? Navigation sur un client téléphonique en ce moment

comment est-ce difficile à mettre en œuvre si ce ne sont que des uniformes qu'ils passent aux matériaux. tout ce qu'ils ont à faire est de remplacer la liste globale des lumières par celle définie dans le matériau, si elle existe, quelque part au plus profond du moteur de rendu webgl.

Voici un JSFiddle simple qui teste l'implémentation des couches de la branche Dev :
https://jsfiddle.net/Angrypickle/t8f7q3vo/4/
Malheureusement, pour le moment, cela ne semble pas fonctionner correctement. Ou est-ce que je fais quelque chose de mal ?

Oui. Les calques ne fonctionnent pas encore avec les lumières. Ils fonctionnent cependant avec une caméra/un objet ! ??

Roger ce monsieur ! Voici un JSFiddle mis à jour qui utilise des caméras superposées pour obtenir un éclairage sélectif avec des calques :
https://jsfiddle.net/Angrypickle/t4a1eusL/
Il semble fonctionner correctement sur ordinateur de bureau et mobile. Quelqu'un voit quelque chose de profondément mauvais avec cette approche ? Au moins jusqu'à ce que les lumières soient liées à la fonctionnalité des calques ?

Quelqu'un voit quelque chose de profondément mauvais avec cette approche ?

bien sûr que c'est mauvais. plutôt que d'avoir une seule caméra pour naviguer dans la scène, les gens devront maintenant faire des choses camera1.add( camera2 ); Je veux dire que c'est WTF quand je le regarde. Comme quoi? appareil photo dans mon appareil photo ? et si j'ai des dizaines de pièces qui doivent être éclairées individuellement ? de combien de caméras ai-je besoin ? et des couches ... il n'y avait pas d' hier couches, à droite, et maintenant je dois apprendre à leur sujet.

rant plus, pour ne pas dire que j'ai la solution parfaite pour cela. Par exemple, les gens d'alternativa3d mettaient des lumières sur des choses qui se trouvaient dans les boîtes englobantes de la lumière. cela présentait l'avantage d'une configuration proche de 0 pour les utilisateurs finaux, mais il s'effondrait lorsque la frontière entre les lumières devait être à l'angle. mais quand même, si je devais résoudre ce problème dans le projet réel en ce moment, je me résoudrais très probablement à gratter les matériaux standard utilisés dans ShaderMaterial-s et à y passer les lumières que je veux à la main.

Les couches
L'approche de @Zob1 n'est certainement pas la bonne approche. Espérons que cela ne prendra pas longtemps avant que les calques fonctionnent également avec les lumières.

Les gars juste pour m'assurer que je suis correctement; disons que j'ai une seule scène et une source lumineuse "principale". Est-il possible avec cette technique que certains matériaux ignorent cette source lumineuse principale, tout en projetant des ombres à partir d'une source lumineuse différente ?

Eh bien, pour cela, nous devrons également ajouter un support de couches aux matériaux.

Ce que nous pouvons faire pour le moment, c'est afficher/masquer les objets de la caméra :

Disons que vous faites un jeu et, dans l'éditeur, vous utilisez des sphères pour afficher les collisionneurs. Ces sphères pourraient être définies sur la couche 1, l'éditeur de la caméra pourrait avoir les couches 0 et 1 activées, mais la caméra du jeu pourrait avoir été définie sur la couche 0. De cette façon, dans votre éditeur, vous voyez tous les mannequins, mais dans le jeu, ils ' tu es parti.

Je pense que cela aura plus de sens chaque fois que j'ajouterai la fonctionnalité à l'éditeur lui-même. Nous devrions probablement faire quelques exemples aussi.

À droite! Donc, en gros, ce que je veux faire, c'est d'avoir des personnages 2D dans mon monde Three JS. Ces personnages ont besoin d'ombres « ponctuelles » pour donner l'impression qu'ils font partie de l'environnement. Je suis actuellement en train d'y parvenir en utilisant des géométries de cercle noir transparent placées à leurs pieds et des trucs assez hacks pour le faire fonctionner à des angles. Même alors, cela ne fonctionne pas du tout bien sur des surfaces complexes.

Mon idée originale était d'avoir des géométries de cercle invisibles placées comme des "halos" au-dessus de chaque personnage et de créer une lumière qui pointe directement vers le bas, couvrant toute la scène. Ces halos ne projetteraient que des ombres à partir de cette source lumineuse, tandis que tout le reste de la scène projetterait des ombres à partir de la source lumineuse "principale".

Je suppose que pour que cette idée fonctionne, nous avons besoin de couches, n'est-ce pas ?

Ces halos ne projetteraient que des ombres à partir de cette source lumineuse, tandis que tout le reste de la scène projetterait des ombres à partir de la source lumineuse "principale".

Nous avions une option shadowOnly , mais elle a été supprimée.

FWIW, il y a cette approche pour créer des ombres...

Ah mais shadowOnly ne fonctionnerait pas vraiment car alors les halos projetteraient des ombres à partir des deux sources de lumière, je veux seulement qu'ils projettent des ombres à partir d'une seule.

Je vais vérifier cet exemple, au téléphone maintenant, mais il semble prometteur.

Edit Hmm mais si cette sphère changeait de position dans la scène et que le maillage du sol avait des hauteurs variables, son ombre correspondrait-elle correctement aux normales de surface du sol ?

Non...

Ouais je le pensais. Besoin de couches ! Héhé

Salut @rohan-deshpande ,

Oui, pour votre cas d'utilisation, vous aurez besoin de couches quelconques. C'est moi qui ai implémenté la fonction shadowmesh il y a quelque temps. Ils étaient destinés à être utilisés pour une scène contenant un sol ou un sol plat, car ce sont des ombres à plan unique. Cependant, si jamais vous avez besoin d'ombres à plan unique rapides et bon marché (mais correctes), celles-ci sont difficiles à battre en termes de performances. La raison pour laquelle je les ai ajoutés était que même pour les scènes de démonstration simples, les shadowmaps ont considérablement réduit ma fréquence d'images. Les Shadowmeshes, par contre, courent vite même sur mon téléphone.

Vous pouvez consulter mon jeu qui les utilise ici :
https://github.com/erichlof/3dLightCycles

Je rends la scène deux fois à travers 2 fenêtres différentes et tous les objets du jeu (cycles et murs de sentiers) ont des ombres correctes. Il fonctionne parfaitement sur mon smartphone, ce qui serait impossible avec des shadowmaps pour 2 rendus de scène à chaque image.

+1 ici pour les couches à l'avenir :)

Le jeu

D'accord, je suppose que je vais attendre les couches. D'ici là, ma solution hacky devra suffire.

Non, il n'a pas encore été mis en œuvre. Vous devrez attendre les couches ou essayer l'une des solutions répertoriées dans ITT (scènes séparées par exemple).

+99999 à nouveau

Ce serait certainement très utile. Et nous avons maintenant des calques qui fonctionnent, ce qui semble être ce qui a retardé cela. Alors, voici la bosse amicale. ;-)

@manthrax vérifie ça !

+99999 à nouveau

J'adorerais pour ça. J'ai une situation où chaque avatar n'est éclairé que par la lumière la plus proche, et je peux avoir des milliers de lumières dans la scène, ce serait bien de spécifier une seule lumière pour chaque avatar.

Salut!
Je vais avoir besoin de cette fonctionnalité, et j'ai pensé à l'implémenter, car je pense avoir trouvé où cela pourrait être fait ( initMaterial dans WebGLRenderer ) et cela devrait être assez simple en utilisant couches existantes.

Je pense créer un masque de bits spécifique à la lumière (en tant qu'objet Layers ) pour sélectionner les calques affectés par un objet lumineux spécifique (indépendant du calque d'objet de la lumière), puis filtrer les lumières/ombres qui sont définis comme des uniformes pour chaque objet dans la fonction citée ci-dessus.

Serait-ce pertinent ?

Je vais essayer ceci et soumettre une demande d'extraction dès que j'y serai parvenu, à moins que vous ne me redirigiez vers une autre méthode avant cela.

METTRE À JOUR:

https://github.com/tiesselune/three.js/tree/selective-lighting

Je vais quelque part. Je ne sais pas comment cela pourrait affecter les performances ou comment optimiser mon code pour les performances, mais cela fonctionne sur les quelques tests que j'ai effectués. Éclairage par couche ! Yay!

Je dois encore tester un peu plus et faire un exemple pertinent avant de soumettre une pull request.

METTRE À JOUR:

J'ai fait quelques tests supplémentaires, et avoir un même matériau sur deux objets qui se trouvent sur des calques différents (et ont des paramètres d'éclairage différents) oblige le moteur de rendu à mettre à jour le matériau en permanence (via needsUpdate ) depuis les paramètres d'éclairage sur les changements matériels entre deux objets, ce qui était impossible auparavant. Cela signifie une énorme baisse de perf et des bizarreries visuelles (puisque le dernier téléchargement de matériel gagne au moment du rendu)

Bien sûr, cela peut être évité en créant une nouvelle instance de matériau au lieu d'utiliser exactement la même pour deux objets avec des paramètres d'éclairage différents. Mais je doute que le clonage pour l'utilisateur soit une bonne idée, car cela impliquerait de surveiller le matériel d'origine pour les modifications afin de les refléter sur le clone.

Voici deux solutions que je pourrais utiliser :

  1. Je pourrais simplement afficher un avertissement lorsque deux objets sur des calques différents avec des paramètres d'éclairage différents partagent un même matériau, afin que l'utilisateur puisse créer et gérer lui-même un nouveau matériau clone.

  2. Je pourrais ajouter des calques au niveau du matériau au lieu du niveau de l'objet (et créer un système de calques parallèles pour les lumières) afin qu'il soit obligatoire d'utiliser différents matériaux pour obtenir différents paramètres d'éclairage. Cela signifierait qu'il y aurait le système de calques actuel pour la visibilité (sur les objets et les caméras) et un autre pour l'éclairage (sur les matériaux et les lumières).

Qu'en pensez-vous?

Je pensais justement à cela lorsque j'ai vu votre commentaire arriver. Je pense qu'afficher un avertissement n'est pas utile, car beaucoup de gens ne le verront probablement pas. Des deux, je préfère définitivement mettre des couches légères sur le matériau plutôt que sur l'objet. C'est un peu contre-intuitif, mais ça a toujours du sens.

Juste pour clarifier, lorsque needsUpdate est défini, dans ce cas, il recalcule simplement les valeurs uniformes, n'est-ce pas ? Il ne devrait pas avoir à recompiler un shader car les différents shaders devraient tous être mis en cache. Quel genre de succès de performance voyez-vous? Avez-vous utilisé un profileur pour voir exactement où se produit le calcul supplémentaire ?

Au fait, filterAmbiantLights devrait être filterAmbientLights .

Tu as raison pour la faute d'orthographe. En fait, j'avais tout écrit avec "ambiant" avant de remarquer que c'était faux et j'ai oublié une occurrence. ??

Je pense que je vais déplacer les informations de calque sur le matériau alors. Cela semble plus pertinent et cohérent avec la façon dont cela fonctionne.

La baisse des performances est venue (et vient toujours) de initMaterial (puis acquireProgram et getShaderParameter ce qui est extrêmement lent pour une raison quelconque) étant appelé plusieurs fois à chaque image parce que le lightHash serait différent à chaque fois, en définissant material.needsUpdate sur true .

BTW, j'utilise les outils de profilage de Chrome. (Échéanciers et profileur).

C'est bien pour moi, mais je ne comprends pas pourquoi acquireProgram devrait fonctionner tout le temps. Si le nombre de chaque type de lumière est ajouté aux paramètres du programme, alors la recompilation du shader ne devrait-elle pas être inutile à chaque fois ?

Je ne comprends pas non plus;

Voici la pile d'appels (à chaque image) et la terrible fuite de mémoire qui s'ensuit, si vous les connaissez, cela pourrait m'aider à comprendre ce qui ne va pas. On dirait qu'il crée de nouveaux WebGLProgram chaque image...

threejscalltree

Peut-être que cela pourrait être replaceLightNums qui met à jour le code du shader de vertex/fragment lors de la création du WebGLProgram, provoquant sa recompilation, ou considérant qu'il s'agit d'un shader différent... ?

EDIT : Quoi qu'il en soit, l'utilisation de calques au niveau du matériau résout le problème comme prévu. J'ai juste une fuite de mémoire quelque part sur laquelle je devrais enquêter, mais sinon, ça a l'air plutôt bien.

C'est probablement une bonne idée de comprendre pourquoi cela se produit juste pour vous assurer que vous comprenez parfaitement le code et que vous n'introduisez pas de nouveau bogue. Pouvez-vous le parcourir pour voir pourquoi le code du shader change chaque image ?

Je ne connais pas assez le WebGLPrograms pour dire ce qui se passe, mais il semble qu'il devrait mettre ces shaders en cache pour vous.

C'est assez simple en fait :

  • pour savoir s'il faut ou non appeler acquireProgram , initMaterial récupère le "code" du shader à partir du cache (c'est plus un hachage, en fait, construit dans getProgramCode ) et compare le "code" du programme du matériel en cours.
  • Étant donné que cette fonction crée le "code" à partir de paramètres comprenant le nombre de chaque type de lumière, qui est filtré et bien que différent entre les objets, le code peut être différent pour un même matériau (pour ainsi dire, le même programme) d'un objet au autre.
  • Comme ce processus est itéré pour chaque objet, le "code" change plusieurs fois par image, ce qui l'oblige à recompiler autant de fois dans une seule image : ce qui provoque la baisse des performances.
  • Cela dit, étant donné que plusieurs objets ont le même matériau, et donc le même programme, le dernier objet itéré a imposé ses paramètres au programme, ce qui a provoqué l'éclairage des deux objets avec la même configuration d'éclairage mais pas nécessairement les mêmes shadowMaps (cela peut être calculé pour des objets dans un ordre différent, mais souffre du même problème "le dernier objet gagne"), provoquant mes bizarreries visuelles.

Maintenant, tout fonctionne comme prévu (puisque chaque objet avec des configurations d'éclairage différentes a un matériau différent et un programme différent), à l'exception d'une optimisation de la mémoire que je pourrais faire avec mes propres hachages lumineux, que je vais bientôt aborder.

Il pourrait y avoir une certaine amélioration si les nombres de lumière étaient variables, de sorte que chaque matériau ne soit que des instances du même programme, mais comme ces nombres sont insérés dans le code du shader (dans replaceLightNums ), cela semble incompatible avec la façon dont les choses sont actuellement sont (et leur optimisation).

J'espère que l'explication était assez compréhensible

Je me demande si on peut passer le masque de calque au shader (un uniforme par objet et un plus uniforme par lumière). Ensuite, nous pourrions ajouter quelque chose comme ça ici .

Quelque chose comme...

for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {

    pointLight = pointLights[ i ];
    pointLight.distance *= float( object.mask & pointlight.mask > 0.0 );

    ...

}

Meh, je ne pense pas que nous puissions faire des opérations au niveau du bit dans glsl ...

Oui, il semble que les opérations au niveau du bit commencent dans GLSL 1.30 et que WebGL standard utilise 1.00. ??

Salut @mrdoob et @tiesselune ,

Chrome 56 et Firefox 51 viennent d'atterrir, ce qui signifie que WebGL 2.0 est activé par défaut (WebGL2 suit la spécification OpenGL ES 3.0). Cela signifie que les opérations Bit (et d'autres trucs sympas comme les textures 3D) sont maintenant disponibles. Je ne sais pas si Three s'est lentement préparé au passage à WebGL 2.0, mais j'ai apporté quelques modifications obligatoires à ma copie de three84.js et activé WebGL 2.0, et j'ai effectué une petite opération dans un shader juste pour m'en assurer a fonctionné, et il l'a fait!
https://developers.google.com/web/updates/2017/01/nic56
https://developer.mozilla.org/en-US/Firefox/Releases/51

Je voulais juste vous faire savoir. +1 pour l'idée du masquage :-)

Salut @erichlof ! C'est une excellente nouvelle pour WebGL2 ; cela signifie que le moteur de rendu WebGL2 sera probablement en mesure d'aborder les problèmes de masquage de manière plus efficace.

Quoi qu'il en soit, étant donné l' utilisation très limitée des navigateurs prenant en charge WebGL2 jusqu'à présent, je ne pense pas que nous puissions abandonner les efforts pour le faire fonctionner dans WebGL 1 : il a fallu beaucoup de temps avant que presque tous les navigateurs puissent exécuter des applications WebGL, donc ce sera probablement un un peu plus longtemps jusqu'à ce que WebGL 2 soit vraiment utilisable à grande échelle... 😕 Mais merci pour l'astuce !

Re-bonjour!

Nouvelle mise à jour : j'ai fait ce que je pensais nécessaire pour la gestion de la mémoire, mais le ramasse-miettes JS semble avoir beaucoup à voir avec ma configuration logicielle (programmes en cours d'exécution, onglets ouverts, extensions) au moment où j'exécute des profils. Quelqu'un avec un peu plus d'expérience dans ce domaine peut-il confirmer que mon code n'est pas aussi gourmand en mémoire par rapport à la version actuelle de threejs ?

Quoi qu'il en soit, j'ai fait un exemple dans examples/webgl_lights_selective_lighting.html . Le fait est que j'ai eu des artefacts visuels liés aux shadowmaps lors de l'utilisation simultanée de deux projecteurs (sur les mêmes calques) sur les objets à peau de la scène. Les objets statiques se comportent comme prévu. J'ai effectué des tests et cela se produit également sur la branche dev, sans tenir compte du tout des couches de lumière sélectives (en fait, je viens d'ajouter un projecteur dans l'exemple shadowmap, sur la branche dev). Est-ce que quelqu'un sait d'où ça vient ?

Voici une capture d'écran :
shadowmap

Il devrait être possible de voir l'exemple en direct ici :

https://rawgit.com/tiesselune/three.js/selective-lighting/examples/webgl_lights_selective_lights.html

J'obtiens une erreur cependant :

Uncaught TypeError: Cannot read property 'set' of undefined
    at init (webgl_lights_selective_lights.html:117)
    at webgl_lights_selective_lights.html:67

@looeee : vous devrez exécuter npm run build-uglify sur un hôte local. Je n'ai volontairement pas inclus de builds dans mes commits à des fins de fusion...

Ou devrais-je?

EDIT : voici un lien fonctionnel sur une branche différente à des fins de test : https://rawgit.com/tiesselune/three.js/selective-lights-test/examples/webgl_lights_selective_lights.html

Hé, +999999 de moi. Cela devrait être implémenté (au moins avec THREE.Layers )

$$('.comment-body').reduce((acc, el) => {
  let mat = el.textContent.match(/\+(\d+)/)
  let num = +(mat && mat[1] || 0)
  return acc + num
}, 0)
>> 1219997

??

@mrdoob il a calculé +Ns dans ce fil

btw, +14570 pour les feux sélectifs

Ce sera incroyablement bien pour affiner le fonctionnement de l'éclairage dans une abstraction plus élevée.

Par exemple, dans le stylo suivant, j'aimerais que l'éclairage fonctionne dans un sens pour les éléments DOM et dans un autre pour la sphère afin que l'éclairage soit plus réaliste :

https://codepen.io/trusktr/pen/RjzKJx

Certains effets qui ressemblent à une lumière ponctuelle peuvent être obtenus en combinant deux lumières ou plus qui n'affectent sélectivement que certains éléments.

Par exemple, dans mon exemple précédent, je peux augmenter l'intensité lumineuse pour obtenir une belle ombre sur l'"élément DOM", mais la sphère aura alors l'air un peu trop brillante et lumineuse. Si je pouvais avoir une lumière plus faible pour la sphère et une lumière plus vive pour "l'élément DOM", alors je pourrais réaliser quelque chose de plus réaliste de cette façon, où il semblerait au spectateur qu'il n'y a toujours qu'une seule lumière. Ensuite, ce genre de chose peut être abstrait dans une API de niveau supérieur qui donne l'impression qu'il n'y a qu'une seule lumière manipulée lorsque derrière la scène deux lumières Three.js sont réellement en jeu.

@WestLangley

En guise de solution de contournement, pouvez-vous répondre à la plupart de vos exigences en créant une scène distincte pour chaque pièce (et ses lumières) ?

Avez-vous un lien vers un exemple de quelque chose comme ça? Peut-il avoir d'autres effets de rendu inattendus sur le résultat ?

d'autres effets de rendu inattendus sur le résultat ?

ordre de rendu des objets transparents, par exemple - les objets transparents de la scène 1 seront rendus avant les objets opaques de la scène 2.

Avez-vous un lien vers un exemple de quelque chose comme ça?

ici, j'en ai fait un rien que pour vous : https://jsfiddle.net/f2Lommf5/524/

ordre de rendu des objets transparents, par exemple - les objets transparents de la scène 1 seront rendus avant les objets opaques de la scène 2.

C'est ce que je pensais; cela rend la solution de contournement uniquement une solution de contournement pour des cas très limités. Dans l'attente de la vraie solution !

eh bien, vous pourriez argumenter que le problème ne se produirait que si vous pouviez voir les objets opaques de la scène2 de la scène1 à travers lesdits objets transparents. mais si c'est le cas, les lumières devraient également passer, et il n'y aurait aucune raison de séparer les scènes pour commencer. mais je suis d'accord que ce genre d'argument n'est pas vraiment convaincant.

@makc Voici un exemple du problème que j'essaie de résoudre :

https://discourse.threejs.org/t/how-to-make-shadows-darker-on-transparent-objects/1389

Je pense qu'un éclairage sélectif aiderait vraiment à cela.

@trusktr Je pense que vous pouvez résoudre ce problème en modifiant le matériau d'ombre de mrdoob. il montre juste une texture d'ombre noir-blanc, et vous pouvez le modifier pour qu'il soit transparent si nécessaire

Les masques dans PlayCanvas semblent vraiment faciles à utiliser pour un éclairage sélectif : https://forum.playcanvas.com/t/set-certain-object-to-not-receive-light/785.

pouvons-nous fusionner cela? Je pense que les problèmes d'ombre étaient dus au shader Lambert, rien à voir avec la modification du code. @tiesselune

@ErikBehar Je cherchais en fait quelque chose à faire cet après-midi, je vais essayer de mettre à jour le code vers les derniers threejs et soumettre une pull request peut-être ? J'aimerais vraiment savoir que j'ai apporté une réelle contribution à un si grand projet. (Et bien d'avoir la confirmation que ce bug n'avait rien à voir avec mes modifications)

EDIT : je viens de découvrir que cette partie du code a beaucoup changé. Il va falloir un peu de temps, je suppose, car les états que j'utilisais auparavant sont passés de WebGLRenderer à WebGLLights.

@tiesselune J'avais en quelque intégrer cela dans un projet, alors je suis allé de l'avant et j'ai porté votre code sur la v93 voir : https://github.com/ErikBehar/three.js/tree/selectiveLights

Je peux faire un PR si vous le souhaitez ? @mrdoob

@ErikBehar Eh bien, cela ressemble à ce que je

@ErikBehar un PR serait génial !

@tiesselune Je vais étudier la posterai le PR bientôt

Quel est le statut à ce sujet ? J'ai fusionné le code r94dev de @ErikBehar dans r94, puis j'y ai fusionné r97, seulement quelques conflits très simples (changement de version, quelques variables pour l'éclairage sélectif et la création de hachage dans renderers/WebGLRenderer.js ; j'aurais être heureux de mettre dans un PR. @tiesselune si vous pouvez me donner une idée de l'endroit où vous vouliez aller l'état d'éclairage sélectif, je serais heureux de le déplacer, de tester et de mettre dans un PR.

ÉDITER:
Un peu plus tard : je vois que cela nécessite un peu de travail pour fonctionner, maintenant, avec le nouveau lighthash.

@VaelynPhi Je pense que, qu'ils soient ou non prêts à accepter le code de @ErikBehar , c'est une bonne idée de soumettre le PR, juste pour remplacer celui qui est obsolète au cas où d'autres le voudraient, comme vous vous-même fait

Désolé de laisser tomber la balle sur ces gars = / ... @VaelynPhi peux-tu poster ton fork / branch ?

Pas de soucis; Je comprends être occupé. Hélas, je n'ai même pas pu faire fonctionner la branche que vous aviez, @ErikBehar; J'ai décidé de lire le code pour essayer de le décomposer afin de pouvoir déplacer l'état vers l'emplacement approprié et, espérons-le, corriger les bogues. Je n'ai pas encore atteint un état de port fonctionnel, même sur la v94. Peut-être que je peux le nettoyer et le mettre dans le PR juste pour le mettre à jour comme le suggère @makc . Donnez-moi un peu; Je suis super occupé. :) À tout le moins, cela aidera peut-être à mettre en évidence les modifications qui doivent être apportées pour intégrer l'éclairage sélectif dans la version récente.

a ajouté un PR basé sur :
https://github.com/ErikBehar/three.js/commit/ac0499b70b82bc7bb780100a8372fcdf318d1424#diff -5e43a0b5002eb2c419def3baf67d4e67
par @ErikBehar
quelqu'un peut-il donner un coup de main avec une critique et l'exemple ?

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

Hé les gars, quel est le statut sur celui-ci? @tiesselune @ErikBehar Puis-je vous aider avec quelque chose ? Ce serait bien de le mettre en place enfin au bout de 4 ans 😄💯

@flyrell Je pense que nous pourrions peut-être clore ce problème car il semble être plus proche d'être terminé dans #15223 peut-être ?

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