Three.js: NodeMaterial

Созданный на 3 нояб. 2015  ·  161Комментарии  ·  Источник: mrdoob/three.js

Привет.

Я начал разработку THREE.NodeMaterial, чтобы согласовать материалы различий между программным обеспечением для 3D-авторинга. В SEA3D Studio есть параметры для создания слоев в Albedo с маской и различными режимами наложения, шейдером обода и другими без необходимости настраивать код шейдера. Я хотел бы перенести это в Three.JS с шейдером узлов.

Я думаю, что MeshPhongMaterial, MeshPhysicalMaterial и другие могут быть легко основаны на NodeMaterial через интерфейс только для обратной совместимости или прокси.

ОБНОВЛЕНО
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

Пример синтаксиса для использования UV1 или UV2 для текстуры:

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

Я тоже делаю редактор, сейчас это будет интерфейс. Цвет - это альбедо, а трансформация - это положение вершины.
editor

Я также позаботился о том, чтобы его можно было использовать в отложенном затенении. Теперь я создам входы отражения и преломления.

Будем делиться новостями в PR, предложения, тесты и доработки приветствуются: +1:

Enhancement

Самый полезный комментарий

Хорошо, поддержка TS готова со следующим выпуском R017 🙌

Все 161 Комментарий

Интересно!

@sunag Нас очень интересует нечто подобное. Чем могу помочь? Я могу хотя бы добавить поддержку Standard.

Мне интересно создавать довольно произвольные графы, чтобы промежуточные узлы также принимали входные данные. Итак, у вас может быть график, который выглядит так:

Текстура (tex1, uv1)
B Текстура (tex2, uv2)
C Blend (A, B, режим)
D Шум (параметр1, параметр2)
E Blend (C, D, режим)

А затем используйте этот последний узел E в качестве входных данных для Материала.

Так что это очень произвольно, не ограничиваясь только текстурами.

Моя цель - помочь создать это в следующие несколько недель, надеюсь, сотрудничать с вами в течение следующей недели или около того, если возможно. Я искал сделать это через библиотеку шейдерграфа здесь: https://github.com/mrdoob/three.js/issues/7339 Но я обнаружил, что создаю его напрямую в ThreeJS. На самом деле любое решение хорошо, если оно гибкое и работает.

Я читаю ваш код, он довольно красиво оформлен. У меня есть первые отзывы. Могу ли я начать PR, используя ваш код в качестве основы, и начать сотрудничать с ним?

(1) Я хотел бы, чтобы материал разрешил ссылки. Обычно ссылки будут иметь имена, которые они просят разрешить в своем материале, и материал будет возвращать фрагмент кода о том, как получить доступ к этим данным. Это также позволит материалу узнать, какие переменные (однородные / вариативные) используются в узлах, чтобы он мог оптимизировать соответствующим образом. Это также позволяет различным материалам по-разному разрешать ссылки, что делает узлы более портативными, вместо того, чтобы знать, как материалы реализуют вещи, особенно когда есть различия между реализациями фрагментов и вершин.

(2) Я пытаюсь использовать объект GeometryContext, который я создал в рефакторинге источников света, он дает постоянный доступ к множеству необходимых локальных переменных. Но, конечно, это можно решить с помощью самого материала.

(3) У меня есть UV просто еще одна ссылка, которая решается материалом. И я бы хотел, чтобы NodeTexture действительно принимала ввод узла, что позволяло бы процедурно сгенерировать UV.

(4) Я бы назвал NodeCube, NodeTextureCube, чтобы они соответствовали остальной части Three.JS. И я бы удалил логику о том, как на самом деле делать из него лучи. Но мне нравится идея стандартных кубических карт, поэтому я бы на самом деле не помещал запрос среды для отражения или рассеивания в узлы, но имел бы это в базовом фонговом материале, и вы можете контролировать только нормаль, используемую для запроса, или Сам результат cubemap (что позволяет ему быть процедурно определенным цветом). Имеет ли это смысл? Таким образом, у меня будет обычный подключаемый материал и подключаемая текстура куба (запрашиваемая по направлению и смещению / lod, и возвращает цвет). Таким образом, один может предоставить текстуру куба для карты освещенности, а другой - для карты отражений. Мы можем заменить истинный sampleCube функцией @tschw cubeToUV2, просто заменив узел.

(5) Я бы попытался добавить NodeFunction, которая позволяет вызывать произвольные функции с параметрами в качестве дополнения к вашему NodeOp (или, может быть, их можно было бы каким-то образом объединить).

(6) Я бы избавился от всех подробных отдельных классов NodeNormal, NodeTransform, NormalMap и т. Д. И просто имел бы несколько простых конструкторов, которые создают NodeReference с именем, которое соответствующим образом разрешается материалом. NodeReference может разрешать униформы, вариации, а также вычисленные значения в шейдере.

(7) Я не понимаю разницы между NodeEnvironment и NodeCube. Я думаю, что NodeEnvironment может быть неполным?

(8) Сбивает с толку то, что NodePhong не является производным от NodeMaterial. Хотя я вижу, что NodeMaterial является производным от ShaderMaterial. Мне интересно, если бы вы назвали прямую производную от ShaderMaterial, GraphMaterial (или NodeGraphMaterial), что имело бы больше смысла, потому что все вместе узлы образуют граф, и именно граф становится материалом, а не отдельным узлом.

(9) Я бы предложил более разнообразную терминологию. Я бы назвал корневой узел MaterialNode, и от него можно было бы получить PhongMaterialNode. У меня есть Vector3Node, FloatNode и т. Д., Полученные из ValueNode - не обязательно константа, а просто значение. Таким образом, можно передать три FloatNode в Vector3Node. Я думаю, у вас может быть помощник, который бы объявлял каждую из этих строк или около того, а не 10 или около того в настоящее время.

(10) Я бы переместил имя «Узел» с начала имен классов на задний план, потому что так оно и есть в остальной части проекта ThreeJS.

(11) Я бы создал новый класс MaterialNode, и он был бы инициализирован списком униформ и вариаций. По умолчанию будет иметься возможность решить эту проблему, а также отслеживать, какие из них были разрешены, чтобы можно было отслеживать, какие функции необходимы. Таким образом, можно было бы иметь ограниченное решение в производном PhongMaterialNode, которое разрешало бы особые случаи и полагалось бы на базовый класс для выполнения простых (варьирование, униформа).

(12) Меня немного смущает разница между NodePhong и NodePhongMaterial. До сих пор я не понимал, что есть и то, и другое.

(13) есть такой код:

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

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

Но выше этого фрагмента вы уже определили generate для NodeGL и не определили его для NodeGLPosition - поэтому я думаю, что это ошибка копирования-вставки-редактирования.

(14) Я бы избавился от NodeReflectUVW и NodeRefractVector и вместо этого просто сделал бы это тем, что можно было бы запросить из материала с помощью разрешения ссылки. Вычислить вектор отражения просто. Я добавил его в GeometryContext в моих несвязанных экспериментальных ветках ThreeJS.

(15) Я бы использовал отражение и преломление в качестве входных цветов Материала. Можно разрешить Refect, ReflectLOD и Refract, RefractLOD простым способом, которым вы разрешили бы любую переменную, а затем передали бы их в эквивалент куба текстуры (процедурный или на основе samplerCube), а затем передали бы полученный цвет в материал. Так ты это делал?

(16) Меня смущает вход света - обычно у него нет подключаемых источников света, скорее параметры света полностью определены в классе света. Думаю, вам нужна дополнительная гибкость? Каким вы это себе представляете.

@bhouston Woow, большое спасибо за отзывы.
Мне понадобится несколько постов для ответа :)

Мне интересно создавать довольно произвольные графы, чтобы промежуточные узлы также принимали входные данные. Итак, у вас может быть график, который выглядит так:
Текстура (tex1, uv1)
B Текстура (tex2, uv2)
C Blend (A, B, режим)
D Шум (параметр1, параметр2)
E Blend (C, D, режим)

В настоящее время синтаксис подобен этому. Пример анимации смещения Uv1:
Думаю, что от NodeMaterial к MaterialNode и THREE.PhongMaterialNode тоже было бы лучше.

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;

Я думаю, что измените порядок с вашим предложением, чтобы улучшить (режим, A, B) до (A, B, режим). Я в процессе создания рефлекс-карт, кубической карты и прочего ...

Окружение и кубическая карта не завершены.

В настоящее время ошибок может быть больше из-за незавершенного конвертера формата. За это отвечает векторное преобразование. Например, vec3 в vec4 или vec4.

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

Например, "текстура" Blend: (я не тестировал этот код)
Это может быть реализовано так же, как 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 () отвечает за генератор кода. Коды calcs хранятся в кеше, если вы хотите использовать более одного входа без потери производительности.

Тем не менее я не настраиваю указатели или константы для оптимизации ...

Компиляция выполняется путем распространения в build () кода вершины и фрагмента.

Могу поставить вас в соавторство? Если вы хотите каким-либо образом отредактировать код, я тоже буду над этим работать.

Могу поставить вас в соавторство? Если вы хотите каким-либо образом отредактировать код, я тоже буду над этим работать.

Спасибо! Я сделаю пиар для вас, чтобы вы утвердили изменения.

Я добавил вас (а также @mrdoob , @WestLangley и @tschw) в мой побочный проект, который пытается определить набор повторно используемых узлов и определений материалов, которые можно переносить между различными рендерами. Его можно отобразить на созданную вами систему шейдерных графов.

Я не думаю, что вам нужно обращать внимание на репо, к которому я только что предоставил вам доступ, если вы не хотите. Это то, что я хочу реализовать поверх всего этого.

(2) Я пытаюсь использовать объект GeometryContext, который я создал в рефакторинге источников света, он дает постоянный доступ к множеству необходимых локальных переменных. Но, конечно, это можно решить с помощью самого материала.

Желаю, чтобы огни были одним LightNode. Меня беспокоит использование кода, уже разработанного для Three.JS.

(3) У меня есть UV просто еще одна ссылка, которая решается материалом. И я бы хотел, чтобы NodeTexture действительно принимала ввод узла, что позволяло бы процедурно сгенерировать UV.

Можно заменить UV на vec2, это будет?

(5) Я бы попытался добавить NodeFunction, которая позволяет вызывать произвольные функции с параметрами в качестве дополнения к вашему NodeOp (или, может быть, их можно было бы каким-то образом объединить).

это было бы здорово. в основном для BlendNode.

(6) Я бы избавился от всех подробных отдельных классов NodeNormal, NodeTransform, NormalMap и т. Д. И просто имел бы несколько простых конструкторов, которые создают NodeReference с именем, которое соответствующим образом разрешается материалом. NodeReference может разрешать униформы, вариации, а также вычисленные значения в шейдере.

В этом направлении я думаю, что MaterialNode может быть основой материального Фонга и Физического материала.

(7) Я не понимаю разницы между NodeEnvironment и NodeCube. Я думаю, что NodeEnvironment может быть неполным?

Я до сих пор не могу доделать эти Узлы.

(8) Сбивает с толку то, что NodePhong не является производным от NodeMaterial. Хотя я вижу, что NodeMaterial является производным от ShaderMaterial. Мне интересно, если бы вы назвали прямую производную от ShaderMaterial, GraphMaterial (или NodeGraphMaterial), что имело бы больше смысла, потому что все вместе узлы образуют граф, и именно граф становится материалом, а не отдельным узлом.

NodeMaterial будет материалом корневого узла, необходимо использовать узел для вершины и фрагмента. NodePhong - это hibrid, а NodePhongMaterial - только прокси-класс. Затем это можно объединить.

(9) Я бы предложил более разнообразную терминологию. Я бы назвал корневой узел MaterialNode, и от него можно было бы получить PhongMaterialNode. У меня есть Vector3Node, FloatNode и т. Д., Полученные из ValueNode - не обязательно константа, а просто значение. Таким образом, можно передать три FloatNode в Vector3Node. Я думаю, у вас может быть помощник, который бы объявлял каждую из этих строк или около того, а не 10 или около того в настоящее время.

Звучит отлично.

(16) Меня смущает вход света - обычно у него нет подключаемых источников света, скорее параметры света полностью определены в классе света. Думаю, вам нужна дополнительная гибкость? Каким вы это себе представляете.

Это будет для карты освещения или возможного LightNode.

Это будет для карты освещения или возможного LightNode.

Мне нравится идея подключаемой карты освещения, потому что для нее можно явно определить UV. :)

@bhouston Исправьте сегодня несколько исправлений в этом файле: Но еще многое предстоит сделать.
https://github.com/sunag/sea3d/blob/gh-pages/Labs/Three.JS-NodeMaterial/three.node.js

Это площадка, которую я создаю: art: Текстуры и кнопки - это перетаскивание, работает только в хроме.

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

Удивительно, штука! Святое дерьмо! Это красиво.

Можно ли поделиться кодом таким образом, чтобы я тоже мог внести свой вклад? Как публичный пиар что ли?

Вы ведь здесь работаете с проектом Sea3D?

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

Так что я могу просто форкнуть его и начать вносить свой вклад? Вы бы приняли PR? Как мы можем эффективно сотрудничать.

Я не спрашивал, но @mrdoob, наверное (?)

Определенно!

Так что я могу просто форкнуть его и начать вносить свой вклад? Вы бы приняли PR? Как мы можем эффективно сотрудничать.

Конечно, я думаю, что ваша помощь будет потрясающей. Я также должен принести другие типы узлов, такие как насыщенность, шум, как вы предложили.

Вы ведь здесь работаете с проектом Sea3D?

Я думаю, что в создании PR для Three.JS с примерами все это определено.

@mrdoob Что вы думаете о названиях материалов, THREE.MaterialNode или THREE.NodeMaterial?

Это тип материала, поэтому он должен быть THREE.NodeMaterial .

Вверх. Думаю, я близок к пиару?
https://github.com/sunag/sea3d/commit/55cf70aea38b2b72110abf96f7b96924dad81c54

Перетащите эту кубическую карту на игровую площадку и любую другую текстуру для тестирования
https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/skyboxsun25degtest.png

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

пример обода шейдера
flow-rimshader-example

пример отражения области
flow-areareflection

Это такой классный @sunag!

@bhouston, спасибо! ты думаешь будет сложно конвертировать на R74?

Это очень впечатляющая работа! Напоминает мне шейдерфордж .

Очень хорошая работа!

@sunag Это будет немного работы, но я хотел бы помочь, и большинство больших структурных изменений в коде шейдера R74 - это моя вина. :)

@GGAlanSmithee он также очень похож на то, что есть в UE4: https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/ExpressionReference/index.html

выглядит красивым мужчиной, с которым весело играть: могу ли я предложить для вдохновения редактор узлов Blender3D. Я считаю это супер эффективным, есть даже несколько отличных видео по PBR через систему узлов Blender, и какие узлы были бы наиболее полезны для создания, чтобы сделать PBR с нуля:

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

Это будет немного поработать, но я хотел бы помочь, и большинство крупных структурных изменений в коде шейдера R74 - это моя вина. :)

@bhouston Вау. С новыми изменениями r74 стало намного чище. Я закончил первую часть, все еще не получив StandardMaterial. Любая проблема, которую я публикую здесь :) Спасибо
https://github.com/sunag/sea3d/commit/d544ad7993272348f8bbea2337cdceb52159a6a8

Еще нам не хватает рефракции. Мне очень нравится использовать буфер рендеринга вместо Cubemap RTT по умолчанию. Было бы намного эффективнее.

@GGAlanSmithee У меня есть несколько ссылок на ShaderFX, которые мне очень нравятся. Shader Forge и UE4 в основном также являются отличными ссылками.

@richardanaya Потрясающие видео. Спасибо!

@mrdoob В какую папку вы рекомендуете положить эти файлы? three.js root (src / materials / node) или в примерах?
https://github.com/sunag/sea3d/tree/gh-pages/Labs/Three.JS-NodeMaterial/node

Я по-прежнему рекомендую называть это «График материалов» или, в перевернутом стиле ThreeJS, «GraphMaterial». Или, если вы настаиваете на использовании термина «узел», я бы назвал его «NodeBasedMaterial». Оба этих имени дают понять, что материал содержит узлы, а не сам узел.

Я по-прежнему рекомендую называть это «График материалов» или, в перевернутом стиле ThreeJS, «GraphMaterial». Или, если вы настаиваете на использовании термина «узел», я бы назвал его «NodeBasedMaterial». Оба этих имени дают понять, что материал содержит узлы, а не сам узел.

Для меня оба выглядят хорошо. Я оставляю решение @mrdoob, что ты думаешь?

Кстати, @sunag, если возможно, я бы использовал кубические карты для преломлений, это проще и точнее. Я думаю, что так делают почти все остальные, и нам также нужен материал RTT для точных отражений. Я думаю, это просто должен быть быстрый рендер на 128 ^ 2 или 256 ^ 2.

Кстати, @sunag, если возможно, я бы использовал кубические карты для преломлений, это проще и точнее. Я думаю, что так делают почти все остальные, и нам также нужен материал RTT для точных отражений. Я думаю, это просто должен быть быстрый рендер на 128 ^ 2 или 256 ^ 2.

Да, мы можем позволить и то, и другое. будет дискуссия между производительностью x точностью. Тем не менее, для плоского преломления (стекло, вода) я рекомендую буфер вместо CubeMap (в большинстве случаев).

@mrdoob В какую папку вы рекомендуете положить эти файлы? three.js root (src / materials / node) или в примерах?

Я бы для начала привел это в примеры. Как только он будет четко определен, мы можем позже переместить его в src 😊

Я по-прежнему рекомендую называть это «График материалов» или, в перевернутом стиле ThreeJS, «GraphMaterial». Или, если вы настаиваете на использовании термина «узел», я бы назвал его «NodeBasedMaterial».

Для меня оба выглядят хорошо. Я оставляю решение @mrdoob, что ты думаешь?

Мне вроде уже нравится NodeMaterial ... Может, NodesMaterial ? NodeGraphMaterial ? @WestLangley есть предложения?

Я бы переименовал текущие узлы ... NodeColor , NodeFloat , NodeTexture , ... в ColorNode , FloatNode , TextureNode

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

Я не могу загрузить это 😐

Я бы для начала привел это в примеры. Как только он будет четко определен, мы можем позже переместить его в src: blush:

@mrdoob будет здорово.

Я бы переименовал текущие узлы ... NodeColor, NodeFloat, NodeTexture, ... в ColorNode, FloatNode, TextureNode

Я перешлю его тогда.

это локальный URL: blush:, попробуйте следующее:
http://sea3d.poonya.com/flow/

@WestLangley есть предложения?

Предлагаю THREE.FlowMaterial .

Второй вариант - THREE.CustomMaterial .

Как совершенно случайный наблюдатель. NodeMaterial мне кажется очень интуитивно понятным, потому что именно так они называются в Blender3D.

Если @mrdoob нравится NodeMaterial, мы можем его придерживаться. :)

NodeMaterial тогда

Это классный проект! Только что посмотрел демо в Твиттере, и оно очень впечатляет.

Интересно, должны ли узлы входить в Three core. Они очень специфичны для реализации. Я тоже создаю редактор шейдерного графа Three.js (еще не выпущенный) для ShaderFrog.com, и решение, которое у меня есть, - просто экспортировать код GLSL и все необходимые метаданные, такие как единые имена, в небольшой файл JSON и загрузить его. с внешней библиотекой времени выполнения

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

Этот редактор графов может работать с полными шейдерами, анализируя их исходный код, что означает, что никаких конкретных типов узлов шейдера не требуется. Можно ли обрабатывать этот тип NodeMaterial полностью вне ядра Three? Все, что вам действительно нужно вывести, - это RawShaderMaterial чтобы кто-то мог использовать его в своем собственном проекте.

Можно ли обрабатывать этот тип NodeMaterial полностью вне ядра Three? Все, что вам действительно нужно вывести, - это RawShaderMaterial, чтобы кто-то мог использовать его в своем собственном проекте.

@DelvarWorld Привет. Да теоретически, но делать хороший шейдер из raw пока рано. На тот момент лучше с начальным интерфейсом. Это также помогает поддерживать совместимость с Skin / Morph и другими исходными компонентами Three.JS.

Я подумал отметить небольшую проблему:
В «Потоке» соединители не выскакивают на верхний уровень при перетаскивании узлов друг на друга.
Может эта проблема ждет слоев или еще чего.

Интересно, есть ли способ объединить оба подхода? Меня интересует многослойный шейдер, и для этого вам нужно иметь несколько BSDF, которые способствуют окончательному результату. Это означает, что нужно больше выделять модель затенения - прямо сейчас она довольно тесно связана с текущим дизайном @sunag . Я думаю, нам следует двигаться в направлении, где не нужно указывать материал Standard или Phong, он может быть сырым, как у @DelvarWorld . Я думаю, что мы можем двигаться туда постепенно, так что то, что есть у @sunag , - хорошее начало.

Это не конкретный ответ, но некоторое время назад я создал приблизительное предложение для переносимого формата шейдера, который включает метаданные, такие как унифицированные имена, их типы, их тип в Three.js и т. Д. Https://github.com /DelvarWorld/ShaderFrog-Runtime/blob/master/THREE_SHADER_FORMAT.md

Все, что действительно необходимо шейдеру для работы в реальной среде, - это необработанный исходный код шейдера (поскольку его компилирует графический процессор) и, для удобства, какие формы пользователь может установить с какими значениями. Это приблизительное предложение не включает никакого понятия о программном создании шейдера, это просто простая доставка для GLSL и метаданных. Он совместим с Three.js, потому что в конце вам просто нужно поместить его в RawShaderMaterial .

В настоящее время нет возможности сделать шейдеры переносимыми в Three.js или экспортировать их из любого приложения, что и натолкнуло меня на идею предложить стандарт, и я думаю, что он может решить обе наши проблемы, поскольку мы создаем внешние приложения. что в конце концов выплюнет заданный материал. Это также означает, что детали реализации компиляции конкретных комбинаций графа оставлены на усмотрение приложений, а не Three.js.

Есть ли место для этого предлагаемого стандарта шейдеров в Three? Я понятия не имею. Сейчас это, наверное, более полезно для меня, чем для ядра Three, поскольку Three строит свои собственные шейдеры по-своему.

@DelvarWorld Я начал этот проект с того, чтобы создать стандартизированный набор узлов шейдерного графа:

https://github.com/OpenMaterialGraph/OpenMaterialGraph

Технические характеристики узла здесь:

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

Минималистичные спецификации BSDF здесь:

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

Однако это ориентировано на физический рендеринг.

Мне кажется, что для ThreeJS нужна оболочка шейдера, которая будет выше уровня необработанного шейдера, но более низкого уровня, чем шейдер Фонга. По сути, шейдер по умолчанию может выполнять морфинг целей, костей и т. Д. И затем все эти шейдеры конкретных схем освещения (Basic, Lambert, Phong, Standard) будут использовать этот шаблон. Прямо сейчас есть подразумеваемый шейдер шаблона (мы включаем одни и те же элементы в каждый шейдер), но я думаю, что мы могли бы прояснить, где их вставлять. Вы можете подключить схемы освещения (фонга, ламберта, базовые или многослойные), и вы можете добавить свойства к тем схемам освещения, которые являются вашими общими узлами.

@bhouston, о, хорошо, похоже, у нас много пересекающихся требований, то есть значения по умолчанию, отображаемого имени, удобочитаемых описаний и т. д. Я не знаю, что нас ждет в будущем, но для меня было бы довольно легко изменить формат больше похож на то, что вы предлагаете.

Формальный формат шейдера имеет большой смысл. Однако он должен жить с библиотекой, чтобы легче было развиваться с ней. Для тех, кто плохо знаком с three.js, есть ли какая-то конкретная причина, по которой такая вещь еще не существует? Как минимум, это должно быть интересно редактору.

* РЕДАКТИРОВАТЬ Может быть, наличие спецификации в three.js нарушит его цель, если она предназначена для использования другими конвейерами рендеринга.

Сейчас это, наверное, более полезно для меня, чем для ядра Three, поскольку Three строит свои собственные шейдеры по-своему.

Вы можете сгенерировать тот же материал на другом языке, если вы внесете изменения внутри THREE.NodeGL.prototype.generate если NodeMaterial (* Flow) является визуальным языком. NodeBuilder может быть дверью к нему. В настоящее время является посредником данных между узлами.

Я убрал пример "сырого" NodeMaterial: он все еще может генерировать несколько ошибок.
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

Я думаю продвинуть это с помощью частиц, созданных корневыми узлами. NodePass for Multi-Pass и NodeMaterialD после PR, что мне делать через несколько дней.

Я предложил THREE.ShaderFrogLoader вместо шейдера времени выполнения.

В «Потоке» соединители не выскакивают на верхний уровень при перетаскивании узлов друг на друга.

@MasterJames Спасибо! Я буду смотреть на это.

: +1:

Я начал создавать примеры. Надеюсь закончить на этой неделе. : sweat_smile:
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html

Мысли?

@sunag +1: -)

+1!

Это так здорово. Я бы по умолчанию использовал текстуру растений + стены, а не смещение, похожее на облачность. :) Это просто прекрасно.

Я бы по умолчанию использовал текстуру растений + стены, а не смещение, похожее на облачность.

Вы ссылаетесь на пример «слоев»? Тем не менее, я опубликую для нас больше примеров

ГПУ мягкое тело
soft-body

Для сравнения с другим подходом, графический редактор Shader Frog теперь доступен, и он находится в фазе «пинают шины». Подчеркну, что никаких изменений в ядре Three.js не требуется.

ShaderFrog в настоящее время имеет больше возможностей, чем традиционные редакторы узлов. Он имеет бесконечное количество типов узлов, с которыми можно работать, потому что он может анализировать и понимать любой шейдер . Например, чтобы применить отражение только к краям объекта, вы можете просто взять шейдер свечения , который является полностью автономным шейдером с фрагментом и вершинным шейдером:

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

... и умножаем его на шейдер отражения ...

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

... используя шейдерный график ...

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

И та-да! Шейдер обода отражения .

Вы также можете, например, замаскировать любые два шейдера с помощью любого другого шейдера и так далее:

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

Обратите внимание, что единственный «тип узла», необходимый для этого процесса, - это узел умножения (в ShaderFrog есть и другие), который почти полностью не зависит от GLSL. ShaderFrog может работать с любыми шейдерами, поэтому у него бесконечное количество типов узлов. Этот передовой технологический подход позволяет выполнять эту манипуляцию независимо от изменений Three.js.

ShaderFrog имеет бесплатную первоклассную поддержку экспорта в Three.js. И все это без изменения исходного кода Three.js. Sea3D - это сторонний продукт, такой как ShaderFrog. Включение механизмов сторонних продуктов в ядро ​​Three кажется несправедливым преимуществом, и я не понимаю этого с политической точки зрения.

@DelvarWorld Я действительно не вижу абстракции построения шейдеров на основе узлов как стороннюю технологию. Во всяком случае, это позволяет большему количеству конкурентов участвовать в технологии шейдеров на основе узлов и извлекать выгоду из дальнейшего преимущества работы друг друга (больше узлов, оптимизированная конструкция и т. Д.).

Как графический программист вроде меня, который разбирается в шейдерах на высоком уровне (из таких инструментов, как Blender 3D), но не на низком уровне, абстракция на основе узлов кажется мне отличным способом программного взаимодействия с шейдерами, используя мои знания 3D-моделирования. Я понимаю, например, настройку узла для PBR, но, Боже, помоги мне, если я когда-нибудь захочу написать это на GLSL.

@DelvarWorld Удивительно. Мне нравится новый редактор.

@DelvarWorld +1 Очень мило! : -)

Спасибо! :)

Я действительно не считаю абстракцию построения шейдеров на основе узлов сторонней технологией.

Я понимаю, например, настройку узла для PBR

Частично мой встречный пример заключается в том, что вы можете получить обе эти вещи бесплатно независимо от Three.js. Все шейдеры ShaderFrog имеют открытый исходный код, поэтому любые узлы, которые становятся частью реализации PBR, также могут быть изучены, отредактированы и улучшены с течением времени (а также составлены с любыми другими шейдерами, а не только с некоторым подмножеством в ядре Three.js). Для меня тот факт, что все это может быть выполнено без трех изменений, означает, что в этом нет необходимости, и стирается грань между Three.js, являющимся API-оболочкой webgl, и теперь управляющим специфическими функциями реализации. Хранение данных шейдерных узлов сильно зависит от приложения, и, насколько мне известно, в настоящее время нет общего стандартного формата редактора узлов для любого программного обеспечения? Применение одного из них может быть вредным для других реализаций.

@DelvarWorld Насколько я понимаю это изменение, ShaderFrog по-прежнему сможет функционировать и при желании сможет выйти за рамки GraphMaterial. Я просмотрел пример исходного кода GraphMaterial и смог понять простоту его работы, даже не задумываясь о стороннем решении / редакторе. Как разработчик графики я озабочен тем, как программно создавать впечатляющие материалы быстро, и я считаю, что это серьезная забота ThreeJS.

Я думаю, что у NodeMaterial и Flow два разных направления. Flow и ShaderFrog являются сторонними решениями визуальных редакторов, которые в настоящее время находятся в закрытом виде (я думаю, в основном для художников). Другая сторона NodeMaterial - редактор шейдеров с открытым исходным кодом для программистов, созданных для Three.JS. Я согласен с @richardanaya в том смысле, что ShaderFrog при желании может выходить за рамки NodeMaterial. Точно так же, как я думаю, Flow не обязательно должен быть просто редактором материалов. Как обычно, я очень надеюсь на большие улучшения ShaderFrog в будущем.

wip: каустик-вороной
http://sunag.github.io/sea3d/Labs/Three.JS-NodeMaterial/webgl_materials_nodes.html
caustic

@sunag Сегодня вечером я просматривал ваш исходный код. Мне действительно нравится это. Некоторые быстрые отзывы о моих чтениях сегодня вечером:

  • Хотелось бы раньше чем позже увидеть пиар. Я могу помочь. :)
  • Может быть круто разрешить произвольные атрибуты, а не только стандартные (uv, uv2, normal, position и т. Д.). Я знаю, что многие шейдеры могут извлечь выгоду из тангенциальных vec4s, более чем 2 uvs, а также несколько цветов. атрибуты. Таким образом, я бы обобщил needsPosition в массив requiredAttributes или что-то в этом роде.
  • Я бы предложил некоторую организацию узлов в основной NodeMaterial, BRDF (Phong, Standard и т. Д.), Узлы текстуры (NodeCubeTexture, NodeTexture), узлы доступа (?) (NodePosition, NodeNormal), математические узлы (NodeOperator и т. Д.) ), служебные узлы (NodeSwitch, ...) и дополнительные (?) (NodeVelocity, ...) Я думаю, это очень поможет.
  • Было бы неплохо иметь средства доступа к матрицам для матриц Projection, View и World.
  • Вам не хватает некоторых операторов: % ^ & << >> ~ |
  • Я не уверен, что вижу значение в NodePhongMaterial, когда класс такой маленький, мне просто нужно было бы, чтобы пользователи создавали его, используя узел NodePhong в сочетании с NodeMaterial (хотя мне все еще не нравится это имя, GraphMaterial чувствует себя сильно больше природы для меня, но я могу жить с этим.)
  • Я бы назвал NodeTimer -> NodeTime ... но опять же личные предпочтения.
  • Интересно, есть ли способ объединить многие узлы переменных в один, как вы это сделали с NodeMath #, NodeOperator. Они кажутся такими похожими: NodeViewPosition, NodeWorldPosition, NodeViewNormal, NodeTransformedNormal, NodeTransformedPosition, NodeProjectPosition ...
  • Я хотел бы видеть набор необязательных аргументов для NodeMath #, NodeOperator в форме, которая может быть списком, чтобы можно было легко заполнить им раскрывающийся список. Прямо сейчас, поскольку они являются членами, которые только что извлекли выгоду из классов, их немного сложнее идентифицировать. Я не уверен в хорошем решении, которое по-прежнему было бы удобным для кодирования. Может быть, просто собрать их в список после их определений как членов класса, чтобы просто добавить эти списки?
  • NodeTransformedNormal, NodeTransformedPosition мне сложно понять, что они собой представляют, не глядя на код. Находятся ли они в мировом пространстве, пространстве просмотра, пространстве объектов? «Преобразованный» - очень общий термин, который просто означает умножение на матрицу. Я сейчас посмотрю на них код ....
  • Я бы позволил NodeUV и NodeColor принимать индекс, а не ограничиваться 2 и 1 каналом соответственно. Опять же, я хотел бы, чтобы они стали общими, на самом деле вы передаете строку или одну из нескольких предустановок, а не жестко закодируете ее для набора определенных каналов. У вас все еще могут быть выделенные пути кода для некоторых переменных, но он будет использовать что-то общее для имен, которые он не распознает, для обработки особых случаев.

Больше отзывов:

  • Я хотел бы иметь график с более чем одним BRDF, в основном с двумя стандартными BRDF, а затем выполнять сохранение энергии между ними. Как только вы получите PR, я хотел бы добавить эту функциональность. Это сделает систему более универсальной и более мощной.

@bhouston Вау! Спасибо!

Изменены атрибуты запроса, организация папок, NodeTime, NodePosition, NodeNormal, NodeView. Также добавлено +3 примера.

в операторы и матрицу мы должны добавить совместимость с преобразованиями integer и matrix . Для этого нужно сделать это автоматически, как в float / vectors #. У нас достаточно работы для следующих обновлений ..: sweat_smile:

Завтра сделаю пиар. Мне нужно еще кое-что пересмотреть.

@sunag :

Я считаю, что это ошибка:

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

                        roughnessA.number = val;

                    }, false, 0, 1 );

Я считаю, что это ошибка:

Спасибо!

У меня просто закружилась голова, когда я перешел на страницу с примером и увидел график узла PBR <3

<3
Изменения последней ревизии
https://github.com/sunag/sea3d/commit/a2e3813b53902331e91dbc0f6bae0136a384ad0c

Niice!

Я собирался предложить использовать ноды для постобработки, но ждал, когда будет сделана первая часть. Блин, как красиво!

NodeMaterial rev 5 + LightNode

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

Кожа
nodematerial-rev5-skin

Toon Shading
nodematerial-rev5-toon

++ color-adjustment и plush примеры.

Niiice!

subsurface scattering : sweat_smile:

Это своего рода шейдер, который может работать в будущих обновлениях.

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

sss-img1
sss-img2

😮!

Спасибо за отличный NodeMaterial!

Есть несколько замечаний / ошибок:

  • завершающий пробел прерывает функциональный узел
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
  • проблема с параметром int в функциональном узле

рабочий пример с параметром 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;

сломанный пример с параметром 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;
  • предложение: передать параметры функции в конструктор 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 с картой рельефа?

еще несколько заметок:

  • проблема с PositionNode.LOCAL во фрагментном шейдере в "сыром" NodeMaterial:
var material = new THREE.NodeMaterial(
        new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.PROJECTION ) ),
        new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.LOCAL ) )
    );

результирующие шейдеры:

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

Вероятно, "трансформированную" функциональность следует перенести с нодовых материалов Фонг / Стандарт на NodeMaterial.

  • Использование 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 ) )
    );

В этом случае шейдер результата содержит
gl_Position = ((projectionMatrix * modelViewMatrix * vec4 (position, 1.0)) * TWO);
но константа TWO не объявлена. Это моя ошибка или ошибка?
Кроме того, ConstNode чувствителен к точкам с запятой, поэтому "float TWO = 2.0" не анализируется.

Спасибо @dimarudol ! Если хотите не стесняйтесь делать заметки, как можно скорее внесу новую редакцию.

но константа TWO не объявлена. Это моя ошибка или ошибка?

Я рассмотрю этот способ использования и в материале, например, material.include( node )

В то время попробуйте глобальную константу:

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

Привет, @sunag , я играл с Sea3d Flow, и он выглядит довольно круто. Просто хотел спросить, есть ли где-нибудь официальное репо для него.
С Уважением.

Привет @rraallvv , пока нет, уже готово. При первой возможности выкладываю новости.

Спасибо @sunag , это очень

Привет @sunag ! Вы действительно хорошо поработали!
У меня есть вопрос: для моего проекта было бы здорово использовать структуру ваших узлов, но мне нужно для каждого цвета вершины (и настраиваемых значений float для каждой вершины), но в вашей системе узлов у вас есть только colorNode и floatNode, примененные ко всей сетке .. Как вы думаете, есть ли способ легко реализовать что-то вроде bufferColorNode (используя THREE.BufferAttribute)?

Например, у меня есть такая сцена:

screenshot from 2016-08-31 16 27 06

Каждая вершина имеет свой цвет. Это возможно с THREE.BufferAttribute и THREE.ShaderMaterial, но в вашем коде нет эквивалента.

Мне нужно что-то вроде:
`let material = new THREE.StandardNodeMaterial ();
let texColorMap = new THREE.TextureNode (новый THREE.TextureLoader (). load ("colorMap.jpg"));
let customData = new THREE.BufferFloatNode (новый Float32Array (...), «данные»); // Второй параметр - это имя атрибута

let colorMap = new THREE.FunctionNode ([
"vec3 colorMap (sampler2D texColorMap, float data) {",
"return vec3 (texture2D (texColorMap, customFunc (data)));", // customFunc возвращает vec2 в зависимости от данных
"}"
] .join ("п"));

пусть colorMapCall = новый THREE.FunctionCallNode (colorMap);
colorMapCall.inputs.texColorMap = texColorMap;

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

Кстати, похоже, что я не могу использовать параметры sampler2D для FunctionNode ...

Я что-то упускаю ?
Думаю, смогу помочь, если понадобится :)

@martinRenou Спасибо! Хм, может, пока что-то вроде:

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

Я еще не думал о назначении атрибута динамической геометрии узлу. Но я думаю, что это хорошая идея ... может быть, что-то вроде THREE.BufferAttributeNode ...

@sunag спасибо за ответ :)
Я попробую это. Если вас это устраивает, я начну работу над THREE.BufferAttributeNode, пока я все еще читаю ваш код и пытаюсь понять структуру.

  1. Что касается THREE.FunctionNode, как я уже сказал, мне действительно нужно установить sampler2D в моих параметрах, поскольку он используется в качестве colorMap. Цвет пикселя рассчитывается с помощью texture2D (), а второй параметр texture2D () рассчитывается с использованием моих пользовательских данных (например, температура).
    Я понимаю, что идея использования параметров vec3 была для удобства пользователей, но FunctionNode также может поддерживать параметры sampler2D, вам не кажется?
  2. Кроме того, THREE.FunctionNode записывает только во фрагментный шейдер, но было бы неплохо иметь возможность писать и в вершинном шейдере?

Это будет мой вариант использования, он называется IsoColor, потому что цвет соответствует данным (температура, давление ...) красный -> высокая температура, синий -> низкая температура:
screenshot from 2016-09-01 17 29 58

  1. Я подумываю написать THREE.IsoColorNode (который заменил бы FunctionNode моей диаграммы) и другие узлы, которые были бы очень интересны для научных визуализаций. Вам это интересно? @mrdoob тебе тоже будет интересно?

Что касается THREE.FunctionNode, как я уже сказал, мне действительно нужно установить sampler2D в моих параметрах, поскольку он используется в качестве colorMap. Цвет пикселя рассчитывается с помощью texture2D (), а второй параметр texture2D () рассчитывается с использованием моих пользовательских данных (например, температура). Я понимаю, что идея использования параметров vec3 была для удобства пользователей, но FunctionNode также может поддерживать параметры sampler2D, вам не кажется?

Теперь я понимаю вашу потребность! Я создам пиар для этой и других заметок @dimarudol ...

Кроме того, THREE.FunctionNode записывает только во фрагментный шейдер, но было бы неплохо иметь возможность писать и в вершинном шейдере?

Я не тестировал это, но полагаю, что да.

Я добавил еще два примера:

  • sampler2D находятся в примере triangle-blur
  • пользовательские BufferAttribute находятся в примере custom-attribute

Он работает, но я все равно дам отполированный код ...

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

Ух ты ! Вы действительно хорошо поработали, у меня тоже получилось: smile:

Еще раз спасибо за вашу работу!

Привет @sunag!

На данный момент у нас не может быть FunctionNode с типом void, так как нам нужно отправить его в материал в качестве параметра (цвет, альфа ...). Например, если я хочу реализовать FunctionNode плоскости отсечения, все, что я хочу сделать, это написать такую ​​часть шейдера:

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

Но это невозможно передать материалу ... Решением было бы вернуть поплавок, который является альфа-каналом, но он не является чистым и оптимизированным. Вам не кажется, что было бы круто добавить в такой материал несколько функций void:

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

В качестве более «дизайнерского» примера, если я хочу проделать дыры в своем чайнике с помощью этой текстуры:
wood-hole-texture
Я бы хотел сделать что-то подобное:

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;

Другое дело, что у нас нет контроля над порядком функций в шейдерах. Если у меня есть функции, которые не являются коммутативными, я не могу контролировать результат ...

давайте посмотрим на этот пример:

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;

Если точка находится за плоскостью прозрачности и выходит за ее пределы из-за смещения, в случае, когда "transparentPlaneCall" вызывается до "displacementCall", альфа = 1., а в случае, когда он вызывается после альфа = 0,5.
Итак, я хотел бы установить порядок вызовов функций ... Вы понимаете, о чем я?

Привет @martinRenou

Хм, около void функций может быть ProxyNode для использования в слоте, потому что для этого нужно следовать порядку или инициализировать в начале или конце кода, может быть functionsStart или functionsEnd slots ...

Использование alpha slot, если alpha равно 0, автоматически сбрасывается.
https://github.com/mrdoob/three.js/blob/dev/examples/js/nodes/materials/PhongNode.js#L180

Итак, я хотел бы установить порядок вызовов функций ...

Последовательность существования см. Здесь:
https://github.com/mrdoob/three.js/blob/dev/examples/js/nodes/materials/PhongNode.js#L122

Порядок функций выполняется автоматически с использованием простого алгоритма dependencies , который должен поместить FunctionCall в предыдущий слот, color - это первый, например specular - второй.

Этот пример представляет собой два разных кода шейдера: от fragment до transparencyPlaneCall и от vertex до displacementCall .

Это заставляет меня думать, что использование переменных ( varying и locals) для расширения не входов и только const будет очень интересным. Может быть VarNode ...

Использование альфа-слота, если альфа равно 0, автоматически отбрасывается.

Простите за это, не видел.

Порядок функций выполняется автоматически с использованием простого алгоритма зависимостей, функция FunctionCall должна быть помещена в предыдущий слот, например, цвет сначала зеркальный, а второй.

Я понимаю, на самом деле я просто хотел убедиться, что функция, которая отбрасывает пиксели, вызывается первой. Для меня неплохо использовать альфа-канал, если вы откажетесь от него сразу после моих функций: smiley:

В этом примере представлены два разных кода шейдера: фрагмент для прозрачностиPlaneCall и вершина для displacementCall.

Верно ! Так что это был не очень хороший пример. Виноват.

Готово r6 - # 9636

Прохладный ! Спасибо за ответы.

Это заставляет меня думать, что использование переменных (переменных и локальных) для расширения не входов, а только константа будет очень интересным. Может быть, VarNode ...

Звучит тоже хорошо, может быть интересно иметь возможность явно написать функцию в вершинном шейдере, использовать varNode и использовать его с функцией во фрагментном шейдере. Вы так не думаете?

@sunag
Я думаю, что есть проблема с использованием AttributeNode с FunctionNode в вершинном шейдере.

Если у меня есть такой код:

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;

Шейдер пишется в таком порядке:

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

Простое решение - инициализировать nVdata данными?

Звучит тоже хорошо, может быть интересно иметь возможность явно написать функцию в вершинном шейдере, использовать varNode и использовать его с функцией во фрагментном шейдере. Вы так не думаете?

Ага! Идея состоит в том, чтобы улучшить взаимодействие с вершинными / фрагментными шейдерами, используя varying как VarNode . Теперь это прекрасно сочетается с функцией keywords .

Я создаю минимальный пример varying но пока нет решения для void function .

Я думаю, что есть проблема с использованием AttributeNode с FunctionNode в вершинном шейдере.

Исправлено - https://github.com/mrdoob/three.js/pull/9681

Привет, @sunag , я видел ваш пример с различными mtl.transform как вы ... Может быть, вы измените это, когда появится возможность создавать пустые функции?
Тем не менее, неплохо было бы использовать ключевые слова: smiley:

На самом деле, я думаю, что было бы неплохо поместить эти переменные в mtl.varyings (mtl.varyings - это массив) следующим образом: mtl.varyings.push(myVar) . Используя ту же идею, мы могли бы поместить функции в вершинные и фрагментные шейдеры следующим образом: mtl.vertexFunctions.push(myVertexFunctionCall) , так же, как с mtl.fragmentFunctions .

Таким образом, мы могли бы провести много вычислений с этими переменными, а затем использовать их для эффектов. Эти функции будут недействительными.

Как показано на скриншотах выше, где узлы соединены визуально, как нам мысленно воссоздать это с помощью этого API? Я вижу, что конструкторы принимают другие узлы. Это способ, которым выходные данные одного узла (переданные в конструктор) являются входными данными для другого узла (он получает узлы в своем конструкторе)? Есть ли у узла не более одного выхода? Сколько узлов могут быть входами для другого узла через конструктор, или это ограничено?

@trusktr Конечно, не ограничено, сколько узлов потребляет больше ресурсов ЦП во время сборки и графического процессора во время выполнения. Узлы настраиваются в соответствии со значениями входов и выходов, преобразование float в vec2 или vec3 например, выполняется автоматически и сохраняется в кеше, если используется более одного раза для оптимизации. (см. TempNode ).

На скриншотах каждый узел представляет собой класс, например: PositionNode в отображении:
https://github.com/mrdoob/three.js/blob/789efa65bafe022e178c7e93e0985a7607a54403/examples/js/nodes/accessors/PositionNode.js#L5

@mrdoob @sunag, не

Теоретически сейчас мы могли бы использовать узлы для нескольких вещей, например:

  • Реализуйте материалы glTF spec / gloss PBR как NodeStandardSGMaterial.
  • Поддержка наборов и преобразований UV для каждой карты
  • Упростите использование встроенных материалов с помощью создания экземпляров

Но трудно оправдать добавление зависимости в GLTFLoader для всех файлов узлов. И, вероятно, трудно оправдать размещение узлов в src/* без более активного использования. Куриное яйцо. 😅

Было бы полезно знать долгосрочный план NodeMaterial, чтобы угадать, какие функции связаны (или не связаны) ... нужно ли это доработать? Могут ли помочь другие участники?

@sunag да, мне тоже было бы любопытно узнать, есть ли у вас какие-то дальнейшие планы на данный момент.

Теоретически сейчас мы могли бы использовать узлы для нескольких вещей, например:

  • Реализуйте материалы glTF spec / gloss PBR как NodeStandardSGMaterial.
  • Поддержка наборов и преобразований UV для каждой карты
  • Упростите использование встроенных материалов с помощью создания экземпляров

Для этих конкретных проблем теперь есть примеры того, как их можно решить с помощью существующих API без необходимости изменять ядро:

Создание экземпляров:
https://github.com/mrdoob/three.js/pull/10750 (развернутый, касается ядра, но может быть исправлен как обезьяна)
https://github.com/mrdoob/three.js/pull/14166 (простые расширения материалов через onBeforeCompile)
https://github.com/mrdoob/three.js/pull/14012 (простое расширение библиотеки через mokey-patching)

per-map-uv наборы
https://github.com/mrdoob/three.js/pull/14174

spec-gloss как собственный класс
https://github.com/mrdoob/three.js/pull/14099

Возможно, это поможет избавиться от ощущения срочности вхождения NodeMaterial в ядро ​​:).

Для тех, кто следит за этой темой, ведется обсуждение на https://github.com/mrdoob/three.js/pull/14149.

Присоединение к темам из # 14149:

tl; dr - NodeMaterial кажется мне очень многообещающим следующим шагом для системы материалов. Я подозреваю, что внедрение NodeMaterial в настоящее время ограничено несколькими вещами:

  • трение включения множества отдельных файлов
  • отсутствие визуального редактора
  • относительно немного примеров, документов

Я бы оставил вопрос о том, когда / должен ли NodeMaterial быть в src/ @mrdoob и @sunag , но я думаю, что мы должны двигаться вперед (по крайней мере) в решении трех вышеперечисленных проблем. Также было бы полезно узнать, видят ли другие NodeMaterial как альтернативу текущей системе материалов или полную замену.



Похоже, что критическая масса формируется заинтересованными сторонами GLTFLoader, и мое (субъективное) наблюдение состоит в том, что потребность возникла из-за неправильно задокументированного onBeforeRender (несколько примеров) и еще меньше документированного onBeforeCompile (один пример).

@pailhead Я начал поддерживать GLTFLoader для решения проблем рабочего процесса в A-Frame, разработчиком которого я также являюсь. Я согласен, что целью является более полезная система материалов, а не загрузка определенного формата. Решение о том, как интегрировать (или не интегрировать) материалы узла, должно основываться на достоинствах для конечных пользователей библиотеки three.js - функциях, гибкости, понятном API.

Вы правы, что крючки onBeforeCompile и onBeforeRender бесконечно гибкие; нет практических ограничений на то, как далеко вы можете манипулировать или заменять лежащие в основе шейдеры. Но оба одинаково ошибочны как API первичного материала:

  1. Внедряет синтаксис WebGL в API материалов даже для относительно простых функций
  2. Зависит от строковых манипуляций шейдеров основных материалов, делая изменения основных материалов со временем более сложными и хрупкими.
  3. Менее доступный для художников
  4. Практически несериализуемый

Декораторы (например, # 14206), безусловно, улучшают это с точки зрения пользователя, но если будущая разработка функций материалов будет основываться на все более сложных декораторах поверх существующих шейдеров материалов, это, на мой взгляд, представляет опасность для ремонтопригодности.

Материалы узла не идеальны, но они широко используются в других графических инструментах и ​​имеют ключевые преимущества:

  1. Гибкость и компоновка
  2. Сохраняет уровень абстракции от внутренних шейдеров WebGL библиотеки, не закрывая при необходимости доступ к простым шейдерам.
  3. Широко популярное представление материалов для художников и разработчиков игр.
  4. По крайней мере, несколько сериализуемый (хотя преобразование в другие форматы все еще сложно)

Вероятно, это звучит так, как будто я говорю, что onBeforeCompile следует исключить, и я не хочу этого - я был бы рад, если бы он остался, и примеры приветствуются. Но это не API, на который я хочу указывать пользователям A-Frame или three.js в большем количестве случаев, чем необходимо; Я не думаю, что это хорошо сочетается с системами материалов в других 3D-инструментах.

  • трение включения множества отдельных файлов

Это не должно быть трением. Я думаю, было бы полезно провести какой-то опрос или что-то в этом роде, чтобы узнать, сколько людей используют сборщики пакетов и инструменты сборки. Импорт js-файлов в html-файл вручную не должен быть подходом в 2018 году. Это единственное число, которое я могу найти , и я думаю, что можно сделать предположение, что все эти пользователи используют его с чем-то, что работает с node.

Я бы приложил больше усилий, чтобы встряхнуть дерево и правильно выполнить import/export this, чем беспокоиться о том, как это будет работать при ручном включении файлов сценариев.

  • отсутствие визуального редактора
  • относительно немного примеров, документов

Я думаю, это должно произойти до того, как это войдет в ядро. Материал зеркального блеска должен быть примером, который не связан с GLTFLoader . Тот факт, что он находится в /src или /examples не имеет значения?

@donmccurdy

Вы правы, что хуки onBeforeCompile и onBeforeRender бесконечно гибкие; нет практических ограничений на то, как далеко вы можете манипулировать или заменять лежащие в основе шейдеры.

Я на самом деле не утверждаю этого, я утверждаю, что такой хук, как onBeforeRender позволяет использовать другой подход к структурированию кода, но его не следует использовать, поскольку он используется сейчас в GLTFLoader (отсюда # 14099).

onBeforeCompile определенно имеет ограничения и может быть неправильно назван. В этом контексте стоит отметить недавний PR №14214. Как только я увидел, что ушло ( build() вместо needsUpdate ), я понял, что увижу там onBeforeCompile . Я использовал его как onBeforeParse поскольку, если я не заменю какие-либо операторы #include <foo> , они все равно будут проанализированы после этой функции и перед фактической компиляцией. В этом PR он используется как onWillRefreshMaterial .

Философия, которую я пытаюсь донести, заключается в том, что, вероятно, при таких обратных вызовах должно быть больше детализации. Их должно быть больше, и при их именовании следует проявлять особую осторожность.

# 14214 - отличный пример того, почему NodeMaterial не обязательно должно быть в ядре. По крайней мере, не связано с чем-либо в /renderer и не связано с ним.

  1. Внедряет синтаксис WebGL в API материалов даже для относительно простых функций

Я слышал об этой проблеме раньше, но она не обсуждалась. Почему это проблема? В любом случае, что такое «материальный API»? Я всегда видел это как «вот некоторые распространенные материалы для затенения поверхностей».

Если вам нужна динамическая карта, я не вижу причин, по которым material.map или 'material.color' не могут принимать 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. Зависит от строковых манипуляций шейдеров основных материалов, делая изменения основных материалов со временем более сложными и хрупкими.

Я хочу сказать, что это уже в некоторой степени возможно с onBeforeCompile но делает эти изменения еще более сложными и более хрупкими, чем то, что вы описываете. Я уже обращался к этому в своей профессиональной жизни, и у меня есть код, который полагается на это. Насколько он хрупкий, вызывает много стресса :(

Декораторы, на которые вы указали №14206, застопорились больше года из-за этого пиара, который сам застопорился на 3 года. По моему субъективному мнению, # 14206 сделает написание этих декораторов возможным, менее утомительным и менее хрупким. Это 30 строк кода, которые ни на что не влияют, если только эти фантомные свойства не определены. Если нам уже дали веревку, на которой можно повеситься, в виде onBeforeCompile почему бы не сделать это немного более гуманно? :улыбка:

В конце концов, я хотел бы для себя решить, какой уровень хрупкости приемлемый, а какой нет.

  1. Менее доступный для художников

Вот почему художники должны иметь визуальный инструмент и какой-то формат для сохранения графиков. Потребление их как «запеченного» GLSL или чего-то, что создает NodeMaterial во время выполнения, должно быть выбором пользователя.

Художник может создать шейдер, инженер может попросить его «скомпилировать», чтобы оптимизировать процесс загрузки. Художник, работающий в одиночку, может просто загрузить график, полагая, что это по какой-то причине проще («скомпилированный» требует больше усилий).

Кроме того, почему и как здесь считаются художниками? Есть ли какая-то статистика, как выглядит средний пользователь "художник", почему они работают с three.js, а не с unity, т.е. что это за трубопровод. Вовлечены ли инженеры, почему бы не использовать отдельный инструмент, который каким-то образом взаимодействует с three.js, который используется в каком-то техническом каталоге и т. Д. Я предполагаю, что 40 000 скачиваний npm в неделю - это не художники. Предполагается, что такая установка используется некоторыми инструментами сборки и вряд ли будет импортирована вручную.

И в этом, и в пункте 2 мой вариант использования не включает художников и, как правило, других пользователей. Я развиваю систему материалов, основанную на встроенных материалах. Я использую свою обычную распаковку с касательными атрибутами, отслаиванием глубины, различными отсечениями и т. Д. Все, что мне нужно, - это структурировать этот код внутри компании и раскрыть как можно меньшие внутренние элементы для классов, указанных выше.

  1. Практически несериализуемый

Я мало что знаю об этом, и я слышал этот аргумент раньше. Я был бы более чем счастлив взглянуть на какой-нибудь код, если бы кто-нибудь мог указать мне на проблемные области. С моим очень ограниченным пониманием (почти полным отсутствием) проблемы я не понимаю, почему просто недостаточно написать

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

Допустим, у вас есть специальный глянцевый материал, созданный с помощью NodeMaterial , вы бы не хотели сериализовать весь график, только входные данные? Какой бы ни была сериализация материала SpecGloss , он должен выглядеть одинаково? Мне здесь, наверное, многого не хватает, был бы признателен за несколько указателей.

Re: сериализация

Достаточно ли добавить:

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

customSerializer( data )

А потом что-то вроде

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

specularMap действительно будет сериализован, потому что он жестко запрограммирован:
https://github.com/mrdoob/three.js/blob/dev/src/materials/Material.js#L213

Но это кажется немного странным, класс Material знает о внутренностях всех встроенных материалов, кажется?

@donmccurdy, если вы хотите провести это обсуждение, возможно, лучше сделать это в декораторе PR, # 14206. В автономном режиме я доступен для рабочего сеанса за пивом или кофе в любом месте в районе залива: слегка_smiling_face:

Согласились с тем, что несколько файлов _не_ должно быть трением и что это не аргумент сам по себе для помещения NodeMaterial в src/ . Это просто одна из нескольких причин, по которым NodeMaterial еще не так активно используется, и есть другие способы решить эту проблему. И я, конечно, согласен с тем, что больше документов было бы предварительным условием для помещения NodeMaterial в src/ или даже для продвижения принятия в examples/js или отдельного вывода сборки.

Я оптимистично отношусь к NodeMaterial как к общему направлению, хотя подозреваю, что нужно еще кое-что, прежде чем оно обретет смысл в src/ . Я очень беспокоюсь об использовании onBeforeCompile и манипуляций со строками в качестве пути для добавления новых функций в систему материалов, как описано выше, и особенно по мере того, как мы движемся к поддержке WebGL2 и (в конечном итоге) WebGPU . Нельзя сказать, что эти два варианта - единственные, но (из двух) это мои мысли.

С другой стороны, кажется, что мы понимаем проблемы и предпочтения друг друга, но все равно не согласны. Я написал все, что у меня есть время написать на этом этапе, и я немного посижу и позволю другим высказать свое мнение. Спасибо за подробное и вежливое обсуждение этого вопроса. 🙂

Я хотел бы наложить текстуру окружающей окклюзии с помощью Multiply на диффузную текстуру, поэтому я пробую это:

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

Это моя текстура АО
ao sx

К сожалению, на моей модели я наблюдал окклюзию окружающей среды.

У вас есть идеи для этого?
Надеюсь, это подходящее место для размещения моего вопроса.

Спасибо!

Я хотел бы иметь возможность думать в направлении сопоставления существующих инструментов на основе узлов с материалами в threejs. Следовательно, я хотел бы видеть NodeMaterial в src / вместе с соответствующей документацией.

@IARI

Не могли бы вы перечислить существующие инструменты на основе узлов?

@donmccurdy

Спасибо за ваш ответ :)

К сожалению, я думаю, что мы до сих пор не понимаем друг друга. Если у вас есть время прочитать этот пост, вот что:

Я очень беспокоюсь об использовании onBeforeCompile и строковых манипуляций в качестве пути для добавления новых функций в систему материалов,

onBeforeCompile - это ужасно, я согласен, единственная причина, по которой я участвую в любом из этих потоков, заключается в том, что я хочу # 13198, который, как мне кажется, превосходит манипуляции со строками onBeforeCompile .

Это не должно быть шаблоном для добавления новых функций в three.js. Это должно позволить пользователям добавлять новые функции в свои приложения. Мне грустно, что @bhouston не поделился какими-либо выводами о поддержке форка для некоторых из этих вещей. Мне было бы любопытно, создали ли они лучшую структуру для изменения шейдеров или действительно взломали ядро ​​для этой функции.

В случае поканальных преобразований uv я бы сделал это примером или модулем npm. Если 3 человека скачивают его каждую неделю, вероятно, этого не должно быть в ядре. Если его скачают 20 тысяч человек, вероятно, именно так и должен был быть разработан three.js.

onBeforeCompile похоже, будет иметь решающее значение для материалов узла, https://github.com/mrdoob/three.js/pull/14214 , поэтому он используется не только для манипуляций со строками .

У меня есть onBeforeCompile и NodeMaterial для этого, я прошу третий вариант. Намного удобнее, чем onBeforeCompile и намного меньше, чем NodeMaterial .

С недавними примерами:
https://github.com/mrdoob/three.js/pull/14206

Старое обсуждение:
https://github.com/mrdoob/three.js/pull/13198

@pailhead Для начала я бы подумал о нескольких основных
Мне также было бы интересно поиграть с Unitys Shadergraph.

@claudioviola Вы можете добавить material.shadow или умножить на диффузный material.color = diffuse * oclusion . Зависимость окклюзии от непрямого света, AmbientLight , HemisphereLight ...

@IARI

Я скачиваю 7,5 гигабайт Unity, чтобы проверить ShaderGraph: слегка_smiling_face:: Я не уверен, что это можно считать инструментом для построения шейдерных графов, я думаю, что это инструмент для построения шейдерных графов для единства. Существуют ли автономные инструменты для создания графиков? Я хочу посмотреть, какой файл это тоже сохраняет график, и как он будет перенесен в three.js и NodeMaterial в /src .

Я думаю, что @pailhead на данный момент изолирован от этого перемещения NodeMaterials в ядро. Я не думаю, что всем полезно спорить с @pailhead целыми днями. Я думаю, что этот проект не должен быть связан с каким-то одним человеком.

Это не было ни спешкой, ни принуждением. Сунаг добавил это много лет назад. В этом сейчас есть потребность, и другие альтернативы не работают (например, слияние), поэтому давайте попробуем этот путь.

Все основные инструменты, 3DS Max, UE4, Blender, Unity, Maya, Sketchfab используют шейдерные графики. Утверждение, что three.js должно быть в постоянном невыгодном положении в этом отношении, кажется несправедливым по отношению к three.js.

Я не уверен, что эта система шейдеров на основе графов идеальна в настоящее время, но как только она будет в ядре, мы все сможем продолжать работать с ней.

Я настаиваю на том, чтобы мы продолжали поддерживать API PhoneMaterial, StandardMaterial и т. Д. В некоторой степени в будущем, чтобы мы не нарушили 95% проектов three.js, это было бы безответственно. Также приятно работать с такими упрощенными и понятными интерфейсами.

У меня нет ни возможности, ни желания предотвратить попадание этого в ядро. Я просто надеюсь, что он сможет разблокировать некоторые несвязанные PR, потому что он упоминается как блокировщик. @bhouston , никогда не хотел с тобой спорить, мне просто было любопытно узнать о твоей вилке и опыте с ней.

Когда я сводил концы с концами как голодный 3D-художник, мне нравилось все, что связано с узлами. Nuke был моим любимым композитором, и я хотел бы научиться делать такие инструменты. Я просто хочу, чтобы это разблокировало именно этот # 14231. Я использую это как обучающую платформу для себя, но если это мешает, я перестану публиковать сообщения, спасибо.

@pailhead Я никогда не работал с этим, но вы, наверное, слышали о конструкторе субстанций? Насколько я понимаю, этот инструмент также выходит за рамки создания графиков / шейдеров - но он в первую очередь ориентирован на процедурный дизайн материалов - может быть, это интересный ключ?

Помимо этого, я не знаю автономных инструментов, но быстрый поиск в Google дал эти два:

Тем не менее, есть также этот инструмент для узлов threejs, который я нашел в твиттере @mrdoob еще в 2015 году - хотя он, кажется, никогда не обновлялся, мне интересно, почему ...

Похоже, здесь упоминается этот инструмент, но я не вижу способа что-либо экспортировать. Первая ссылка выглядит потрясающе, но вывод довольно грубый, не очень читаемый по сравнению с GLSL. Интересно, можно ли это уже использовать для повторной сборки NodeMeterial или даже ShaderMaterial .

Я посмотрел на единство, но я не смог найти инструмент шейдерного графа,

Кстати, если я как-то заблокировал это, во что бы то ни стало, пусть будет разблокировано. PR с 2015 года, первый ответ я ответил 8 дней назад.

(Извините, это немного оффтоп ..)
@pailhead Для
Вот руководство по настройке, начиная с создания нового проекта: https://youtu.be/Ar9eIn4z6XE?t=98

Редактор нодов материала Sea3D Flow (http://sea3d.poonya.com/flow/) принадлежит @sunag , тому же парню, который написал NodeMaterial.

Большое спасибо @sunag
Как я могу получить непрямой свет? Это значение в рендерере или как его вычислить?

Я хотел бы применить эффект постобработки только к выделенным объектам (т.е. изменить насыщенность).
Однако я не могу найти ничего, связанного с маскированием (если нет другого способа) с узлами.
В настоящее время я читаю OutlinePass (не являющийся узлом), который записывает кучу информации в кучу буферов, что я могу рассматривать как возможный метод для достижения того, что я хочу, но у меня нет ни малейшего представления о том, как подойти это с узлами.

Редактор нодов материала Sea3D Flow будет таким же автономным, как редактор three.js, или будет его частью? Будет ли он по-прежнему называться Sea3D или что-то еще, связанное с three.js? Спасибо @sunag за выпуск этого визуального редактора для сообщества three.js.

но я не имею ни малейшего представления о том, как подойти к этому с узлами.

@IARI

Похоже, вы знаете GLSL, поскольку можете читать OutlinePass и понимать, что он делает. Вы также, кажется, понимаете это достаточно, чтобы понять, что вы не можете добиться этого с помощью узлов. Я подумал, что если вы знаете, как это кодировать, вы будете знать, как создавать ноды. Более того, если вы не знаете, как его кодировать, вы можете знать, как его создать. Где отключение?

Я вообще не видел этих постов за 2016 год. Интересно посмотреть Shader Frog. Интересно, можно ли это рассматривать как vim vs emacs или что-то в этом роде. Мне нравится использовать Sublime Text, вам нравится использовать что-то еще. Один любит использовать шейдерную лягушку, другой любит использовать редактор Sea3D от three.js.

Мне нравится, как Shader Frog просто выводит шейдер, но это не с открытым исходным кодом, как Sea3D.

Тогда вот это.

Включение механизмов сторонних продуктов в ядро ​​Three кажется несправедливым преимуществом, и я не понимаю этого с политической точки зрения.

Для меня тот факт, что все это может быть выполнено без трех изменений, означает, что в этом нет необходимости, и стирается грань между Three.js, являющимся API-оболочкой webgl, и теперь управляющим специфическими функциями реализации. Хранение данных шейдерных узлов сильно зависит от приложения, и, насколько мне известно, в настоящее время нет общего стандартного формата редактора узлов для любого программного обеспечения? Применение одного из них может быть вредным для других реализаций.

@bhouston
Я не могу дождаться, пока приземлится NodeMaterial , так как это может разблокировать другие PR и жизнь может вернуться в нормальное русло. Похоже, что другие голоса пытались заблокировать это в прошлом.

Я думаю, что @pailhead на данный момент изолирован от этого перемещения NodeMaterials в ядро.
Я думаю, что этот проект не должен быть связан с каким-то одним человеком.

Спасибо.

Я не вижу причин, по которым этого нельзя было бы достичь с помощью узлов точно так же, как это делает контурpass, - но таким способом, который был бы читабельным, понятным и модульным, чтобы части можно было повторно использовать.
Почему не должно быть, например, выходных узлов, которые пишут в буферы и прочее.

И я действительно не очень хорошо знаю glsl, и я также нахожу это - простите за формулировку - супервизорой для чтения и написания кода шейдера. И, вдобавок ко всему, это очень болезненно, если его завернуть в дурацкий массив строк в коде javascript.

Вы используете webpack или что-то в этом роде?

глупый массив

Это глупо, если вам нужно импортировать его в файл .html. Когда вы работаете с webpack и у вас есть современный синтаксис JS, вы можете хранить свой GLSL в файлах .glsl, .vs, .fs и иметь подсветку синтаксиса и тому подобное.

shader.fs:

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

javascript (мама смотри, никаких тупых массивов)

import mShader from './shader.fs'

Меня беспокоит то, что я не вижу особой ценности в ваших потребностях, поскольку вы конкретно спрашиваете, как создать эффект, а не как что-то кодировать. NodeMaterial откроет двери для тысяч вопросов "как мне затенять этот эффект", на которые будет просто общий ответ:

Используй узлы, Люк!

Нет, мне всегда больно читать (не говоря уже о написании) кода на двух разных языках в одном файле. Также webpack ничего не помогает, когда вы пытаетесь изучить пример кода шейдера threejs, который весь обернут уродливыми строковыми массивами, соединенными разрывами строк.
В любом случае, этот вопрос касается системы узлов, и я задал простой вопрос об узлах - не для обсуждения личных предпочтений кодирования - который ни к чему не приведет.

@IARI

Извините, я почему-то не увидел в вашем сообщении вопросительных знаков, поэтому пропустил ваш вопрос.

Это определенно не должно быть обсуждением личных предпочтений кодирования, но следует учитывать тот факт, что они разные. Меня также немного беспокоит шквал вопросов «Как мне сделать этот шейдер».

Раньше эта планка была довольно высокой, люди просто сдаются с i don't know glsl или когда видят «тупой массив в строках». А если ниже, то все будут пытаться писать шейдеры.

Я не нашел ваш вопрос, но мне любопытно, что это. Это:

Как создать ToonShader с помощью NodeMaterial?

В таком случае мне любопытно, каков ответ.

Вы не можете, потому что NodeMaterial не поддерживает некоторую абстракцию.
Вы можете просто использовать NodeMaterial для соединения узлов

Может быть, эту дискуссию стоит разбить на две части? Это большое количество публикаций, уходящих очень далеко в прошлое (2015 год). NodeMaterial находится в / examples, так что вы, вероятно, сможете построить из него свой мультяшный шейдер. Может быть, вы могли бы открыть другую проблему или опубликовать сообщение о переполнении стека специально для этого, а остальная часть разговора могла бы перейти к новой проблеме?

Мы с радостью можем перенести это обсуждение в другое место, например, на какой-нибудь слабый канал или что-то в этом роде - я действительно чувствую, что это не здесь, но в основном будет раздражать людей.

В этом конкретном случае форум может быть лучше, чем бездельник.

@pailhead , вся эта дискуссия сорвалась из-за того, что была продуктивной. Можно также закрыть эту проблему и создать новую, сосредоточенную на актуальной проблеме.

@bhouston

Согласен, за исключением того, что я думаю, что это несколько вопросов.

  • как реализовать nodematerial
  • должны ли быть заблокированы другие связанные и не связанные PR
  • как позволить людям, которые не умеют писать шейдеры, реализовывать определенные шейдерные эффекты

Как создать ToonShader с помощью NodeMaterial?
В таком случае мне любопытно, каков ответ.
Вы не можете, потому что NodeMaterial не поддерживает некоторую абстракцию.
Вы можете просто использовать NodeMaterial для соединения узлов

Ржу не могу. Я согласен с @bhouston ... это может быть только шуткой. Вы могли видеть пример webgl_materials_nodes до того, как это произнесли?

А если вы хотите использовать код, посмотрите выражение using FunctionNode .

toon

@sunag, я думаю, ты меня неправильно понял. Мне было любопытно, почему, если это в настоящее время находится в /examples а не в /src , это превращается в гражданина первого класса. Этот вопрос, похоже, был поднят @AndrewRayCode еще в 2015 году.

Я только что сказал, что этот вопрос перегружен, начиная с 2015 года и из-за обсуждения различных тем. Если кто-то спросит, «как мне сделать whatever », его направят на переполнение стека.

Если это будет капитальный ремонт three.js _ (тот факт, что единство должно быть настроено специально для этого, несколько пугает меня) _, тогда я думаю, что здесь, на github, должна быть постоянная проблема для таких вопросов - usage of NodeMaterial . Так как люди, которые просят случайные вещи (# 14232), попадают в эту ветку, это делает общение беспорядочным :)

Недавно мне пришлось написать мультяшный шейдер, но он был основан на строках, а точнее на жирных строках @WestLangley . Так что даже с потребностью в "мультяшном" шейдере у меня все было бы совсем иначе. Это также потребует переноса жирных строк на NodeMaterial что может занять неизвестно сколько времени. Все это разные темы, которые здесь запутаны.

И если вы хотите использовать код, см. Выражение using FunctionNode.

Если я кодирую, я использую возвышенный текст, ShaderMaterial мне подходит, и мне не нужно FunctionNode . Если я создаю визуальные эффекты, я, вероятно, поищу визуальный редактор, но это мое личное предпочтение. Я здесь только потому, что это заблокировало другие PR :) Не так давно я понял, что на самом деле в интересах троих, чтобы это приземлилось как можно быстрее. Распутывание этого разговора, вероятно, поможет ускорить процесс. В этом я согласен с @bhouston, это должен быть йолод как можно скорее!

Спасибо.

Для справки: меня не интересуют шейдеры мультяшек или что-то в этом роде.
Я внедряю систему, которая позволяет людям, которые не пишут код, вставлять простые предопределенные эффекты в определенные позиции.

К сожалению, я боюсь, что у меня не будет времени изучать, как писать узлы прямо сейчас, и мне все равно придется наверстать упущенное в базовом кодировании glsl, поэтому сейчас я буду реализовывать вещи без узлов: он не будет расширяться , он будет использовать несколько проходов рендеринга, где одного, вероятно, будет достаточно с хорошей реализацией узла, он будет менее читабельным, ...

В целом, к сожалению, я просто новичок в общей теме, и мне нужно получить гораздо больше базовых знаний, но, судя по тому, что я знаю, узлы были бы лучшим способом сделать это по-настоящему элегантным и расширяемым образом.
Мне очень хотелось бы получить некоторую информацию о реализации узлов, например статью в блоге или учебное пособие.

Отказ от ответственности: я ничего не требую, просто надеюсь прояснить свой расплывчатый запрос сверху.
Спасибо всем за проделанную здесь работу - это просто потрясающе.

В ветке https://github.com/mrdoob/three.js/issues/14232 меня попросили прокомментировать реализацию шейдера на основе узлов. Я считаю, что это очень плохо. Мне нравится эта идея, но реализация, на мой взгляд, совершенно неадекватна, поэтому, поскольку я настроен так отрицательно, я собираюсь привести некоторые конкретные причины, почему.

Понятность

После прочтения кода для узлов и различных служебных классов я могу с уверенностью сказать, что это огромная проблема для понимания.

  • имена переменных не описательны
  • никаких комментариев
  • имена методов неясны или вводят в заблуждение. (например, как вы думаете, что делает метод "build"? - предположите)

Структура кода совершенно странная. Рассмотрим этот фрагмент:
https://github.com/mrdoob/three.js/blob/e2b49c017b2d1f37ab34317033a27df7b5a71d4d/examples/js/nodes/FunctionNode.js#L39 -L50

Вы можете добиться того же с помощью:

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

«Эмерджентная архитектура»

Что такое «узел»? Я прошу дать определение структуры данных, потому что кажется, что это просто расплывчатая концепция, поскольку между разными «узлами» мало общего, это похоже на утиное написание, если оно крякает как узел - это узел.

Разделение проблем

Как перейти от Node к ShaderMaterial ? Сейчас это сочетание ответственности между различными частями логики от каждого узла, некоторыми построителями, некоторым кешем, парсерами и т. Д. Нет четкой ответственности за этот процесс. Node использует NodeBuilder? Что за ...? Судя по названию, которое я бы назвал, NodeBuilder - это фабрика, которая производит или конструирует узлы, поскольку оказывается, что на самом деле это вспомогательная структура. Насколько я могу судить, здесь нужно выполнять довольно разные работы:

  • Построить график
  • Подтвердить
  • Построить промежуточное представление
  • оптимизировать
  • компилировать в GLSL

Это совсем не то, что вы найдете в текущем коде.

Заключение

Без хорошей документации и комментариев я считаю эту реализацию совершенно неадекватной. С этими вещами дело в спагетти-коде и отсутствии дизайна. С учетом сказанного - я признаю, что это мощный инструмент и рабочая реализация очень полезной концепции.

@Usnul, мы никогда не будем кодировать так в Three.JS "return this.inputs.find (input => input.name === name);"

Причина в том, что "=>" создает функцию, которая должна вызываться для каждого ввода. Вызов функций в JavaScript выполняется очень медленно по сравнению с циклами for или while. Таким образом, мы всегда выполняем явные циклы вместо кода, ориентированного на обратный вызов. Я знаю, что это более многословно, но это необходимо. Все Three..JS такие и намеренно.

@Usnul , ваши проблемы с дизайном очень полезны, не могли бы вы тогда помочь с рефакторингом? Я думаю, что все будут признательны за ваш дизайнерский вклад и вклад. :)

Причина в том, что "=>" создает функцию, которая должна вызываться для каждого ввода. Вызов функций в JavaScript выполняется очень медленно по сравнению с циклами for или while. Таким образом, мы всегда выполняем явные циклы вместо кода, ориентированного на обратный вызов. Я знаю, что это более многословно, но это необходимо. Все Three..JS такие и намеренно.

это справедливый момент. Лично я придерживаюсь философии, согласно которой производительность и удобочитаемость должны быть в масштабе, а не в одном или другом масштабе, но согласованность - это хорошо. Моя основная проблема с этим конкретным примером заключается в том, что это не обычный способ итерации по массиву. Вот идиоматический способ:

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

или, скажем, у вас есть фрагмент кода длиной 50 строк в форме:

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

это не так читаемо, как:

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

@Usnul, не могли бы вы помочь в рефакторинге кода, чтобы учесть это? Я думаю, что рефакторинг должен быть простым, не так ли? Я большой сторонник Code Complete, эта книга сильно на меня повлияла.

@usnul, если вам это не нравится, вы можете провести рефакторинг? Насколько я понимаю, не имеет значения, выглядит это так или нет, просто важно, чтобы он был построен поверх этого.
Я не знаю, должны ли возникать рефракторы, пока это есть в примерах (или, возможно, в другом репо), или его нужно сразу же переместить в src, как предлагает @bhouston .

@IARI

Я действительно не очень хорошо знаю glsl , и я также нахожу это - простите за формулировку - супер головной болью при чтении и написании кода шейдера .

но, судя по тому, что я знаю , узлы - лучший способ сделать это по-настоящему элегантным и расширяемым образом.

Я также не могу утверждать, что знаю GLSL очень хорошо, но я знаю его достаточно, чтобы решить свои проблемы. Насколько я знаю, я в основном согласен с тем, что написал здесь @usnul и что @AndrewRayCode . Я считаю, что элемент node более подробный по сравнению с GLSL.

Если вы не знаете GLSL, думаю, будет очень сложно сравнить его с чем-то другим. Как вы сами написали, если мы judge on what you know , а вы сами это сказали you don't know glsl я думаю, что ваше мнение следует принять с оговоркой :)

Это как если бы я сказал:

Япония - худшее место на этой планете ... но я никогда не был в Японии ».

Спасибо.

имена методов неясны или вводят в заблуждение. (например, как вы думаете, что делает метод "build"? - предположите)

Вау, я даже не понял, что это ShaderMaterial внизу. Я предполагаю, что это делает все то же самое, что THREE.WebGLRenderer с шаблонами шейдеров.

Я действительно не очень хорошо знаю glsl, и я также нахожу это - простите за формулировку - супер головной болью при чтении и написании кода шейдера.
но, судя по тому, что я знаю, узлы - лучший способ сделать это по-настоящему элегантным и расширяемым образом.

@pailhead Он имеет в виду, что между вещами есть промежуточные уровни.

Я не понимаю, почему эта тревога. @mrdoob никогда не объединит ничего, кроме отличного решения. Весь отличный пиар, улучшения от кого-либо в NodeMaterial или нет, очень полезны для сообщества. Если это все еще не было слиянием в ядре, это потому, что нам нужно улучшить с помощью дополнительной работы.

@sunag, есть ли что-нибудь, что другие могут сделать, чтобы помочь вам с этим проектом? Я был бы готов написать документацию, если вы готовы к документам и можете их просмотреть.

@sunag, есть ли что-нибудь, что другие могут сделать, чтобы помочь вам с этим проектом? Я был бы готов написать документацию, если вы готовы к документам и можете их просмотреть.

Это будет здорово. Без сомнения очень помогает.

Система материалов на основе узлов выглядит потрясающе, она расширила бы выразительность.

Как мы переключимся с существующей системы материалов на систему материалов на основе узлов в ядре? Будем ли мы использовать две системы или заменить существующую на узловую?

Извините, может быть, я не думаю, что пойму эту тему, потому что она слишком большая ...

Будем ли мы использовать две системы или заменить существующую на узловую?

Я считаю замену конечной целью, она лучше как с точки зрения производительности, так и с точки зрения обслуживания. Следующий шаг - сделать так, чтобы MeshStandardNodeMaterial и другие материалы узла в ядре работали точно так же, как ядро ​​в визуальном плане, синтаксисе и производительности.

Я должен показать shadowMap в моем проекте.

У меня есть сцена с направленным светом и 2 геометриями, в которых используется MeshStandardNodeMaterial.

Я включил
castShadow = true для света
castShadow и receiveShadow для обоих объектов.
shadowEnabled = true для Renderer

Почему не работает?
Должен ли я использовать свойство shadow для MeshStandardNodeMaterial? Это цель?

Кто-нибудь может мне помочь?
Спасибо!

@claudioviola
Вопросы поддержки отправляются на форум stackoverflow.

@sunag Как вы думаете, NodeMaterial достаточно стабилен, чтобы мы могли начать с предоставления файлов объявлений TypeScript? Если вы не планируете серьезных изменений API в ближайшем будущем, я бы начал с этой задачи, поскольку NodeMaterial - это последняя группа модулей без поддержки TS.

@sunag Как вы думаете, NodeMaterial достаточно стабилен, чтобы мы могли начать с предоставления файлов объявлений TypeScript? Если вы не планируете серьезных изменений API в ближайшем будущем, я бы начал с этой задачи, поскольку NodeMaterial - последняя группа модулей без поддержки TS.

@ Mugen87 Да, должно быть больше дополнений, чем изменений. Добавить поддержку TS будет здорово. 👍

Хорошо, поддержка TS готова со следующим выпуском R017 🙌

Была ли эта страница полезной?
0 / 5 - 0 рейтинги