Создание материалов и текстур для трехмерных моделей. Подсказки по созданию текстур для реалистичных материалов

Обновление (01.07.2015) : обновил информацию (в основном по бампу).

Обычно, для создания хорошего материала хватает 4-х типов текстур. Но для некоторых материалов могут понадобится еще текстуры или, наоборот, некоторые типы текстур не понадобятся. Обо всём этом ниже.

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

  • Diffuse или просто цвет. Цвет металла близок к чёрному (но желательно не использовать идеально чёрный). На дифузе неметаллов не должно быть информации из других каналов (спекуляра, бампа). Т.е. не должно быть бликов, теней от мелких деталей, каких-то нечётких отражений.
  • Reflect (он же Specular или просто сила отражения). Чистый отполированный металл отражает очень хорошо, а значит на текстуре он почти белый (опять же, в реальном мире ничто не может быть идеальным, поэтому мы не используем идеально белый или идеально чёрный цвета). Шершавый металл отражает хуже, а значит на текстуре спекуляра он серый. Ржавый металл и вовсе не является металлом, а значит отражает еще хуже и поэтому на текстуре он тёмно серый. Ткань слабо отражает, а значит она еще темнее. Также спекуляр металла не будет просто серым - он будет цветным (если металл цветной). Т.е. чтобы блики на золотом кольце были жёлтые, нужно рефлект окрашивать в жёлтый. Царапина на ржавом металле будет отражать сильно (ведь мы добрались до чистого металла сквозь ржавчину). Много царапин на отполированном металле могут создать противоположный эффект. Т.е. эти все царапины на микроуровне создали область размытых отражений (поверхность металла уже не такое идеальное зеркало), а значит там текстура рефлекта будет темнее.
  • Bump или по простому - выпуклости. Напоминаю, что серый цвет (RGB: 128,128,128) значит, что мы получаем такую же поверхность как и без бампа. Чем белее цвет, тем выше выпирает деталь. Чем чернее цвет, к примеру, царапины, тем глубже царапина. К примеру, на металле лезвия ножа царапины должны быть не глубокие (разница в цвете на один-два деления серого), ведь металл поцарапать глубоко очень сложно. Почему я использую бамп, а не карты нормалей? Карты нормалей нужны для низкополигональной сетки, тогда от них есть больше прока, чем от бампа. Ведь нормали визуально сглаживают переход между полигонами, которые на самом деле расположены под острым углом. А под V-Ray я всегда рендерю сглаженную поверхность модификатором Turbosmooth, к примеру, поэтому мне ничего сглаживать не нужно. Но вот у бампа появляется преимущество - его удобно рисовать ручками: сделал деталь белее - она стала выше выпирать.
  • Glossiness или Glossy (глоси) - глянцевитость поверхности или сила размытия отражений. У блестящего металла отражения почти не размываются, а значит они на карте глоси будут почти белые. На ржавых частях металла отражения размываются очень сильно, а значит глоси будет серой в этом месте. А на ткани и вовсе не видно отражений, но это не значит, что их нет. Ткань на карте глоси будет серой (возможно тёмно серой).
  • Fresnel reflections (). Эта галочка в настройках материалов V-Ray хорошо добавляет реалистичности материалу. Но её особенность в том, что она влияет только на канал Reflect и никаким образом не затрагивает другие каналы (Diffuse, Glossiness). А ведь почти все неметаллические материалы требуют, чтобы по такому же принципу работали текстуры дифьюз или/и глоси. К примеру, когда мы смотрим на ткань, то под скользящим углом её цвет становится слегка выбеленным (она как-бы обесцвечивается). Это происходит из-за малюсеньких ворсинок, которые торчат во все стороны и, сильно рассеивая свет, придают ткани белёсый налёт. Этот белёсый налёт можно имитировать еще одной текстурой цвета, где цвета будут слегка выбелены. Если брать матовый пластик, бумагу или кожу, то можно заметить, что под очень большим (скользящим вдоль поверхности) углом они начинают зеркально отражать. А это значит, что нужно рисовать еще одну текстуру глоси для такого случая. Но об этом в другой статье по настройке материалов (если вам это будет интересно).

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

  • кожа;
  • ткань (подкладка);
  • металл (кнопки).

Текстура Diffuse:

Все текстуры кликабельны.

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

Но это также может пойти нам на пользу (а зачастую так и есть). Ведь 3D - это всегда мухлёж.

К примеру, для крупного плана, где поры будут большими, V-Ray будет легче их отрендерить, а значит цвет пор можно полностью отдать на просчёт рендереру (на основе бампа, отражений и т.д.).

Но если эти перчатки будут далеко от камеры, то все эти поры будут очень мелкими, а значит нужно будет накручивать сабдивы (Max subdivs) и Color threshold для Adaptive image sampler, чтобы VRay смог отобразить/просчитать эти поры правильно (чётко, красиво - как мы и хотим). Поэтому, излишний контраст пор в канале дифуз нам не помешает, а наоборот сыграет на руку. Ведь даже на низких настройках мы сможем увидеть что-то рябое, напоминающее поры

Это же касается и затенений на оверлоке, где нитка глубоко входит в кожу и сминает её.

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

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

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

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

Текстура Reflect/Specular:

Здесь всё сделано очень хорошо. Самые белые части - это металлические кнопки. Кожа также достаточно светлая, поскольку она должна хорошо отражать. Ткань (в том числе и нитки оверлока) тёмно серая, ведь она отражает плохо.

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

Но вот где закрались мелкие ошибки, так это на самых затёртых местах. К примеру, в самом низу текстуры (слева) мы видим край перчатки. Он, обычно, больше всего затёрт, ведь постоянно трётся о части одежды (рукава плаща, пальто, куртки). И раз он затёрт, то кожа там должна отражать меньше (т.е. весь лоск стёрся). И значит эта часть должна быть темнее, а художник сделал её светлее.

А вот мелкие помятости художник нарисовал правильно. Он сделал их темнее. Ведь в тех местах, где кожа постоянно мнётся, она будет отражать хуже. Она там становится такой шершавой и даже слегка ворсистой.

Также допущена ошибка с идеально белой кнопкой. Металл не может отражать 100% света. А особенно кнопка на перчатках, которая постоянно царапается. Но я этот момент смог поправить благодаря смешиванию этой текстуры с чёрным цветом для материала металла кнопки.

Текстура Bump:

Эта текстура сделана отлично. Впадинки между порами более тёмные. Нитки оверлока светлые, но лежат в тёмной канавке (ведь нитка придавливает кожу и впивается в неё). Помятости сделаны более светлыми, но при этом (хоть и не так контрастно) всё равно видны поры.

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

На этапе создания материала я добавил этот бамп в карту цветокоррекции (о ней ниже) и замиксовал этот бамп с . Также по этой ссылке вы найдёте плагин для Photoshop-а NVidia NormalMapFilter, который легко конвертирует чёрно белую карту бампа в карту нормалей.

Еще одна ошибка этого бампа - это наличие идеально белого и чёрных цветов (об этом также ниже).

Чтобы текстура бампа работала очень хорошо (была чёткой и просматривалась хорошо при разных углах), нужно в её настройках (карта Bitmap) на свитке Coordinates выставить значение параметра Blur в пределах 0,3-0,6 (я обычно ставлю 0,5). Также Autodesk советует поднять значение Blur offset больше нуля (но для меня этот их совет не сработал, не знаю почему, поэтому я оставляю Blur offset равным нулю).

Текстура Glossiness/Glossy:

Текстура глоси для перчаток не рисовалась. Поэтому я покажу её на быстро сварганенном примере бердыша. Вы должны понимать, что для этого примера я не использовал текстуру спекуляра. Другими словами, можно представить, что текстура то есть, но это сплошной цвет (светло серый) для всего бердыша. Т.е. все вот эти эффекты (зеркальные и матовые отражения) на рендере ниже получились лишь благодаря текстурам глоси, дифуза и бампа:

Сама текстура глоси:

Здесь почти всё сделано правильно за исключением того, что царапины на боковой части лезвия (там где орёл-рукоятка удерживает лезвие на поворотном механизме) должны быть светлее, но не темнее. Ведь от трения лезвия по орлу (во время многократных поворотов) металл полируется, а значит должен иметь в том месте более зеркальные отражения.

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

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

Царапины на лезвии также нарисованы более светлыми. Ведь царапина - это тоненькая полосочка отполированного чистого металла.

Если бы бердыш долго пролежал в земле, то в эти бы царапины набилась грязь. И тогда эти царапины должны были бы быть, наоборот, тёмными на текстуре глоси (ну и на текстуре спекуляр).

Цветокоррекция текстур.

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

Поэтому при работе с текстурами я очень часто прибегаю к такой карте как Color Correction :

Первым делом я переключаюсь в режим Advanced . Это позволяет более "правильно" править яркость и контраст текстуры. Другими словами, мы имитируем параметры воображаемой камеры, через объектив которой, мы смотрим на текстуру.

Результат можно наблюдать по второй градиентной полосочке . Первая градиентная полосочка показывает, что у нас на входе, а вторая - то что получилось после правки счётчиков и . На примере выше, накрутив гамму до 3 (по умолчанию там 1), я превратил почти все оттенки серого в белый цвет (оставив лишь чёрный цвет нетронутым). А подняв гейн до 140 (по умолчанию там 100) я сделал цвет более светлым (т.е. вот та узкая тёмная полосочка стала тёмно серой).

Грубо говоря, гамма - это аналог контраста. Если её увеличивать, то она сдвигает белый цвет в сторону чёрного, так что переход от чёрного к белому становится резким. Если гамму уменьшать (меньше единицы), то, наоборот, наступает (прям как атака на войне) чёрный цвет. И почти все оттенки серого (кроме очень белых) становятся чёрными.

А если грубо описать принцип работы счётчика гейн, то это простая операция умножения. Т.е. цвет пикселя умножается на эту величину.

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

Подпишитесь на обновление блога (вот

Рисунок 1 – Нумерация страниц виртуальной текстуры внутри mip-уровней

Как видно из рисунка 1, очевидно, что удобнее всего виртуальную текстуру будет хранить на жестком диске в виде последовательности страниц 0,1,2,3,4… и так далее. Таким образом, доступ к данным страницы просто вычислить по формуле:

PageFileOffset = PageNumber * PageSize * PageSize * Bpp (2)

где:
PageFileOffset – смещение относительно заголовка файла;
PageNumber – номер страницы;
PageSize – размер страницы;
Bpp – количество байт на пиксель.

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

4. Конвейер

Весь процесс работы с виртуальной текстурой можно разбить на несколько основных этапов:
1. Определение видимых страниц виртуальной текстуры
2. Анализ пункта 1, формирование списков страниц на загрузку, отсортированных по приоритетам (очередь приоритетов).
3. В соответствии с очередью приоритетов, загрузка виртуальных страниц в оперативную память, формирование списка загруженных страниц (данный этап можно вынести в отдельный поток).
4. Обновление текстурного кэша.
5. Обновление таблицы переадресации.
6. Рендеринг сцены.

4.1 Определение видимых страниц виртуальной текстуры

На данном этапе нам нужно определить номера видимых страниц, ну и, соответственно, номер mip-уровня, к которому данная страница принадлежит.

Я пробовал два способа определения видимых страниц виртуальной текстуры. Первый из них основывался на принципе рендеринга в сцены в текстурном пространстве . То есть мы рисуем сцену в текстуру, используя не мировые координаты вершин, а текстурные. При этом размер одной страницы в текстурном пространстве соответствовал одному пикселу. Данный метод имеет кучу проблем, так как при рендеринге в текстурном пространстве стандартные способы отсечения уже не работают, а в шейдер нужно передавать информацию о плоскостях пирамиды видимости (frustum) и рассчитывать clipping distances. Кроме того, необходим ручной backface-culling. Еще одним существенным недостатком данного метода является необходимость определения, не загораживает ли один объект другой, чтобы не допустить рендеринг невидимых в данный момент объектов. Ну и последний недостаток, который заставил меня выбрать другой метод, это необходимость в, так называемом, консервативном растеризаторе (conservative rasterizer) . Дело в том, что если видно только около 50% процентов страницы, то стандартный GPU растеризатор попросту не будет растеризировать ее в один пиксель, таким образом, мы теряем ценную информацию о нужной странице. Учитывая сложность реализации консервативного растеризатора данный метод в нашем случае оказался неэффективным.

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

На входе вершинного шейдера мы оперируем виртуальными координатами текстуры (virtUV). Этап получения номера страницы состоит из определения текущего mip-уровня (miplevel) и положения страницы относительно текущего mip-уровня (pageOffset):

pageOffset = virtUV * exp2(miplevel) (3)

На выходе в pageOffset будет номер страницы по x и по y относительно текущего mip-уровня. Далее не составит сложности простыми арифметическими операциями преобразовать pageOffset в pageNumber (рисунок 1). Здесь есть небольшая тонкость: дело в том, что в шейдере мы можем закодировать число от 0 до 255 на один канал. При размере виртуальной текстуры, используемой в игре Rage (128к x 128k пикселей), на верхнем mip-уровне pageOffset может превысить число 255. Решить это ограничение можно используя дополнительный канал, в котором кодируются дополнительные восемь бит (по четыре на pageOffset.x и pageOffset.y). Таким образом, максимальное количество страниц, которые мы можем закодировать увеличивается до 4095 по x и столько же по y. В оставшийся четвертый канал мы записываем номер mip-уровня страницы. Еще одним способом снять ограничение является использование float текстур с 32-битными каналами, но в нашем случае это накладно, т.к. в последствии нам нужно будет передавать текстуру в оперативную память для ее анализа.

Теперь, когда мы имеем feedback буфер, мы можем приступить к его анализу.

4.2 Анализ feedback буфера

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

В цикле мы для каждого пикселя feedback буфера декодируем pageOffset и miplevel, преобразуя их в PageNumber (нумерация страниц изображена на рисунке 1). Здесь нам понадобится дополнительная структура данных, так называемая таблица страниц (pageTable). Физически это обычный массив, размер которого равен общему числу страниц (TotalPages). Каждый элемент представляет собой структуру из положения страницы в текстурном кэше (pageX, pageY) и ее mip-уровеня. Также предлагается создать аналогичного размера массив pageInfoTable. Поскольку предложенная организация расположения страниц внутри mip-уровней отлично подходит для реализации Quad-tree, в pageInfoTable мы можем сохранить дополнительную информацию о странице, а именно о ее потомке, а также переменную для хранения флагов (Cached, Needed). Было решено отделить pageTable и pageInfoTable только ради удобства, подробнее об этом будет сказано чуть позже (на пятом этапе, при создании таблицы переадресации).

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

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

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

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

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

Текстурные математические модели обычно применяется для воспроизводства внешнего вида текстуры. Натуральные текстуры проявляют локальные свойства, которые обычно можно моделировать случайными процессами, хотя с других точек зрения эти характеристики далеко не случайны. Ниже приведено краткое описание наиболее часто встречаемых в литературе текстурных моделей . Time-series модель рассматривает периодичность в пространственном сканировании изображения. В процессе сканирования, каждый последующий пиксель определяется на основе предшествующих - . Текстурное поле моделируется построчно, пиксель за пикселем, пока все строки не будут заполнены. Недостатком такой модели является то, что она плохо описывает структуру текстуры в направлении (направлениях) перпендикулярных сканированию. Для моделирования натуральных ячеистых текстур используется ячеистая модель. Моделирование происходит в два этапа. На первом текстурное поле разделяется на некоторое количество ячеек и для каждой из них вычисляется центр инерции (ядро). На втором этапе происходит последовательное сканирование изображения и сравнения расстояния от точки до всех центров инерции. В результате пиксель назначается в группу, соответствующую ближайшему ядру. Проведенные эксперименты показали хорошее визуальное сходство смоделированной текстуры с натуральной ячеистой текстурой . Синтаксические текстурные модели сравнивают символы формальной грамматики со структурными примитивами текстуры. Для моделирования текстур были расширены и переработаны ряд правил грамматики применительно к теории вероятности. Синтаксические модели применяются для описания сильно структурированных текстур. Двумерная модель случайного марковского поля рассматривает условные вероятности яркостей на элементарном текстурном образце. Марковские свойства модифицируются определением переходной вероятности на окрестности смежных или несмежных точек. Этот метод достиг хороших результатов в моделировании прототипов текстур. Однако он практически не применяется на практике в связи с большим размером модели.

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

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

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

Автокорреляционная функция определяется следующим выражением:


где I (u, v) - прозрачность диапозитива в точке с координатами (u, v), (вне прямоугольной площади диапозитива прозрачность равна нулю),
(х, у) - величина сдвига в направлении и в направлении у.

Еще одним методом, основанным на измерении пространственной частоты, является оптический метод анализа текстуры. Этот метод основан на том, что при освещении фрагмента изображения, мы получаем создаваемое линзой распределение света, которое известно под названием «дифракционная картина Фраунгофера». Из дифракционной картины можно выделить вектор признаков, который может использоваться для распознавания фрагментов. К этой группе методов можно также отнести метод цифровых преобразований. При анализе текстуры этим методом изображение разбивают на небольшие непересекающиеся квадратные фрагменты размера n*n пикселей.Суть преобразований в том, что базисные векторы новой координатной системы хорошо интерпретируются в терминах пространственной частоты или порядка следования. В качестве характеристики текстуры может использоваться количество перепадов яркости на единицу площади изображения. Приходящийся на пиксель изображения перепад можно обнаружить, сравнивая значения локальных признаков двух непересекающихся фрагментов изображения, соседствующих с этой клеткой.

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

где - яркость некоторого элемента изображения, N - число элементов изображения в его окрестности, - средняя яркость этих элементов, а - некоторая метрика.

Один из аспектов текстуры связан с пространственным распределением и пространственной взаимозависимостью значений яркости локальной области изображения. Статистики пространственной взаимозависимости значений яркости вычисляются по матрицам переходов значений яркости между ближайшими соседними точками. Матрица смежности (или матрица совместной встречаемости) уровней яркости представляет собой оценку плотности распределения вероятностей второго порядка, полученную по изображению в предположений, что плотность вероятности зависит лишь от расположения двух пикселей. Обозначим эту матрицу , где i и j – яркости соседних точек на изображении, расположенных на расстоянии d друг от друга, при угловом направлении . Поскольку число таких матриц может быть очень большим, то обычно ограничиваются лишь рассмотрением пикселей, находящиеся в непосредственной близости либо усредняют матрицы, составленные для различных ориентаций . Совершенно очевидно, что такие матрицы содержат информацию характеризующую текстуру. По матрице совместной встречаемости вычисляется около двадцати признаков, ниже приведены наиболее употребимые из них:
степень однородности или энергия
энтропия
максимальная вероятность
контраст
обратный момент разности
коэффициент корреляции
вероятность серии длинны n с яркостью i (изображение марковское)

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

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

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

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

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

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

Итак, возьмем за основу проект из предыдущей статьи, и для начала нужно добавить в него изображения, на базе которых впоследствии мы создадим текстуры. Я не стал особо заморачиваться, просто нарисовал по-быстрому в paint’е 6 картинок, по одной для каждой грани куба 😉 Получилось вот так:

Тем, кто как и я, использует Qt Creator теперь необходимо добавить эти файлы в проект. Для этого нужно создать пустой файл ресурсов и прописать в нем пути для всех используемых изображений. Не будем в эту тему углубляться, все-таки статья не об этом 😉

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

void MainScene:: generateTextures () { glGenTextures(6 , textures) ; QImage texture1; texture1.load (":/cubeOne.jpg" ) ; texture1 = QGLWidget:: convertToGLFormat (texture1) ; glBindTexture(GL_TEXTURE_2D, textures[ 0 ] ) ; glTexImage2D(GL_TEXTURE_2D, 0 , 3 , (GLsizei) texture1.width () , (GLsizei) texture1.height () , 0 , GL_RGBA, GL_UNSIGNED_BYTE, texture1.bits () ) ; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ;

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

Давайте разбираться, что тут происходит…

Первым делом вызываем функцию glGenTextures() – она генерирует специальные имена для каждой из текстур и помещает их в массив, который мы передаем в качестве одного из аргументов. А первый аргумент – количество текстур, которые нам понадобятся (в данном случае у нас 6 граней, значит передаем в функцию аргумент “6”). Эта функция вызывается только один раз, в самом начале функции generateTextures() .

И, кстати, не забудьте объявить массив в нашем классе MainScene :

GLuint textures[ 6 ] ;

С этим все понятно, переходим дальше. Теперь мы создаем объект класса QImage и загружаем в него наше изображение. Функция glBindTexture делает активной текстуру с номером, соответствующим аргументу функции. В данном случае это текстура для первой грани (textures ). Вызовом этой функции мы как бы показываем , что дальнейшие действия нужно производить именно с той текстурой, которую мы выбрали. Поэтому вызов glTexImage2D() произведет генерацию текстуры, соответствующей номеру textures (напоминаю, в этом массиве у нас хранятся уникальные номера-идентификаторы для каждой из текстур проекта).

Функция glTexImage2D() принимает на вход кучу аргументов, так что давайте рассмотрим каждый из них в отдельности:

  • первый параметр говорит о том, что мы будем работать с 2D текстурой
  • второй параметр – уровень детализации, у нас 0
  • третий – 3 – число цветовых компонент – RGB
  • четвертый, пятый – ширина, высота текстуры, у нас они определяются автоматически
  • пятый – относится к границе текстуры, его просто оставляем нулевым
  • шестой, седьмой – дают информацию о цветах и типе данных исходного изображения
  • и, наконец, седьмой параметр передает сами данные изображения, из которых нужно формировать текстуру

На этом создание текстуры заканчивается, но нужно еще настроить некоторые параметры отображения текстур:

Как вы уже догадались, работать с текстурами мы будем также через массивы. Каждой вершине грани (квадрата) нужно поставить в соответствие 2D координату текстуры, причем нужно обязательно учесть, что текстуры в имеют нормированные координаты, то есть от 0 до 1. В нашем примере текстура квадратная, значит она будет иметь такие координаты:

Рассмотрим код для наложения текстуры на первую (переднюю) грань куба. Для остальных граней все делается аналогично.

glBindTexture(GL_TEXTURE_2D, textures[ 0 ] ) ; cubeVertexArray[ 0 ] [ 0 ] = 0.0 ; cubeVertexArray[ 0 ] [ 1 ] = 0.0 ; cubeVertexArray[ 0 ] [ 2 ] = 1.0 ; cubeVertexArray[ 1 ] [ 0 ] = 0.0 ; cubeVertexArray[ 1 ] [ 1 ] = 1.0 ; cubeVertexArray[ 1 ] [ 2 ] = 1.0 ; cubeVertexArray[ 2 ] [ 0 ] = 1.0 ; cubeVertexArray[ 2 ] [ 1 ] = 1.0 ; cubeVertexArray[ 2 ] [ 2 ] = 1.0 ; cubeVertexArray[ 3 ] [ 0 ] = 1.0 ; cubeVertexArray[ 3 ] [ 1 ] = 0.0 ; cubeVertexArray[ 3 ] [ 2 ] = 1.0 ; cubeVertexArray[ 4 ] [ 0 ] = 0.0 ; cubeVertexArray[ 4 ] [ 1 ] = 0.0 ; cubeVertexArray[ 4 ] [ 2 ] = 0.0 ; cubeVertexArray[ 5 ] [ 0 ] = 0.0 ; cubeVertexArray[ 5 ] [ 1 ] = 1.0 ; cubeVertexArray[ 5 ] [ 2 ] = 0.0 ; cubeVertexArray[ 6 ] [ 0 ] = 1.0 ; cubeVertexArray[ 6 ] [ 1 ] = 1.0 ; cubeVertexArray[ 6 ] [ 2 ] = 0.0 ; cubeVertexArray[ 7 ] [ 0 ] = 1.0 ; cubeVertexArray[ 7 ] [ 1 ] = 0.0 ; cubeVertexArray[ 7 ] [ 2 ] = 0.0 ; cubeTextureArray[ 0 ] [ 0 ] = 0.0 ; cubeTextureArray[ 0 ] [ 1 ] = 0.0 ; cubeTextureArray[ 1 ] [ 0 ] = 1.0 ; cubeTextureArray[ 1 ] [ 1 ] = 0.0 ; cubeTextureArray[ 2 ] [ 0 ] = 1.0 ; cubeTextureArray[ 2 ] [ 1 ] = 1.0 ; cubeTextureArray[ 3 ] [ 0 ] = 0.0 ; cubeTextureArray[ 3 ] [ 1 ] = 1.0 ; cubeIndexArray[ 0 ] [ 0 ] = 0 ; cubeIndexArray[ 0 ] [ 1 ] = 3 ; cubeIndexArray[ 0 ] [ 2 ] = 2 ; cubeIndexArray[ 0 ] [ 3 ] = 1 ; glVertexPointer(3 , GL_FLOAT, 0 , cubeVertexArray) ; glTexCoordPointer(2 , GL_FLOAT, 0 , cubeTextureArray) ; glDrawElements(GL_QUADS, 4 , GL_UNSIGNED_BYTE, cubeIndexArray) ;

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

Наша задача на сегодня реализована, поэтому на этом я заканчиваю статью, обязательно еще вернемся к теме OpenGL на нашем сайте, так что не проходите мимо 😉

Вот полный проект с примером программы –

Таблица 3

Таблица 4.

Подсчёт грансостава

Цена одного деления окуляр-микрометра…….мм

Размеры фракций, мм

Количество делений окуляр-микрометра

Условные единицы

Сумма условных единиц

Примечание

меньше 0,01

Сумма всех зёрен (не менее 300)

Рис. 1. Шапка для построения кривых и описания результатов

Изучение текстурных особенностей алевро-песчаных пород

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

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

Вторичные текстуры возникают в уже сформированной породе.

Первичные текстуры Текстуры поверхности слоя

Знаки ряби – система параллельных валиков на поверхности осадка, перпендикулярных направлению водного или воздушного потока. Эоловая рябь характеризуется преобладанием длины поперечного сечения валика над его высотой. Рябь, возникающая в результате течений или волнений (колебаний) воды), представляет собой чередование пологих желобков и острых гребней.

Трещины усыхания – образуются в глинистом или известковом осадке, накопившемся в водной среде при последующем высыхании его на воздухе. Трещины заполнены инородным материалом.

Отпечатки капель дождя и града – округлые углубления с бортиками по периферии.

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

Следы животных – отпечатки лап, хвостов и т.п.

Внутрислоевые текстуры

I. Однородные массивные текстуры характеризуются беспорядочным расположением в породе ее составных частей (фото 1).

II. Неоднородная текстура

Горизонтальная слоистость :

1)ритмичная

а)равномерное чередование слойков глин и песчано-алевритовых пород более или менее одинаковой толщины (фото 2)

б)неравномерное чередование. Песчано-алеврито-глинистые слойки имеют разную толщину (фото 3).

2)линейная – четко заметны линии раздела слоев

3)горизонтальная прерывистая слоистая – прерывистое расположение компонентов слоев (фото 4).

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

Волнистая слоистость

1.Пологоволнистая (фото 5,6)

2.Линзовидноволнистая (фото 8)

3.Мульдообразная

4.Перекрестная (фото 10)

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

Косая слоистость (фото 11,12,13) менее распространена, чем горизонтальная. Характеризуется расположением слойков под углом к границам серий слойков. Направление падения косых слойков совпадает с направлением движения среды отложения. Ориентировка слойков может меняться на небольшом отрезке.