Three.js: NodeMaterial

Criado em 3 nov. 2015  ·  161Comentários  ·  Fonte: mrdoob/three.js

Oi.

Comecei a desenvolver um THREE.NodeMaterial para conciliar as diferenças de materiais entre softwares de autoria 3D. No SEA3D Studio há opções para criar camadas em Albedo com máscara e vários modos de mesclagem, sombreador Rim e outros sem a necessidade de código de sombreador personalizado. Eu gostaria de trazer isso para Three.JS com node shader.

Eu acho que MeshPhongMaterial, MeshPhysicalMaterial e outros podem ser facilmente baseados em NodeMaterial por meio de uma interface para compatibilidade com versões anteriores ou proxy apenas.

ATUALIZADA
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

Exemplo de sintaxe para usa UV1 ou 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

Também estou fazendo um editor, atualmente esta seria a interface. A cor é o albedo e a transformação é a posição do vértice.
editor

Também estou tomando cuidado para que possa ser usado em um sombreamento diferido. Agora vou criar entradas de reflexão e refração.

Estará compartilhando a novidade para o PR, sugestões, testes e aprimoramentos são bem vindos: +1:

Enhancement

Comentários muito úteis

Ok, o suporte para TS está pronto no próximo lançamento R017 🙌

Todos 161 comentários

Interessante!

@sunag Estamos muito interessados ​​em algo assim. Como posso ajudar? Posso adicionar suporte para Standard, pelo menos.

Estou interessado em criar gráficos razoavelmente arbitrários, de modo que os nós intermediários também recebam entradas. Portanto, você pode ter um gráfico semelhante a este:

Uma textura (tex1, uv1)
Textura B (tex2, uv2)
Mistura C (A, B, modo)
Ruído D (param1, param2)
Mistura E (modo C, D)

E então use esse nó final E, como uma entrada para um Material.

Portanto, é muito arbitrário, não se limita apenas a texturas.

Meu objetivo seria ajudar a criar isso nas próximas semanas, espero colaborar com você na próxima semana ou assim, se possível. Eu estava tentando fazer isso por meio da biblioteca shadergraph aqui: https://github.com/mrdoob/three.js/issues/7339 Mas estou descobrindo criá-lo diretamente no ThreeJS. Na verdade, qualquer solução é boa, desde que seja flexível e funcione.

Estou lendo seu código, é muito bem projetado. Eu tenho alguns comentários iniciais. Posso começar um PR usando seu código como base para começar a colaborar nele?

(1) Eu faria com que o material resolvesse as referências. Basicamente, as referências teriam nomes que eles solicitariam que seu material resolvesse, e o material retornaria um fragmento de código sobre como acessar esses dados. Isso também permitiria ao material saber quais variáveis ​​(uniformes / variadas) são utilizadas nos nós, para que ele possa otimizar de forma adequada. Isso também permite que materiais diferentes resolvam referências de maneira diferente, tornando os nós mais portáteis, ao invés de ter que saber como os materiais implementam as coisas, especialmente quando há diferenças entre implementações de fragmento e vértice.

(2) Tento usar o objeto GeometryContext que criei no refatorador de luzes, ele dá acesso consistente a muitas das variáveis ​​locais necessárias. Mas é claro que isso pode ser resolvido pelo próprio material.

(3) Tenho o UV sendo apenas mais uma referência, que é resolvida pelo material. E eu teria que NodeTexture deveria realmente receber uma entrada de nó, permitindo assim para UVs gerados proceduralmente.

(4) Eu chamaria NodeCube, NodeTextureCube para ser consistente com o resto de Three.JS. E eu removeria a lógica de como realmente fazer os raios lançados a partir dele. Mas eu gosto da ideia de mapas de cubo padrão, então eu realmente não colocaria a consulta de ambiente para especular ou difusa nos nós, mas teria isso no material phong de base, e você só pode controlar o normal usado para a consulta, ou o O próprio resultado do mapa do cubo (permitindo, assim, que seja uma cor determinada por procedimento). Isso faz sentido? Então, eu teria o plugável normal no material e a textura do cubo plugável (questionável por uma direção e viés / lod e retorna uma cor). Assim, pode-se fornecer uma textura de cubo para o mapa de irradiância e outra para o mapa especular. Podemos trocar verdadeira sampleCube com a função cubeToUV2 's @tschw como apenas uma troca de nó.

(5) Eu tentaria adicionar um NodeFunction que permite chamar funções arbitrárias com parâmetros como um acréscimo ao seu NodeOp (ou talvez eles possam ser mesclados de alguma forma).

(6) Eu me livraria de todas as classes individuais detalhadas de NodeNormal, NodeTransform, NormalMap, etc. e teria apenas alguns construtores simples que criam uma NodeReference com um nome que é resolvido pelo material conforme apropriado. NodeReference pode resolver uniformes, variações, bem como valores calculados no sombreador.

(7) Eu não entendo a diferença entre NodeEnvironment e NodeCube. Eu acho que NodeEnvironment pode estar incompleto?

(8) É confuso que o NodePhong não seja derivado do NodeMaterial. Embora eu veja que NodeMaterial é derivado de ShaderMaterial. Eu me pergunto se você chamou a derivada direta de ShaderMaterial, GraphMaterial (ou NodeGraphMaterial) que faria mais sentido - porque todos os nós juntos formam um gráfico, e é o gráfico que se torna o material, não um nó individual.

(9) Eu sugeriria talvez uma terminologia mais variada. Eu chamaria o nó raiz de MaterialNode, e alguém poderia derivar PhongMaterialNode dele. Eu tenho Vector3Node, FloatNode, etc. derivados de ValueNode - não necessariamente constante, mas apenas um valor. Assim, pode-se canalizar três FloatNodes para um Vector3Node. Acho que você pode ter um ajudante que faria declarar cada uma dessas uma linha ou mais, em vez das 10 ou mais atualmente.

(10) Eu moveria o nome "Node" do início dos nomes das classes para o final, porque é assim que funciona no restante do projeto ThreeJS.

(11) Eu criaria a nova classe MaterialNode e ela seria inicializada com uma lista de uniformes e variações. Seria o padrão ser capaz de resolver isso e também rastrear o que foi resolvido para que se possa rastrear quais recursos são necessários. Pode-se, portanto, ter uma resolução limitada no PhongMaterialNode derivado que resolveria os casos especiais e dependeria da classe subjacente para fazer os mais simples (variações, uniformes).

(12) Estou meio confuso entre a diferença entre NodePhong e NodePhongMaterial. Eu não sabia que havia ambos até agora.

(13) existe um 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 ) {

Mas acima deste snippet você já definiu generate para NodeGL e não definiu um para NodeGLPosition - portanto, acho que é um erro de copiar-colar-editar.

(14) Eu me livraria de NodeReflectUVW e NodeRefractVector e, em vez disso, apenas faria isso algo que alguém pudesse solicitar do material por meio de um resolução de referência. Calcular um vetor de reflexão é simples. Eu o adicionei a GeometryContext em meus branches experimentais não mesclados do ThreeJS.

(15) A maneira como eu implementaria reflexão e refração seria tê-las como entradas de cores no Material. Seria possível resolver Refect, ReflectLOD e Refract, RefractLOD da maneira simples como você resolveria qualquer variável e, em seguida, passaria para o equivalente do cubo de textura (procedural ou samplerCube-based) e então passaria a cor resultante para o Material. É assim que você estava fazendo?

(16) Estou confuso sobre a entrada de luz - geralmente um não tem luzes sendo conectáveis, em vez disso, os parâmetros de luz são totalmente definidos na classe de luz. Eu acho que você precisa dessa flexibilidade adicional? Como você imagina isso.

@bhouston woow, muito obrigado pelo feedback.
Vou precisar de vários posts para responder :)

Estou interessado em criar gráficos razoavelmente arbitrários, de modo que os nós intermediários também recebam entradas. Portanto, você pode ter um gráfico semelhante a este:
Uma textura (tex1, uv1)
Textura B (tex2, uv2)
Mistura C (A, B, modo)
Ruído D (param1, param2)
Mistura E (modo C, D)

Atualmente a sintaxe é assim. Exemplo de animação de deslocamento Uv1:
Eu acho que NodeMaterial para MaterialNode e THREE.PhongMaterialNode seria melhor também.

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;

Acho que inverter a ordem com a sua sugestão para melhorar (modo, A, B) para (modo A, B). Estou em processo de criação de mapas de reflexo, mapa de cubo e outros ...

O ambiente e o Cubemap estão incompletos.

Atualmente os bugs podem acontecer mais por causa do conversor de formato ainda inacabado. Isso é responsável pela conversão do vetor. vec3 a vec4 ou vec4, por exemplo.

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

Uma "textura" do Blend, por exemplo: (não testei este código)
Pode ser implementado no mesmo de um 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 () é o responsável pelo gerador de código. Os códigos de cálculo são armazenados em um cache se você quiser usar em mais de uma entrada sem perder desempenho.

Ainda não configuro ponteiros ou constantes para otimização ...

A compilação é feita por propagação em build () para código de vértice e fragmento.

Posso te colocar como colaborador? Se você quiser editar o código de alguma forma, estarei trabalhando nisso também.

Posso te colocar como colaborador? Se você quiser editar o código de alguma forma, estarei trabalhando nisso também.

Obrigado! Vou fazer PRs para você para que possa aprovar as alterações.

Eu adicionei você (assim como @mrdoob , @WestLangley e @tschw) a um projeto paralelo meu que está tentando definir um conjunto de nós reutilizáveis ​​e definições de material que podem ser transferíveis entre vários renderizadores. É mapeável neste sistema de gráfico de sombreador que você criou.

Não acho que você deva prestar atenção ao repo que acabei de lhe dar acesso, se não quiser. É o que estou interessado em implementar além disso.

(2) Tento usar o objeto GeometryContext que criei no refatorador de luzes, ele dá acesso consistente a muitas das variáveis ​​locais necessárias. Mas é claro que isso pode ser resolvido pelo próprio material.

Eu desejo que as luzes sejam um LightNode. Minha preocupação é aproveitar o código já desenvolvido para Three.JS.

(3) Tenho o UV sendo apenas mais uma referência, que é resolvida pelo material. E eu teria que NodeTexture deveria realmente receber uma entrada de nó, permitindo assim para UVs gerados proceduralmente.

Você pode substituir UV por um vec2 seria isso?

(5) Eu tentaria adicionar um NodeFunction que permite chamar funções arbitrárias com parâmetros como um acréscimo ao seu NodeOp (ou talvez eles possam ser mesclados de alguma forma).

isso seria ótimo. principalmente para um BlendNode.

(6) Eu me livraria de todas as classes individuais detalhadas de NodeNormal, NodeTransform, NormalMap, etc. e teria apenas alguns construtores simples que criam uma NodeReference com um nome que é resolvido pelo material conforme apropriado. NodeReference pode resolver uniformes, variações, bem como valores calculados no sombreador.

Nesta linha de pensamento, acho que o MaterialNode poderia ser uma base de material Phong e material físico.

(7) Eu não entendo a diferença entre NodeEnvironment e NodeCube. Eu acho que NodeEnvironment pode estar incompleto?

Ainda não consigo terminar esses nós.

(8) É confuso que o NodePhong não seja derivado do NodeMaterial. Embora eu veja que NodeMaterial é derivado de ShaderMaterial. Eu me pergunto se você chamou a derivada direta de ShaderMaterial, GraphMaterial (ou NodeGraphMaterial) que faria mais sentido - porque todos os nós juntos formam um gráfico, e é o gráfico que se torna o material, não um nó individual.

NodeMaterial seria o material do nó raiz, é necessário usar um nó para vértice e fragmento. NodePhong é híbrido e NodePhongMaterial é apenas uma classe de proxy. Isso pode então ser mesclado.

(9) Eu sugeriria talvez uma terminologia mais variada. Eu chamaria o nó raiz de MaterialNode, e alguém poderia derivar PhongMaterialNode dele. Eu tenho Vector3Node, FloatNode, etc. derivados de ValueNode - não necessariamente constante, mas apenas um valor. Assim, pode-se canalizar três FloatNodes para um Vector3Node. Acho que você pode ter um ajudante que faria declarar cada uma dessas uma linha ou mais, em vez das 10 ou mais atualmente.

Soa bem.

(16) Estou confuso sobre a entrada de luz - geralmente um não tem luzes sendo conectáveis, em vez disso, os parâmetros de luz são totalmente definidos na classe de luz. Eu acho que você precisa dessa flexibilidade adicional? Como você imagina isso.

Isso seria para o mapa de luz ou um possível LightNode.

Isso seria para o mapa de luz ou um possível LightNode.

Eu gosto da ideia de um mapa de luz plugável porque é possível definir os UVs para ele explicitamente. :)

@bhouston Corrija várias correções hoje neste arquivo: Mas ainda há muito a fazer.
https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/three.node.js

Este é o playground que estou criando: arte: texturas e botões é arrastar e soltar, funciona apenas no cromo

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

Coisas incríveis! Puta merda! É lindo.

Seria possível compartilhar o código de uma forma que eu também possa contribuir? Como RP público ou algo assim?

Você está trabalhando com o projeto Sea3D aqui, certo?

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

Posso apenas fazer um fork e começar a contribuir? Você aceitaria PRs? Como podemos colaborar de forma eficaz.

Eu não perguntei, mas provavelmente @mrdoob (?) Adoraria ter isso dentro do próprio projeto ThreeJS.

Com certeza!

Posso apenas fazer um fork e começar a contribuir? Você aceitaria PRs? Como podemos colaborar de forma eficaz.

Claro, acho que sua ajuda seria incrível. Também tenho que trazer outros tipos de nós, como saturação, ruído como você sugeriu.

Você está trabalhando com o projeto Sea3D aqui, certo?

Acho que em fazer um PR for Three.JS com exemplos para que tudo isso seja definido.

@mrdoob O que você acha dos nomes dos materiais, THREE.MaterialNode ou THREE.NodeMaterial?

É um tipo de material, então deve ser THREE.NodeMaterial .

um exemplo de rim shader
flow-rimshader-example

exemplo de reflexão de área
flow-areareflection

Isso é tão incrível @sunag!

@bhouston obrigado! você acha que será difícil converter para R74?

Este é um trabalho muito impressionante! Me lembra de Shaderforge .

Muito bom trabalho até agora!

@sunag Será um pouco trabalhoso, mas gostaria de ajudar e a maioria das grandes mudanças estruturais no código de sombreador R74 são minha culpa. :)

parece um homem bonito e divertido de brincar: posso oferecer como inspiração o editor de nó do Blender3D. Acho que é supereficiente, há até alguns vídeos excelentes sobre PBR através do sistema de nós do Blender e quais nós seriam mais úteis para criar para fazer o PBR do zero:

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

Será um pouco trabalhoso, mas gostaria de ajudar e a maioria das grandes mudanças estruturais no código de sombreador R74 são minha culpa. :)

@bhouston Uau. Ficou muito mais limpo com as novas alterações do r74. Terminei a primeira parte ainda faltando StandardMaterial. Qualquer problema eu posto aqui:) Obrigado
https://github.com/sunag/sea3d/commit/d544ad7993272348f8bbea2337cdceb52159a6a8

Outra coisa que ainda falta é a refração. Eu realmente gosto de usar o buffer de renderização no lugar de um Cubemap RTT como padrão. Seria muito mais eficiente.

@GGAlanSmithee Tenho algumas referências do ShaderFX das quais sou um grande fã. Shader Forge e UE4, principalmente, também são ótimas referências.

@richardanaya Vídeos incríveis. Thks!

@mrdoob Em qual pasta você recomenda colocar esses arquivos? raiz three.js (src / materiais / nó) ou em exemplos?
https://github.com/sunag/sea3d/tree/gh-pages/Labs/Three.JS-NodeMaterial/node

Ainda assim, recomendo chamar isso de "Gráfico de material" ou, no estilo ThreeJS invertido, de "GraphMaterial". Ou se você insiste em usar o termo "Node", eu o chamaria de "NodeBasedMaterial". Ambos os nomes deixam claro que o material contém nós, em vez de ser um nó em si.

Ainda assim, recomendo chamar isso de "Gráfico de material" ou, no estilo ThreeJS invertido, de "GraphMaterial". Ou se você insiste em usar o termo "Node", eu o chamaria de "NodeBasedMaterial". Ambos os nomes deixam claro que o material contém nós, em vez de ser um nó em si.

Para mim, ambos parecem bons. Deixo a decisão para @mrdoob o que você acha?

BTW, @sunag, eu ficaria com mapas de cubos para refrações, se possível, é mais fácil e preciso. Eu acho que é assim que quase todo mundo faz isso e precisamos do material RTT para reflexões precisas também. Acho que só precisa ser uma renderização rápida em 128 ^ 2 ou 256 ^ 2.

BTW, @sunag, eu ficaria com mapas de cubos para refrações, se possível, é mais fácil e preciso. Eu acho que é assim que quase todo mundo faz isso e precisamos do material RTT para reflexões precisas também. Acho que só precisa ser uma renderização rápida em 128 ^ 2 ou 256 ^ 2.

Sim, podemos deixar ambos. seria uma discussão entre desempenho x precisão. Ainda para refração plana (vidro, água) eu recomendo o buffer no lugar de um CubeMap (para a maioria dos casos).

@mrdoob Em qual pasta você recomenda colocar esses arquivos? raiz three.js (src / materiais / nó) ou em exemplos?

Eu colocaria isso em exemplos para começar. Assim que estiver bem definido, podemos movê-lo posteriormente para src 😊

Ainda assim, recomendo chamar isso de "Gráfico de material" ou, no estilo ThreeJS invertido, de "GraphMaterial". Ou se você insiste em usar o termo "Node", eu o chamaria de "NodeBasedMaterial".

Para mim, ambos parecem bons. Deixo a decisão para @mrdoob o que você acha?

Já gosto de NodeMaterial ... Talvez NodesMaterial ? NodeGraphMaterial ? @WestLangley alguma sugestão?

No entanto, eu renomeia os nós atuais ... NodeColor , NodeFloat , NodeTexture , ... para ColorNode , FloatNode , TextureNode

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

Não consigo carregar isso 😐

Eu colocaria isso em exemplos para começar. Assim que estiver bem definido, podemos movê-lo posteriormente para src: blush:

@mrdoob vai ser ótimo.

Gostaria de renomear os nós atuais embora ... NodeColor, NodeFloat, NodeTexture, ... para ColorNode, FloatNode, TextureNode

Eu irei encaminhá-lo então.

este é o url local: blush:, tente isto:
http://sea3d.poonya.com/flow/

@WestLangley alguma sugestão?

Eu sugiro THREE.FlowMaterial .

Minha segunda opção seria THREE.CustomMaterial .

Como um espectador completamente aleatório. NodeMaterial parece muito intuitivo para mim, porque é assim que eles são chamados no Blender3D

Se @mrdoob gosta de NodeMaterial, podemos ficar com ele. :)

NodeMaterial então é 😁

Este projeto é incrível! Acabei de ver a demonstração no Twitter e é muito impressionante.

Eu me pergunto se os nós devem ser algo que vá para o Três núcleos. Eles são muito específicos de implementação. Eu também estou construindo um editor de gráfico de sombreador Three.js (ainda não lançado) para ShaderFrog.com, e a solução que tenho é apenas exportar o código GLSL e todos os metadados necessários, como nomes uniformes, em um pequeno arquivo JSON e carregá-lo com uma biblioteca de tempo de execução externa

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

Este editor de gráfico pode trabalhar com shaders completos, analisando seu código-fonte, o que significa que nenhum tipo específico de nó de shader é necessário. Esse tipo de NodeMaterial também poderia ser manipulado inteiramente fora do núcleo do Three? Tudo o que você realmente precisa é um RawShaderMaterial para alguém usar em seu próprio projeto.

Esse tipo de NodeMaterial também poderia ser manipulado inteiramente fora do núcleo do Three? Tudo o que você realmente precisa é um RawShaderMaterial para alguém usar em seu próprio projeto.

@DelvarWorld Olá. Sim, em teoria, mas é muito cedo para fazer um bom shader a partir do raw. Na hora é melhor com uma interface inicial. Também ajuda a manter a compatibilidade com Skin / Morph e outros componentes nativos do Three.JS.

Pensei em observar um pequeno problema:
Em "Fluxo", os conectores não chegam ao nível superior ao arrastar nós uns sobre os outros.
Talvez esse problema esteja esperando por camadas ou algo parecido.

Eu me pergunto se existe uma maneira de unificar as duas abordagens? Estou interessado em um sombreador de várias camadas e, para isso, você precisa ter vários BSDFs que contribuam para o resultado final. Isso significa que é necessário separar mais o modelo de sombreamento - agora ele está fortemente acoplado ao design atual de @sunag . Acho que devemos ir em uma direção em que não seja necessário ter um material padrão ou Phong especificado, pode ser cru como o que @DelvarWorld tem. Eu acho que podemos mover para lá gradualmente, então o que @sunag tem é um bom começo.

Esta não é uma resposta detalhada, mas há algum tempo criei uma proposta aproximada para um formato de shader portátil que inclui metadados, como nomes uniformes, seus tipos, seu tipo em Three.js, etc. https://github.com /DelvarWorld/ShaderFrog-Runtime/blob/master/THREE_SHADER_FORMAT.md

Tudo o que um shader realmente precisa para ser executado em um ambiente real é o código-fonte do shader bruto (já que a GPU o compila) e, por conveniência, quais uniformes o usuário pode definir com quais valores. Esta proposta grosseira não inclui nenhuma noção de construção de um sombreador programaticamente, é apenas uma entrega simples para GLSL e metadados. É compatível com Three.js porque você só precisa colocá-lo em RawShaderMaterial no final.

Atualmente não há como tornar os shaders portáteis no Three.js ou exportá-los de qualquer aplicativo, o que me deu a ideia de propor um padrão, e acho que poderia resolver os dois problemas, já que estamos construindo aplicativos externos que no final cuspiu um material pré-determinado. Isso também significa que os detalhes de implementação da compilação de combinações específicas de um gráfico são deixados para os aplicativos, não Three.js.

Este padrão de sombreador proposto tem um lugar no Três? Eu não faço ideia. No momento, é provavelmente mais útil para mim do que para o núcleo do Three, já que o Three constrói seus próprios shaders do seu próprio jeito.

@DelvarWorld Eu

https://github.com/OpenMaterialGraph/OpenMaterialGraph

Especificações do nó aqui:

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

Especificações minimalistas de BSDFs aqui:

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

No entanto, isso é orientado para a renderização baseada em física.

Meu sentimento é que é necessário ter um shell de um shader para ThreeJS que seja de nível mais alto do que um shader bruto, mas um nível mais baixo do que o shader Phong. Basicamente, o shader padrão seria capaz de transformar alvos, bones, etc. E então todos esses shaders de esquema de iluminação específicos (Basic, Lambert, Phong, Standard) usariam esse modelo. No momento, há um shader de modelo implícito (incluímos as mesmas coisas em cada shader) - mas acho que poderíamos deixar mais claro onde conectar as coisas. Você pode conectar esquemas de iluminação (phong, lambert, basic ou multicamadas) e pode conectar propriedades a esses esquemas de iluminação que são seus nós gerais.

@bhouston oh legal, parece que temos muitos requisitos sobrepostos, também conhecido como valor padrão, nome de exibição, descrições legíveis por humanos, etc. Não sei o que o futuro reserva, mas seria uma mudança moderadamente fácil para mim usar um formato mais parecido com o que você propõe.

Um formato de shader formal faz muito sentido. No entanto, ele deve viver com a lib, para que possa evoluir com ela mais facilmente. Para alguém que é novo em three.js, existe alguma razão específica para tal coisa ainda não existir? Deve ser interessante para o editor se nada mais.

* EDITAR Talvez ter a especificação em three.js anularia seu propósito se fosse para ser consumido por outros canais de renderização.

No momento, é provavelmente mais útil para mim do que para o núcleo do Three, já que o Three constrói seus próprios shaders do seu próprio jeito.

Você pode gerar o mesmo material em outro idioma se fizer modificações dentro de THREE.NodeGL.prototype.generate , uma vez que um NodeMaterial (* Flow) é uma linguagem visual. O NodeBuilder pode ser a porta para isso. Atualmente é o intermediário de dados entre nós.

Limpei um exemplo de NodeMaterial "bruto": ele ainda pode gerar vários bugs.
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

Acho que para avançar isso com partículas criadas nódulos de raiz. NodePass para Multi-Pass e NodeMaterialD após o PR o que devo fazer em alguns dias.

Eu sugeri um THREE.ShaderFrogLoader em vez de um sombreador de tempo de execução.

Em "Fluxo", os conectores não chegam ao nível superior ao arrastar nós uns sobre os outros.

@MasterJames Obrigado! Eu estarei olhando para ele.

: +1:

Comecei a criar os exemplos. Espero terminar esta semana. : sweat_smile:
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html

Pensamentos?

@sunag +1: -)

+1!

Isso é tão incrível. Eu prefiro a textura das plantas + parede ao invés do deslocamento parecido com o turvo. :) Isso é simplesmente lindo.

Eu prefiro a textura das plantas + parede ao invés do deslocamento parecido com o turvo.

Você se refere ao exemplo de 'camadas'? Ainda postarei mais exemplos para nós

gpu soft-body
soft-body

Para comparação com uma abordagem diferente, o editor gráfico Shader Frog agora está ao vivo e está na fase de "chute os pneus". Eu gostaria de enfatizar que não requer nenhuma alteração no núcleo do Three.js.

ShaderFrog atualmente tem mais poder do que os editores de nó tradicionais. Ele tem infinitos tipos de nós para trabalhar porque pode analisar e entender qualquer sombreador . Por exemplo, para aplicar um reflexo apenas às bordas de um objeto, você pode simplesmente pegar um shader de brilho , que é um shader totalmente autônomo com um shader de fragmento e vértice:

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

... e multiplique por um shader de reflexão ...

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

... usando o gráfico de sombreador ...

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

E ta-da! Um shader de borda de reflexão .

Você também pode, por exemplo, mascarar quaisquer dois sombreadores usando qualquer outro sombreador e assim por diante:

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

Observe que o único "tipo de nó" exigido por este processo é um nó múltiplo (existem outros em ShaderFrog), que é quase totalmente independente de GLSL. O ShaderFrog pode funcionar com qualquer sombreador, e é por isso que possui infinitos tipos de nós. Essa abordagem de tecnologia avançada permite essa manipulação independente das alterações do Three.js.

ShaderFrog tem suporte de exportação de primeira classe para Three.js, gratuitamente. Tudo sem modificar o código-fonte do Three.js. Sea3D é um produto de terceiros, como o ShaderFrog. Colocar a mecânica do produto de terceiros no núcleo do Three parece uma vantagem injusta e não entendo politicamente.

@DelvarWorld Eu realmente não vejo uma abstração de construção de sombreador baseada em nó como tecnologia específica de terceiros. Se houver alguma coisa, ele permite que mais concorrentes se envolvam na tecnologia de sombreador baseada em nós e todos se beneficiem do benefício adicional do trabalho uns dos outros (mais nós, construção otimizada, etc.).

Como um programador gráfico como eu, que entende shaders em alto nível (de ferramentas como o Blender 3D), mas não em um nível baixo, a abstração baseada em nó parece uma ótima maneira de interagir programaticamente com shaders usando meu conhecimento de modelagem 3D. Eu entendo a configuração do nó para PBR, por exemplo, mas Deus me ajude se eu quiser escrever isso em GLSL.

@DelvarWorld incrível. Eu amo o novo editor.

@DelvarWorld +1 Muito bom! : -)

Obrigado! :)

Eu realmente não vejo uma abstração de construção de sombreador baseada em nó como tecnologia específica de terceiros.

Eu entendo a configuração do nó para PBR, por exemplo

Parte do meu contra-exemplo aqui é que você pode obter essas duas coisas gratuitamente, independentemente do Three.js. Todos os shaders ShaderFrog são de código aberto, portanto, quaisquer nós que se tornem parte de uma implementação PBR também podem ser aprendidos, editados e aprimorados ao longo do tempo (bem como compostos com quaisquer outros shaders, não apenas alguns subconjuntos no núcleo Three.js). Para mim, o fato de que tudo isso pode ser realizado sem as alterações do Three significa que é desnecessário e confunde a linha entre Three.js ser uma API webgl wrapper e agora direcionar recursos específicos de implementação. O armazenamento de dados de nó de sombreador é altamente específico do aplicativo e, até onde eu sei, não há atualmente um formato padrão de editor de nó comum para qualquer software. Reforçar um pode ser prejudicial para outras implementações.

@DelvarWorld Pelo que entendi esta mudança, ShaderFrog ainda será capaz de funcionar e continuaria a ser capaz de ir além do GraphMaterial se assim desejado. Eu olhei o exemplo de código-fonte do GraphMaterial e pude entender a simplicidade de como ele funcionava sem nem mesmo ter que pensar em uma solução / editor de terceiros. Como um desenvolvedor gráfico, estou preocupado em como fazer materiais que impressionem rapidamente de maneira programática. Acho que essa é uma preocupação adequada da ThreeJS.

Acho que NodeMaterial e Flow têm dois focos diferentes. Flow e ShaderFrog são ambos editores visuais de solução de terceiros atualmente em código fechado (acho que principalmente em artistas para isso). O NodeMaterial é um editor de sombreador de código aberto para programadores feito para o Three.JS. Eu concordo com @richardanaya no sentido de que ShaderFrog pode ir além do NodeMaterial se desejar. Assim como acho que Flow não precisa ser apenas um editor de materiais. Eu realmente espero grandes melhorias no ShaderFrog no futuro, como de costume.

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

@sunag Eu estava

  • Eu gostaria de ver um PR mais cedo ou mais tarde. Eu posso ajudar. :)
  • Pode ser legal permitir atributos arbitrários em vez de apenas os padrões (uv, uv2, normal, posição, etc.) Eu sei que muitos sombreadores podem se beneficiar dos vec4s tangentes, mais do que apenas 2 uvs e também cores múltiplas atributos. Portanto, eu generalizaria o needsPosition em um array requiredAttributes ou algo assim.
  • Eu sugeriria alguma organização dos nós no NodeMaterial principal, os BRDFs (Phong, Standard, etc), nós de textura (NodeCubeTexture, NodeTexture), nós acessadores (?) (NodePosition, NodeNormal), nós matemáticos (NodeOperator, etc. ), nós de utilidade (NodeSwitch, ...) e extra (?) (NodeVelocity, ...) Acho que isso ajudaria muito.
  • Seria bom ter acessores de matriz para as matrizes Projection, View e World.
  • Estão faltando alguns dos operadores: % ^ & << >> ~ |
  • Não tenho certeza se vejo o valor em NodePhongMaterial quando a classe é tão pequena, eu apenas faria com que os usuários tivessem que criá-lo usando o nó NodePhong combinado com um NodeMaterial (embora eu ainda não goste desse nome, GraphMaterial parece muito mais natureza para mim, mas posso viver com ela.)
  • Eu chamaria NodeTimer -> NodeTime ... mas novamente preferência pessoal.
  • Eu me pergunto se há alguma maneira de combinar muitos dos nós variáveis ​​em um, como você fez com NodeMath #, NodeOperator. Eles parecem tão semelhantes: NodeViewPosition, NodeWorldPosition, NodeViewNormal, NodeTransformedNormal, NodeTransformedPosition, NodeProjectPosition ...
  • Gostaria de ver o conjunto de argumentos opcionais para NodeMath #, NodeOperator em um formato que pode ser uma lista, para que seja possível preencher facilmente uma caixa suspensa com ele. No momento, porque eles são membros apenas capitalizados nas classes, é um pouco mais difícil identificá-los. Não tenho certeza de uma boa solução que ainda seja conveniente para codificação. Talvez apenas coletando-os em uma lista após suas definições como membros da classe, então apenas adicionar essas listas?
  • NodeTransformedNormal, NodeTransformedPosition são difíceis para mim descobrir o que são sem olhar para o código. Eles estão no espaço do mundo, espaço de visão, espaço do objeto? "Transformado" é um termo muito genérico, o que significa apenas multiplicado por uma matriz. Vou olhar o código para eles agora ....
  • Eu permitiria que NodeUV e NodeColor obtivessem um índice em vez de serem limitados a 2 e 1 canal, respectivamente. Novamente, eu gostaria de ver isso genérico, na verdade você passa uma string ou uma de uma série de presets, em vez de codificá-la para um conjunto de canais específicos. Você ainda pode ter alguns caminhos de código dedicados para algumas variáveis, mas voltaria a algo genérico para nomes que não reconhece para tratamento de casos especiais.

Mais feedback:

  • Eu gostaria de ter um gráfico com mais de um BRDF, basicamente dois Standard BRDF e depois fazer preservação de energia entre eles. Depois de obter o PR, gostaria de adicionar esta funcionalidade. Isso tornará o sistema mais genérico e poderoso.

@bhouston Uau! Obrigado!

Os atributos de solicitação, organização de pastas, NodeTime, NodePosition, NodeNormal, NodeView foram revisados. Adicionados +3 exemplos também.

nos operadores e na matriz, temos que adicionar compatibilidade com integer e matrix conversões. Para que isso seja feito de forma automática como em float / vetores #. Temos trabalho suficiente para as próximas atualizações ..: sweat_smile:

Amanhã farei o PR. Eu tenho que revisar algumas coisas ainda.

@sunag :

Acredito que seja um bug:

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

                        roughnessA.number = val;

                    }, false, 0, 1 );

Acredito que seja um bug:

Obrigado!

Acabei de ir para a página de exemplo e ver um gráfico de nó PBR <3

Niice!

Eu ia sugerir o uso de nós para pós-processamento, mas estava esperando que a primeira parte fosse concluída. Droga, isso é lindo!

NodeMaterial rev 5 + LightNode

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

Pele
nodematerial-rev5-skin

Toon Shading
nodematerial-rev5-toon

++ color-adjustment e plush exemplos.

Legal!

subsurface scattering : sweat_smile:

Este é um tipo de sombreador que pode funcionar em atualizações futuras.

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

sss-img1
sss-img2

😮!

Obrigado pelo incrível NodeMaterial!

Tenho vários comentários / bugs:

  • nó de função de quebra de espaço em branco à direita
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 com o parâmetro int no nó de função

exemplo de trabalho com 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;

exemplo quebrado com 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;
  • sugestão: passe os parâmetros da função no construtor 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) ] );
  • o PhongNodeMaterial é compatível com o mapa de relevo?

mais algumas notas:

  • problema com PositionNode.LOCAL no sombreador de fragmento no NodeMaterial "bruto":
var material = new THREE.NodeMaterial(
        new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.PROJECTION ) ),
        new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.LOCAL ) )
    );

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

Provavelmente a funcionalidade "transformada" deve ser movida de materiais de nó Phong / Standart para 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 ) )
    );

Nesse caso, o shader de resultado contém
gl_Position = ((projectionMatrix * modelViewMatrix * vec4 (position, 1.0)) * TWO);
mas a constante DOIS não é declarada. É meu erro ou bug?
Além disso, ConstNode é sensível ao ponto-e-vírgula, portanto, "float TWO = 2.0" não é analisado.

Obrigado @dimarudol ! Se quiser se sentir à vontade com as notas o mais rápido possível faremos a nova revisão.

mas a constante DOIS não é declarada. É meu erro ou bug?

Vou considerar esta forma de uso e em material por exemplo material.include( node )

Na época, tente uma 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 ) )
    );

Olá @sunag , tenho tocado com Sea3d Flow e parece muito legal. Só queria perguntar se existe um repositório oficial em algum lugar para isso.
Cumprimentos.

Olá @rraallvv , ainda não, já está para ficar pronto. Assim que possível, posto a notícia.

Obrigado @sunag , é muito apreciado.

Olá @sunag ! Você fez um trabalho muito bom!
Eu tenho uma pergunta: para o meu projeto seria ótimo usar sua estrutura de nós, mas eu preciso de cor por vértice (e valores flutuantes personalizados por vértice), mas em seu sistema de nós você só tem colorNode e floatNode aplicados a toda a malha .. Você acha que existe uma maneira de implementar facilmente algo como bufferColorNode (usando THREE.BufferAttribute)?

Por exemplo, eu tenho esta cena:

screenshot from 2016-08-31 16 27 06

Cada vértice tem sua própria cor. É possível com THREE.BufferAttribute e um THREE.ShaderMaterial, mas não há equivalente em seu código.

Eu precisaria de algo como:
`deixe material = novo THREE.StandardNodeMaterial ();
deixe texColorMap = new THREE.TextureNode (new THREE.TextureLoader (). load ("colorMap.jpg"));
deixe customData = new THREE.BufferFloatNode (new Float32Array (...), "dados"); // O segundo parâmetro é o nome do atributo

deixe colorMap = new THREE.FunctionNode ([
"vec3 colorMap (sampler2D texColorMap, float data) {",
"return vec3 (texture2D (texColorMap, customFunc (data)));", // customFunc retorna um vec2 dependendo dos dados
"}"
] .join ("n"));

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

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

A propósito, parece que não posso usar os parâmetros sampler2D para o FunctionNode ...

Estou esquecendo de algo ?
Acho que poderia ajudar se necessário :)

@martinRenou Obrigado! Hmm, talvez algo como por agora:

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

Eu não tinha pensado ainda em atribuir um atributo de geometria dinâmica com nó. Mas acho que é uma boa ideia ... talvez algo como THREE.BufferAttributeNode ...

@sunag obrigado pela sua resposta :)
Vou tentar isso. Se estiver tudo bem para você, começarei a trabalhar em um THREE.BufferAttributeNode, por enquanto ainda estou lendo seu código e tentando entender a estrutura.

  1. Com relação a THREE.FunctionNode, como eu disse, eu realmente preciso definir um sampler2D em meus parâmetros, pois ele é usado como um mapa de cores. A cor do pixel é calculada com texture2D () e o segundo parâmetro de texture2D () é calculado usando meus dados personalizados (que é, por exemplo, uma temperatura).
    Eu entendo que a ideia de usar parâmetros vec3 era para ser amigável com os usuários, mas FunctionNode também poderia suportar parâmetros sampler2D, você não acha?
  2. Além disso, THREE.FunctionNode escreve apenas no sombreador de fragmento, mas não seria bom poder escrever no sombreador de vértice também?

Este seria o meu caso de uso, é denominado IsoColor, porque a cor corresponde a um dado (temperatura, pressão ...) vermelho -> alta temperatura, azul -> baixa temperatura:
screenshot from 2016-09-01 17 29 58

  1. Estou pensando em escrever um THREE.IsoColorNode (que substituiria o FunctionNode do meu diagrama) e outros nós que seriam muito interessantes para visualizações científicas. Você está interessado nisso? @mrdoob você também estaria interessado?

Com relação a THREE.FunctionNode, como eu disse, eu realmente preciso definir um sampler2D em meus parâmetros, pois ele é usado como um mapa de cores. A cor do pixel é calculada com texture2D () e o segundo parâmetro de texture2D () é calculado usando meus dados personalizados (que é, por exemplo, uma temperatura). Eu entendo que a ideia de usar parâmetros vec3 era para ser amigável com os usuários, mas FunctionNode também poderia suportar parâmetros sampler2D, você não acha?

Eu entendo sua necessidade agora! Vou criar um PR para esta e outras notas do @dimarudol ...

Além disso, THREE.FunctionNode escreve apenas no sombreador de fragmento, mas não seria bom poder escrever no sombreador de vértice também?

Eu não testei isso, mas acho que sim.

Eu adicionei mais dois exemplos:

  • sampler2D estão em triangle-blur exemplo
  • custom BufferAttribute estão em custom-attribute exemplo

Está funcionando mas ainda vou dar um polido no código ...

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

Uau ! Você realmente fez um bom trabalho, está funcionando para mim também: sorria:

Obrigado novamente por seu trabalho !

Olá @sunag ,

Por enquanto, não podemos ter FunctionNode com o tipo "void", pois precisamos enviá-lo para o material como um parâmetro (color, alpha ...). Por exemplo, se eu quiser implementar um FunctionNode de plano de clipe, tudo que quero fazer é escrever uma parte de sombreador como esta:

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

Mas não dá para dar ao material ... Uma solução seria devolver uma bóia que é canal alfa, mas que não está limpa e otimizada. Você não acha que seria legal adicionar algumas funções de vazio a um material como este:

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 um exemplo mais "design", se eu quiser fazer furos no meu bule com esta textura:
wood-hole-texture
Eu gostaria de fazer algo assim:

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;

Outra coisa é que não temos controle sobre a ordem das funções nos shaders. Se tenho funções que não são comutativas, não tenho controle sobre o resultado ...

vamos ver este exemplo:

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;

Se um ponto está atrás do plano de transparência e vem além devido ao deslocamento, no caso em que "transparentPlaneCall" é chamado antes de "displacementCall" alfa = 1., e no caso em que é chamado depois de alfa = 0,5.
Então, eu gostaria de definir a ordem das chamadas de função ... Você sabe o que quero dizer?

Olá @martinRenou

Hmm, cerca de void funções talvez ProxyNode para usar no slot porque isso precisa seguir uma ordem ou inicializar no início ou no final do código, talvez functionsStart ou functionsEnd slots ...

Usando alpha slot se alpha for 0 é descartado automaticamente.
https://github.com/mrdoob/three.js/blob/dev/examples/js/nodes/materials/PhongNode.js#L180

Gostaria de definir a ordem das chamadas de função ...

Existe uma sequência, veja aqui:
https://github.com/mrdoob/three.js/blob/dev/examples/js/nodes/materials/PhongNode.js#L122

A ordem das funções é feita automaticamente usando o algoritmo dependencies simples, deve colocar FunctionCall em um slot anterior, color é o primeiro specular é o segundo, por exemplo.

Este exemplo são dois códigos de shader diferentes: fragment to transparencyPlaneCall e vertex to displacementCall .

Isso me faz pensar que usar variáveis ​​( varying e locais) para expandir não as entradas e apenas const será muito interessante. Talvez um VarNode ...

O uso do slot alpha se alpha for 0 é descartado automaticamente.

Desculpe por isso, não vi.

A ordem das funções é feita automaticamente usando algoritmo de dependências simples, deve colocar o FunctionCall em um slot anterior, a cor é o primeiro especular é o segundo por exemplo.

Eu entendo, na verdade eu só queria ter certeza de que a função que descartar pixels foi chamada primeiro. Parece bom usar alfa se você descartá-lo logo após minhas funções: smiley:

Este exemplo é um código de sombreador diferente: fragment to transparentPlaneCall e vertex to displacementCall.

Direito ! Então esse não foi um bom exemplo. Meu erro.

Concluído r6 - # 9636

Legal ! Obrigado por suas respostas.

Isso me faz pensar que usar variáveis ​​(variando e locais) para expandir não as entradas e apenas const será muito interessante. Talvez um VarNode ...

Parece bom também, pode ser interessante ser capaz de escrever explicitamente uma função no sombreador de vértice, usar um varNode e usá-lo com uma função no sombreador de fragmento. Você não acha?

@sunag
Acho que há um problema com o uso de AttributeNode com FunctionNode no sombreador de vértice.

Se eu tiver um 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;

O shader é escrito nesta ordem:

...
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;
...
}

Uma correção simples seria inicializar nVdata para dados?

Parece bom também, pode ser interessante ser capaz de escrever explicitamente uma função no sombreador de vértice, usar um varNode e usá-lo com uma função no sombreador de fragmento. Você não acha?

Isso! A ideia é uma melhor comunicação com sombreadores de vértice / fragmento usando varying como VarNode . Isso se encaixa perfeitamente agora com o recurso keywords .

Eu crio um exemplo mínimo de varying mas ainda não há solução para void function .

Acho que há um problema com o uso de AttributeNode com FunctionNode no sombreador de vértice.

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

Olá @sunag , vi seu exemplo variado e me parece estranho colocar a variável em mtl.transform como você fez ... Talvez você mude isso quando for possível criar funções nulas?
No entanto, parece uma boa ideia que as palavras-chave apresentem: smiley:

Na verdade, acho que seria uma boa ideia colocar essas variações em mtl.varyings (mtl.varyings é uma matriz) assim: mtl.varyings.push(myVar) . Usando a mesma ideia, poderíamos colocar funções em shaders de vértice e fragmento como este: mtl.vertexFunctions.push(myVertexFunctionCall) , da mesma forma com mtl.fragmentFunctions .

Dessa forma, poderíamos fazer muitos cálculos sobre essas variações e, em seguida, usá-los para efeitos. Essas funções seriam funções nulas.

Como nas imagens acima, onde os nós estão conectados visualmente, como podemos recriar isso mentalmente com esta API? Vejo que os construtores aceitam outros nós. É assim que a saída de um nó (passada para um construtor) é entrada para outro nó (ele recebe os nós em seu construtor)? Um nó tem no máximo uma saída? Quantos nós podem ser entradas para outro nó por meio do construtor, ou é limitado?

@trusktr É ilimitado claro quanto mais nós isso consome mais CPU em tempo de construção e GPU em tempo de execução. Os nós são ajustados de acordo com os valores de entradas e saídas, a conversão de float em vec2 ou vec3 por exemplo é automática e armazena em cache se usado mais de uma vez para otimização (veja TempNode ).

Nas capturas de tela, cada nó é uma classe, por exemplo: PositionNode no display é:
https://github.com/mrdoob/three.js/blob/789efa65bafe022e178c7e93e0985a7607a54403/examples/js/nodes/accessors/PositionNode.js#L5

@mrdoob @sunag , você gostaria de comentar sobre o status atual do código NodeMaterial e como ele se encaixa no roteiro do three.js?

Em teoria, poderíamos usar nós para várias coisas agora, como:

  • Implemente materiais PBR de especificação / brilho glTF como NodeStandardSGMaterial.
  • Suporta conjuntos e transformações UV por mapa
  • Simplifique o uso de materiais embutidos com instanciação

Mas é difícil justificar a adição de uma dependência no GLTFLoader para todos os arquivos de nó. E provavelmente é difícil justificar colocar nós em src/* sem um uso mais ativo. Ovo de galinha. 😅

Seria útil conhecer o plano de longo prazo do NodeMaterial, para adivinhar quais recursos estão (ou não) relacionados ... isso precisa de mais desenvolvimento? Existem coisas que outros colaboradores poderiam estar fazendo para ajudar?

@sunag sim, eu também gostaria de saber se você tem mais planos neste momento.

Em teoria, poderíamos usar nós para várias coisas agora, como:

  • Implemente materiais PBR de especificação / brilho glTF como NodeStandardSGMaterial.
  • Suporta conjuntos e transformações UV por mapa
  • Simplifique o uso de materiais embutidos com instanciação

Esses problemas específicos agora têm exemplos de como serem resolvidos com as APIs existentes, sem a necessidade de modificar o núcleo:

Instanciando:
https://github.com/mrdoob/three.js/pull/10750 (totalmente desenvolvido, toca no núcleo, mas pode ser corrigido)
https://github.com/mrdoob/three.js/pull/14166 (extensões de material simples via onBeforeCompile)
https://github.com/mrdoob/three.js/pull/14012 (simples, extensão de biblioteca via patch de mokey)

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

spec-gloss como sua própria classe
https://github.com/mrdoob/three.js/pull/14099

Talvez possa servir para aliviar a sensação de urgência de colocar NodeMaterial no núcleo :).

Para aqueles que seguem este tópico, há alguma discussão em andamento em https://github.com/mrdoob/three.js/pull/14149.

Unindo tópicos de # 14149:

tl; dr - NodeMaterial me parece uma próxima etapa muito promissora para o sistema de materiais. Suspeito que a adoção do NodeMaterial está atualmente limitada por algumas coisas:

  • atrito de incluir muitos arquivos individuais
  • falta de um editor visual
  • relativamente poucos exemplos, docs

Eu deixaria a questão de quando / se NodeMaterial deveria estar em src/ para @mrdoob e @sunag , mas acho que devemos avançar com (pelo menos) abordando as três questões acima. Também seria útil saber se outras pessoas veem o NodeMaterial como uma alternativa ao sistema de materiais atual ou uma substituição completa.



A massa crítica parece estar se formando pelas partes interessadas do GLTFLoader, e minha observação (subjetiva) é que a necessidade surgiu por causa da documentação incorreta noBeforeRender (alguns exemplos) e ainda menos documentada noBeforeCompile (um exemplo).

@pailhead Comecei a manter o GLTFLoader para resolver problemas de fluxo de trabalho no A-Frame, do qual também sou um desenvolvedor. Concordo que o objetivo é um sistema de material mais útil, não carregar um formato específico. A decisão de como integrar (ou não) os materiais do nó deve ser baseada nos méritos dos usuários finais da biblioteca three.js - recursos, flexibilidade, uma API compreensível.

Você está certo que onBeforeCompile e onBeforeRender ganchos são infinitamente flexíveis; não há limite prático para o quanto você pode manipular ou substituir os sombreadores subjacentes. Mas ambos são igualmente falhos como API de material primário:

  1. Força a sintaxe WebGL na API de material, mesmo para recursos relativamente simples
  2. Depende da manipulação de string de shaders de material do núcleo, tornando as alterações nos materiais do núcleo mais difíceis ao longo do tempo e mais frágeis
  3. Menos acessível para artistas
  4. Praticamente não serializável

Decoradores (por exemplo, # 14206) certamente melhoram isso da perspectiva do usuário - mas se o desenvolvimento de recursos futuros de materiais for baseado em decoradores cada vez mais complicados sobre os sombreadores de material existentes, isso é um risco de manutenção, em minha opinião.

Os materiais do nó não são perfeitos, mas são amplamente adotados em outras ferramentas gráficas e têm vantagens importantes:

  1. Flexível e compostável
  2. Preserva uma camada de abstração dos shaders WebGL internos da biblioteca sem remover o acesso aos shaders simples quando necessário
  3. Representação de material amplamente popular para artistas e desenvolvedores de jogos
  4. Pelo menos um pouco serializável (embora a conversão para outros formatos ainda seja difícil)

Isso provavelmente soa como se eu estivesse dizendo que onBeforeCompile deveria ser descontinuado, e não é minha intenção - ficaria feliz em vê-lo persistir, e exemplos são bem-vindos. Mas não é uma API que eu quero apontar para os usuários A-Frame ou three.js para mais casos do que o necessário; Não acho que se compare bem com os sistemas de materiais em outras ferramentas 3D.

  • atrito de incluir muitos arquivos individuais

Isso não deve ser atrito. Acho que seria útil fazer algum tipo de pesquisa ou algo assim, para ver quantas pessoas usam bundlers e ferramentas de construção. Importar arquivos js em um arquivo html manualmente não deve ser uma abordagem em 2018. Este é o único número que posso encontrar , e acho que pode-se supor que todos esses usuários estão usando com algo que funciona com o nó.

Eu colocaria mais esforço em sacudir a árvore e ser capaz de import/export isso da maneira adequada do que me preocupar sobre como isso funcionaria ao incluir manualmente os arquivos de script.

  • falta de um editor visual
  • relativamente poucos exemplos, docs

Eu acho que isso deve acontecer antes de chegar ao núcleo. O material de brilho especular deve ser um exemplo que não está associado a GLTFLoader . O fato de estar em /src ou /examples deve ser irrelevante?

@donmccurdy

Você está certo de que os ganchos onBeforeCompile e onBeforeRender são infinitamente flexíveis; não há limite prático para o quanto você pode manipular ou substituir os sombreadores subjacentes.

Na verdade, não estou afirmando isso, estou afirmando que um gancho como onBeforeRender permite uma abordagem diferente para estruturar o código, mas que não deve ser usado como é usado agora no GLTFLoader (portanto, # 14099).

onBeforeCompile definitivamente tem limitações e pode ser nomeado incorretamente. Uma boa coisa a se destacar neste contexto é um recente PR # 14214. Assim que vi o que foi embora ( build() em favor de needsUpdate ), sabia que veria onBeforeCompile ali. Usei-o como onBeforeParse pois se eu não substituir nenhuma instrução #include <foo> , eles ainda serão analisados ​​após esta função e antes da compilação real. Neste PR está sendo usado como onWillRefreshMaterial .

A filosofia que estou tentando transmitir é que provavelmente deveria haver mais granularidade com esse tipo de retorno de chamada. Deve haver mais deles, e muito cuidado deve ser tomado ao nomeá-los.

# 14214 é um ótimo exemplo de por que NodeMaterial não precisa estar no núcleo. Pelo menos não junto com nada em /renderer , e não junto com ele.

  1. Força a sintaxe WebGL na API de material, mesmo para recursos relativamente simples

Já ouvi esse problema antes, mas não foi elaborado. Por que isso é um problema? O que é a "API material" de qualquer maneira? Eu sempre vi isso como "aqui estão alguns materiais de sombreamento de superfície comuns".

Se você quer um mapa dinâmico, não vejo razão para material.map , ou 'material.color' não poder levar 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 da manipulação de string de shaders de material do núcleo, tornando as alterações nos materiais do núcleo mais difíceis ao longo do tempo e mais frágeis

Meu ponto é que isso já é possível com onBeforeCompile mas torna essas mudanças ainda mais difíceis e mais frágeis do que o que você está descrevendo. Já procurei isso na minha vida profissional e tenho alguns códigos que dependem disso. Como é frágil, causa muito estresse :(

Os decoradores que você apontou # 14206 estão paralisados ​​há mais de um ano por causa desse PR, que já está paralisado há 3 anos. Meu sentimento subjetivo é que o # 14206 tornaria a escrita desses decoradores possível, menos tediosa e menos frágil. São 30 linhas de código que não afetam absolutamente nada, a menos que essas propriedades fantasmas sejam definidas. Se já temos uma corda para nos enforcarmos na forma de onBeforeCompile por que não torná-la um pouco mais humana? :sorriso:

No final, gostaria de decidir por mim mesmo o que é um nível aceitável de fragilidade e o que não é.

  1. Menos acessível para artistas

É por isso que os artistas deveriam ter uma ferramenta visual e algum tipo de formato para salvar os gráficos. Consumi-los como GLSL "cozido" ou algo que constrói NodeMaterial em tempo de execução deve ser uma escolha dada ao usuário.

Um artista pode criar um shader, um engenheiro pode pedir que ele seja "compilado" para otimizar o processo de carregamento. Um artista trabalhando sozinho poderia simplesmente carregar o gráfico, supondo que por algum motivo seja mais fácil ("compilar" exige mais esforço).

Além disso, por que e como os artistas estão sendo considerados aqui? Existem algumas estatísticas, como é a aparência de um usuário "artista" médio, por que eles estão trabalhando com o three.js e não com a unidade, ou seja. que tipo de pipeline é. Há engenheiros envolvidos, por que não uma ferramenta autônoma que se comunica com o three.js de alguma forma que algum diretório de tecnologia adota, etc. Estou assumindo que os downloads de 40k npm por semana não são artistas. Presume-se que esse tipo de instalação está sendo usado por algumas ferramentas de construção e é altamente improvável que seja importado manualmente.

Tanto neste quanto no ponto 2, meu caso de uso não envolve artistas e geralmente nenhum outro usuário. Estou desenvolvendo um sistema de materiais, construído sobre materiais embutidos. Eu uso meu próprio desempacotamento normal com atributos tangentes, peeling de profundidade, recorte diferente, etc. Tudo o que me importa é estruturar esse código internamente e expor o mínimo de detalhes internos para as classes acima.

  1. Praticamente não serializável

Não sei muito sobre isso e já ouvi esse argumento antes. Eu ficaria mais do que feliz em examinar algum código se alguém pudesse me indicar as áreas problemáticas. Com meu entendimento muito limitado (quase nenhum) do problema, não entendo por que simplesmente não é suficiente escrever

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

Digamos que você tenha um material de brilho de especificação construído com NodeMaterial , você não gostaria de serializar o gráfico inteiro, apenas as entradas? Qualquer que seja a serialização de um material SpecGloss , ela deve ter a mesma aparência? Provavelmente estou faltando muito aqui, gostaria de receber algumas dicas.

Re: serialização

Bastaria acrescentar:

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

customSerializer( data )

E então algo como

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

specularMap seria na verdade serializado porque está codificado:
https://github.com/mrdoob/three.js/blob/dev/src/materials/Material.js#L213

Mas isso parece meio estranho, a classe Material está ciente dos componentes internos de todos os materiais embutidos, parece?

@donmccurdy se você quiser ter essa discussão, pode ser melhor fazê-lo no decorador PR, # 14206. Off-line, estou disponível para uma sessão de trabalho tomando cerveja ou café em qualquer lugar na área da baía: ligeiramente_smiling_face:

Concordou que vários arquivos _não_ devem ser atritos, e que não é um argumento por si só para colocar NodeMaterial em src/ . É simplesmente uma das várias razões pelas quais o NodeMaterial ainda não é muito usado, e há outras maneiras de resolver isso. E eu certamente concordo que mais documentos seriam um pré-requisito para colocar o NodeMaterial em src/ , ou mesmo para empurrar a adoção em examples/js ou uma saída de compilação separada.

Estou otimista sobre NodeMaterial como uma direção geral, embora eu suspeite que há mais algumas coisas necessárias antes que isso pudesse fazer sentido em src/ . Estou muito preocupado em usar onBeforeCompile e manipulação de string como um caminho para colocar novos recursos no sistema de materiais, conforme descrito acima, e especialmente à medida que avançamos em direção ao suporte WebGL2 e (eventualmente) WebGPU . Isso não quer dizer que essas duas escolhas sejam as únicas opções, mas (das duas) essas são minhas ideias.

Sobre os outros pontos, parece que entendemos as preocupações e preferências uns dos outros, mas ainda discordamos. Já escrevi tudo o que tenho tempo para escrever neste momento e vou ficar de fora por um tempo e deixar que outros opinem. Obrigado por uma discussão cuidadosa e completa sobre isso. 🙂

Eu gostaria de colocar uma textura de oclusão ambiente com Multiply em uma textura difusa, então estou tentando isto:

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

Esta é a minha textura AO
ao sx

Infelizmente, tenho visto oclusão ambiental no meu modelo.

Você tem alguma ideia para fazer isso?
Espero que este seja o lugar certo para postar minha pergunta.

Obrigado!

Eu gostaria de ser capaz de pensar na direção de um mapeamento de ferramentas baseadas em nós existentes para materiais em três. Conseqüentemente, eu adoraria ver o NodeMaterial em src / junto com uma documentação adequada.

@IARI

Você pode listar as ferramentas baseadas em nós existentes?

@donmccurdy

Obrigado pela resposta :)

Infelizmente, acho que ainda não nos entendemos. Se você tiver tempo para ler esta postagem, essas coisas:

Estou muito preocupado em usar onBeforeCompile e manipulação de string como um caminho para colocar novos recursos no sistema de materiais,

onBeforeCompile é horrível, concordo, a única razão pela qual estou envolvido em qualquer um desses tópicos é que eu quero # 13198, que considero superior à manipulação de string de onBeforeCompile .

Este não deve ser um padrão para adicionar novos recursos ao three.js. Deve permitir que os usuários adicionem novos recursos aos seus aplicativos. Estou triste que @bhouston não compartilhou nenhuma descoberta sobre a manutenção de um fork para fazer algumas dessas coisas. Eu ficaria curioso se eles fizeram uma estrutura melhor para alterar os shaders ou se realmente hackearam o núcleo para esse recurso.

No caso de transformações uv por canal, eu faria disso um exemplo, ou módulo npm. Se 3 pessoas fizerem o download toda semana, provavelmente é algo que não deveria estar no núcleo. Se 20 mil pessoas fizerem o download, é provavelmente como o three.js deveria ter sido projetado em primeiro lugar.

onBeforeCompile parece que será crucial para os materiais do nó, https://github.com/mrdoob/three.js/pull/14214 , portanto, não é usado apenas para manipulação de strings .

Tenho onBeforeCompile e NodeMaterial para fazer isso, solicito uma terceira opção. Muito mais conveniente do que onBeforeCompile e muito menor do que NodeMaterial .

Com exemplos recentes:
https://github.com/mrdoob/three.js/pull/14206

Discussão antiga:
https://github.com/mrdoob/three.js/pull/13198

@pailhead Para começar, eu pensaria em alguns nós básicos do Blender Cycles.
Eu também acharia interessante brincar com Unitys Shadergraph.

@claudioviola Você pode adicionar material.shadow ou multiplicar por material.color = diffuse * oclusion difuso. A oclusão depende de luz indireta, AmbientLight , HemisphereLight ...

@IARI

Estou baixando 7,5 GB de Unity para verificar o ShaderGraph: ligeiramente_smiling_face:: Não tenho certeza se isso se qualificará como uma ferramenta para construir gráficos de sombreador, acho que é uma ferramenta para construir gráficos de sombreador para a unidade. Existem ferramentas autônomas para a criação de gráficos? Eu quero ver que tipo de arquivo isso salva o gráfico também, e como ele será transferido para three.js e NodeMaterial em /src .

Acho que @pailhead está isolado contra essa mudança de NodeMaterials para o núcleo neste momento. Não acho que seja útil para todos discutirem com @pailhead por dias. Acho que o projeto não deve ficar em dívida com um único indivíduo.

Isso não foi precipitado e não foi forçado. Sunag adicionou isso anos atrás. No momento, há uma necessidade para isso e outras alternativas não funcionaram (por exemplo, mescladas), então vamos tentar este caminho.

Todas as ferramentas principais, 3DS Max, UE4, Blender, Unity, Maya, Sketchfab usam gráficos de shader. Argumentar que o three.js deve estar em desvantagem permanente a esse respeito parece injusto com o three.js.

Não tenho certeza se este sistema de sombreador baseado em gráfico é perfeito no momento, mas uma vez que estiver no núcleo, todos nós podemos continuar a trabalhar com ele.

Eu insisto que continuemos a oferecer suporte à API de PhoneMaterial, StandardMaterial, etc. de alguma forma daqui para frente, para que não quebremos 95% dos projetos three.js, fazer isso seria irresponsável. Também é bom trabalhar com essas interfaces simples e diretas.

Não tenho capacidade nem desejo de impedir que isso se mova para o núcleo. Eu só estou esperando que ele possa desbloquear alguns PRs não relacionados, porque foi referido como um bloqueador. @bhouston , também nunca quis discutir com você, só estava curioso sobre seu fork e as experiências com ele.

Quando fiz as contas como um artista 3D faminto, gosto de todas as coisas baseadas em nós. Nuke era meu compositor favorito e gostaria de aprender a fazer ferramentas como essa. Eu só desejo que isso desbloqueie este em particular # 14231. Estou usando isso como uma plataforma de aprendizado para mim, mas se for perturbador, vou parar de postar, obrigado.

@pailhead Eu nunca trabalhei com isso, mas você provavelmente já ouviu falar do designer de substâncias? Pelo que eu entendi, essa ferramenta também vai além da criação de gráficos / shaders - mas é focada principalmente no design procedural de materiais - talvez essa seja uma pista interessante?

Além disso, não conheço ferramentas autônomas de cabeça, mas uma rápida pesquisa no Google resultou em dois:

No entanto, há também essa ferramenta para os nodes do threejs, que encontrei em um post do Twitter de @mrdoob em 2015 - embora pareça nunca ter sido atualizado, eu me pergunto por quê ....

Essa ferramenta parece ter sido referenciada aqui, mas não vejo uma maneira de exportar nada. O primeiro link parece incrível, mas a saída é bastante irregular, não muito legível em comparação com GLSL. Eu me pergunto se isso já pode ser usado para remontar o NodeMeterial , ou mesmo um ShaderMaterial .

Dei uma olhada na unidade, mas não consegui encontrar a ferramenta de gráfico de sombreador,

A propósito, se eu de alguma forma bloqueei isso, por todos os meios, deixe-o ser desbloqueado. O PR é de 2015, respondi pela primeira vez há 8 dias.

(Desculpe, isso é um pouco offtopic ..)
@pailhead Para
Aqui está um tutorial para configurá-lo começando com um novo projeto sendo configurado: https://youtu.be/Ar9eIn4z6XE?t=98

Esse editor de nó de material Sea3D Flow (http://sea3d.poonya.com/flow/) é de @sunag , o mesmo cara que escreveu NodeMaterial.

Muito obrigado @sunag
Como posso obter a luz indireta? É um valor no renderizador ou como posso calculá-lo?

Gostaria de aplicar um efeito de pós-processamento apenas a uma seleção de objetos (ou seja, alterar a saturação).
No entanto, não consigo encontrar nada relacionado ao mascaramento (se não houver outra maneira) com nós.
Atualmente estou lendo o OutlinePass (não-nó) que grava um monte de coisas em um monte de buffers, que posso ver como um método viável para alcançar o que quero - mas não tenho a menor ideia de como abordar isso com nós.

O editor do nó de material Sea3D Flow será autônomo da mesma forma que o editor three.js ou fará parte dele? Ele ainda se chamará Sea3D ou alguma outra coisa relacionada a three.js? Obrigado @sunag por lançar esse editor visual para a comunidade three.js.

mas não tenho a menor idéia de como abordar isso com nós.

@IARI

Parece que você conhece o GLSL, já que é capaz de ler o OutlinePass e entender o que ele faz. Você também parece entender isso o suficiente para ver que não pode alcançá-lo com nós. Eu pensei que se você sabe como codificá-lo, você saberá como fazer o nó. Ainda mais, se você não sabe como codificá-lo, você pode saber como fazer um nó. Onde está a desconexão?

Eu não vi esses posts de 2016. Interessante ver Shader Frog. Eu me pergunto se isso pode ser visto como vim vs emacs ou algo assim. Eu gosto de usar Sublime Text, você gosta de usar outra coisa. Um gosta de usar o shader frog, outro gosta de usar o editor Sea3D do three.js.

Eu gosto de como o Shader Frog apenas produz um shader, mas não é um código aberto como o Sea3D.

Então há isso.

Colocar a mecânica do produto de terceiros no núcleo do Three parece uma vantagem injusta e não entendo politicamente.

Para mim, o fato de que tudo isso pode ser realizado sem as alterações do Three significa que é desnecessário e confunde a linha entre Three.js ser uma API de wrapper webgl e agora direcionar recursos específicos de implementação. O armazenamento de dados de nó de sombreador é altamente específico do aplicativo e, até onde eu sei, não há atualmente um formato padrão de editor de nó comum para qualquer software. Reforçar um pode ser prejudicial para outras implementações.

@bhouston
Mal posso esperar que NodeMaterial pouse, pois isso pode desbloquear outros PRs e a vida pode voltar ao normal. Parece que outras vozes tentaram bloquear isso no passado.

Acho que @pailhead está isolado contra essa mudança de NodeMaterials para o núcleo neste momento.
Acho que o projeto não deve ficar em dívida com um único indivíduo.

Obrigada.

Não vejo nenhuma razão para que isso não possa ser alcançado com nós exatamente da mesma maneira que o outlinepass o faz - mas de uma forma que seja legível, compreensível e modular de forma que as partes possam ser reutilizadas.
Por que não deveria haver, por exemplo, nós de saída que gravam em buffers e outras coisas.

E eu realmente não conheço glsl muito bem, e também acho - perdoem minhas palavras - uma super chata de ler e escrever código de shader. E, além disso, é mais doloroso se estiver envolto em uma matriz estúpida de strings em código javascript.

Você usa webpack ou algo assim?

array estúpido

Só é estúpido se você tiver que importá-lo para um arquivo .html. Quando você trabalha com webpack e tem a sintaxe JS moderna, pode manter seu GLSL em arquivos .glsl, .vs, .fs e ter realce de sintaxe e outros.

shader.fs:

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

javascript (olha mãe, sem matrizes estúpidas)

import mShader from './shader.fs'

Minha preocupação é que não vejo muito valor em sua necessidade, já que você está perguntando especificamente como criar um efeito, não como codificar algo. NodeMaterial abrirá portas para milhares de perguntas "como faço para sombrear este efeito", que terão apenas uma resposta genérica:

Use os nós, Luke!

Não, ter que ler (muito menos escrever) código em duas linguagens diferentes dentro do mesmo arquivo para mim é sempre uma dor de ver. Além disso, o webpack não ajuda em nada, quando você está tentando estudar três exemplos de código de sombreador, que está todo embrulhado em feias matrizes de string unidas por quebras de linha.
De qualquer forma, este problema é sobre o sistema de nós, e eu fiz uma pergunta simples sobre nós - não para uma discussão sobre preferências pessoais de codificação - que não leva a lugar nenhum.

@IARI

Desculpe, de alguma forma não vi nenhum ponto de interrogação em sua postagem, então perdi sua pergunta.

Isso definitivamente não deve ser uma discussão sobre preferências pessoais de codificação, mas o fato de que existem diferentes deve ser considerado. Também estou um pouco preocupado com a enxurrada de perguntas do tipo "Como faço para fazer este shader".

Antes, essa barreira era muito alta, as pessoas simplesmente desistiam com i don't know glsl ou quando veem "uma matriz estúpida de strings". Mas se for mais baixo, todos tentarão escrever sombreadores.

Não encontrei sua pergunta, mas estou curioso para saber o que é. É isso:

Como faço um ToonShader com NodeMaterial?

Nesse caso, estou curioso para saber qual é a resposta.

Você não pode porque NodeMaterial não suporta alguma abstração.
Você pode, apenas usar NodeMaterial, para conectar nós

Talvez essa discussão pudesse se beneficiar em ser interrompida? É um número alto de posts, indo muito para trás (2015). NodeMaterial está em / examples, então você provavelmente pode construir seu toon shader a partir dele. Talvez você pudesse abrir outro problema ou postar no estouro de pilha especificamente para isso, e o resto da conversa poderia passar para um novo problema?

Podemos alegremente levar essa discussão para outro lugar, como algum canal de folga ou qualquer coisa - eu realmente tenho a sensação de que não pertence a este lugar, mas principalmente irritará as pessoas.

O fórum pode ser melhor do que folga para este caso específico.

@pailhead , toda essa discussão deixou de ser produtiva. Seria melhor encerrar este problema e fazer um novo focado no problema real em questão.

@bhouston

Concordo, exceto que acho que são vários problemas.

  • como implementar material de nó
  • devem outros PRs relacionados e não relacionados ser bloqueados
  • como permitir que pessoas que não sabem escrever sombreadores implementem certos efeitos de sombreador

Como faço um ToonShader com NodeMaterial?
Nesse caso, estou curioso para saber qual é a resposta.
Você não pode porque NodeMaterial não suporta alguma abstração.
Você pode, apenas usar NodeMaterial, para conectar nós

Lol. Eu concordo com @bhouston ... isso só pode ser uma piada. Você poderia ter visto o exemplo webgl_materials_nodes antes de dizer isso?

E se você quiser usar código, consulte a expressão usando FunctionNode .

toon

@sunag, acho que você me entendeu mal. Eu estava curioso para saber por que, se isso está atualmente em /examples e não em /src isso está sendo transformado em um cidadão de primeira classe. Este problema parece ter sido levantado por @AndrewRayCode em 2015.

Acabei de dizer que esse problema está sobrecarregado, por se estender até 2015 e por discutir vários tópicos diferentes. Se alguém perguntasse "como faço para fazer whatever ", seria chamado de estouro de pilha.

Se isso vai ser uma revisão massiva de three.js _ (o fato de que a unidade deve ser configurada especificamente para isso me assusta um pouco) _ então eu acho que deveria haver um problema em andamento dedicado aqui no github para essas questões - usage of NodeMaterial . Do jeito que está, pessoas que estão pedindo coisas aleatórias (# 14232) estão sendo encaminhadas para este tópico, isso torna a comunicação confusa :)

Recentemente, tive que escrever um toon shader, mas era baseado em linhas, mais especificamente nas linhas grossas de NodeMaterial que pode levar sabe-se lá quanto tempo. Todos esses são vários tópicos complicados aqui.

E se você quiser usar código, consulte a expressão usando FunctionNode.

Se eu codificar, usarei texto sublime, ShaderMaterial está bom para mim, não há necessidade de FunctionNode . Se eu criar efeitos visuais, provavelmente irei procurar um editor visual, mas esta é minha preferência. Só estou aqui porque isso bloqueou outros PRs :) Percebi não faz muito tempo que é do interesse de três que isso aconteça o mais rápido possível. Desembaraçar essa conversa provavelmente ajudaria a apressar as coisas. Concordo com @bhouston, isso deve ser yolod o mais rápido possível!

Obrigada.

Para que conste: não estou interessado em um toon shader ou algo parecido.
Estou implementando um sistema que permite que pessoas que não escrevem código conectem efeitos predefinidos simples em certas posições.

Infelizmente, não terei tempo para estudar como escrever nós agora, e tenho que atualizar a codificação glsl básica de qualquer maneira, então, por enquanto, estarei implementando coisas sem nós: não será extensível , ele usará várias passagens de renderização onde uma única provavelmente seria suficiente com uma boa implementação de nó, será menos legível, ...

Resumindo, infelizmente, sou novo no tópico geral e preciso obter um conhecimento muito mais básico, mas, a julgar pelo que sei, os nós seriam a melhor maneira de fazer isso de uma forma verdadeiramente elegante e extensível.
Eu adoraria ter algumas informações sobre a implementação de nós, como um artigo de blog ou tutorial.

Disclaimer: Não estou exigindo nada, apenas espero esclarecer meu pedido vago de cima.
Obrigado a todos por todo o trabalho que está sendo feito aqui - é absolutamente incrível.

No tópico https://github.com/mrdoob/three.js/issues/14232 pediram que eu comentasse sobre a implementação do shader baseado em Node. Eu acho muito ruim. Eu adoro a ideia, mas a implementação é totalmente inadequada na minha opinião, então, já que estou sendo tão negativo, vou fornecer algumas razões concretas para explicar o porquê.

Compreensibilidade

Depois de ler parte do código para os nós e várias classes de utilitários - posso dizer que é um grande desafio entender.

  • nomes de variáveis ​​não são descritivos
  • nenhum comentário
  • nomes de métodos são obscuros ou totalmente enganosos. (por exemplo, o que você acha que o método "build" faz? - faça uma suposição)

A estrutura do código é totalmente estranha. Considere este snippet:
https://github.com/mrdoob/three.js/blob/e2b49c017b2d1f37ab34317033a27df7b5a71d4d/examples/js/nodes/FunctionNode.js#L39 -L50

Você pode conseguir o mesmo com:

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

"Arquitetura Emergente"

O que é um "Nó"? Estou pedindo uma definição da estrutura de dados, porque parece que é apenas um conceito nebuloso, pois há poucos pontos em comum entre os diferentes "Nodes", parece um ducktyping, se grasna como um Node - é um Node.

Separação de preocupações

Como você vai de Node para ShaderMaterial ? No momento, é uma mistura de responsabilidades entre várias partes da lógica de cada nó, alguns construtores, alguns cache, analisadores etc. Não há uma responsabilidade clara por esse processo. Node usa NodeBuilder? O que ...? Pelo nome, eu diria que NodeBuilder é uma fábrica que produz ou constrói nós, pois na verdade é uma estrutura auxiliar. Pelo que eu posso dizer, há trabalhos bastante distintos a serem feitos aqui:

  • Construir um gráfico
  • Validar
  • Construir representação intermediária
  • otimizar
  • compilar para GLSL

Isso não é o que você encontrará no código atual.

Conclusão

Sem uma boa documentação e comentários, considero esta implementação totalmente inadequada. Com essas coisas no lugar, é uma questão de código espaguete e falta de design. Com isso dito - eu reconheço que é uma ferramenta poderosa e uma implementação de trabalho de um conceito muito útil.

@Usnul nunca iremos codificar assim em Three.JS "return this.inputs.find (input => input.name === name);"

O motivo é que o "=>" cria uma função que deve ser chamada em cada entrada. As chamadas de função são muito lentas em JavaScript em comparação com um loop for ou loop while. Assim, sempre fazemos loops explícitos em vez de código orientado a callback. Eu sei que é mais prolixo, mas é necessário. All of Three..JS é assim e propositalmente.

@Usnul , suas preocupações com design são muito úteis. Você poderia ajudar com alguma refatoração, então? Acho que todos gostariam de receber suas contribuições e sugestões sobre o design. :)

O motivo é que o "=>" cria uma função que deve ser chamada em cada entrada. As chamadas de função são muito lentas em JavaScript em comparação com um loop for ou loop while. Assim, sempre fazemos loops explícitos em vez de código orientado a callback. Eu sei que é mais prolixo, mas é necessário. All of Three..JS é assim e propositalmente.

esse é um ponto justo. Pessoalmente, tenho a filosofia de que o desempenho e a legibilidade devem estar em uma escala e não um ou outro, mas a consistência é boa. Meu principal problema com esse exemplo específico é que não é uma maneira comum de iterar em um array. Esta é uma forma idiomática:

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

ou digamos que você tenha um trecho de código com 50 linhas no formato:

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

não é tão legível quanto:

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

@Usnul você poderia ajudar a refatorar o código para levar isso em consideração? Acho que refatorar deve ser fácil, certo? Eu sou um grande defensor do Code Complete, aquele livro me influenciou muito.

@usnul se você não gostar disso, estará livre para refatorar isso? Não importa se parece assim ou não, é importante que seja construído em cima disso, no meu entendimento.
Não sei, porém, se os refratores devem acontecer enquanto isso está nos exemplos (ou possivelmente em outro repo) ou se ele deve ser movido para src imediatamente, como @bhouston está sugerindo.

@IARI

Eu realmente não conheço glsl muito bem , e também acho - perdoem minhas palavras - uma super chata de ler e escrever código de shader .

mas, a julgar pelo que eu sei , nós seriam a melhor maneira de fazer isso de uma forma verdadeiramente elegante e extensível.

Também não posso afirmar que conheço GLSL muito bem, mas sei o suficiente para resolver meus problemas. Pelo que sei, concordo em grande parte com o que @usnul escreveu aqui e com o que @AndrewRayCode escreveu antes. Acho que a coisa do nó é prolixa em comparação com GLSL.

Se você não conhece GLSL, acho que seria muito difícil compará-lo com qualquer outra coisa. Como você mesmo escreveu, se nós judge on what you know e você mesmo dissesse you don't know glsl acho que sua opinião deve ser tomada com uma isenção de responsabilidade :)

É como se eu dissesse:

O Japão é o pior lugar do planeta ... mas na verdade eu nunca estive no Japão ".

Obrigada.

nomes de métodos são obscuros ou totalmente enganosos. (por exemplo, o que você acha que o método "build" faz? - faça uma suposição)

Uau, eu nem percebi que isso é um ShaderMaterial embaixo. Meu palpite é que isso faz todas as coisas que THREE.WebGLRenderer faz com modelos de sombreador.

Eu realmente não conheço glsl muito bem, e também acho - perdoem minhas palavras - uma super chata de ler e escrever código de shader.
mas, a julgar pelo que sei, os nós seriam a melhor maneira de fazer isso de uma forma verdadeiramente elegante e extensível.

@pailhead O que ele

Eu não entendo por que esse alarme. @mrdoob nunca NodeMaterial ou não, são muito úteis para a comunidade. Se isso ainda não foi fusão no núcleo é porque precisamos melhorar com mais trabalho.

@sunag, há algo em particular que outras pessoas possam fazer para ajudá-lo neste projeto? Eu estaria disposto a escrever documentação, se você estiver pronto para documentos e puder revisá-los.

@sunag, há algo em particular que outras pessoas possam fazer para ajudá-lo neste projeto? Eu estaria disposto a escrever documentação, se você estiver pronto para documentos e puder revisá-los.

Isso vai ser ótimo. Sem dúvida ajuda muito.

O sistema de material baseado em nó parece incrível, ele expandiria o poder de expressão.

Como vamos mudar do sistema de material existente para o sistema de material baseado em nós no núcleo? Iremos ambos os sistemas ou substituir o existente pelo nó um?

Desculpe, talvez eu não ache que alcancei este tópico porque ele é muito grande ...

Iremos ambos os sistemas ou substituir o existente pelo nó um?

Eu vejo a substituição como o objetivo final, é melhor tanto para desempenho quanto para manutenção. A próxima etapa é fazer com que MeshStandardNodeMaterial e outros materiais de nó no núcleo sejam executados exatamente como o núcleo em visual, sintaxe e desempenho.

Tenho que mostrar o shadowMap no meu projeto.

Eu tenho uma cena com uma luz direcional e 2 geometrias que usam MeshStandardNodeMaterial.

Eu liguei
castShadow = true para luz
castShadow e receiveShadow para ambos os objetos.
shadowEnabled = true para Renderer

Por que não funciona?
Devo usar a propriedade shadow do MeshStandardNodeMaterial? É este o propósito?

Alguém pode me ajudar?
Obrigado!

@claudioviola
as perguntas de suporte vão para o fórum do stackoverflow.

@sunag Você acha que NodeMaterial é estável o suficiente para que possamos começar fornecendo arquivos de declaração TypeScript? Se você não está planejando grandes mudanças de API em um futuro próximo, eu começaria com esta tarefa, já que NodeMaterial é o último grupo de módulos sem suporte a TS.

@sunag Você acha que NodeMaterial é estável o suficiente para que possamos começar fornecendo arquivos de declaração TypeScript? Se você não está planejando grandes mudanças de API em um futuro próximo, eu começaria com esta tarefa, já que NodeMaterial é o último grupo de módulos sem suporte a TS.

@ Mugen87 Sim, deve haver mais adições do que mudanças. Adicionar suporte a TS será ótimo. 👍

Ok, o suporte para TS está pronto no próximo lançamento R017 🙌

Esta página foi útil?
0 / 5 - 0 avaliações