Three.js: УФ-смещение / повторение должно быть частью материалов, а не текстур.

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

УФ-смещение и повторение (и, вероятно, некоторые другие свойства текстуры) - это формы, которые странным образом передаются из текстуры в материал, что приводит к проблемам, когда вам нужно клонировать текстуры для каждого материала (тратя тонну памяти), если вы хотите, чтобы -материал смещает / повторяет, или сверните свой собственный шейдер. Заставлять людей делать это очень неэффективно, в лучшем случае, если кто-то хочет выложить текстуру на поверхность в зависимости от размера объекта, к которому она применяется, или использовать текстуру в качестве таблицы спрайтов для анимации. Я могу рассматривать текущую систему только как помеху без каких-либо реальных преимуществ, так как вероятность того, что потребуется совместное использование UV-смещений / повторов на «общей» текстуре, мала, и, как правило, лучше было бы использовать общий доступ к материалу. В любом случае обновление униформы за пределами текстуры - это странно, так как на самом деле не имеет отношения к тому, чтобы быть частью текстуры, и в конечном итоге сбивает с толку конечного пользователя. Например, изменение смещения / повторения, когда к материалу применено более одной карты, например diffuse + normalmap, использует только смещение / повторение диффузной карты, поэтому значение смещения / повторения normalmaps совершенно бесполезно в этом контексте. , когда он действительно предполагает, что это должно повлиять на смещение / повторение карты нормалей. Все вокруг сбивает с толку.

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

Suggestion

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

эта ветка TL; DR для меня. но я только что обнаружил этот код в r68 (старый проект, да):

        // uv repeat and offset setting priorities
        //  1. color map
        //  2. specular map
        //  3. normal map
        //  4. bump map
        //  5. alpha map

        var uvScaleMap;

        if ( material.map ) {

            uvScaleMap = material.map;

        } else if ( material.specularMap ) {

            uvScaleMap = material.specularMap;

        } else if ( material.normalMap ) {

            uvScaleMap = material.normalMap;

        } else if ( material.bumpMap ) {

            uvScaleMap = material.bumpMap;

        } else if ( material.alphaMap ) {

            uvScaleMap = material.alphaMap;

        }

        if ( uvScaleMap !== undefined ) {

            var offset = uvScaleMap.offset;
            var repeat = uvScaleMap.repeat;

            uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );

        }

так что да...

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

Я пытался установить разные повторы на диффузных картах и ​​картах нормалей и выдергивал волосы, потому что это не сработало. поскольку API помещает этот параметр в текстуру, я думал, что смогу это сделать. так что да, как насчет того, чтобы сохранить мои волосы в качестве веского аргумента? этот билет все еще открыт, 3js все еще имеет эту настройку для текстур, и она соблюдается только для одной из текстур = это, по сути, уже разрешенная настройка IS.

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

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

Связанное сообщение: https://github.com/mrdoob/three.js/issues/3549

вам нужно клонировать текстуры для каждого материала (тратя кучу памяти)

В каком смысле тратятся тонны памяти?

вероятность необходимости общих смещений / повторов UV на «общей» текстуре мала.

Что ты имеешь в виду?

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

если у вас есть объект с большим количеством кадров / листов, создается много бесполезных объектов, и, как вы заявили, изображение многократно копируется на графический процессор, что чрезвычайно расточительно. Еще более расточительно, если у вас есть несколько объектов, которые должны находиться в разных точках в разных анимациях, вам придется создавать уникальный набор текстур для каждого уникального материала / объекта, поэтому его быстро становится неудобно обрабатывать, в то время как униформа материала может гораздо легче манипулировать без этих дополнительных структур данных смещения / повторения текстуры, построенных на плохо продуманном API, просто для того, чтобы заставить его работать. У меня есть серьезное замедление в определенном варианте использования моего приложения, когда мне приходится создавать эти уникальные группы текстур повсюду, и я чувствую, что единственным решением было бы заменить все стандартные материалы, которые я использую, шейдерными материалами, чтобы обойти эту единственную проблему. в противном случае создайте вилку моей версии THREE.js и внесите необходимые изменения.

Что касается второго утверждения:

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

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

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

material.map
material.mapOffset
material.mapRepeat
material.env
material.envOffset
material.envRepeat
... так далее.

но опять же, смещение / повтор не работают для каждого типа карты даже сейчас, так что на самом деле это неверный аргумент. В любом случае было бы потрачено слишком много униформы, чтобы иметь ее для каждого типа карты (не говоря уже о том, что вы обычно используете только один набор UV, поэтому у вас действительно не будет нескольких смещений для normalmap / bumpmap / diffusemap / specularmap). Я думаю, если вы разумно взвесите все варианты, это действительно должно быть свойство материала, а не свойство текстуры. Я действительно не считаю, что у нынешней системы есть какие-то преимущества. Я считаю, что анимация материалов с помощью UV-смещения - основная причина вообще иметь это свойство, и даже не может использоваться для этого должным образом. Не говоря уже о том, что если вам не нужны эти униформы, их можно было бы исключить из компиляции шейдеров, тогда как теперь они существуют, пока есть карта.

@QuaziKb При всем уважении, если вы собираетесь предложить фундаментальное изменение библиотеки, подобное тому, которое вы предложили здесь, вы должны предоставить ясный и убедительный аргумент в пользу этого изменения. Рассуждения, исходящие из системы взглядов вашего конкретного приложения, не помогут.

При этом я тоже хотел бы, чтобы смещение / повтор перемещалось из Texture в материалы.

Я считаю разумным предположить, что следующие карты имеют одинаковые значения смещения / повтора:

specularMap
normalMap
bumpMap
alphaMap
aoMap (future)
glossMap (future)
displacementMap (future)

Единственное исключение -


Так это реализовано сейчас; хотя каждая карта имеет свои собственные значения смещения / повтора, они не учитываются.

Итак, мы могли бы добавить к MeshPhongMaterial , MeshLambertMaterial , MeshBasicMaterial и SpriteMaterial , мы бы добавили

mapOffset // or mapTranslate
mapRepeat // or mapScale

Мы удалим offset и repeat из Texture .

Таким образом, реализовать спрайт-лист очень просто. У каждого спрайта есть материал, и эти материалы имеют единую текстуру. Текстура имеет изображение. Текстуру больше не нужно клонировать. На стороне графического процессора материалы будут использовать одну шейдерную программу.

ИМХО, это более естественный API.

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

Извините, я не хотел сказать, что это было конкретно для моего примера, просто текущий api приводит к значительному раздуванию при использовании для анимации листов / смещений спрайтов для уникального объекта / материала без реального решения. Естественно, основная цель использования этого как униформы, а не просто запекание смещения / повтора в вершинных UV-координатах модели, состоит в том, чтобы анимировать смещение, и я предполагал, что этого нельзя сделать, не обойдя API, сделав единый гораздо менее полезно приложить к текстурам, чем если бы это было к материалу.

Я считаю разумным предположить, что следующие карты имеют одинаковые значения смещения / повтора:
карта
...
alphaMap

FWIW, это поведение (текущая реализация) вызывает у меня серьезное разочарование именно в этот момент. Я пытаюсь оживить раскрытие сетки, изменяя смещение alphaMap материала сетки независимо от его диффузной карты (которая остается фиксированной). После некоторого разочарования я обнаружил через https://github.com/mrdoob/three.js/pull/4987 и эту ошибку, что это невозможно.

@jcarpenter О какой «ошибке» вы говорите? Что вы предлагаете по улучшению?

Исправление: под "ошибкой" я имел в виду эту проблему. Путаница из-за чрезмерного количества времени в культуре Bugzilla. : p Я понимаю, что это не ошибка, а предполагаемое поведение.

WRT к улучшению, основываясь на моем опыте работы с традиционными приложениями для создания 3D-контента, такими как Cinema 4D, я полагаю, что пользователь сможет:

  • определить смещение / масштаб / повторение для каждой текстуры в материале, независимо от других текстур, _и_
  • определить смещение / масштаб / повторение исходного материала

В качестве альтернативы для варианта использования, над которым я работаю («попытка оживить раскрытие меша»), было бы фантастически иметь возможность для wrapS и wrapT, которая вообще не оборачивается. Согласно приложенному GIF от Cinema4D, в котором есть возможность полностью отключить мозаику для отображения UVW. На основании довольно обширного тестирования с использованием существующих методов wrapS и wrapT ничего подобного невозможно. Это означает, что мои варианты анимации отображения элементов в three.js, похоже, ограничены промежуточным положением и непрозрачностью всей сетки ... Если я что-то не упускаю.

c4d-tile-2

Согласовано. План состоит в том, чтобы упростить все это (используя одну матрицу3 в шейдере) и имея смещение / повтор (или преобразование / масштабирование) для каждой текстуры.

Будем очень признательны всем, кто хочет помочь с этим!

@jcarpenter

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

Существует постоянный компромисс между удобством использования, производительностью и расширяемостью. Я предлагаю переписать то, как текстуры и материалы работают в настоящее время в api, чтобы текстуры были строго параметрами, которые вы подключаете, а значения, которые фактически являются единообразными в шейдере, такие как режим смещения / повторения / переноса, были связаны специально с материал. В некоторых случаях вы не хотите, чтобы униформа тратилась впустую на управление UV для текстур, которые никогда не нужно менять (было бы огромной тратой иметь 4 * 5 дополнительных униформ в материале фонга, если он вам нужен только для диффузного), так что было бы круто, если бы за кулисами была какая-то магия, которая обнаруживала, нужны ли определенные UV, и текстура перестраивается, чтобы удовлетворить эти требования, или если бы можно было при желании передать какой-то параметр, чтобы указать количество требуемых настраиваемых UV и что карты они смещают и как, но это трудный вопрос.

План состоит в том, чтобы упростить все это (используя одну матрицу3 в шейдере) и имея смещение / повтор (или преобразование / масштабирование) для каждой текстуры.

@mrdoob

  1. Вы имеете в виду _per material.map_, чтобы преобразовать текстуру в материал? К сожалению, карт материалов очень много. Мы могли бы продолжать предполагать, что все преобразования текстуры одинаковы, за исключением карты освещения.
  2. Вы тоже хотите поддерживать ротацию? Если это так, вам также необходимо добавить центр вращения - если вы не хотите жестко привязать центр вращения к центру текстуры.

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

  1. Вы имеете в виду _per material.map_, чтобы преобразовать текстуру в материал? К сожалению, карт материалов очень много. Мы могли бы продолжать предполагать, что все преобразования текстуры одинаковы, за исключением карты освещения.

Я думаю, у нас должен быть mat3 на карту, и он должен состоять из свойств Texture .

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

Вращение да. Центрировать или нет ... Не уверен, но насколько я понимаю, все это можно закодировать в одном mat3 для шейдера (на карту).

Вот прототип, показывающий, как Matrix3 можно передать шейдеру и представить преобразование, определяемое offsetX , offsetY , repeatX , repeatY , rotation , rotationCenterX и rotationCenterY .

Если center не допускается в качестве опции, тогда его следует жестко привязать к ( 0.5, 0.5 ) .

Комментарии приветствуются.

РЕДАКТИРОВАТЬ: демоверсия обновлена

rotateuvs

ОТЛИЧНО! : +1:: +1:

Я бы предпочел translation и scale (вместо offset и repeat ).

Какими конкретно должны быть свойства нового материала? Материальных карт очень много.

Что нужно убрать из свойств текстуры?

Я предполагаю, что на текстуре должен остаться wrapS/T .

Я думаю, что texture.offset и texture.repeat следует удалить.

Я думаю, что новые свойства должны быть ... texture.translation , texture.rotation , texture.scale , texture.center и texture.matrix . Вероятно, нам также понадобится метод texture.updateMatrix() который будет вызываться во время рендеринга. Это, конечно, связано с тем, что мы делаем это только один раз, даже если текстура используется повторно.

Ссылаясь на заголовок этого сообщения и аргументы в https://github.com/mrdoob/three.js/issues/5876#issuecomment -69483293, я подумал, что смысл в том, чтобы переместить эти свойства в материал.

/ ping @bhouston для комментариев.

Я считаю, что смещение / повторение текстуры должно быть максимально запечено в UV. Легче. По большей части именно так это делают UE4 / Unity 5.

Исключением является то, что в Unity 5 есть возможность указать одно глобальное смещение / повторение для каждого материала, которое является общим для всех текстур, но это не влияет на то, что считается запеченными картами, такими как карты lightMap или ambientOcclusion (те нет смысла настраивать.)

Причина, по которой я не выступаю за большую гибкость здесь, заключается в том, что профессионально созданные модели имеют правильные UV-развертки, которые обычно делают это ненужным - инструменты создания контента имеют способы запечь это. Другая проблема заключается в том, что WebGL имеет смехотворно низкий нижний предел для униформ фрагментов - 16 Vec4. Если вам нужно иметь повторение / смещение для каждой карты, и мы скоро получим много карт, мы тратим зря Fragment Uniform за очень небольшую стоимость.

На самом деле я недавно добавил в Clara.io элементы управления повторением / смещением, а затем яркостью / усилением для каждой текстуры, и я буду отменять эти изменения, потому что это приводит к переполнению униформ фрагментов на устройствах низкого уровня, таких как каждое устройство Apple iOS. Хотя повторение / смещение и яркость / усиление отлично работают на настольных компьютерах с NVIDIA 980s, но мы должны проектировать для всех, а не для высокопроизводительных машин. ;)

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

Исключением является то, что Unity 5 имеет возможность указывать одно глобальное смещение / повторение для каждого материала.

В основном это то, что делает three.js сейчас - хотя он получает смещение / повторение из диффузной карты, а все другие текстуры материалов используют настройку из этой карты.

Предлагается удалить смещение / повторение из текстуры и вместо этого добавить его в материал - возможно, с изменением имени. Опять же, все текстуры материалов будут иметь одни и те же настройки (даже если некоторым пользователям это не понравится). Это снизит равномерное использование.

К сожалению, мы не достигли консенсуса по этому поводу.

Делать то, что делает Unity 5, - хорошая идея. Я бы тоже нанес его на материал, а не на текстуру. У тебя моя поддержка.

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

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

Единственное предлагаемое изменение шейдера - заменить

vUv = uv * offsetRepeat.zw + offsetRepeat.xy;

с участием

vUv = ( uvTransform * vec3( uv, 1 ) ).xy;

Ok. Как насчет этого ... Мы добавляем texture.dynamic (по умолчанию false ), что дает:

vUV = uv;

Если пользователь устанавливает texture.dynamic равным true тогда мы вычисляем texture.matrix из texture.translation , texture.rotation , texture.scale и texture.center , мы передаем это программе и производим:

vUv = ( uvTransform * vec3( uv, 1 ) ).xy;

Конечно, если texture.dynamic изменится, нам нужно перекомпилировать программу.

Таким образом мы получим лучшее из обоих миров?

@mrdoob

  1. На ваш взгляд, scale является свойством текстуры или texture.scale является свойством материала? Я надеюсь, что это последнее, потому что это то, о чем весь этот поток.
  2. Нам не нужно свойство .matrix . Новая форма Matrix3 заменяет материальную форму offsetRepeat . Он вычисляется из других параметров в рендерере и передается в графический процессор, как и любая другая униформа.
  1. На ваш взгляд, scale является свойством текстуры или texture.scale является свойством материала? Я надеюсь, что это последнее, потому что это то, о чем весь этот поток.

Я не согласен с этой веткой. Я не думаю, что мы должны загрязнять материалы mapMatrix , envMapMatrix , ... Ни mapTranslation , mapRotation , mapScale . Я думаю, будет чище, если в THREE.Texture есть translation , rotation , scale и, возможно, center .

  1. Нам не нужно свойство .matrix . Новая форма Matrix3 заменяет материальную форму offsetRepeat . Он вычисляется из других параметров в рендерере и передается в графический процессор, как и любая другая униформа.

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

Я не согласен с этой веткой. Я не думаю, что мы должны загрязнять материалы mapMatrix, envMapMatrix, ... Ни mapTranslation, mapRotation, mapScale. Думаю, будет чище, если у THREE.Texture есть перевод, поворот, масштаб и, возможно, центр.

Нужно ли клонировать текстуру, чтобы иметь другие свойства повтора? В маленьких сценах это, вероятно, не имеет большого значения, но в больших, где уже есть 40+ текстур, это кошмар памяти.

@titansoftime image следует отделить от THREE.Texture . В идеале один единственный THREE.Image может использоваться разными THREE.Texture каждый с разными конфигурациями translation , rotation , ....

Изображение @titansoftime должно быть отделено от THREE.Texture. В идеале один THREE.Image может использоваться разными THREE.Texture, каждая из которых имеет разные конфигурации смещения, поворота и т. Д.

В этом есть смысл. Работает ли texture.clone () таким образом, или его нужно настраивать вручную?

texture.clone() работает таким образом, но WebGLRenderer не может знать, что изображение такое же, поэтому загрузка текстуры не требуется ...

Я не согласен с этой веткой. Я не думаю, что мы должны загрязнять материалы mapMatrix, envMapMatrix, ... Ни mapTranslation, mapRotation, mapScale. Думаю, будет чище, если у THREE.Texture есть перевод, поворот, масштаб и, возможно, центр.

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

FWIW, я думаю, мы должны сделать то, что я сказал в https://github.com/mrdoob/three.js/issues/5876#issuecomment -69483293.

Я не понимаю, почему API не может позволить делать то, что хочет сделать @jcarpenter (анимировать смещение alphaMap , в то время как map остается прежним). Это можно было бы сделать на холсте, но я думаю, что это задача для графического процессора.

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

Наличие только одного uvTransform на материал кажется очень ограничивающим.

Ой, подожди. Думаю, я понимаю, почему вы, ребята, предпочитаете материал. Таким образом, одиночный vUv вычисляется в вершинном шейдере вместо вычисления uv на пиксель во фрагментном шейдере. Верно?

на материал идеален, потому что смещения фактически просто реализованы с использованием униформы материала и не имеют ничего общего с текстурой, поэтому мы получаем бессмысленный обходной путь, если нам нужно изменить форму для каждого материала, который должен сделать тонны новых объектов / текстур (что довольно плохо в JS / ужасно в WebGL) просто для управления чем-то, что на самом деле является просто особенностью материальной униформы, которая скрыта от пользователей. Ни в коем случае это часть текстуры не является более выгодной, более эффективной или даже более четкой, и это означает, что одно реальное приложение для определения UV, которые меняются во время выполнения, анимации, отображается медленно и неэффективно из-за api.

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

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

Что касается преобразований на карту, хотя было бы неплохо, единообразная стоимость слишком высока без всякой причины в большинстве случаев, за исключением случаев, когда у нас есть сложный API для управления, когда и как преобразования должны быть уникальными, общими или динамическими, ИМО иметь такой контроль было бы хорошо, но его нужно тщательно продумать.

Ой, подожди. Думаю, я понимаю, почему вы, ребята, предпочитаете материал. Таким образом, одиночный vUv вычисляется в вершинном шейдере вместо вычисления uv на пиксель во фрагментном шейдере. Верно?

Нет. Как всегда, uv вычисляется в вершинном шейдере.

Представьте себе лист спрайтов и 20 спрайтов. В настоящее время нам нужно 20 клонированных материалов и 20 клонированных текстур - как в http://threejs.org/examples/misc_ubiquity_test2.html. (Кстати, обратите внимание, что у нас уже есть SpriteMaterial.rotation .)

Для переноса смещения на материал нам понадобится 20 клонированных материалов и одна текстура.

Фактически, для перемещения смещения на спрайт нам понадобится 1 материал и 1 текстура.

Представьте себе лист спрайтов и 20 спрайтов. На данный момент нам нужно 20 клонированных материалов и 20 клонированных текстур.

О, я не рассматривал этот вариант использования. Спасибо!

Я подумаю об этом ...

Я рекомендую не использовать УФ-трансформации текстуры.

По двум причинам: (1) это сбивает с толку, (2) нужно распространять больше событий, и (2) это расточительно.

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

Больше распространения событий: Другая проблема, с которой я столкнулся в Clara.io, - это распространение событий при попытке анимировать параметры текстуры. Каждой текстуре нужно отслеживать каждый материал, который ее использует, а затем сообщать этим материалам, что они грязные и нуждаются в пересчете. Это не невозможно, просто еще работа.

Расточительно: другая проблема заключается в том, что если у вас есть несколько экземпляров 3D-модели или злобы, и все они имеют одинаковую анимированную текстуру. В этом случае вам нужно будет иметь отдельные копии текстуры в памяти, чтобы анимировать их по-разному, даже если сами данные текстуры одинаковы. В этом смысле это немного расточительно по сравнению с нанесением данных УФ-преобразования на материалы.

Таким образом, если бы у нас было только одно разрешенное УФ-преобразование для каждого материала, я бы применил его к самому материалу. Я бы следил за моделью Unity 5, где у них есть UV-смещение, вращение в материале. Разработчики игр уже знакомы с этим подходом.

Я думаю, что UV Transform хорошо обрабатывает спрайты и на материалах - это очень похоже на случай с 3D-моделью выше.

Having only one uvTransform per material seems very very limiting.

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

Но как сделать эту функциональность доступной, не забиваясь клонами?

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

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

Но как сделать эту функциональность доступной, не забиваясь клонами?

THREE.ShaderMaterial или THREE.RawShaderMaterial дадут вам эту возможность, и, учитывая, что в настоящее время она не работает с обычными материалами, это маршрут, который вам все равно придется использовать.

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

+1 за это, ребята.

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

Есть новости по этому поводу? Эта проблема по-прежнему является довольно явным недостатком API. Большинство типов карт имеют смещения / повторы, которые не используются, а распространение событий делает что-то вроде анимированного спрайта на плоскости намного медленнее / тяжелее, чем должно быть.

Гибкости для анимированных карт НЕ СУЩЕСТВУЕТ в текущей системе. Возникает аргумент, что мы уменьшим гибкость, привязывая настройки к материалу. Этот аргумент является спорным, потому что такой гибкости не существует в нынешней системе. Вы можете установить только смещение / повторение глобально для материала, и оно берется из диффузной карты (?). Это приводит к еще более серьезной проблеме, когда на большинстве используемых карт есть избыточные настройки «смещения» / «повторения», и всякий раз, когда вы хотите поделиться текстурами для анимации, которую вы не можете, вам нужно сделать клон, поэтому гибкость значительно возрастет. уменьшенный. Вы ожидаете, что каждая текстура / карта будет иметь уникальные смещения, но в нынешних условиях это невозможно, и в большинстве случаев вам действительно нужен один набор смещений UV, потому что было бы неприятно устанавливать одно и то же смещение для normal / spec. / diffuse (прокручивающаяся карта нормалей поверх фиксированной диффузной карты - это ниша, где можно использовать шейдерный материал).

Если вы посмотрите на фактические создаваемые шейдеры, смещение / повторение текстуры привязано к материалу, но странным образом скопировано с одной карты, которая никоим образом не должна контролироваться. Материал НЕОБХОДИМО контролировать, чтобы все было быстро и элегантно без избыточности.

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

Решением этой проблемы является

Также добавляю свой +1 для этого! Сделал бы работу со спрайт-листами намного приятнее.

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

Есть ли у кого-нибудь способ решения этой проблемы? Можно ли управлять смещением UV, напрямую задав форму в шейдере, минуя интерфейс текстуры?

Решением этой проблемы является

@bhouston , не могли бы вы дать ссылку? Под учетной записью

@ rhys-vdw Он находится только здесь, в ветке dev:

https://github.com/mrdoob/three.js/tree/dev/examples/js/nodes

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

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

@bhouston Я могу создать пример с Node, выглядит неплохо.

Что касается THREE.SpriteMaterial вы можете получить доступ к смещению / масштабу для создания spritesheet например:

var offsetX = frameX / mapWidth;
var scaleX = mapWidth / frameWidth;

sprite.material.map.offset.x = offsetX;
sprite.material.map.repeat.x = scaleX;

https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/plugins/SpritePlugin.js#L53

Система на основе узлов не является исправлением ... Она все еще не решает проблемы с api. Требуется 2 секунды, чтобы добавить смещение / повторение к прототипу материала и заставить средство визуализации считывать это вместо текстуры. Я уже сделал это для своего проекта, но факт остается очевидным недостатком в api, который должен быть официально изменен, чтобы предотвратить головную боль для новых пользователей, которые БУДУТ столкнуться с этой проблемой, если они попытаются сделать что-то обычное.

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

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

Что касается THREE.SpriteMaterial, вы можете получить доступ к смещению / масштабу для создания таблицы спрайтов, например ...

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

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

@QuaziKb Есть ли PR, на который я могу нацелить свой проект?

Хотя все это не было бы проблемой, если бы, как сказал @WestLangley , верно следующее:

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

Это верно?

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

Хм, для этого NodeMaterial безусловно, решит, вы сможете использовать одну и ту же текстуру с разными материалами и независимым УФ-смещением и такими преимуществами, как настраиваемые фильтры и другие вещи, которые может предложить материал на основе узлов.

https://github.com/mrdoob/three.js/issues/7522

Но в данный момент кто-то пытался создать экземпляр uuid следующим образом:

THREE.Texture.prototype.createInstance = function() {

    var inst = this.clone();

    inst.uuid = this.uuid;
    inst.version = this.version;

    return inst;

}

если вы используете needsUpdate обновите все экземпляры version тоже.

Пример:

var uniqueTextureOffset = map.createInstance();
var material = new THREE.SpriteMaterial( { map: uniqueTextureOffset } );

Сохранять тот же uuid и version будут совместно использовать texture на GPU.

https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L2832
https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/WebGLProperties.js#L11

Хотя для меня это временное решение. Я верю в будущее за NodeMaterial .

Можем ли мы переместить УФ трансформации в материальные?

Как насчет лучшего из обоих миров. Добавьте отметку overrideOffsetRepeat на материале с новыми uvOffset и uvRepeat на материале. Таким образом, если флаг установлен в false, он обратно совместим и используется по умолчанию. И если это правда, он использует смещение / повтор материала. Я бы поддержал это, так как кажется, что потребность очень велика и широко распространена. @WestLangley? @mrdoob?

(Хотя я действительно поддерживаю использование NodeMaterial для всего будущего, но переходить на него - боль).

Я все еще думаю, что решение этой проблемы - создать THREE.Image . https://github.com/mrdoob/three.js/issues/5876#issuecomment -81189892

THREE.Image

@mrdoob , будет ли это означать, что каждый назначенный Texture будет клонирован вместе с Material ?

@mrdoob написал:

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

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

Я предполагаю, что это решение потребует вдвое больше новых объектов для набора спрайтов - одна текстура для каждого спрайта и один материал? Где другой подход, который просто потребовал бы нового материала для каждого спрайта?

Я знаю, что Unity поддерживает повтор / смещение для каждого материала, но высококачественные инструменты VFX, такие как 3DS Max, Maya, Softimage, этого не делают - у них просто есть узел Bitmap и узел Texture (который содержит как узел Bitmap, так и UV-отображение). nod), который похож на дизайн @mrdoob .

UE4 также похож на то, что предлагает @mrdoob , у них есть узел «Текстура», который является загрузчиком растровых изображений, а затем у них есть серия узлов UV-сопоставления для выполнения различных типов UV-сопоставлений.

Расширенные инструменты разделяют изображение / растровое изображение из текстуры, а также выделяют отдельный узел UV-сопоставления в такой форме:

 -> Bitmap
 -> UVMapping

В настоящее время мы не допускаем большого количества опций UVMapping в основном StandardMaterial. Но различные типы UVMappings, используемые в UE4, Maya, Softimage, 3DS Max, будут определять, какой канал использовать, преобразование, которое нужно применить к нему, использовать мировые координаты в качестве источника или если нужно сделать сферическую, кубическую, плоскую проекцию. на основе требуемых параметров для этих прогнозов.

UE4 имеет текстуру спрайта, которая позволяет повторение / смещение внутри материала:

https://docs.unrealengine.com/latest/INT/Engine/Paper2D/Sprites/index.html

Maya, Softimage, 3DS Max и UE4 имеют разделение Bitmap / Image от текстуры (и от UV Generation), как предлагает @mrdoob , но все они также используют шейдерные графики для достижения этой цели. Unity3D, в котором нет шейдерных графов, - это инструмент, который включает смещение / повторение в сам материал, вероятно, потому, что он не может должным образом разделить его на узел шейдерного графа.

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

Ровно 😊

Наверное, немного неуместно упоминать, но я бы порекомендовал включить PTEX как можно скорее.
http://ptex.us/PtexFile.html
Есть ли способ сделать типичные проекции и т.д. преобразованием / преобразованием в NodeTexture (?) Или вариант, который представляет собой новую, более мощную и всеобъемлющую систему наложения текстур на базовом уровне? ... ну тогда, может быть, об этом стоит подумать заранее.
[Продолжение того же пункта:]
Концепция ptex заключается в том, что на самом деле это не 2-мерное изображение, а отношение ультрафиолета, поэтому вы можете рисовать / штамповать / проецировать вокруг сложной поверхности без концепции / вызова того, как преобразовать 2d в 3d, что в лучшем случае является математическим взломом для сравнения ( всегда технически борюсь с десторцией).
Я просто отмечаю, что ptex должен был иметь больше смысла и быть приоритетом более 20 лет назад и не должен считаться расширением или исполнителем второго класса, но на самом деле для меня это наоборот. Это должен быть старый оригинальный способ декларативно сказать, как 2-мерное изображение проецируется / штампуется в единую истинную, всегда функционирующую систему базового уровня ptex. В любом случае, просто воплощая идею, он должен быть интегрирован, если не лучше, чтобы взять более центральный поворот.
Спасибо за возможность сделать высокие предложения. Я был так счастлив, что ptex был сделан в соответствии со спецификацией. Я сам думал об этом 10 с лишним лет назад, но в детстве не мог определять новые характеристики и т. Д. Оглядываясь назад, я должен был увидеть, что, возможно, я мог бы попытаться изменить ситуацию вместо того, чтобы иметь возможность наблюдать за тем, что я до сих пор поддерживаю. Итак, вот попытка исправить давнюю ошибку.

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

@MasterJames вроде не по теме ... создайте новую тему, пожалуйста?

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

@QuaziKb Ага. Вот что решает NodeMaterial .

Разве не Texture использует один и тот же экземпляр текстуры OpenGL для каждого .clone() , или я что-то упускаю. Он действительно перезагружает его для каждого клона? Если это так, то это очень серьезная проблема.

@evrimoztamur , мне кажется, он каждый раз копирует текстуру. Вы можете проверить, что происходит, с помощью WebGL Inspector .

Я пробовал все подходы, которые мог придумать, включая обходной путь @sunag , но ничего не Sprite и SpriteManager API Babylon.js - это решение, которое удовлетворяет мои конкретные потребности. Он обрабатывает листы спрайтов, смещение и повторение, а также анимацию. Возможно, это более высокий уровень абстракции, чем стремится предоставить THREE.js, но, возможно, стоит взглянуть на него в качестве справочного материала.

@ rhys-vdw: В текущем проекте я выбрал убитую версию MeshBasicMaterial:
https://gist.github.com/karimbeyrouti/790d2e1a8c0137b16bae

Когда вы устанавливаете карту, это автоматически назначает униформу смещения / повтора (которая находится в спрятанном материале). Вы можете легко установить их по отдельности - это избавит вас от необходимости клонировать текстуры на данный момент. (работает с r73)

Я только что отправил PR, который должен решить эту проблему, PR № 8278.

@WestLangley написал:

Я считаю разумным предположить, что следующие карты имеют одинаковые значения смещения / повтора:

карта
specularMap
normalMap
bumpMap
alphaMap
aoMap (будущее)
glossMap (будущее)
displacementMap (будущее)

Не всегда. В настоящее время я использую разные значения повторения для карты и карты рельефа на одном и том же материале (асфальте), чтобы скрыть тот факт, что оба они выложены довольно маленькими плитками. Таким образом, мне не нужно создавать / иметь большую текстуру. Это очень удобно. :-)

РЕДАКТИРОВАТЬ: Ну, по крайней мере, я думал, что сделал. Уловку, вероятно, проигнорировали. И я могу добиться аналогичных результатов, добавив шум в шейдер или что-то в этом роде. Демо-версия Matrix3 от WestLangley - это круто.

Думаю, это решает проблему экземпляров с разным UV в Sprite. Можно изменить vertex и pixel shader сохранив ту же текстуру.

https://threejs.org/examples/#webgl_sprites_nodes

Он использует SpriteNodeMaterial и Mesh с общим PlaneBufferGeometry . Интерфейс не подходит для Sprite но работает. Может быть, он может развиться до SpriteMesh чтобы сделать интерфейс более дружелюбным.

эта ветка TL; DR для меня. но я только что обнаружил этот код в r68 (старый проект, да):

        // uv repeat and offset setting priorities
        //  1. color map
        //  2. specular map
        //  3. normal map
        //  4. bump map
        //  5. alpha map

        var uvScaleMap;

        if ( material.map ) {

            uvScaleMap = material.map;

        } else if ( material.specularMap ) {

            uvScaleMap = material.specularMap;

        } else if ( material.normalMap ) {

            uvScaleMap = material.normalMap;

        } else if ( material.bumpMap ) {

            uvScaleMap = material.bumpMap;

        } else if ( material.alphaMap ) {

            uvScaleMap = material.alphaMap;

        }

        if ( uvScaleMap !== undefined ) {

            var offset = uvScaleMap.offset;
            var repeat = uvScaleMap.repeat;

            uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );

        }

так что да...

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

Я пытался установить разные повторы на диффузных картах и ​​картах нормалей и выдергивал волосы, потому что это не сработало. поскольку API помещает этот параметр в текстуру, я думал, что смогу это сделать. так что да, как насчет того, чтобы сохранить мои волосы в качестве веского аргумента? этот билет все еще открыт, 3js все еще имеет эту настройку для текстур, и она соблюдается только для одной из текстур = это, по сути, уже разрешенная настройка IS.

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

@sunag Для PR:
https://github.com/mrdoob/three.js/pull/11531

Одна проблема, с которой я столкнулся:
https://jsfiddle.net/f0j2v3s8/

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

Любые идеи?

@karimbeyrouti написал:

Когда вы устанавливаете карту, это автоматически назначает униформу смещения / повтора (которая находится в спрятанном материале). Вы можете легко установить их по отдельности - это избавит вас от необходимости клонировать текстуры на данный момент. (работает с r73)

Я считаю, что это устарело, поскольку uniforms.offsetRepeat заменяется на uniforms.uvTransform (r88).

Что касается варианта использования «повторное использование атласа текстуры с несколькими экземплярами Object3D», я предлагаю простую прогулку:

  1. сохранить данные UV (смещение, повтор) в json-объекте атласа;
  2. подключить пару функций onBeforeRender\onAfterRender объекта Object3D;
  3. в обратном вызове перед рендерингом загрузите данные UV из объекта atlas json и установите значение material.map;
  4. в обратном вызове после рендеринга сбросьте его обратно;

Это приведет к:

  1. только одна текстура и один материал, общие для нескольких объектов, клонирование не требуется, и счетчик info.memory.textures не будет увеличиваться;
  2. но все же все остальные карты (normal, ao, displacement ...) должны соответствовать той же UV трансляции;
Была ли эта страница полезной?
0 / 5 - 0 рейтинги