Three.js: Iluminación selectiva

Creado en 10 ago. 2014  ·  101Comentarios  ·  Fuente: mrdoob/three.js

No estoy seguro de si esta ya es una función planificada o tal vez incluso una terminada, así que intentaré explicar la tarea primero.

Necesito hacer iluminación selectiva para diferentes habitaciones. Por ejemplo, tengo dos habitaciones. Una luz solo debe afectar a los objetos y las paredes internas de una habitación. La segunda habitación no debe verse afectada por esta luz.

Actualmente, si agrego una luz a la escena, afecta a todos los objetos a su distancia. Y obtengo un efecto extraño cuando la luz entra "a través de la pared" de la segunda habitación.

Entonces creo que necesito algún tipo de grupos o canales para la iluminación, para poder establecer los objetos que se ven afectados por una fuente de luz y los objetos que se ven afectados por otra.

No he encontrado nada de eso ni en luces ni en objetos, así que pensé que tal vez podría ser una buena característica.

Y, por cierto, si aún no está implementado, ¿cuál es el enfoque recomendado para resolver tales tareas usando el estado actual de three.js?

Enhancement

Comentario más útil

¿Tiene un enlace a un ejemplo de algo como esto?

aquí, hice uno solo para ti: https://jsfiddle.net/f2Lommf5/524/

Todos 101 comentarios

Lo que estoy diciendo es básicamente tener un campo channel en THREE.Light y un campo lightChannel en THREE.Mesh o algo así. Si este último es nulo, se verá afectado por todas las fuentes de luz. Si este último no es nulo, solo se verán afectados los canales de luz con el mismo valor.

O tal vez podría agregarse no a la malla en sí, sino a caras separadas de la geometría de la malla.

¿Suena como si quisieras usar sombras?

Bueno, podría lograr algo así con sombras (y ya lo he intentado), pero da diferentes efectos secundarios y siento que es un truco, porque no necesito iluminar algunos objetos y luego proyectar sombras sobre ellos. . No debo encenderlos en primer lugar.

Lo que necesito es que una fuente de luz específica no afecte a un conjunto de mallas, sino que afecte al otro conjunto.

Por lo general, hago esto usando una técnica como esa: Ejemplo de hilo de discusión :

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]);

Entonces parece una característica diferente a solo sombras. ¿O me estoy perdiendo algo?

Sí ... creo que esto puede ser útil. Sin embargo, no estoy seguro de cómo debería verse la API.

Quizás la solución más simple podría ser la más efectiva aquí:

  1. Agregue channel (o group ) a THREE.Light
  2. Agregue un affectedByLightChannel (o affectedByLightGroup ) a THREE.Mesh (O tal vez incluso a una cara en la geometría)

¿Qué piensas?

Tal vez el 'protectedByLightChannel' sea demasiado largo y algo como 'lightChannel' sería suficiente, pero creo que sería conveniente: solo números de canal en la fuente de luz y los receptores.

Como eso:

    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 es igual a 0, entonces se verá afectado por todos los canales. Si channel es igual a 0, afecta a todas las mallas.

Por lo tanto, sería totalmente compatible con el comportamiento actual.

Eso puede ser un poco difícil de entender ... Quizás sea mejor algo como esto:

cube.lightInfluences = [ light1, light2 ];

Me parece absolutamente bien.

Quizás sea un poco más difícil de usar en algunos casos, pero es más fácil de entender, obviamente.

¿Qué pasa con una propiedad de máscara de entero simple para mallas y luces?

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);

Los objetos solo se iluminan con luces si el Y lógico de sus máscaras no es cero.
Esto permitiría que las luces se vieran influenciadas por más de un canal, sin métodos adicionales en los objetos.

Una máscara predeterminada de 0xffffffff no afectaría el código existente.

Lo que dijo @ satori99 .

Aunque, creo que mask debería ser una propiedad de Light y Mesh*Material , en su lugar. (Solo aquellos materiales afectados por las luces).

Además, la propiedad podría denominarse alternativamente lightMask , lightChannel o channel .

El problema del enfoque de canal / máscara es que el usuario deberá comprender las operaciones bit a bit. Un poco demasiado intenso si lo comparas con el resto de la API.

¿Qué puede hacer con las máscaras que no pueda hacer con el enfoque de matriz?

Podría dar un ejemplo de la tarea con dos habitaciones arriba.

El punto principal de utilizar el enfoque de canal sobre el enfoque de matriz es que las operaciones simples como 'mover la luz1 de la habitación 1 a la habitación 2' se vuelven más complicadas si usa matrices.

En lugar de simplemente establecer

light1.channel = 2

(anteriormente estaba establecido en 1)

tendría que encontrar todos los objetos en la habitación 1 que tenían light1 en la matriz lightInfluences previamente, luego quitar la luz de sus matrices y luego agregarla a todos los objetos en la habitación 2.

Lo mismo ocurre con la operación simple como 'mover el objeto 1 de la habitación 1 a la habitación 2'. En lugar de establecer su influenceChannel de 1 a 2, necesitaría encontrar todas las luces en esa habitación, luego eliminarlas de su matriz de influencia, luego encontrar todas las luces en la habitación dos y agregarlas.

No es que no se pueda hacer, por eso dije que el enfoque de LightInfluences está absolutamente bien para mí. Pero las cosas del canal serían lo primero que implementaría arriba para mí solo para hacer operaciones comunes tan simples como una asignación.

Creo que debería implementarse como una máscara. (Si está implementado en la CPU o en la GPU es un tema para discusión posterior).

Podemos mostrar a través de ejemplos cómo configurarlo, y los usuarios pueden seguir el patrón.

Si cree que todavía es demasiado complicado, podemos crear una API THREE.Channels para ello.

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

Mismos métodos para Mesh*Material .

Me gusta esa API :)
Puedo ver que esto funciona para objetos y luces, pero ¿cómo ves que funciona para materiales?

Solo los materiales responden a las luces. Creo que esto tendría que ser una propiedad del material.

Estoy de acuerdo en esto con @westlangley. Las luces dependen de los materiales.

Lo mismo ocurre con la operación simple como 'mover el objeto 1 de la habitación 1 a la habitación 2'.

Bueno, eso es un problema. Channels no estaría basado en objetos.

Bueno, eso es un problema. Los canales no estarían basados ​​en objetos.

¿Pero por qué? ¿Es una limitación técnica?

Porque invalida la idea de todo eso. Porque puede haber diferentes objetos, que reutilizan el mismo material, pero uno de ellos debe estar encendido y el otro no.

¿Pero por qué? ¿Es una limitación técnica?

No. Es porque los objetos no responden a las luces. Solo los materiales lo hacen.

Porque puede haber diferentes objetos, que reutilizan el mismo material, pero uno de ellos debe estar encendido y el otro no.

Puede usar el mismo material para todos los objetos en la escena, solo clone el material para los objetos cuyo material requiere diferentes valores uniformes. Todavía debería haber un solo programa de sombreado compartido por todos.

Creo que debería implementarse como una máscara. (Si está implementado en la CPU o en la GPU es un tema para discusión posterior).

¿Se puede manejar esto con cierta facilidad en la GPU directamente?

¿Se puede manejar esto con cierta facilidad en la GPU directamente?

Sí, debe pasar los uniformes adicionales de channels para las luces y los materiales.

¿Qué tal un sistema de gestión de capas? Agruparía las mallas en capas y aplicaría las máscaras desde allí (podría afectar las luces, las sombras, la visibilidad, etc.), ¿la unidad sería un buen ejemplo?

Las sombras también es un tema relacionado. Creo que también debería haber algo como la proyección de sombras selectiva. Como 'receiveShadowFrom = ...' (y una lista de fuentes) en lugar de solo 'receiveShadow = true'.

Porque cuando configura luces que solo afectan a una habitación específica (en mi ejemplo), también desearía inmediatamente que esas luces proyectaran sombras solo en los objetos de esta habitación.

Los atributos de sombras realmente deberían estar en los materiales y no en los objetos por las mismas razones que las anteriores en este hilo.

Los atributos de sombras realmente deberían estar en los materiales y no en los objetos por las mismas razones que las anteriores en este hilo.

¡Sí, tiene sentido!

¿Hay planes para incluir esta función (como un lanzamiento de destino planificado para el primer borrador)?

Como solución alternativa, ¿puede lograr la mayoría de sus requisitos al tener una escena separada para cada habitación (y sus luces)?

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

¡Mmmm, intentaré este enfoque!

La iluminación / sombras selectivas es imprescindible para futuras versiones, en mi opinión.

GRANDE +9999 para este, me encantaría poder seleccionar si un material proyecta una sombra desde la fuente de luz A o desde la fuente de luz B. ¿Alguien tiene una solución actualmente que no sean dos escenas? Eso me hará las cosas bastante dolorosas ...

mierda, ¿cómo es que esto todavía no se ha implementado? después de +9999 de rohan)

Jaja, mi conjetura es que es un poco difícil de implementar @tsone, ¿puedes proporcionar información sobre ese compromiso? Navegando en un cliente telefónico ahora mismo

¿Cómo es difícil de implementar si estos son solo uniformes que pasan a los materiales? todo lo que tienen que hacer es sustituir la lista global de luces con la definida en el material, si existe, en algún lugar profundo del renderizador webgl.

Aquí hay un JSFiddle simple que prueba la implementación de capas de la rama Dev:
https://jsfiddle.net/Angrypickle/t8f7q3vo/4/
Desafortunadamente, a partir de este momento, no parece que esté funcionando correctamente. ¿O estoy haciendo algo mal?

Si. Las capas aún no funcionan con luces. ¡Sin embargo, funcionan con cámara / objeto! 😊

¡Confirmado Senor! Aquí hay un JSFiddle actualizado que usa cámaras superpuestas para lograr una iluminación selectiva con capas:
https://jsfiddle.net/Angrypickle/t4a1eusL/
Parece funcionar correctamente en computadoras de escritorio y dispositivos móviles. ¿Alguien ve algo profundamente malo con este enfoque? ¿Al menos hasta que las luces estén vinculadas a la funcionalidad de las capas?

¿Alguien ve algo profundamente malo con este enfoque?

por supuesto que es malo. en lugar de tener una sola cámara navegando por la escena, la gente ahora tendrá que hacer cosas camera1.add( camera2 ); Quiero decir, esto es WTF cuando lo miro. ¿Cómo qué? cámara en mi cámara? ¿Qué pasa si tengo docenas de habitaciones que deben iluminarse individualmente? cuantas cámaras necesito? y capas ... ayer no había capas, cierto, y ahora tengo que pensar en ellas.

despotricar, por no decir que tengo la solución perfecta para esto. Por ejemplo, alternativa3d la gente solía poner luces en cosas que estaban en los recuadros delimitadores de la luz. esto tenía la ventaja de una configuración próxima a 0 para los usuarios finales, pero se estaba desmoronando cuando el borde entre las luces tenía que estar en ángulo. pero aún así, si tuviera que resolver este problema en un proyecto real en este momento, lo más probable es que resuelva raspar los materiales estándar usados ​​en ShaderMaterial-s y pasar las luces que quiero a mano allí.

¡Las capas
El enfoque de @ Zob1 definitivamente no es el adecuado. Con suerte, no pasará mucho tiempo hasta que las capas también funcionen con las luces.

Chicos, solo para asegurarse de que estoy siguiendo correctamente; digamos que tengo una sola escena y una fuente de luz "principal". ¿Es posible con esta técnica hacer que ciertos materiales ignoren esta fuente de luz principal y al mismo tiempo proyecten sombras desde una fuente de luz diferente?

Bueno, para eso también tendremos que agregar capas de soporte a los materiales.

Lo que podemos hacer en este momento es mostrar / ocultar objetos de la cámara:

Digamos que estás haciendo un juego y, en el editor, usas esferas para mostrar colisionadores. Esas esferas podrían configurarse en la capa 1, el editor de la cámara podría tener las capas 0 y 1 habilitadas, pero la cámara del juego podría haberse configurado en la capa 0. De esa manera, en tu editor ves todos los maniquíes, pero en el juego ellos ' te has ido.

Creo que esto tendrá más sentido cada vez que agregue la funcionalidad al propio editor. Probablemente también deberíamos hacer algunos ejemplos.

¡Correcto! Entonces, básicamente, lo que quiero hacer es tener personajes 2D en mi mundo Three JS. Estos personajes necesitan sombras "puntuales" para que parezcan parte del entorno. Actualmente estoy logrando esto usando geometrías de círculo negro transparente colocadas a sus pies y algunas cosas bastante hacky para que funcione en ángulos. Incluso entonces no funciona bien en superficies complejas.

Mi idea original era colocar geometrías de círculos invisibles como "halos" sobre cada personaje y crear una luz que apunta directamente hacia abajo, cubriendo toda la escena. Estos halos solo arrojarían sombras de esta fuente de luz, mientras que todo lo demás en la escena arrojaría sombras de la fuente de luz "principal".

Supongo que para que esta idea funcione, necesitamos capas, ¿verdad?

Estos halos solo arrojarían sombras de esta fuente de luz, mientras que todo lo demás en la escena arrojaría sombras de la fuente de luz "principal".

Solíamos tener una opción shadowOnly , pero fue eliminada.

FWIW, existe este enfoque para crear sombras ...

Ah, pero shadowOnly realmente no funcionaría porque entonces los halos proyectarían sombras de ambas fuentes de luz, solo quiero que proyecten sombras de una.

Veré ese ejemplo, en el teléfono ahora mismo, pero parece prometedor.

Edite Hmm, pero si esa esfera cambiara su posición en la escena y la malla del suelo tuviera alturas variables, ¿coincidiría su sombra con las normales de la superficie del suelo correctamente?

No...

Sí, eso pensaba. ¡Necesito capas! Jeje

Hola @ rohan-deshpande,

Sí, para su caso de uso, necesitará capas de algún tipo. Yo fui quien implementó la función shadowmesh hace un tiempo. Estaban destinados a ser utilizados para una escena que contiene un piso o terreno plano, porque son sombras de un solo plano. Sin embargo, si alguna vez necesita sombras de un solo plano rápidas y baratas (pero correctas), estas son difíciles de superar en términos de rendimiento. La razón por la que agregué estos fue porque incluso para escenas de demostración simples, los mapas de sombras redujeron considerablemente mi velocidad de fotogramas. Shadowmeshes, por otro lado, se ejecuta rápido incluso en mi teléfono.

Puedes ver mi juego que los usa aquí:
https://github.com/erichlof/3dLightCycles

Estoy renderizando la escena dos veces a través de 2 ventanas gráficas diferentes y todos los objetos del juego (ciclos y paredes de senderos) tienen sombras correctas. Funciona con suavidad como la seda en mi teléfono inteligente, lo que sería imposible con mapas de sombras para 2 representaciones de escenas en cada cuadro.

+1 aquí para capas en el futuro :)

El juego

Está bien, supongo que esperaré por capas. Hasta entonces, mi solución hacky tendrá que ser suficiente.

No, aún no se ha implementado. Tendrá que esperar las capas o probar una de las soluciones enumeradas en ITT (escenas separadas, por ejemplo).

+99999 otra vez

Definitivamente esto sería muy útil. Y ahora tenemos capas funcionando, lo que parece ser lo que ha estado retrasando esto. Entonces, aquí está el golpe amistoso. ;-)

@manthrax , ¡

+99999 otra vez

Me encantaría esto. Tengo una situación en la que cada avatar está iluminado solo por la luz más cercana, y puedo tener miles de luces en la escena, sería bueno especificar una sola luz para cada avatar.

¡Hola!
Necesitaré esta función, y pensé en implementarla, ya que creo que he localizado dónde se podría hacer esto ( initMaterial en WebGLRenderer ) y debería ser bastante sencillo usar capas existentes.

Estoy pensando en crear una máscara de bits específica de la luz (como un objeto Layers ) para seleccionar qué capas se ven afectadas por un objeto de luz específico (independientemente de la propia capa de objeto de la luz), luego filtrar las luces / mapas de sombras que se establecen como uniformes para cada objeto en la función antes citada.

¿Sería eso relevante?

Intentaré esto y enviaré una solicitud de extracción tan pronto como lo haya logrado, a menos que me redirija a algún otro método antes de eso.

ACTUALIZAR:

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

Estoy llegando a alguna parte. No estoy seguro de cómo esto podría afectar el rendimiento o cómo optimizar mi código para el rendimiento, pero está funcionando en las pocas pruebas que hice. ¡Iluminación por capa! ¡Hurra!

Sin embargo, todavía tengo que probar un poco más y hacer un ejemplo relevante antes de enviar una solicitud de extracción.

ACTUALIZAR:

Hice algunas pruebas más, y tener un mismo material en dos objetos que están en diferentes capas (y tienen diferentes configuraciones de iluminación) hace que el renderizador actualice el material constantemente (a través de needsUpdate ) desde la configuración de iluminación sobre los cambios materiales entre dos objetos, lo que antes era imposible. Esto significa una gran caída de rendimiento y rarezas visuales (ya que la última carga de material gana en el tiempo de renderizado)

Por supuesto, esto se puede evitar creando una nueva instancia de material en lugar de usar exactamente la misma para dos objetos con diferentes configuraciones de iluminación. Pero dudo que clonarlo para el usuario sea una buena idea, ya que significaría mirar el material original en busca de cambios para reflejarlos en el clon.

Aquí hay dos soluciones que podría usar:

  1. Podría mostrar una advertencia cuando dos objetos en diferentes capas con diferentes configuraciones de iluminación comparten el mismo material, para que el usuario pueda crear y administrar un nuevo material de clonación por sí mismo.

  2. Podría agregar capas a nivel de material en lugar del nivel del objeto (y crear un sistema de capas paralelas para luces) de modo que sea obligatorio usar diferentes materiales para lograr diferentes configuraciones de iluminación. Eso significaría que habría el sistema de capas actual para la visibilidad (en objetos y cámaras) y uno diferente para la iluminación (en materiales y luces).

¿Qué piensan ustedes?

Estaba pensando en esto cuando vi llegar su comentario. Creo que mostrar una advertencia no es útil, ya que muchas personas probablemente no lo verán. De los dos, definitivamente prefiero colocar capas de luz sobre el material en lugar de sobre el objeto. Es un poco contrario a la intuición, pero todavía tiene sentido.

Solo para aclarar, cuando se establece needsUpdate , en este caso, simplemente recalcula los valores uniformes, ¿verdad? No debería tener que volver a compilar un sombreador porque los diferentes sombreadores deben almacenarse en caché. ¿Qué tipo de impacto de rendimiento estás viendo? ¿Usó un generador de perfiles para ver exactamente dónde está ocurriendo el cálculo adicional?

Por cierto, filterAmbiantLights debería ser filterAmbientLights .

Tiene razón sobre el error ortográfico. De hecho, había escrito todo con "ambiant" antes de darme cuenta de que estaba mal y olvidé una ocurrencia. 😇

Entonces creo que voy a mover la información de la capa sobre el material. Parece más relevante y coherente con la forma en que funciona.

La caída del rendimiento se produjo (y sigue siendo) de initMaterial (y luego acquireProgram y getShaderParameter que es tremendamente lento por alguna razón) que se llamó a cada cuadro varias veces porque el lightHash sería diferente cada vez, estableciendo material.needsUpdate en true .

Por cierto, estoy usando las herramientas de creación de perfiles de Chrome. (Líneas de tiempo y perfilador).

Eso está bien para mí, pero no tengo claro por qué acquireProgram debería estar ejecutándose todo el tiempo. Si el número de cada tipo de luz se agrega a los parámetros del programa, ¿no debería ser innecesario volver a compilar el sombreador cada vez?

Yo tampoco lo entiendo;

Aquí está la pila de llamadas (en cada cuadro) y la terrible pérdida de memoria que sigue, si está familiarizado con esto, eso podría ayudarme a comprender qué sale mal. Parece que está creando nuevos WebGLProgram s en cada cuadro ...

threejscalltree

¿Quizás podría ser replaceLightNums que actualice el código del sombreador de vértices / fragmentos durante la creación del WebGLProgram, haciendo que se vuelva a compilar o considerando que es un sombreador diferente ...?

EDITAR: De todos modos, el uso de capas a nivel de material resuelve el problema como se esperaba. Solo tengo una pérdida de memoria en algún lugar que debería investigar, pero por lo demás se ve bastante bien.

Probablemente sea una buena idea comprender por qué sucede esto solo para asegurarse de que comprende completamente el código y no está introduciendo algún error nuevo. ¿Puedes recorrerlo para ver por qué el código de sombreado cambia cada fotograma?

No conozco el WebGLPrograms suficientemente bien como para decir lo que está pasando, pero parece que debería estar almacenando en caché esos sombreadores por ti.

De hecho, es bastante simple:

  • para saber si llamar o no acquireProgram , initMaterial obtiene el "código" del sombreador de la caché (es más un hash, en realidad, construido en getProgramCode ) y compara al "código" del programa del material actual.
  • Dado que esta función crea el "código" a partir de parámetros que incluyen el número de cada tipo de luz, que se filtra y, aunque es diferente entre los objetos, el código puede ser diferente para un mismo material (por así decirlo, el mismo programa) de un objeto a la otro.
  • Dado que este proceso se repite para cada objeto, el "código" cambia varias veces por fotograma, lo que hace que se vuelva a compilar tantas veces en un solo fotograma: lo que provoca la caída de rendimiento.
  • Dicho esto, dado que varios objetos tienen el mismo material y, por lo tanto, el mismo programa, el último objeto iterado impuso sus parámetros al programa, lo que provocó que ambos objetos se iluminaran con la misma configuración de luz pero no necesariamente con los mismos mapas de sombras (que se puede calcular para objetos en un orden diferente, pero sufre el mismo problema de "el último objeto gana"), lo que provoca mis rarezas visuales.

Ahora todo funciona como se esperaba (ya que cada objeto con diferentes configuraciones de luz tiene un material diferente y un programa diferente), excepto por una optimización de memoria que podría hacer con mis propios hashes de luz, que voy a abordar pronto.

Podría haber alguna mejora si los números de luz fueran variables, de modo que cada material sean solo instancias del mismo programa, pero dado que esos números se insertan en el código de sombreado (en replaceLightNums ) parece incompatible con la forma en que las cosas actualmente son (y su optimización).

Espero que la explicación sea lo suficientemente comprensible

Me pregunto si podemos pasar la máscara de capa al sombreador (un uniforme por objeto y uno más por luz). Entonces podríamos agregar algo como esto aquí .

Algo como...

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

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

    ...

}

Meh, no creo que podamos hacer operaciones bit a bit en glsl ...

Sí, parece que las operaciones bit a bit comienzan en GLSL 1.30 y que WebGL estándar usa 1.00. 😕

Hola @mrdoob y @tiesselune ,

Chrome 56 y Firefox 51 acaban de aterrizar, lo que significa que WebGL 2.0 está habilitado de forma predeterminada (WebGL2 sigue la especificación OpenGL ES 3.0). Eso significa que las operaciones de Bit (y otras cosas interesantes como texturas 3D) ahora están disponibles. No sé si Three se ha estado preparando lentamente para el cambio a WebGL 2.0, pero hice algunos cambios obligatorios en mi copia de three84.js y habilité WebGL 2.0, e hice una pequeña operación en un sombreador solo para asegurarme funcionó, ¡y lo hizo!
https://developers.google.com/web/updates/2017/01/nic56
https://developer.mozilla.org/en-US/Firefox/Releases/51

Sólo quería hacerte saber. +1 para la idea de enmascaramiento :-)

¡Hola @erichlof ! Esa es una gran noticia para WebGL2; significa que el renderizador WebGL2 probablemente podrá abordar los problemas de enmascaramiento de una manera más eficiente.

De todos modos, dado el uso muy limitado de navegadores compatibles con WebGL2 hasta ahora, no creo que podamos descartar los esfuerzos para que funcione en WebGL 1: ha pasado mucho tiempo hasta que casi todos los navegadores puedan ejecutar aplicaciones WebGL, por lo que probablemente será un problema. un poco más hasta que WebGL 2 sea realmente utilizable a gran escala ... 😕 ¡Pero gracias por la pista!

¡Hola de nuevo!

Nueva actualización: he hecho lo que creía necesario para la administración de la memoria, pero la recolección de basura del montón de JS parece tener mucho que ver con la configuración de mi software (programas en ejecución, pestañas abiertas, extensiones) en el momento en que ejecuto los perfiles. ¿Puede alguien con un poco más de experiencia confirmar que mi código no tiene tanta memoria en comparación con la versión actual de threejs?

De todos modos, hice un ejemplo en examples / webgl_lights_selective_lighting.html . El caso es que obtuve artefactos visuales relacionados con el mapa de sombras al usar dos focos (en las mismas capas) simultáneamente en los objetos de la escena con piel. Los objetos estáticos se comportan como se esperaba. Ejecuté pruebas y también sucede en la rama de desarrollo, sin considerar en absoluto las capas de luz selectivas (en realidad, acabo de agregar un foco en el ejemplo del mapa de sombras, en la rama de desarrollo). ¿Alguien sabe de dónde viene eso?

Aquí tienes una captura de pantalla:
shadowmap

Debería ser posible ver el ejemplo en vivo aquí:

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

Sin embargo, recibo un error:

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

@looeee : tendrás que ejecutar npm run build-uglify en un host local. De forma voluntaria, no incluí compilaciones en mis confirmaciones con fines de fusión ...

¿O debería?

EDITAR: aquí hay un enlace de trabajo en una rama diferente para fines de prueba: https://rawgit.com/tiesselune/three.js/selective-lights-test/examples/webgl_lights_selective_lights.html

Oye, +999999 de mi parte. Esto debe implementarse (al menos con 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 calculó + Ns en este hilo

por cierto, +14570 para luces selectivas

Esto será increíblemente bueno para ajustar cómo funciona la iluminación en una mayor abstracción.

Por ejemplo, en el siguiente lápiz, me gustaría que la iluminación funcione de una manera para los elementos DOM frente a otra forma para la Esfera para que la iluminación sea más realista:

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

Ciertos efectos que parecen una luz de un solo punto se pueden lograr combinando dos o más luces que afectan selectivamente solo ciertos elementos.

Por ejemplo, en mi ejemplo anterior, puedo aumentar la intensidad de la luz para obtener una buena sombra en el "elemento DOM", pero luego la Esfera se verá un poco demasiado brillante y brillante. Si pudiera tener una luz más tenue para la Esfera y una luz más brillante para el "elemento DOM", entonces podría lograr algo más realista de esta manera, donde al espectador le parecería que todavía hay una sola luz. Luego, este tipo de cosas se pueden abstraer en una API de nivel superior que hace que parezca que solo se está manipulando una luz cuando detrás de la escena dos luces Three.js están realmente en juego.

@WestLangley

Como solución alternativa, ¿puede lograr la mayoría de sus requisitos al tener una escena separada para cada habitación (y sus luces)?

¿Tiene un enlace a un ejemplo de algo como esto? ¿Puede tener otros efectos de renderización inesperados en el resultado?

otros efectos de renderizado inesperados en el resultado?

orden de renderizado de objetos transparentes, por ejemplo: los objetos transparentes en la escena 1 se renderizarán antes que los objetos opacos en la escena 2.

¿Tiene un enlace a un ejemplo de algo como esto?

aquí, hice uno solo para ti: https://jsfiddle.net/f2Lommf5/524/

orden de renderizado de objetos transparentes, por ejemplo: los objetos transparentes en la escena 1 se renderizarán antes que los objetos opacos en la escena 2.

Eso es lo que estaba pensando; hace que la solución provisional sea solo una solución alternativa para casos muy limitados. ¡Esperamos la solución real!

bueno, podría argumentar que el problema solo sucedería si pudiera ver objetos opacos de scene2 de scene1 a través de dichos objetos transparentes. pero si ese es el caso, las luces también deberían pasar, y no habría ninguna razón para separar las escenas para empezar. pero estoy de acuerdo en que este tipo de argumento no es realmente convincente.

@makc Aquí hay un ejemplo del problema que estoy tratando de resolver:

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

Creo que la iluminación selectiva realmente ayudaría con esto.

@trusktr Creo que puedes resolver eso alterando el material de sombra de mrdoob. solo muestra una textura de sombra en blanco y negro, y puede modificarla para que sea transparente según sea necesario

Las máscaras en PlayCanvas parecen realmente fáciles de usar para iluminación selectiva: https://forum.playcanvas.com/t/set-certain-object-to-not-receive-light/785.

¿Podemos fusionar esto? Creo que los problemas de sombra se debieron al sombreador de Lambert, nada que ver con el cambio en el código. @tiesselune

@ErikBehar En realidad, estaba buscando algo que hacer esta tarde, voy a intentar actualizar el código a los últimos tresjs y enviar una solicitud de extracción, ¿tal vez? De hecho, disfrutaría sabiendo que hice una contribución real a un proyecto tan grande. (Y es bueno tener la confirmación de que este error no tuvo nada que ver con mis cambios)

EDITAR: acabo de descubrir que esta parte del código cambió mucho. Supongo que necesitará un poco de tiempo, ya que los estados que estaba usando anteriormente se trasladaron de WebGLRenderer a WebGLLights.

@tiesselune Necesitaba https://github.com/ErikBehar/three.js/tree/selectiveLights

¿Puedo hacer un PR si lo desean? @mrdoob

@ErikBehar Bueno, parece lo que estaba buscando, pero no tuve el tiempo para hacerlo por completo. Creo que habría movido las funciones de filtrado / hash de WebGLRenderer y las habría agregado al objeto de estado de WebGLLights. Siento que pertenecen allí ahora, el sistema de capas es parte del estado y no del renderizador.

¡@ErikBehar, un PR sería genial!

@tiesselune Buscaré moverlo como sugieres, o siéntete libre de presionar un PR en mi tenedor lol =] y publicaré el PR pronto @mrdoob

¿Cuál es el estado de esto? Fusioné el código r94dev de @ErikBehar en r94, luego fusioné r97 en él, solo un par de conflictos muy sencillos (cambio de versión, algunas variables para iluminación selectiva y la creación de hash en renderizadores / WebGLRenderer.js; yo Estaré feliz de poner un PR.

EDITAR:
Un poco más tarde: veo que esto necesita algo de trabajo para funcionar, ahora, con el nuevo lighthash.

@VaelynPhi Creo que, independientemente de si están dispuestos a aceptar el código de @ErikBehar o no, es una buena idea enviar el PR, solo para reemplazar el desactualizado en caso de que otras personas lo quieran, como usted. hizo

Lamento dejar caer la pelota sobre esto chicos = / ... @VaelynPhi ¿puedes publicar tu bifurcación / rama?

No hay problema; Entiendo estar ocupado. Por desgracia, ni siquiera pude hacer funcionar la rama que tenías, @ErikBehar; Me decidí por leer el código para tratar de desglosarlo para poder mover el estado a la ubicación adecuada y, con suerte, corregir cualquier error. Todavía tengo que llegar a un estado de puerto que funcione incluso en v94. Quizás pueda limpiarlo y poner el PR solo para actualizarlo como sugiere @makc . Dame un poco; Estoy super ocupada. :) Como mínimo, tal vez eso ayude a resaltar los cambios que se deben realizar para llevar la iluminación selectiva a la versión reciente.

agregó un PR basado en:
https://github.com/ErikBehar/three.js/commit/ac0499b70b82bc7bb780100a8372fcdf318d1424#diff -5e43a0b5002eb2c419def3baf67d4e67
por @ErikBehar
¿Alguien puede echar una mano con alguna reseña y el ejemplo?

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

Hola chicos, ¿cuál es el estado de este? @tiesselune @ErikBehar ¿Puedo ayudarte con algo? Sería bueno implementarlo finalmente después de 4 años 😄💯

@flyrell Creo que tal vez podríamos cerrar este problema, ya que parece estar más cerca de terminar en el # 15223, ¿tal vez?

¿Fue útil esta página
0 / 5 - 0 calificaciones