Three.js: NodeMaterial

Creado en 3 nov. 2015  ·  161Comentarios  ·  Fuente: mrdoob/three.js

Hola.

Comencé a desarrollar un THREE.NodeMaterial para conciliar las diferencias de materiales entre el software de autoría 3D. En SEA3D Studio tiene opciones para crear capas en Albedo con máscara y varios modos de fusión, Sombreador de borde y otros sin necesidad de código de sombreado personalizado. Me gustaría llevar esto a Three.JS con el sombreador de nodos.

Creo que MeshPhongMaterial, MeshPhysicalMaterial y otros pueden basarse fácilmente en NodeMaterial a través de una interfaz para compatibilidad con versiones anteriores o solo proxy.

ACTUALIZADO
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_postprocessing_nodes.html

Ejemplo de sintaxis para usos UV1 o UV2 para textura:

var usesUv2 = true;
var isLightmap = false;

var t = new THREE.NodeTexture( texture, new THREE.NodeUV( usesUv2 ) );

var nodemat = new THREE.NodePhongMaterial();
if (isLightmap) nodemat.light = t;
else nodemat.color = t;
nodemat.build(); // build shader

También estoy haciendo un editor, actualmente esta sería la interfaz. El color es el albedo y la transformación es la posición del vértice.
editor

También me estoy ocupando de que se pueda usar en un sombreado diferido. Ahora crearé entradas de reflexión y refracción.

Estaremos compartiendo las novedades con el PR, sugerencias, pruebas y mejoras son bienvenidas: +1:

Enhancement

Comentario más útil

Bien, el soporte de TS está listo con la próxima versión R017 🙌

Todos 161 comentarios

¡Interesante!

@sunag Estamos muy interesados ​​en algo como esto. ¿Cómo puedo ayudar? Puedo agregar soporte para Standard al menos.

Me interesa crear gráficos bastante arbitrarios, de modo que los nodos intermedios también tomen entradas. Entonces puede tener un gráfico que se ve así:

Una textura (tex1, uv1)
Textura B (tex2, uv2)
Mezcla C (modo A, B)
D Ruido (param1, param2)
Mezcla E (modo C, D)

Y luego use ese nodo final E, como entrada a un Material.

Entonces es muy arbitrario, no se limita solo a las texturas.

Mi objetivo sería ayudar a crear esto en las próximas semanas, con suerte colaborando contigo en la próxima semana más o menos si es posible. Estaba buscando hacer esto a través de la biblioteca de shadergraph aquí: https://github.com/mrdoob/three.js/issues/7339 Pero creo que lo creo directamente dentro de ThreeJS. Realmente cualquier solución es buena siempre que sea flexible y funcione.

Estoy leyendo tu código, está muy bien diseñado. Tengo algunos comentarios iniciales. ¿Podría iniciar un PR usando su código como base para comenzar a colaborar en él?

(1) Haría que el material resolviera las referencias. Básicamente, las referencias tendrían nombres que le pedirían a su material que resolviera, y el material devolvería un fragmento de código sobre cómo acceder a esos datos. Esto también permitiría al material saber qué variables (uniformes / variaciones) se utilizan los nodos, para que pueda optimizarlos adecuadamente. Esto también permite que diferentes materiales resuelvan las referencias de manera diferente, lo que hace que los nodos sean más portátiles, en lugar de tener que saber cómo implementar los materiales, especialmente cuando hay diferencias entre las implementaciones de fragmentos y vértices.

(2) Intento usar el objeto GeometryContext que creé en el refactor de luces, da acceso consistente a muchas de las variables locales requeridas. Pero, por supuesto, eso puede resolverse con el propio material.

(3) He tenido UV solo como otra referencia, que se resuelve con el material. Y tendría que NodeTexture debería tomar una entrada de nodo, permitiendo así UV generados por procedimientos.

(4) Llamaría a NodeCube, NodeTextureCube para que sea coherente con el resto de Three.JS. Y eliminaría la lógica de cómo hacer los rayos de él. Pero me gusta la idea de mapas de cubo estándar, por lo que en realidad no pondría la consulta de entorno para especular o difusa en los nodos, sino que tendría eso en el material phong base, y solo puede controlar el normal utilizado para la consulta, o el el resultado del mapa de cubos en sí mismo (lo que permite que sea un color determinado por procedimientos). ¿Tiene sentido? Entonces tendría lo normal enchufable en el material y la textura del cubo enchufable (consultable por una dirección y sesgo / lod, y devuelve un color). Por lo tanto, se puede proporcionar una textura de cubo al mapa de irradiancia y otra al mapa especular. Podemos intercambiar cierto sampleCube con la función cubeToUV2 @tschw 's como un simple intercambio de nodo.

(5) Intentaría agregar una NodeFunction que le permita a uno llamar funciones arbitrarias con parámetros como una adición a su NodeOp (o tal vez podrían fusionarse de alguna manera).

(6) Me desharía de todas las clases individuales detalladas de NodeNormal, NodeTransform, NormalMap, etc. y solo tendría algunos constructores simples que crean una NodeReference con un nombre que el material resuelve según corresponda. NodeReference podría resolver uniformes, variaciones y valores calculados en el sombreador.

(7) No entiendo la diferencia entre NodeEnvironment y NodeCube. Creo que NodeEnvironment puede estar incompleto.

(8) Es confuso que NodePhong no se derive de NodeMaterial. Aunque veo que NodeMaterial se deriva de ShaderMaterial. Me pregunto si llamó a la derivada directa de ShaderMaterial, GraphMaterial (o NodeGraphMaterial) que tendría más sentido, porque todos los nodos juntos forman un gráfico, y es el gráfico el que se convierte en el material, no en un nodo individual.

(9) Sugeriría quizás alguna terminología más variada. Llamaría al nodo raíz, MaterialNode, y se podría derivar PhongMaterialNode de él. Tengo Vector3Node, FloatNode, etc. derivado de ValueNode, no necesariamente constante, sino solo un valor. Por lo tanto, uno podría canalizar tres FloatNodes a un Vector3Node. Creo que puede tener un ayudante que declararía cada una de estas una línea más o menos en lugar de las 10 más o menos actualmente.

(10) Movería el nombre "Nodo" desde el principio de los nombres de las clases hacia atrás porque así es en el resto del proyecto ThreeJS.

(11) Crearía la nueva clase MaterialNode y se inicializaría con una lista de uniformes y variaciones. Por defecto, sería capaz de resolver esto y también realizar un seguimiento de lo que se ha resuelto para que uno pueda realizar un seguimiento de las funciones que se necesitan. Por lo tanto, uno podría tener una resolución limitada en el PhongMaterialNode derivado que resolvería los casos especiales y dependería de la clase subyacente para hacer los simples (variaciones, uniformes).

(12) Estoy un poco confundido entre la diferencia entre NodePhong y NodePhongMaterial. No me di cuenta de que había ambos hasta ahora.

(13) hay un código como este:

THREE.NodeGLPosition.prototype = Object.create( THREE.Node.prototype );
THREE.NodeGLPosition.prototype.constructor = THREE.NodeGLPosition;

THREE.NodeGL.prototype.generate = function( material, shader ) {

Pero por encima de este fragmento ya definió generate para NodeGL y no definió uno para NodeGLPosition , por lo que creo que es un error de copiar-pegar-editar.

(14) Me desharía de NodeReflectUVW y NodeRefractVector y, en su lugar, haría de esto algo que uno pueda solicitar del material a través de una resolución de referencia. Calcular un vector de reflexión es sencillo. Lo he agregado a GeometryContext en mis ramas experimentales de ThreeJS no fusionadas.

(15) La forma en que implementaría la reflexión y la refracción sería tenerlas como entradas de color en el Material. Uno resolvería Refect, ReflectLOD y Refract, RefractLOD de la manera simple en que resolvería cualquier variable, y luego los pasaría al equivalente del cubo de textura de uno (procedural o basado en samplerCube) y luego pasaría el color resultante a Material. ¿Así es como lo estabas haciendo?

(16) Estoy confundido acerca de la entrada de luz; por lo general, uno no tiene luces que se puedan enchufar, sino que los parámetros de luz están completamente definidos en la clase de luz. ¿Supongo que necesita esta flexibilidad adicional? ¿Cómo lo imaginas?

@bhouston woow, muchas gracias por sus comentarios.
Necesitaré varias publicaciones para responder :)

Me interesa crear gráficos bastante arbitrarios, de modo que los nodos intermedios también tomen entradas. Entonces puede tener un gráfico que se ve así:
Una textura (tex1, uv1)
Textura B (tex2, uv2)
Mezcla C (modo A, B)
D Ruido (param1, param2)
Mezcla E (modo C, D)

Actualmente la sintaxis es como esta. Ejemplo animado de compensación Uv1:
Creo que NodeMaterial a MaterialNode y THREE.PhongMaterialNode también sería mejor.

var uv2 = false;
var uv_offset = new THREE.NodeFloat(0);     
var uv = new THREE.NodeOperator( '+', new THREE.NodeUV( uv2 ), uv_offset);
var texture = new THREE.NodeTexture( imgTexture, uv );

nodematerial.color = t;

// onUpdate
uv_offset.number += .01;

Creo que invierta el orden con su sugerencia para mejorar (modo, A, B) a (A, B, modo). Estoy en el proceso de creación de mapas reflejos, mapas de cubos y otros ...

El entorno y Cubemap están incompletos.

Actualmente los errores pueden ocurrir más debido a que el convertidor de formato aún no está terminado. Esto es responsable de la conversión de vectores. vec3 a vec4 o vec4, por ejemplo.

https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/index.html#L365

Una "textura" de mezcla, por ejemplo: (no he probado este código)
Se puede implementar en el mismo de un THREE.NodeOperator

https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/index.html#L1105

THREE.NodeBlend = function( a, b, mode ) {

    THREE.NodeInput.call( this, 'blend' );

    this.mode = mode;
    this.a = a;
    this.b = b;

};

THREE.NodeBlend.prototype = Object.create( THREE.NodeInput.prototype );
THREE.NodeBlend.prototype.constructor = THREE.NodeBlend;

THREE.NodeBlend.prototype.generate = function( material, shader, output ) {

    var a = this.a.build( material, shader, output );
    var b = this.b.build( material, shader, output );

    switch(this.mode)
    {
        case 'multiply':

            return this.format( '(' + a + '*' + b + ')', this.a.type, output);

            break;
    }

    return a;

};

.generate () es el responsable del generador de código. Los códigos de cálculo se almacenan en una caché si desea utilizarlos en más de una entrada sin perder rendimiento.

Todavía no configuro punteros o constantes para la optimización ...

La compilación se realiza mediante propagación en build () para el código de vértice y fragmento.

¿Puedo ponerte como colaborador? Si desea editar el código de alguna manera, también estaré trabajando en él.

¿Puedo ponerte como colaborador? Si desea editar el código de alguna manera, también estaré trabajando en él.

¡Gracias! Le haré RP a los suyos para que pueda aprobar los cambios.

Te agregué (así como a @mrdoob , @WestLangley y @tschw) a un proyecto paralelo mío que intenta definir un conjunto de nodos reutilizables y definiciones de materiales que se pueden transferir entre varias representaciones. Se puede asignar a este sistema de gráficos de sombreado que ha creado.

No creo que debas prestar atención al repositorio al que te acabo de dar acceso si no quieres. Es lo que me interesa implementar además de esto.

(2) Intento usar el objeto GeometryContext que creé en el refactor de luces, da acceso consistente a muchas de las variables locales requeridas. Pero, por supuesto, eso puede resolverse con el propio material.

Deseo que las luces sean un LightNode. Mi preocupación es aprovechar el código ya desarrollado para Three.JS.

(3) He tenido UV solo como otra referencia, que se resuelve con el material. Y tendría que NodeTexture debería tomar una entrada de nodo, permitiendo así UV generados por procedimientos.

Puede reemplazar UV a un vec2, ¿sería esto?

(5) Intentaría agregar una NodeFunction que le permita a uno llamar funciones arbitrarias con parámetros como una adición a su NodeOp (o tal vez podrían fusionarse de alguna manera).

esto sería genial. principalmente para un BlendNode.

(6) Me desharía de todas las clases individuales detalladas de NodeNormal, NodeTransform, NormalMap, etc. y solo tendría algunos constructores simples que crean una NodeReference con un nombre que el material resuelve según corresponda. NodeReference podría resolver uniformes, variaciones y valores calculados en el sombreador.

En esta línea de pensamiento, creo que MaterialNode podría ser una base de material Phong y material físico.

(7) No entiendo la diferencia entre NodeEnvironment y NodeCube. Creo que NodeEnvironment puede estar incompleto.

Todavía no puedo terminar estos nodos.

(8) Es confuso que NodePhong no se derive de NodeMaterial. Aunque veo que NodeMaterial se deriva de ShaderMaterial. Me pregunto si llamó a la derivada directa de ShaderMaterial, GraphMaterial (o NodeGraphMaterial) que tendría más sentido, porque todos los nodos juntos forman un gráfico, y es el gráfico el que se convierte en el material, no en un nodo individual.

NodeMaterial sería el material del nodo raíz, es necesario utilizar un nodo para vértice y fragmento. NodePhong es híbrido y NodePhongMaterial es solo una clase de proxy. Esto luego se puede fusionar.

(9) Sugeriría quizás alguna terminología más variada. Llamaría al nodo raíz, MaterialNode, y se podría derivar PhongMaterialNode de él. Tengo Vector3Node, FloatNode, etc. derivado de ValueNode, no necesariamente constante, sino solo un valor. Por lo tanto, uno podría canalizar tres FloatNodes a un Vector3Node. Creo que puede tener un ayudante que declararía cada una de estas una línea más o menos en lugar de las 10 más o menos actualmente.

Suena bien.

(16) Estoy confundido acerca de la entrada de luz; por lo general, uno no tiene luces que se puedan enchufar, sino que los parámetros de luz están completamente definidos en la clase de luz. ¿Supongo que necesita esta flexibilidad adicional? ¿Cómo lo imaginas?

Esto sería para el mapa de luz o un posible LightNode.

Esto sería para el mapa de luz o un posible LightNode.

Me gusta la idea de un mapa de luz enchufable porque uno podría definir los UV explícitamente. :)

@bhouston Corregimos varias correcciones hoy en este archivo: pero aún
https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/three.node.js

Este es el patio de recreo que estoy creando: arte: Texturas y botones es un arrastrar y soltar, funciona solo en Chrome

http://sea3d.poonya.com/flow/

¡Cosas increíbles! ¡Santo cielo! Es hermoso.

¿Sería posible compartir el código de manera que yo también pueda contribuir? ¿Como relaciones públicas públicas o algo así?

Estás trabajando con el proyecto Sea3D aquí, ¿verdad?

https://github.com/sunag/sea3d/tree/gh-pages/Labs/Three.JS-NodeMaterial

¿Entonces puedo dividirlo y empezar a contribuir? ¿Aceptarías relaciones públicas? ¿Cómo podemos colaborar de forma eficaz?

No he preguntado, pero a @mrdoob probablemente (?)

¡Definitivamente!

¿Entonces puedo dividirlo y empezar a contribuir? ¿Aceptarías relaciones públicas? ¿Cómo podemos colaborar de forma eficaz?

Por supuesto, creo que su ayuda sería increíble. También tengo que traer otros tipos de nodos, como saturación, ruido como sugieres.

Estás trabajando con el proyecto Sea3D aquí, ¿verdad?

Creo que en hacer un PR para Three.JS con ejemplos para que todo esto esté definido.

@mrdoob ¿Qué

Es un tipo de material, por lo que debería ser THREE.NodeMaterial .

un ejemplo de sombreador de borde
flow-rimshader-example

ejemplo de reflexión de área
flow-areareflection

¡Esto es increíble @sunag!

@bhouston gracias! ¿Cree que será difícil convertirlo a R74?

¡Este es un trabajo muy impresionante! Me recuerda a Shaderforge .

¡Muy buen trabajo hasta ahora!

@sunag Será un poco de trabajo, pero me gustaría ayudar y la mayoría de los grandes cambios estructurales en el código de sombreado R74 son culpa mía. :)

se ve hermoso y divertido para jugar: ¿podría ofrecer como inspiración el editor de nodos de Blender3D? Lo encuentro súper eficiente, incluso hay algunos videos geniales en PBR a través del sistema de nodos de Blender y qué nodos serían más útiles para crear para hacer PBR desde cero:

https://www.youtube.com/playlist?list=PLlH00768JwqG4__RRtKACofTztc0Owys8

Será un poco de trabajo, pero me gustaría ayudar y la mayoría de los grandes cambios estructurales en el código de sombreado R74 son culpa mía. :)

@bhouston ¡ Guau! Estaba mucho más limpio con los cambios de la nueva r74. Terminé la primera parte y aún faltaba StandardMaterial. Cualquier problema que publique aquí :) Gracias
https://github.com/sunag/sea3d/commit/d544ad7993272348f8bbea2337cdceb52159a6a8

Otra cosa que todavía nos falta es la refracción. Realmente me gusta usar el búfer de renderizado en lugar de un Cubemap RTT por defecto. Sería mucho más eficiente.

@GGAlanSmithee Tengo algunas referencias de ShaderFX que soy un gran fan. Shader Forge y UE4 principalmente también son grandes referencias.

@richardanaya Videos increíbles. ¡Gracias!

@mrdoob ¿ En qué carpeta recomiendas poner estos archivos? three.js root (src / materials / node) o en ejemplos?
https://github.com/sunag/sea3d/tree/gh-pages/Labs/Three.JS-NodeMaterial/node

Aún así, recomendaría llamar a esto un "Gráfico de material" o en estilo ThreeJS invertido, un "Material gráfico". O si insiste en usar el término "Nodo", lo llamaría "NodeBasedMaterial". Ambos nombres dejan en claro que el material contiene nodos, en lugar de ser un nodo en sí.

Aún así, recomendaría llamar a esto un "Gráfico de material" o en estilo ThreeJS invertido, un "Material gráfico". O si insiste en usar el término "Nodo", lo llamaría "NodeBasedMaterial". Ambos nombres dejan en claro que el material contiene nodos, en lugar de ser un nodo en sí.

Para mí ambos se ven bien. Dejo la decisión a @mrdoob ¿qué os parece?

Por cierto, @sunag , me quedaría con cubemaps para refracciones si es posible, es más fácil y más preciso. Creo que así es como casi todo el mundo lo hace y también necesitamos el material RTT para reflejos precisos. Creo que solo necesita ser un renderizado rápido a 128 ^ 2 o 256 ^ 2.

Por cierto, @sunag , me quedaría con cubemaps para refracciones si es posible, es más fácil y más preciso. Creo que así es como casi todo el mundo lo hace y también necesitamos el material RTT para reflejos precisos. Creo que solo necesita ser un renderizado rápido a 128 ^ 2 o 256 ^ 2.

Sí, podemos dejar ambos. sería una discusión entre rendimiento x precisión. Aún para la refracción del plano (vidrio, agua), recomiendo el búfer en lugar de un CubeMap (en la mayoría de los casos).

@mrdoob ¿ En qué carpeta recomiendas poner estos archivos? three.js root (src / materials / node) o en ejemplos?

Lo pondría en ejemplos para empezar. Una vez que esté bien definido, luego podemos moverlo a src 😊

Aún así, recomendaría llamar a esto un "Gráfico de material" o en estilo ThreeJS invertido, un "Material gráfico". O si insiste en usar el término "Nodo", lo llamaría "NodeBasedMaterial".

Para mí ambos se ven bien. Dejo la decisión a @mrdoob ¿qué os parece?

Ya me gusta NodeMaterial ... ¿Quizás NodesMaterial ? NodeGraphMaterial ? @WestLangley alguna sugerencia?

Cambiaría el nombre de los nodos actuales aunque ... NodeColor , NodeFloat , NodeTexture , ... a ColorNode , FloatNode , TextureNode

http://sea3d.poonya.dev/flow/

No puedo hacer que esto se cargue 😐

Lo pondría en ejemplos para empezar. Una vez que esté bien definido, luego podemos moverlo a src: blush:

@mrdoob será genial.

Sin embargo, cambiaría el nombre de los nodos actuales ... NodeColor, NodeFloat, NodeTexture, ... a ColorNode, FloatNode, TextureNode

Lo reenviaré entonces.

esta es la URL local: blush :, prueba esto:
http://sea3d.poonya.com/flow/

@WestLangley alguna sugerencia?

Sugiero THREE.FlowMaterial .

Mi segunda opción sería THREE.CustomMaterial .

Como un espectador completamente al azar. NodeMaterial me suena muy intuitivo, porque así se llaman en Blender3D

Si a @mrdoob le gusta NodeMaterial, podemos seguir con él. :)

NodeMaterial es entonces 😁

¡Este proyecto es genial! Acabo de ver la demostración en Twitter y es muy impresionante.

Me pregunto si los nodos deberían ser algo que entren en tres núcleos. Son muy específicos de implementación. Yo también estoy construyendo un editor de gráficos de sombreado Three.js (aún no lanzado) para ShaderFrog.com, y la solución que tengo es simplemente exportar el código GLSL y todos los metadatos necesarios, como nombres uniformes, en un pequeño archivo JSON y cargarlo con una biblioteca de tiempo de ejecución externa

screen shot 2015-11-20 at 12 05 26 pm

Este editor de gráficos puede trabajar con sombreadores completos analizando su código fuente, lo que significa que no se requieren tipos de nodos de sombreadores específicos. ¿Podría este tipo de NodeMaterial manejarse completamente fuera del núcleo de Three también? Todo lo que realmente tiene que generar es un RawShaderMaterial para que alguien lo use en su propio proyecto.

¿Podría este tipo de NodeMaterial manejarse completamente fuera del núcleo de Three también? Todo lo que realmente tiene que generar es un RawShaderMaterial para que alguien lo use en su propio proyecto.

@DelvarWorld Hola. Sí, en teoría, pero es muy pronto para hacer un buen sombreador a partir de raw. En ese momento es mejor con una interfaz inicial. También ayuda a mantener la compatibilidad con Skin / Morph y otros componentes nativos de Three.JS.

Pensé en señalar un problema menor:
En "Flujo", los conectores no saltan al nivel superior cuando se arrastran nodos unos sobre otros.
Tal vez este tema esté esperando capas o algo aún.

Me pregunto si hay una manera de unificar ambos enfoques. Estoy interesado en un sombreador de múltiples capas y para eso necesita tener múltiples BSDF que contribuyan al resultado final. Esto significa que es necesario separar más el modelo de sombreado; en este momento, está bastante acoplado en el diseño actual de @sunag . Creo que deberíamos ir en una dirección en la que uno no necesita tener un material estándar o Phong especificado, podría ser crudo como lo que tiene @DelvarWorld . Sin embargo, creo que podemos avanzar gradualmente, así que lo que tiene @sunag es un buen comienzo.

Esta no es una respuesta completa, pero hace un tiempo creé una propuesta aproximada para un formato de sombreador portátil que incluye metadatos, como nombres uniformes, sus tipos, su tipo en Three.js, etc. https://github.com /DelvarWorld/ShaderFrog-Runtime/blob/master/THREE_SHADER_FORMAT.md

Todo lo que un sombreador realmente necesita para ejecutarse en un entorno real es el código fuente sin procesar del sombreador (ya que la GPU lo compila) y, para mayor comodidad, qué uniformes puede establecer el usuario con qué valores. Esta propuesta aproximada no incluye ninguna noción de construir un sombreador de manera programática, es solo una entrega simple para GLSL y metadatos. Es compatible con Three.js porque solo tienes que ponerlo en RawShaderMaterial al final.

Actualmente no hay forma de hacer que los sombreadores sean portátiles en Three.js o exportarlos desde cualquier aplicación, que es lo que me dio la idea de proponer un estándar, y creo que podría resolver ambos problemas, ya que estamos construyendo aplicaciones externas. que al final escupe un material predeterminado. También significa que los detalles de implementación de la compilación de combinaciones específicas de un gráfico se dejan en manos de las aplicaciones, no de Three.js.

¿Este estándar de sombreado propuesto tiene un lugar en Three? No tengo ni idea. En este momento, probablemente sea más útil para mí que para el núcleo de Three, ya que Three crea sus propios sombreadores a su manera.

@DelvarWorld Comencé este proyecto en una forma de crear un conjunto estandarizado de nodos de gráficos de sombreado:

https://github.com/OpenMaterialGraph/OpenMaterialGraph

Especificaciones de nodo aquí:

https://github.com/OpenMaterialGraph/OpenMaterialGraph/tree/master/spec/nodes

Especificaciones de BSDF minimalistas aquí:

https://github.com/OpenMaterialGraph/OpenMaterialGraph/tree/master/spec/bsdfs

Sin embargo, esto está orientado hacia el renderizado basado en la física.

Mi sensación es que uno necesita tener un caparazón de un sombreador para ThreeJS que tenga un nivel más alto que un sombreador sin formato pero un nivel más bajo que el sombreador Phong. Básicamente, el sombreador predeterminado podría hacer objetivos de transformación, huesos, etc. Y luego todos estos sombreadores de esquemas de iluminación específicos (Básico, Lambert, Phong, Estándar) usarían esa plantilla. En este momento hay un sombreador de plantilla implícito (incluimos las mismas cosas en cada sombreador), pero creo que podríamos aclarar dónde conectar las cosas. Puede conectar esquemas de iluminación (phong, lambert, básico o multicapa) y puede conectar propiedades a esos esquemas de iluminación que son sus nodos generales.

@bhouston oh bien, parece que tenemos muchos requisitos superpuestos, también conocido como valor predeterminado, nombre para mostrar, descripciones legibles por humanos, etc. No sé lo que depara el futuro, pero sería un cambio moderadamente fácil para mí usar un formato más parecido a lo que propones.

Un formato de sombreado formal tiene mucho sentido. Sin embargo, debería convivir con la lib, para que pueda evolucionar con ella más fácilmente. Para alguien que es bastante nuevo en three.js, ¿hay alguna razón específica por la que tal cosa no existe? Debería ser interesante para el editor al menos.

* EDITAR Tal vez tener la especificación en three.js frustraría su propósito si está destinado a ser consumido por otras tuberías de renderizado.

En este momento, probablemente sea más útil para mí que para el núcleo de Three, ya que Three crea sus propios sombreadores a su manera.

Puede generar el mismo material en otro idioma si realiza modificaciones dentro de THREE.NodeGL.prototype.generate una vez que NodeMaterial (* Flow) es un lenguaje visual. NodeBuilder puede ser la puerta a eso. Actualmente es el intermediario de datos entre nodos.

Limpié un ejemplo de NodeMaterial "raw": todavía puede generar varios errores.
https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/index.html#L179
https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/node/NodeMaterial.js#L9

Creo que avanzar en esto con partículas creadas nodos de raíz. NodePass para Multi-Pass y NodeMaterialD después del PR, ¿qué debo hacer en unos días?

Sugerí un THREE.ShaderFrogLoader en lugar de un sombreador en tiempo de ejecución.

En "Flujo", los conectores no saltan al nivel superior cuando se arrastran nodos unos sobre otros.

@MasterJames ¡ Gracias! Lo estaré mirando.

: +1:

Empecé a crear los ejemplos. Espero terminar esta semana. : sweat_smile:
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html

¿Pensamientos?

@sunag +1: -)

+1!

Esto es tan asombroso. Predeciría las plantas + textura de la pared en lugar del desplazamiento nublado. :) Eso es simplemente hermoso.

Predeciría las plantas + textura de la pared en lugar del desplazamiento nublado.

¿Se refiere al ejemplo de las 'capas'? Sin embargo, publicaré más ejemplos para nosotros.

gpu cuerpo blando
soft-body

Para compararlo con un enfoque diferente, el editor de gráficos Shader Frog ahora está activo y está en la fase de "patear los neumáticos". Me gustaría subrayar que no requiere ningún cambio en el núcleo de Three.js.

ShaderFrog actualmente tiene más poder que los editores de nodos tradicionales. Tiene infinitos tipos de nodos con los que trabajar porque puede analizar y comprender cualquier sombreador . Por ejemplo, para aplicar un reflejo solo a los bordes de un objeto, podría simplemente tomar un sombreador de brillo , que es un sombreador completamente independiente con un sombreador de fragmentos y vértices:

screen shot 2015-12-08 at 1 48 24 pm

... y multiplicarlo por un sombreador de reflexión ...

screen shot 2015-12-08 at 1 49 39 pm

... usando el gráfico de sombreado ...

screen shot 2015-12-08 at 1 50 40 pm

¡Y ta-da! Un sombreador de borde de reflexión .

También puede, por ejemplo, enmascarar dos sombreadores cualesquiera usando cualquier otro sombreador , y así sucesivamente:

screen shot 2015-12-08 at 1 56 03 pm

Tenga en cuenta que el único "tipo de nodo" requerido por este proceso es un nodo múltiple (hay otros en ShaderFrog), que es casi completamente independiente de GLSL. ShaderFrog puede funcionar con cualquier sombreador, por lo que tiene infinitos tipos de nodos. Este enfoque de tecnología avanzada permite esta manipulación independientemente de los cambios de Three.js.

ShaderFrog tiene soporte de exportación de primera clase a Three.js, de forma gratuita. Todo sin modificar el código fuente de Three.js. Sea3D es un producto de terceros, como ShaderFrog. Poner la mecánica de productos de terceros en el núcleo de Three parece una ventaja injusta y no lo entiendo políticamente.

@DelvarWorld Realmente no veo una abstracción de construcción de sombreadores basada en nodos como tecnología específica de terceros. En todo caso, permite que más competidores se involucren en la tecnología de sombreado basada en nodos y todos se beneficien del beneficio adicional del trabajo de los demás (más nodos, construcción optimizada, etc.).

Como programador de gráficos como yo, que comprende los sombreadores a un alto nivel (de herramientas como Blender 3D), pero no a un nivel bajo, la abstracción basada en nodos me parece una excelente manera de interactuar programáticamente con los sombreadores utilizando mis conocimientos de modelado 3D. Entiendo la configuración del nodo para PBR, por ejemplo, pero Dios me ayude si alguna vez quise escribir eso en GLSL.

@DelvarWorld Increíble. Amo al nuevo editor.

@DelvarWorld +1 ¡Muy bonito! : -)

¡Gracias! :)

Realmente no veo una abstracción de construcción de sombreadores basada en nodos como tecnología específica de terceros.

Entiendo la configuración del nodo para PBR, por ejemplo

Parte de mi contraejemplo aquí es que puede obtener ambas cosas de forma gratuita, independientemente de Three.js. Todos los sombreadores de ShaderFrog son de código abierto, por lo que cualquier nodo que se convierta en parte de una implementación de PBR también se puede aprender, editar y mejorar con el tiempo (así como componerse con cualquier otro sombreador, no solo con un subconjunto del núcleo de Three.js). Para mí, el hecho de que todo esto se pueda lograr sin tres cambios significa que es innecesario y difumina la línea entre Three.js, que es una API contenedora de webgl y ahora impulsa las características específicas de implementación. El almacenamiento de datos de nodos de sombreado es muy específico de la aplicación y, hasta donde yo sé, actualmente no existe un formato estándar de editor de nodos común para ningún software. Hacer cumplir uno podría ser perjudicial para otras implementaciones.

@DelvarWorld Según tengo entendido este cambio, ShaderFrog aún podrá funcionar y seguirá pudiendo ir más allá de GraphMaterial si así lo desea. Miré el código fuente de ejemplo para GraphMaterial y pude comprender la simplicidad de cómo funcionaba sin siquiera tener que pensar en una solución / editor de terceros. Como desarrollador de gráficos, me preocupa cómo hacer mediante programación materiales que impresionen rápidamente, creo que estos son una preocupación propia de ThreeJS.

Creo que NodeMaterial y Flow tienen dos enfoques diferentes. Flow y ShaderFrog son soluciones de terceros editores visuales actualmente en código cerrado (creo que principalmente en artistas para esto) otro lado NodeMaterial es un editor de sombreado de código abierto para programadores hecho en Three.JS. Estoy de acuerdo con @richardanaya en el sentido de que ShaderFrog puede ir más allá de NodeMaterial si lo desea. Al igual que creo que Flow no necesita ser solo un editor de material. Realmente espero grandes mejoras de ShaderFrog en el futuro como de costumbre.

wip: cáustico-voronoi
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html
caustic

@sunag Esta noche estaba revisando tu código fuente. Me encanta de verdad. Algunos comentarios rápidos de mis lecturas esta noche:

  • Me gustaría ver un PR lo antes posible. Puedo ayudar. :)
  • Puede ser genial permitir atributos arbitrarios en lugar de solo los estándar (uv, uv2, normal, posición, etc.) Sé que muchos sombreadores pueden beneficiarse de los vec4s tangentes, más que solo 2 uvs y también colores múltiples atributos. Por lo tanto, generalizaría la needPosition en una matriz requiredAttributes o algo así.
  • Sugeriría alguna organización de los nodos en el NodeMaterial principal, los BRDF (Phong, Standard, etc.), los nodos de textura (NodeCubeTexture, NodeTexture), los nodos de acceso (?) (NodePosition, NodeNormal), los nodos matemáticos (NodeOperator, etc. ), nodos de utilidad (NodeSwitch, ...) y extra (?) (NodeVelocity, ...) Creo que esto ayudaría mucho.
  • Sería bueno tener accesores de matriz para matrices de proyección, vista y mundo.
  • Le faltan algunos de los operadores: % ^ & << >> ~ |
  • No estoy seguro de ver el valor en NodePhongMaterial cuando la clase es tan pequeña, solo haría que los usuarios tuvieran que crearla usando el nodo NodePhong combinado con un NodeMaterial (aunque todavía no me gusta ese nombre, GraphMaterial se siente mucho más naturaleza para mí, pero puedo vivir con eso.)
  • Llamaría NodeTimer -> NodeTime ... pero nuevamente preferencia personal.
  • Me pregunto si hay alguna forma de combinar muchos de los nodos variables en uno como lo ha hecho con NodeMath #, NodeOperator. Estos parecen muy similares: NodeViewPosition, NodeWorldPosition, NodeViewNormal, NodeTransformedNormal, NodeTransformedPosition, NodeProjectPosition ...
  • Me gustaría ver el conjunto de argumentos opcionales para NodeMath #, NodeOperator en un formulario que puede ser una lista, de modo que uno pueda rellenar fácilmente un cuadro desplegable con él. En este momento, debido a que son miembros que acaban de sacar provecho de las clases, es un poco más difícil identificarlos. No estoy seguro de una buena solución que sea conveniente para la codificación. Tal vez solo los recopile en una lista después de sus definiciones como miembros de la clase, así que simplemente agregue esas listas.
  • NodeTransformedNormal, NodeTransformedPosition me resulta difícil averiguar qué son sin mirar el código. ¿Están en el espacio del mundo, el espacio de visión, el espacio de objetos? "Transformado" es un término muy genérico, que simplemente significa multiplicado por una matriz. Veré el código para ellos ahora ...
  • Permitiría que NodeUV y NodeColor tomen un índice en lugar de limitarse a 2 y 1 canal respectivamente. Una vez más, me gustaría que estos se hicieran genéricos, en realidad se pasa una cadena o uno de varios ajustes preestablecidos en lugar de tenerlo codificado en un conjunto de canales específicos. Todavía puede tener algunas rutas de código dedicadas para algunas variables, pero recurriría a algo genérico para los nombres que no reconoce para el manejo de casos especiales.

Más comentarios:

  • Me gustaría tener un gráfico con más de un BRDF, básicamente dos BRDF estándar y luego hacer la preservación de energía entre ellos. Una vez que obtenga el PR, me gustaría agregar esta funcionalidad. Hará que el sistema sea más genérico y más potente.

@bhouston ¡Guau! ¡Gracias!

Se revisaron los atributos de solicitud, organización de carpetas, NodeTime, NodePosition, NodeNormal, NodeView. También se agregaron +3 ejemplos.

en operadores y matriz tenemos que agregar compatibilidad con conversiones integer y matrix . Para que esto se haga de forma automática como en float / vectors #. Tenemos suficiente trabajo para las próximas actualizaciones ..: sweat_smile:

Mañana haré el PR. Tengo que repasar algunas cosas todavía.

@sunag :

Creo que esto es un error:

addGui( 'metalnessA', roughnessA.number, function( val ) {

                        roughnessA.number = val;

                    }, false, 0, 1 );

Creo que esto es un error:

¡Gracias!

Me mareé al ir a la página de ejemplo y ver un gráfico de nodo PBR <3

¡Niice!

Iba a sugerir el uso de los nodos para el posprocesamiento, pero estaba esperando a que terminara la primera parte. ¡Maldita sea, eso es hermoso!

NodeMaterial rev 5 + LightNode

http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html

Piel
nodematerial-rev5-skin

Sombreado de Toon
nodematerial-rev5-toon

++ color-adjustment y plush ejemplos.

¡Niiice!

subsurface scattering : sweat_smile:

Este es un tipo de sombreador que puede funcionar en futuras actualizaciones.

http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html

sss-img1
sss-img2

😮!

¡Gracias por el increíble NodeMaterial!

Tengo varios comentarios / errores:

  • el espacio en blanco final rompe el nodo de la función
var n1 = new THREE.FunctionNode(" float mul_2_float(float x) { return x*2.0; }"); // problem
var n2 = new THREE.FunctionNode("float mul_2_float(float x) { return x*2.0; }"); // ok
  • problema con el parámetro int en el nodo de función

ejemplo de trabajo con parámetro float:

var floatFuncNode= new THREE.FunctionNode("float mul_2_float(float x) { return x*2.0; }");

var funcCallNode = new THREE.FunctionCallNode(floatFuncNode);
funcCallNode.inputs.x = new THREE.FloatNode(0.2);

var colorResNode = new THREE.OperatorNode(new THREE.ColorNode(0x00ff00),
    funcCallNode, THREE.OperatorNode.MUL);

var mat = new THREE.PhongNodeMaterial();
mat.color = colorResNode;

ejemplo roto con el parámetro int:

var intFuncNode= new THREE.FunctionNode("float mul_2_int(int x) { return float(x)*2.0; }");

var funcCallNode = new THREE.FunctionCallNode(intFuncNode);
funcCallNode.inputs.x = new THREE.IntNode(1);

var colorResNode = new THREE.OperatorNode(new THREE.ColorNode(0x00ff00),
    funcCallNode, THREE.OperatorNode.MUL);

var mat = new THREE.PhongNodeMaterial();
mat.color = colorResNode;
  • sugerencia: pasar parámetros de función en el constructor FunctionCallNode
//current:
var funcCallNode = new THREE.FunctionCallNode(floatFuncNode);
funcCallNode.inputs.param1 = new THREE.FloatNode(1);
funcCallNode.inputs.param2 = new THREE.ColorNode(0x0f0f0f);

// proposed:
var funcCallNode = new THREE.FunctionCallNode(floatFuncNode, 
    { param1: new THREE.FloatNode(1), param2: new THREE.ColorNode(0x0f0f0f) } );

// and, i think suitable in some cases: 
var funcCallNode = new THREE.FunctionCallNode(floatFuncNode, 
    [ new THREE.FloatNode(1), new THREE.ColorNode(0x0f0f0f) ] );
  • ¿PhongNodeMaterial es compatible con el mapa de relieve?

algunas notas más:

  • problema con PositionNode.LOCAL en el sombreador de fragmentos en NodeMaterial "sin procesar":
var material = new THREE.NodeMaterial(
        new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.PROJECTION ) ),
        new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.LOCAL ) )
    );

sombreadores resultantes:

varying vec3 vPosition;
void main(){
gl_Position = (projectionMatrix * modelViewMatrix * vec4( position, 1.0 ));
vPosition = transformed;
}
varying vec3 vPosition;
void main(){
gl_FragColor = vec4(vPosition,0.0);
}

Probablemente la funcionalidad "transformada" debería trasladarse de los materiales de nodo Phong / Standart a NodeMaterial

  • Uso de ConstNode
    var material = new THREE.NodeMaterial(
        new THREE.RawNode( 
            new THREE.OperatorNode(
                new THREE.PositionNode( THREE.PositionNode.PROJECTION ),
                new THREE.ConstNode("float TWO = 2.0;"),
                THREE.OperatorNode.MUL)
            ),
        new THREE.RawNode( new THREE.ColorNode( 0xff0000 ) )
    );

En ese caso, el sombreador de resultados contiene
gl_Position = ((projectionMatrix * modelViewMatrix * vec4 (posición, 1.0)) * DOS);
pero DOS constantes no se declaran. ¿Es mi error o error?
Además, ConstNode es sensible al punto y coma, por lo que "float TWO = 2.0" no se analiza.

¡Gracias @dimarudol ! Si quieres sentirte libre con las notas lo antes posible harás la nueva revisión.

pero DOS constantes no se declaran. ¿Es mi error o error?

Consideraré esta forma de uso y en material, por ejemplo material.include( node )

En ese momento, pruebe una constante global:

var TWO = new THREE.ConstNode("float TWO = 2.0;");
THREE.NodeLib.add( TWO ); // global

 var material = new THREE.NodeMaterial(
        new THREE.RawNode( 
            new THREE.OperatorNode(
                new THREE.PositionNode( THREE.PositionNode.PROJECTION ),
                TWO,
                THREE.OperatorNode.MUL)
            ),
        new THREE.RawNode( new THREE.ColorNode( 0xff0000 ) )
    );

Hola @sunag , he estado jugando con Sea3d Flow y se ve muy bien. Solo quería preguntar si hay un repositorio oficial en algún lugar para ello.
Saludos.

Hola @rraallvv , todavía no, ya está listo. Lo antes posible publico la noticia.

Gracias @sunag , es muy apreciado.

¡Hola @sunag ! ¡Hiciste un muy buen trabajo!
Tengo una pregunta: para mi proyecto, sería genial usar la estructura de sus nodos, pero necesito el color de cada vértice (y valores flotantes personalizados por vértice), pero en su sistema de nodos solo tiene colorNode y floatNode aplicados a toda la malla .. ¿Crees que hay una manera de implementar fácilmente algo como un bufferColorNode (usando THREE.BufferAttribute)?

Por ejemplo, tengo esta escena:

screenshot from 2016-08-31 16 27 06

Cada vértice tiene su propio color. Es posible con THREE.BufferAttribute y THREE.ShaderMaterial pero no hay equivalente en su código.

Necesitaría algo como:
`let material = new THREE.StandardNodeMaterial ();
let texColorMap = new THREE.TextureNode (new THREE.TextureLoader (). load ("colorMap.jpg"));
let customData = new THREE.BufferFloatNode (new Float32Array (...), "data"); // El segundo parámetro es el nombre del atributo

let colorMap = new THREE.FunctionNode ([
"vec3 colorMap (sampler2D texColorMap, datos flotantes) {",
"return vec3 (texture2D (texColorMap, customFunc (data)));", // customFunc devuelve un vec2 dependiendo de los datos
"}"
] .unir ("n"));

let colorMapCall = new THREE.FunctionCallNode (colorMap);
colorMapCall.inputs.texColorMap = texColorMap;

material.color = colorMapCall;
material.build (); `

Por cierto, parece que no puedo usar los parámetros sampler2D para FunctionNode ...

Me estoy perdiendo de algo ?
Creo que podría ayudar si fuera necesario :)

@martinRenou ¡Gracias! Hmm, tal vez algo como por ahora:

bufferGeometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 4 ) );
...
colorMapCall.inputs.data = new THREE.ColorsNode(); // send color.x to float slot

Todavía no había pensado en asignar un atributo de geometría dinámica con node. Pero creo que es una buena idea ... tal vez algo como THREE.BufferAttributeNode ...

@sunag gracias por tu respuesta :)
Lo intentaré. Si está bien para usted, comenzaré a trabajar en un THREE.BufferAttributeNode, por ahora todavía estoy leyendo su código y tratando de entender la estructura.

  1. Con respecto a THREE.FunctionNode, como dije, realmente necesito establecer un sampler2D en mis parámetros, ya que se usa como un mapa de colores. El color del píxel se calcula con texture2D () y el segundo parámetro de texture2D () se calcula usando mis datos personalizados (que es, por ejemplo, una temperatura).
    Entiendo que la idea de usar parámetros vec3 era para ser amigable con los usuarios, pero FunctionNode también podría admitir parámetros sampler2D, ¿no crees?
  2. Además, THREE.FunctionNode solo escribe en el sombreador de fragmentos, pero ¿no sería bueno poder escribir también en el sombreador de vértices?

Este sería mi caso de uso, se llama IsoColor, porque el color corresponde a un dato (temperatura, presión ...) rojo -> alta temperatura, azul -> baja temperatura:
screenshot from 2016-09-01 17 29 58

  1. Estoy pensando en escribir un THREE.IsoColorNode (que reemplazaría el FunctionNode de mi diagrama), y otros nodos que serían muy interesantes para visualizaciones científicas. ¿Estás interesado en eso? @mrdoob , ¿también te interesaría?

Con respecto a THREE.FunctionNode, como dije, realmente necesito establecer un sampler2D en mis parámetros, ya que se usa como un mapa de colores. El color del píxel se calcula con texture2D () y el segundo parámetro de texture2D () se calcula usando mis datos personalizados (que es, por ejemplo, una temperatura). Entiendo que la idea de usar parámetros vec3 era para ser amigable con los usuarios, pero FunctionNode también podría admitir parámetros sampler2D, ¿no crees?

¡Entiendo tu necesidad ahora! Crearé un PR para esta y otras notas del

Además, THREE.FunctionNode solo escribe en el sombreador de fragmentos, pero ¿no sería bueno poder escribir también en el sombreador de vértices?

No probé esto, pero supongo que sí.

Agregué más dos ejemplos:

  • sampler2D están en triangle-blur ejemplo
  • custom BufferAttribute están en custom-attribute ejemplo

Está funcionando, pero todavía daré un código pulido ...

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

Guau ! Realmente hiciste un buen trabajo, a mí también me está funcionando: sonríe:

¡Gracias de nuevo por tu trabajo!

Hola @sunag ,

Por ahora no podemos tener FunctionNode con el tipo "void" ya que necesitamos enviarlo al material como parámetro (color, alpha ...). Por ejemplo, si quiero implementar un FunctionNode de plano de recorte, todo lo que quiero hacer es escribir una parte de sombreado como esta:

void clipPlane(vec4 plane){
 if(dot(position, plane.xyz) > plane.w) discard;
}

Pero eso no es posible dárselo al material ... Una solución sería devolver un flotador que sea canal alfa, pero que no esté limpio y optimizado. ¿No crees que sería genial agregar algunas funciones de vacío a un material como ese?

var clipPlane = new FunctionNode([
"void clipPlane(vec 4 plane){",
" if (dot(position, plane.xyz) > plane.w) discard;",
"}"].join("\n"));
var clipPlaneCall = new FunctionCallNode(clipPlane);
clipPlaneCall.inputs.plane = myVec4Node;

var threshold = new FunctionNode([
"void threshold(float upperBound, float lowerBound, float data){",
" if(data < lowerBound) discard;",
" if(data > upperBound) discard;",
"}"].join("\n"));
var thresholdCall = new FunctionCallNode(threshold);
thresholdCall.inputs.upperBound = myFloatNode1;
thresholdCall.inputs.lowerBound = myFloatNode2;
thresholdCall.inputs.data = myAttributeNode;

var myMaterial = new StandardNodeMaterial();
myMaterial.color = ...
myMaterial.alpha = ...

// voidFunctions is not a good name I'm not inspired...
myMaterial.voidFunctions = [clipPlaneCall, thresholdCall];

Para un ejemplo más de "diseño", si quiero hacer agujeros en mi tetera con esta textura:
wood-hole-texture
Me gustaría hacer algo como eso:

var holes = new FunctionNode([
"void holes(vec3 texColor){",
" if (/*texColor too much dark*/) discard;",
"}"].join("\n"));
var holesCall = new FunctionCallNode(holes);
holesCall.inputs.texColor = new TextureNode(LoadTexture("holes-text.jpg"));

var myMaterial = new StandardNodeMaterial();
myMaterial.voidFunctions = [holesCall];
myMaterial.side = THREE.DoubleSide;

Otra cosa es que no tenemos control sobre el orden de las funciones en los sombreadores. Si tengo funciones que no son conmutativas, no tengo control sobre el resultado ...

veamos este ejemplo:

var transparencyPlane = new FunctionNode([
"float transparencyPlane(vec 4 plane){",
" if (dot(position, plane.xyz) > plane.w) return 0.5.;",
" return 1.;",
"}"].join("\n"));
var transparencyPlaneCall = new FunctionCallNode(transparencyPlane);
transparencyPlaneCall.inputs.plane = myVec4Node;

var displacement = new FunctionNode([
"vec3 displacement(vec3 vector){",
" return position + vector;",
"}"].join("\n"));
var displacementCall = new FunctionCallNode(displacement);
displacementCall.inputs.vector = myVec3Node;

var myMaterial = new StandardNodeMaterial();
myMaterial.transform = displacementCall;
myMaterial.alpha = transparencyPlaneCall;

Si un punto está detrás del plano de transparencia y viene más allá debido al desplazamiento, en el caso de que se llame a "transparenciaPlaneCall" antes de "displacementCall" alpha = 1., y en el caso de que se llame después de alpha = 0.5.
Así que me gustaría establecer el orden de las llamadas a funciones ... ¿Sabes a qué me refiero?

Hola @martinRenou

Hmm, alrededor de void funciones tal vez ProxyNode para usar en la ranura porque esto necesita seguir un orden o inicializarse al principio o al final del código, tal vez functionsStart o functionsEnd ranuras ...

El uso de la ranura alpha si alpha es 0 se descarta automáticamente.
https://github.com/mrdoob/three.js/blob/dev/examples/js/nodes/materials/PhongNode.js#L180

Entonces me gustaría establecer el orden de las llamadas a funciones ...

Existe una secuencia, consulte aquí:
https://github.com/mrdoob/three.js/blob/dev/examples/js/nodes/materials/PhongNode.js#L122

El orden de la función se realiza automáticamente usando el algoritmo dependencies simple, debe colocar el FunctionCall en una ranura anterior, color es el primero specular es el segundo, por ejemplo.

Este ejemplo son dos códigos de sombreado diferentes: fragment a transparencyPlaneCall y vertex a displacementCall .

Me hace pensar que usar variables ( varying y locales) para expandir no entradas y solo const será muy interesante. Quizás un VarNode ...

El uso de la ranura alfa si alfa es 0 se descarta automáticamente.

Lo siento, no lo vi.

El orden de las funciones se realiza automáticamente utilizando un algoritmo de dependencias simples, debe colocar FunctionCall en una ranura anterior, el color es el primero especular y el segundo, por ejemplo.

Entiendo, de hecho, solo quería asegurarme de que se llamara primero a la función que descarta píxeles. Me parece bien usar alpha si lo descartas justo después de mis funciones: smiley:

Este ejemplo son dos códigos de sombreado diferentes: fragmento a transparenciaPlaneCall y vértice a displacementCall.

Derecha ! Entonces ese no fue un buen ejemplo. Mi error.

Hecho r6 - # 9636

Frio ! Gracias por tus respuestas.

Me hace pensar que usar variables (variables y locales) para expandir no entradas y solo const será muy interesante. Quizás un VarNode ...

También suena bien, podría ser interesante poder escribir explícitamente una función en el sombreador de vértices, usar un varNode y usarlo con una función en el sombreador de fragmentos. ¿No te parece?

@sunag
Creo que hay un problema con el uso de AttributeNode con FunctionNode en el sombreador de vértices.

Si tengo un código como este:

var customData = new THREE.AttributeNode("data", "float");

var myFunc = new THREE.FunctionNode([
 "vec3 myFunc(float data){",
 " return vec3(data, 0., 0.);"
 "}"].join("\n"));
var myFuncCall = new THREE.FunctionCallNode(myFunc);
myFuncCall.inputs.data = customData;

material.transform = myFuncCall;

El sombreador está escrito en este orden:

...
varying float nVdata;
attribute float data;
...
float myFunc(float data){
 return return vec3(data, 0., 0.);
}

void main(){
...
transformed = myFunc(nVdata); // We use nVdata but it is not initialized
...
nVdata = data;
...
}

¿Una solución simple sería inicializar nVdata a datos?

También suena bien, podría ser interesante poder escribir explícitamente una función en el sombreador de vértices, usar un varNode y usarlo con una función en el sombreador de fragmentos. ¿No te parece?

¡Sí! La idea es una mejor comunicación con los sombreadores de vértices / fragmentos usando varying como VarNode . Esto encaja muy bien ahora con la función keywords .

Creo un ejemplo mínimo de varying pero todavía no hay ninguna solución para void function .

Creo que hay un problema con el uso de AttributeNode con FunctionNode en el sombreador de vértices.

Corregido - https://github.com/mrdoob/three.js/pull/9681

Hola @sunag , vi tu ejemplo de variación, y me suena extraño poner la variación en mtl.transform como lo hiciste ... ¿Quizás cambies esto cuando sea posible crear funciones vacías?
Sin embargo, suena una buena idea que las palabras clave incluyan: smiley:

De hecho, creo que sería una buena idea poner esas variaciones en mtl.varyings (mtl.varyings es una matriz) así: mtl.varyings.push(myVar) . Usando la misma idea, podríamos poner funciones en sombreadores de vértices y fragmentos como este: mtl.vertexFunctions.push(myVertexFunctionCall) , de la misma manera con mtl.fragmentFunctions .

De esta manera podríamos hacer muchos cálculos sobre esas variaciones y luego usarlos para efectos. Esas funciones serían funciones nulas.

Como en las capturas de pantalla anteriores donde los nodos están conectados visualmente, ¿cómo recreamos esto mentalmente con esta API? Veo que los constructores aceptan otros nodos. ¿Es esa la forma en que la salida de un nodo (pasada a un constructor) es entrada para otro nodo (recibe los nodos en su constructor)? ¿Tiene un nodo como máximo una salida? ¿Cuántos nodos pueden ser entradas a otro nodo a través del constructor o es limitado?

@trusktr Es ilimitado, por supuesto, cuántos nodos más consume más CPU en tiempo de compilación y GPU en tiempo de ejecución. Los nodos se ajustan de acuerdo con los valores de entradas y salidas, la conversión de float a vec2 o vec3 por ejemplo es automática y se almacena en la caché si se usa más de una vez para la optimización (ver TempNode ).

En las capturas de pantalla, cada nodo es una clase, por ejemplo: PositionNode en la pantalla es:
https://github.com/mrdoob/three.js/blob/789efa65bafe022e178c7e93e0985a7607a54403/examples/js/nodes/accessors/PositionNode.js#L5

@mrdoob @sunag , ¿estaría dispuesto a comentar sobre el estado actual del código NodeMaterial y cómo encaja con la hoja de ruta de three.js?

En teoría, ahora podríamos usar nodos para varias cosas, como:

  • Implemente materiales PBR con brillo / especificación glTF como NodeStandardSGMaterial.
  • Admite conjuntos y transformaciones UV por mapa
  • Simplifique el uso de materiales incorporados con instancias

Pero es difícil justificar la adición de una dependencia en GLTFLoader para todos los archivos de nodo. Y probablemente sea difícil justificar poner nodos en src/* sin un uso más activo. Gallina, huevo. 😅

Sería útil conocer el plan a largo plazo para NodeMaterial, para adivinar qué características están (o no) relacionadas ... ¿necesita esto más desarrollo? ¿Hay cosas que otros contribuyentes podrían estar haciendo para ayudar?

@sunag sí, también me gustaría saber si tienes más planes en este momento.

En teoría, ahora podríamos usar nodos para varias cosas, como:

  • Implemente materiales PBR con brillo / especificación glTF como NodeStandardSGMaterial.
  • Admite conjuntos y transformaciones UV por mapa
  • Simplifique el uso de materiales incorporados con instancias

Estos problemas particulares ahora tienen ejemplos de cómo resolverse con las API existentes, sin la necesidad de modificar el núcleo:

Instancia:
https://github.com/mrdoob/three.js/pull/10750 (en toda regla, toca el núcleo, pero podría tener un parche de mono)
https://github.com/mrdoob/three.js/pull/14166 (extensiones de material simples a través de onBeforeCompile)
https://github.com/mrdoob/three.js/pull/14012 (simple, extensión de biblioteca a través de mokey-patching)

conjuntos por mapa-uv
https://github.com/mrdoob/three.js/pull/14174

spec-gloss como su propia clase
https://github.com/mrdoob/three.js/pull/14099

Quizás pueda servir para aliviar la sensación de urgencia de introducir NodeMaterial en el núcleo :).

Para aquellos que siguen este tema, hay una discusión en curso en https://github.com/mrdoob/three.js/pull/14149.

Uniendo hilos de # 14149:

tl; dr - NodeMaterial me parece un próximo paso muy prometedor para el sistema de materiales. Sospecho que la adopción de NodeMaterial está actualmente limitada por algunas cosas:

  • fricción de incluir muchos archivos individuales
  • falta de un editor visual
  • relativamente pocos ejemplos, documentos

Dejaría la pregunta de cuándo / si NodeMaterial debería estar en src/ a @mrdoob y @sunag , pero creo que deberíamos seguir adelante con (al menos) abordar los tres problemas anteriores. También sería útil saber si otros ven NodeMaterial como una alternativa al sistema de materiales actual o un reemplazo completo.



La masa crítica parece estar formada por las partes interesadas de GLTFLoader, y mi observación (subjetiva) es que la necesidad surgió debido a onBeforeRender documentado incorrectamente (pocos ejemplos) e incluso menos documentado onBeforeCompile (un ejemplo).

@pailhead Comencé a mantener GLTFLoader para abordar problemas de flujo de trabajo en A-Frame, del cual también soy desarrollador. Estoy de acuerdo en que el objetivo es un sistema de materiales más útil, no cargar un formato en particular. Decidir cómo integrar (o no integrar) los materiales del nodo debe basarse en los méritos para los usuarios finales de la biblioteca three.js: características, flexibilidad, una API comprensible.

Tienes razón en que los ganchos onBeforeCompile y onBeforeRender son infinitamente flexibles; no existe un límite práctico en cuanto a la medida en que puede manipular o reemplazar los sombreadores subyacentes. Pero ambos tienen defectos similares como API de material primario:

  1. Fuerza la sintaxis de WebGL en la API de material incluso para funciones relativamente simples
  2. Depende de la manipulación de cuerdas de los sombreadores de material del núcleo, lo que hace que los cambios en los materiales del núcleo sean más difíciles con el tiempo y más frágiles
  3. Menos accesible para los artistas
  4. Prácticamente inserializable

Los decoradores (por ejemplo, # 14206) ciertamente mejoran esto desde la perspectiva del usuario, pero si el desarrollo de características futuras de los materiales se basará en decoradores cada vez más complicados sobre los sombreadores de materiales existentes, eso es un peligro de mantenimiento en mi opinión.

Los materiales de los nodos no son perfectos, pero se adoptan ampliamente en otras herramientas gráficas y tienen ventajas clave:

  1. Flexible y componible
  2. Conserva una capa de abstracción de los sombreadores WebGL internos de la biblioteca sin eliminar el acceso a sombreadores simples cuando sea necesario
  3. Representación de material ampliamente popular para artistas y desarrolladores de juegos.
  4. Al menos algo serializable (aunque la conversión a otros formatos sigue siendo difícil)

Esto probablemente suena como si estuviera diciendo que onBeforeCompile debería estar en desuso, y no es mi intención, me alegraría ver que se queda, y los ejemplos son bienvenidos. Pero no es una API a la que quiero señalar a los usuarios de A-Frame o three.js para más casos de los necesarios; No creo que se compare bien con los sistemas de materiales de otras herramientas 3D.

  • fricción de incluir muchos archivos individuales

Esto no debería ser fricción. Creo que sería útil hacer algún tipo de encuesta o algo, para ver cuántas personas usan paquetes y herramientas de construcción. Importar archivos js en un archivo html manualmente no debería ser un enfoque en 2018. Este es el único número que puedo encontrar , y creo que se podría suponer que todos estos usuarios lo están usando con algo que se ejecuta con node.

Pondría más esfuerzo en sacudir los árboles y poder import/export esto, que preocuparme por cómo funcionaría esto al incluir manualmente archivos de script.

  • falta de un editor visual
  • relativamente pocos ejemplos, documentos

Creo que esto debería suceder antes de que esto se convierta en el núcleo. El material de brillo especular debe ser un ejemplo que no esté acoplado con GLTFLoader . ¿El hecho de que esté en /src o /examples debería ser irrelevante?

@donmccurdy

Tiene razón en que los ganchos onBeforeCompile y onBeforeRender son infinitamente flexibles; no existe un límite práctico en cuanto a la medida en que puede manipular o reemplazar los sombreadores subyacentes.

En realidad, no estoy afirmando esto, estoy afirmando que un gancho como onBeforeRender permite un enfoque diferente para estructurar el código, pero que no debe usarse como se usa ahora en GLTFLoader (de ahí # 14099).

onBeforeCompile definitivamente tiene limitaciones y podría tener un nombre incorrecto. Algo bueno para señalar en este contexto es un PR # 14214 reciente. Tan pronto como vi lo que desapareció ( build() a favor de needsUpdate ) supe que iba a ver onBeforeCompile allí. Lo usé como onBeforeParse ya que si no reemplazo ninguna instrucción #include <foo> , aún se analizan después de esta función y antes de la compilación real. En este PR se usa como onWillRefreshMaterial .

La filosofía que estoy tratando de transmitir es que probablemente debería haber más granularidad con este tipo de devoluciones de llamada. Debería haber más de ellos, y se debe tener mucho cuidado al nombrarlos.

# 14214 es un gran ejemplo de por qué NodeMaterial no tiene que estar en el núcleo. Al menos no junto con nada en /renderer , y no incluido con él.

  1. Fuerza la sintaxis de WebGL en la API de material incluso para funciones relativamente simples

Escuché este problema antes, pero no fue elaborado. ¿Por qué es esto un problema? ¿Qué es la "API material" de todos modos? Siempre lo vi como "aquí hay algunos materiales de sombreado de superficies comunes".

Si desea un mapa dinámico, no veo ninguna razón por la que material.map , o 'material.color' no puedan tomar NodeTexture , GLSLTexture , TextureTexture .

myMaterial.color = new SomeNodeGraph() //outputs vec4 in the end

myMaterial.color = new GLSLInput() // inputs various documented variables, outputs some vec4

myMaterial.color = new THREE.Color()

myMaterial.color = new CustomColorGradientTopBottom() // dunno if its Node, GLSL, regular color whatever, i just know it's compatible with the slot
  1. Depende de la manipulación de cuerdas de los sombreadores de material del núcleo, lo que hace que los cambios en los materiales del núcleo sean más difíciles con el tiempo y más frágiles

Mi punto es que esto ya es algo posible con onBeforeCompile pero hace que estos cambios sean aún más difíciles y frágiles de lo que estás describiendo. Ya busqué esto en mi vida profesional y tengo un código que se basa en él. Lo frágil que es, causa mucho estrés :(

Los decoradores que señaló # 14206 se han estancado durante más de un año debido a este RP, que a su vez se ha estancado durante 3 años. Mi sentimiento subjetivo es que el número 14206 haría posible la escritura de estos decoradores, menos tediosa y menos frágil. Son 30 líneas de código que no afectan absolutamente nada, a menos que se definan estas propiedades fantasma. Si ya nos dieron una cuerda para colgarnos en forma de onBeforeCompile ¿por qué no hacerlo un poco más humano? :sonrisa:

Al final, me gustaría decidir por mí mismo qué es un nivel aceptable de frágil y qué no.

  1. Menos accesible para los artistas

Es por eso que los artistas deben tener una herramienta visual y algún tipo de formato para guardar los gráficos. Consumirlos como GLSL "horneados" o algo que construya el NodeMaterial en tiempo de ejecución debe ser una opción dada al usuario.

Un artista podría crear un sombreador, un ingeniero podría pedir que se "compile" para optimizar el proceso de carga. Un artista que trabaja solo podría simplemente cargar el gráfico, asumiendo que por alguna razón es más fácil ("compilar" requiere más esfuerzo).

Además, ¿por qué y cómo se considera a los artistas aquí? ¿Hay algunas estadísticas, cómo se ve un usuario "artista" promedio, por qué están trabajando con three.js y no con unity, es decir. qué tipo de tubería es. ¿Hay ingenieros involucrados? ¿Por qué no una herramienta independiente que se comunica con three.js de alguna manera que adoptan algunos directorios de tecnología, etc. Asumo que las descargas de 40k npm por semana no son de artistas? Se supone que ese tipo de instalación está siendo utilizada por algunas herramientas de compilación y es muy poco probable que se importe manualmente.

Tanto en este como en el punto 2, mi caso de uso no involucra artistas y, por lo general, ningún otro usuario. Estoy cultivando un sistema de materiales, construido sobre materiales incorporados. Utilizo mi propio desempaquetado normal con atributos tangentes, pelado de profundidad, recorte diferente, etc. Todo lo que me importa es estructurar ese código internamente y exponerlo como pequeños elementos internos a las clases anteriores.

  1. Prácticamente inserializable

No sé mucho sobre esto y he escuchado este argumento antes. Estaría más que feliz de ver algún código si alguien pudiera señalarme las áreas problemáticas. Con mi comprensión muy limitada (casi nula) del problema, no entiendo por qué simplemente no es suficiente escribir

"materialFoo": {
  "color":"#ff0000",
  "specularMap": "some_path.jpg",
  "glossiness": "0.5"
}

Supongamos que tiene un material de brillo de especificaciones construido con NodeMaterial , ¿no querría serializar todo el gráfico, solo las entradas? Cualquiera que sea la serialización de un material SpecGloss , ¿debería verse igual? Probablemente me esté perdiendo mucho aquí, agradecería algunos consejos.

Re: serialización

Sería suficiente agregar:

https://github.com/mrdoob/three.js/blob/dev/src/materials/Material.js#L160

customSerializer( data )

Y luego algo como

SpecularGlossMaterial.prototype.toJSON = ()=>{
  Material.prototype.call(this, undefined, data =>{
    if ( this.roughness !== undefined ) data.roughness = this.roughness;
  })
}

specularMap realidad se serializaría porque está codificado:
https://github.com/mrdoob/three.js/blob/dev/src/materials/Material.js#L213

Pero esto se siente un poco extraño, ¿la clase Material es consciente de los componentes internos de todos los materiales incorporados, parece?

@donmccurdy si desea tener esta discusión, sería mejor hacerlo en el decorador PR, # 14206. Fuera de línea, estoy disponible para una sesión de trabajo con cerveza o café en cualquier lugar del Área de la Bahía: little_smiling_face:

Estuvo de acuerdo en que varios archivos _no deberían_ ser fricción, y que no es un argumento en sí mismo para poner NodeMaterial en src/ . Es simplemente una de las varias razones por las que NodeMaterial aún no se usa mucho, y hay otras formas de resolverlo. Y ciertamente estoy de acuerdo en que más documentos serían un requisito previo para colocar NodeMaterial en src/ , o incluso para impulsar la adopción en examples/js o una salida de compilación separada.

Soy optimista acerca de NodeMaterial como dirección general, aunque sospecho que se necesitan algunas cosas más antes de que pueda tener sentido en src/ . Estoy muy preocupado por usar onBeforeCompile y la manipulación de cadenas como una ruta para poner nuevas funciones en el sistema de materiales, como se describió anteriormente, y especialmente a medida que avanzamos hacia la compatibilidad con WebGL2 y (eventualmente) WebGPU . Eso no quiere decir que estas dos opciones sean las únicas opciones, pero (de las dos) estos son mis pensamientos.

En los otros puntos, parece que entendemos las preocupaciones y preferencias de los demás, pero aún así no estamos de acuerdo. He escrito todo lo que tengo tiempo para escribir en este momento, y dejaré esto por un tiempo y dejaré que otros opinen. Gracias por una discusión completa y cortés sobre esto. 🙂

Me gustaría poner una textura de oclusión ambiental con Multiply en una textura difusa, así que estoy probando esto:

const aoNode = new OperatorNode(
        new Math1Node( aoTexture, Math1Node.INVERT ),
        aoScale,
        OperatorNode.MUL
    );
material.ao = aoNode;

Esta es mi textura AO
ao sx

Desafortunadamente, he visto oclusión ambiental en mi modelo.

¿Tienes alguna idea para hacer eso?
Espero que este sea el lugar adecuado para publicar mi pregunta.

¡Gracias!

Me gustaría poder pensar en la dirección de un mapeo de herramientas basadas en nodos existentes a materiales en threejs. En consecuencia, me encantaría ver NodeMaterial en src / junto con la documentación adecuada.

@IARI

¿Puede enumerar las herramientas basadas en nodos existentes?

@donmccurdy

Gracias por la respuesta :)

Desafortunadamente, creo que todavía no nos entendemos. Si tienes tiempo para leer esta publicación, estas cosas:

Estoy muy preocupado por usar onBeforeCompile y la manipulación de cadenas como una ruta para poner nuevas características en el sistema de materiales,

onBeforeCompile es horrible, estoy de acuerdo, la única razón por la que estoy involucrado en cualquiera de estos hilos es que quiero # 13198 que veo como superior a la manipulación de cadenas de onBeforeCompile .

Este no debería ser un patrón para agregar nuevas funciones a three.js. Debería permitir a los usuarios agregar nuevas funciones a sus aplicaciones. Me entristece que @bhouston no haya compartido ningún hallazgo sobre el mantenimiento de una bifurcación para hacer algunas de estas cosas. Tendría curiosidad si hicieron un marco mejor para cambiar los sombreadores, o si realmente han pirateado el núcleo de esta función.

En el caso de las transformaciones uv por canal, lo convertiría en un ejemplo, o en un módulo npm. Si 3 personas lo descargan cada semana, probablemente sea algo que no debería estar en el núcleo. Si 20k personas lo descargan, probablemente sea así como debería haberse diseñado three.js en primer lugar.

onBeforeCompile parece que será crucial para los materiales del nodo, https://github.com/mrdoob/three.js/pull/14214 , por lo que no solo se usa para la manipulación de cadenas .

Tengo onBeforeCompile y NodeMaterial para hacer esto, solicito una tercera opción. Mucho más conveniente que onBeforeCompile y mucho más pequeño que NodeMaterial .

Con ejemplos recientes:
https://github.com/mrdoob/three.js/pull/14206

Discusión antigua:
https://github.com/mrdoob/three.js/pull/13198

@pailhead Para empezar, pensaría en algunos nodos básicos de Blender Cycles.
También me resultaría interesante jugar con Unitys Shadergraph.

@claudioviola Puedes agregar material.shadow o multiplicar con material.color = diffuse * oclusion difusos. Depende de la oclusión de la luz indirecta, AmbientLight , HemisphereLight ...

@IARI

Estoy descargando 7.5 gigas de Unity para ver el ShaderGraph. ¿Existen herramientas independientes para la creación de gráficos? Quiero ver qué tipo de archivo también guarda el gráfico y cómo se transferirá a three.js y NodeMaterial en /src .

Creo que @pailhead está aislado en contra de este movimiento de NodeMaterials al núcleo en este momento. No creo que sea útil para todos discutir con @pailhead durante días. Creo que el proyecto no debería estar en deuda con una sola persona.

Esto no ha sido apresurado ni forzado. Sunag agregó esto hace años. En este momento existe una necesidad para esta y otras alternativas no han funcionado (por ejemplo, fusionadas), así que intentemos esta ruta.

Todas las herramientas principales, 3DS Max, UE4, Blender, Unity, Maya, Sketchfab usan gráficos de sombreado. Argumentar que three.js debería estar en desventaja permanente a este respecto parece injusto para three.js.

No estoy seguro de si este sistema de sombreado basado en gráficos es perfecto en este momento, pero una vez que esté en el núcleo, todos podemos seguir trabajando con él.

Insisto en que continuemos apoyando la API de PhoneMaterial, StandardMaterial, etc. de alguna manera en el futuro para que no rompamos el 95% de los proyectos de three.js, hacerlo sería irresponsable. También es bueno trabajar con interfaces tan sencillas y sencillas.

No tengo ni la capacidad ni el deseo de evitar que esto se mueva hacia el núcleo. Solo espero que pueda desbloquear algunos RP no relacionados, porque se ha hecho referencia a él como un bloqueador. @bhouston ,

Cuando logré llegar a fin de mes como artista 3D hambriento, me gustan todas las cosas basadas en nodos. Nuke era mi compositor favorito y me gustaría aprender a hacer herramientas como esa. Solo deseo que esto desbloquee esto en particular # 14231. Estoy usando esto como una plataforma de aprendizaje para mí, pero si me resulta problemático dejaré de publicar, gracias.

@pailhead Nunca he trabajado con él, pero probablemente hayas oído hablar del diseñador de sustancias. Por lo que tengo entendido, esa herramienta también va más allá de la creación de gráficos / sombreadores, pero se centra principalmente en el diseño de procedimientos de materiales, ¿tal vez sea una pista interesante?

Aparte de eso, no conozco las herramientas independientes desde la parte superior de mi cabeza, pero una búsqueda rápida en Google arrojó estas dos:

Sin embargo, también existe esta herramienta para los nodos threejs, que encontré en una publicación de Twitter de @mrdoob de 2015, aunque parece que nunca se actualizó, me pregunto por qué ...

Parece que se hizo referencia a esa herramienta aquí, pero no veo una forma de exportar nada. El primer enlace se ve increíble, pero el resultado es bastante retorcido, no muy legible en comparación con GLSL. Me pregunto si eso ya se puede usar para reensamblar el NodeMeterial , o incluso un ShaderMaterial .

Eché un vistazo a la unidad, pero en realidad no pude encontrar la herramienta de gráfico de sombreado,

Por cierto, si de alguna manera bloqueé esto, por supuesto, déjelo desbloquear. El RP es de 2015, respondí por primera vez hace 8 días.

(Lo siento, esto es un poco fuera de tema ..)
@pailhead Para
Aquí hay un tutorial para configurarlo comenzando con un nuevo proyecto que se está configurando: https://youtu.be/Ar9eIn4z6XE?t=98

Ese editor de nodos de material de Sea3D Flow (http://sea3d.poonya.com/flow/) es de @sunag , el mismo tipo que escribió NodeMaterial.

Muchas gracias @sunag
¿Cómo puedo conseguir la luz indirecta? ¿Es un valor en el renderizador o cómo puedo calcularlo?

Me gustaría aplicar un efecto de posprocesamiento solo a una selección de objetos (es decir, cambiar la saturación).
Sin embargo, no puedo encontrar nada relacionado con el enmascaramiento (si no hay otra forma) con los nodos.
Actualmente estoy leyendo el OutlinePass (sin nodo) que escribe un montón de cosas en un montón de búferes, que puedo ver como un método factible para lograr lo que quiero, pero no tengo la menor idea de cómo abordar esto con nodos.

El editor de nodos de material de Sea3D Flow será independiente al igual que el editor de three.js, ¿o formará parte de él? ¿Seguirá llamándose Sea3D o algo más relacionado con three.js? Gracias @sunag por lanzar ese editor visual a la comunidad three.js.

pero no tengo la menor idea de cómo abordar esto con nodos.

@IARI

Parece que conoce GLSL ya que puede leer el OutlinePass y comprender lo que hace. También parece entenderlo lo suficiente como para ver que no puede lograrlo con nodos. Pensé que si sabes cómo codificarlo, sabrás cómo anudarlo. Aún más, si no sabe cómo codificarlo, es posible que sepa cómo crear un nodo. ¿Dónde está la desconexión?

No vi estas publicaciones de 2016 en absoluto. Interesante ver Shader Frog. Me pregunto si esto puede verse como vim vs emacs o algo así. Me gusta usar Sublime Text, a ti te gusta usar otra cosa. A uno le gusta usar shader frog, a otro le gusta usar el editor Sea3D de three.js.

Me gusta cómo Shader Frog solo genera un sombreador, pero no es de código abierto como Sea3D.

Luego está esto.

Poner la mecánica de productos de terceros en el núcleo de Three parece una ventaja injusta y no lo entiendo políticamente.

Para mí, el hecho de que todo esto se pueda lograr sin tres cambios significa que es innecesario y difumina la línea entre Three.js, que es una API contenedora de webgl y ahora impulsa las características específicas de implementación. El almacenamiento de datos de nodos de sombreado es muy específico de la aplicación y, hasta donde yo sé, actualmente no existe un formato estándar de editor de nodos común para ningún software. Hacer cumplir uno podría ser perjudicial para otras implementaciones.

@bhouston
No puedo esperar a que llegue NodeMaterial , ya que puede desbloquear otros RP y la vida puede volver a la normalidad. Parece que otras voces han intentado bloquear esto en el pasado.

Creo que @pailhead está aislado en contra de este movimiento de NodeMaterials al núcleo en este momento.
Creo que el proyecto no debería estar en deuda con una sola persona.

Gracias.

No veo ninguna razón por la que no se pueda lograr con nodos exactamente de la misma manera que lo hace outlinepass, pero de una manera que sea legible, comprensible y modular, de modo que las partes se puedan reutilizar.
¿Por qué no debería haber, por ejemplo, nodos de salida que escriban en búferes y demás?

Y realmente no conozco muy bien glsl, y también me parece, perdón por la redacción, un súper dolor de cabeza leer y escribir código de sombreado. Y además de eso, es más doloroso si está envuelto en una estúpida matriz de cadenas en código javascript.

¿Usas webpack o algo así?

estúpida matriz

Solo es estúpido si tiene que importarlo en un archivo .html. Cuando trabaja con webpack y tiene la sintaxis JS moderna, puede mantener su GLSL en archivos .glsl, .vs, .fs y tener resaltado de sintaxis y demás.

shader.fs:

void main(){
  gl_FragColor = vec4(1.);
} 

javascript (mira mamá, sin matrices estúpidas)

import mShader from './shader.fs'

Mi preocupación es que no veo mucho valor en su necesidad, ya que está preguntando específicamente cómo crear un efecto, no cómo codificar algo. ¿ NodeMaterial abrirán puertas a miles de preguntas de "cómo atenúo este efecto", que solo tendrán una respuesta genérica:

¡Usa los nodos, Luke!

No, tener que leer (y mucho menos escribir) código en dos idiomas diferentes dentro del mismo archivo para mí es siempre un dolor de cabeza. Además, el paquete web no ayuda en nada, cuando intentas estudiar el código de sombreado de ejemplo de threejs, que está todo envuelto en feos conjuntos de cadenas unidos por saltos de línea.
De todos modos, este problema es sobre el sistema de nodos, y hice una pregunta simple sobre los nodos, no para una discusión sobre preferencias personales de codificación, que no lleva a ninguna parte.

@IARI

Disculpas, de alguna manera no vi ningún signo de interrogación en tu publicación, así que me perdí tu pregunta.

Definitivamente, esto no debería ser una discusión sobre las preferencias personales de codificación, pero se debe considerar el hecho de que hay diferentes. También estoy un poco preocupado por la avalancha de preguntas de "¿Cómo hago este sombreador?".

Antes, esta barra era bastante alta, la gente simplemente se da por vencida con i don't know glsl o cuando ven "una matriz estúpida en cadenas". Pero si es menor, todos intentarán escribir sombreadores.

No encontré tu pregunta, pero tengo curiosidad por saber cuál es. Lo es:

¿Cómo hago un ToonShader con NodeMaterial?

En cuyo caso, tengo curiosidad por saber cuál es la respuesta.

No puede porque NodeMaterial no admite alguna abstracción.
Puede, solo use NodeMaterial, para conectar nodos

¿Quizás esta discusión podría beneficiarse de estallar? Es una gran cantidad de publicaciones, que se remontan mucho atrás (2015). NodeMaterial está en / examples, por lo que probablemente pueda construir su sombreador de toon a partir de él. ¿Quizás podría abrir otro problema o publicar en el desbordamiento de pila para eso específicamente, y el resto de la conversación podría pasar a un nuevo problema?

Con mucho gusto podemos llevar esta discusión a otro lugar, como un canal flojo o lo que sea. Realmente tengo la sensación de que no pertenece aquí, pero en su mayoría molestará a la gente.

El foro podría ser mejor que holgura para este caso particular.

@pailhead , toda esta discusión ha dejado de ser productiva. También podría cerrar este problema y hacer uno nuevo centrado en el problema real que nos ocupa.

@bhouston

De acuerdo, excepto que creo que son varios problemas.

  • cómo implementar nodematerial
  • ¿Deberían bloquearse otros RP relacionados y no relacionados?
  • cómo permitir que las personas que no saben cómo escribir sombreadores implementen ciertos efectos de sombreado

¿Cómo hago un ToonShader con NodeMaterial?
En cuyo caso, tengo curiosidad por saber cuál es la respuesta.
No puede porque NodeMaterial no admite alguna abstracción.
Puede, solo use NodeMaterial, para conectar nodos

Jajaja. Estoy de acuerdo con @bhouston ... esto solo puede ser una broma. ¿Podría haber visto el ejemplo webgl_materials_nodes antes de decirlo?

Y si desea usar código, vea la expresión usando FunctionNode .

toon

@sunag creo que me /examples y no en /src se está convirtiendo en un ciudadano de primera clase? Este problema parece haber sido planteado por @AndrewRayCode en 2015.

Acabo de decir que este tema está sobrecargado, ya que se remonta a 2015 y se discutieron varios temas diferentes. Si alguien pregunta "cómo puedo hacer un whatever ", se le remitirá al desbordamiento de pila.

Si esto va a ser una revisión masiva de three.js _ (el hecho de que la unidad tenga que configurarse específicamente para esto me asusta un poco) _ entonces creo que debería haber un problema continuo dedicado aquí en github para tales preguntas - usage of NodeMaterial . Como está, las personas que están pidiendo cosas al azar (# 14232) están siendo referidas a este hilo, hace que la comunicación sea complicada :)

Recientemente tuve que escribir un sombreador de toon pero estaba basado en líneas, y más específicamente en las líneas gruesas de NodeMaterial que podría llevar quién sabe cuánto tiempo. Todos estos son varios temas que se complican aquí.

Y si desea usar código, vea expresión usando FunctionNode.

Si codifico, usaré texto sublime, ShaderMaterial está bien para mí, no necesito FunctionNode . Si creo efectos visuales, probablemente buscaré un editor visual, pero esta es mi preferencia. Solo estoy aquí porque esto bloqueó a otros RP :) No hace mucho me di cuenta de que en realidad es lo mejor para tres que esto aterrice lo más rápido posible. Desenredar esta conversación probablemente ayudaría a acelerar las cosas. En esto estoy de acuerdo con @bhouston ¡ esto debería ser yolod lo antes posible!

Gracias.

Para el registro: no estoy interesado en un sombreador de dibujos animados ni nada de eso.
Estoy implementando un sistema que permite a las personas que no escriben código conectar efectos simples predefinidos en ciertas posiciones.

Lamentablemente, me temo que no tendré tiempo para estudiar cómo escribir nodos en este momento, y tengo que ponerme al día con la codificación glsl básica de todos modos, así que por ahora implementaré cosas sin nodos: no será extensible , usará múltiples pasadas de renderización donde una sola probablemente sería suficiente con una buena implementación de nodo, será menos legible, ...

En general, lamentablemente, soy demasiado nuevo en el tema general y necesito obtener una comprensión mucho más básica, pero a juzgar por lo que sé, los nodos serían la mejor manera de hacerlo de una manera verdaderamente elegante y extensible.
Me encantaría tener información sobre la implementación de nodos, como un artículo de blog o un tutorial.

Descargo de responsabilidad: no estoy exigiendo nada, solo espero aclarar mi vaga solicitud desde arriba.
Gracias a todos por todo el trabajo que se está haciendo aquí, es absolutamente asombroso.

Me pidieron en el hilo https://github.com/mrdoob/three.js/issues/14232 que comentara sobre la implementación del sombreador basado en nodos. Creo que es muy pobre. Me encanta la idea, pero la implementación es totalmente inadecuada en mi opinión, así que, dado que estoy siendo tan negativo, voy a proporcionar algunas razones concretas de por qué.

Comprensibilidad

Después de leer parte del código para los nodos y varias clases de servicios públicos, puedo decir decididamente que es un gran desafío entenderlo.

  • los nombres de las variables no son descriptivos
  • sin comentarios en absoluto
  • los nombres de los métodos son oscuros o completamente engañosos. (p. ej., ¿qué crees que hace el método "build"? - adivina)

La estructura del código es francamente extraña. Considere este fragmento:
https://github.com/mrdoob/three.js/blob/e2b49c017b2d1f37ab34317033a27df7b5a71d4d/examples/js/nodes/FunctionNode.js#L39 -L50

Podrías lograr lo mismo con:

return this.inputs.find(input => input.name === name);

"Arquitectura emergente"

¿Qué es un "nodo"? Estoy pidiendo una definición de la estructura de datos, porque parece que es solo un concepto nebuloso, ya que hay poca similitud entre los diferentes "Nodos", parece un tipo de pato, si grazna como un Nodo, es un Nodo.

Separación de intereses

¿Cómo se pasa de Node a ShaderMaterial ? En este momento es una combinación de responsabilidades entre varias piezas de lógica de cada nodo, algunos constructores, algo de caché, analizadores, etc. No hay una responsabilidad clara para este proceso. Node usa NodeBuilder? Que ...? Por el nombre que tendría, aunque NodeBuilder es una fábrica que produce o construye nodos, resulta que en realidad es una estructura auxiliar. Por lo que puedo decir, hay trabajos bastante distintos que hacer aquí:

  • Construye una gráfica
  • Validar
  • Construir una representación intermedia
  • optimizar
  • compilar a GLSL

Eso no es en absoluto lo que encontrará en el código actual.

Conclusión

Sin una buena documentación y comentarios, veo esta implementación como completamente inadecuada. Con esas cosas en su lugar, es una cuestión de código espagueti y falta de diseño. Dicho esto, reconozco que es una herramienta poderosa y una implementación funcional de un concepto muy útil.

@Usnul nunca codificaremos así en Three.JS "return this.inputs.find (input => input.name === name);"

La razón es que "=>" crea una función que se debe llamar en cada entrada. Las llamadas a funciones son muy lentas en JavaScript en comparación con un bucle for o while. Por lo tanto, siempre hacemos bucles explícitos en lugar de código orientado a devolución de llamada. Sé que es más detallado, pero es necesario. All of Three..JS es así ya propósito.

@Usnul , sus preocupaciones de diseño son muy útiles, ¿podría ayudarnos con la refactorización? Creo que todos agradecerían sus aportes y contribuciones al diseño. :)

La razón es que "=>" crea una función que se debe llamar en cada entrada. Las llamadas a funciones son muy lentas en JavaScript en comparación con un bucle for o while. Por lo tanto, siempre hacemos bucles explícitos en lugar de código orientado a devolución de llamada. Sé que es más detallado, pero es necesario. All of Three..JS es así ya propósito.

ese es un buen punto. Personalmente, soy de la filosofía de que el rendimiento y la legibilidad deben estar en una escala y no en una u otra, pero la consistencia es buena. Mi principal problema con ese ejemplo específico es que no es una forma común de iterar sobre una matriz. He aquí una forma idiomática:

for(var i=0, count=array.length; i<count; i++){
    var element = array[i];
    ...
}

o digamos que tiene un fragmento de código que tiene 50 líneas de la forma:

function complex(a){
  if(a){
      //do a ton of stuff
      ...
      return result;
  }
}

eso no es tan legible como:

function complex(a){
  if(!a){
      //omg! not A?!11 
      return;
  }
  //do a ton of stuff
  ...
  return result;
}

@Usnul, ¿ podrías ayudar a refactorizar el código para

@usnul, si no te gusta esto, ¿podrás refactorizarlo? No importa si se ve así o no, es importante que se construya sobre esto, según tengo entendido.
Sin embargo, no sé si los refractores deberían ocurrir mientras esto está en los ejemplos (o posiblemente en otro repositorio) o si se debe mover a src de inmediato como sugiere @bhouston .

@IARI

Realmente no conozco glsl muy bien , y también me parece, perdón por mi redacción, un súper dolor de cabeza leer y escribir código de sombreado .

pero a juzgar por lo que sé , los nodos serían la mejor manera de hacer esto de una manera verdaderamente elegante y extensible.

Tampoco puedo afirmar que conozco muy bien GLSL, pero lo sé lo suficiente como para resolver mis problemas. Por lo que sé, en general estoy de acuerdo con lo que @usnul escribió aquí y lo que @AndrewRayCode escribió antes. Encuentro que el nodo es detallado en comparación con GLSL.

Si no conoce GLSL, creo que sería muy difícil compararlo con otra cosa. Como lo escribió usted mismo, si judge on what you know , y usted mismo lo dijo you don't know glsl creo que su entrada debe tomarse con un descargo de responsabilidad :)

Es como si dijera:

Japón es el peor lugar del planeta ... pero nunca he estado en Japón ".

Gracias.

los nombres de los métodos son oscuros o completamente engañosos. (p. ej., ¿qué crees que hace el método "build"? - adivina)

Vaya, ni siquiera me di cuenta de que esto es un ShaderMaterial debajo. Supongo que esto hace todo lo que hace THREE.WebGLRenderer con las plantillas de sombreado.

Realmente no conozco muy bien glsl, y también me parece, perdón por mi redacción, un súper dolor de cabeza leer y escribir código de sombreado.
pero a juzgar por lo que sé, los nodos serían la mejor manera de hacer esto de una manera verdaderamente elegante y extensible.

@pailhead Lo que quiere decir es que hay niveles intermedios entre las cosas.

No entiendo por qué esta alarma. @mrdoob nunca fusionará algo más que una gran solución. Todas las buenas relaciones públicas, las mejoras de cualquiera en NodeMaterial o no son muy útiles para la comunidad. Si esto todavía no se ha fusionado en el núcleo es porque necesitamos mejorar con más trabajo.

@sunag, ¿hay algo en particular que otros puedan hacer para ayudarte con este proyecto? Estaría dispuesto a escribir documentación, si está listo para los documentos y podría revisarlos.

@sunag, ¿hay algo en particular que otros puedan hacer para ayudarte con este proyecto? Estaría dispuesto a escribir documentación, si está listo para los documentos y podría revisarlos.

Esto será genial. Sin duda ayuda mucho.

El sistema de material basado en nodos se ve increíble, expandiría el poder de expresión.

¿Cómo cambiaremos del sistema de materiales existente al sistema de materiales basado en nodos en el núcleo? ¿Seremos los dos en dos sistemas o sustituiremos el existente por el de nodo?

Lo siento, tal vez no creo que alcance este hilo porque este hilo es demasiado grande ...

¿Seremos los dos en dos sistemas o sustituiremos el existente por el de nodo?

Veo el reemplazo como el objetivo final, es mejor tanto para el rendimiento como para el mantenimiento. El siguiente paso es hacer un MeshStandardNodeMaterial y otros materiales de nodo en el núcleo se ejecutan exactamente como el núcleo en visual, sintaxis y rendimiento.

Tengo que mostrar shadowMap en mi proyecto.

Tengo una escena con una luz direccional y 2 geometrías que usan MeshStandardNodeMaterial.

He encendido
castShadow = verdadero para la luz
castShadow y ReceiveShadow para ambos objetos.
shadowEnabled = true para Renderer

¿Por qué no funciona?
¿Tengo que usar la propiedad de sombra de MeshStandardNodeMaterial? ¿Es este el propósito?

¿Alguien puede ayudarme?
¡Gracias!

@claudioviola
las preguntas de soporte van al foro de stackoverflow.

@sunag ¿Crees que NodeMaterial es lo suficientemente estable como para que podamos empezar proporcionando archivos de declaración de TypeScript? Si no está planeando cambios importantes en la API en el futuro cercano, comenzaría con esta tarea ya que NodeMaterial es el último grupo de módulos sin soporte de TS.

@sunag ¿Crees que NodeMaterial es lo suficientemente estable como para que podamos comenzar proporcionando archivos de declaración de TypeScript? Si no está planeando cambios importantes en la API en el futuro cercano, comenzaría con esta tarea ya que NodeMaterial es el último grupo de módulos sin soporte de TS.

@ Mugen87 Sí, debe haber más adiciones que cambios. Agregar soporte de TS será genial. 👍

Bien, el soporte de TS está listo con la próxima versión R017 🙌

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