LXF135:POV-Ray

Материал из Linuxformat.

Перейти к: навигация, поиск
POV-Ray За­ни­ма­тель­ная ме­ха­ни­ка – соз­да­ем фи­гу­ры пра­виль­ной гео­мет­ри­че­ской фор­мы

Содержание

POV-Ray: Алхимия текстур

POV-Ray
Когда мы пишем эти строки, в большей части России стоит жара. Поэтому Вячеслав Ястребцев решил залить сцену водой... приятной, прохладной водой!

В прошлый раз мы изготовили две шестерёнки. Эта парочка смотрелась сиротливо, и сегодня мы создадим таинственную лабораторию, использовав POV-Ray на все сто!

Голые стены

Как обычно, разделим сцену на несколько файлов. Скопируйте в папку с проектом файлы tower_shapes.inc и tower_textures.inc. В первом описаны необходимые формы, во втором – базовые текстуры; без них работать будет нельзя. Откроем текстовый редактор и создадим главный POV-файл сцены (tower.pov на DVD). Подключим эти файлы директивой #include:

#include “tower_shapes.inc”
#include “tower_textures.inc”

Далее, размещаем камеру и создаём светильник:

camera {
	 location <0, 5, -40>
	 look_at 0
	 angle 37
}
light_source {
	 <0, 200, 0>,
	 color rgb <.9, .8, 1>
	 parallel
	 point_at <70,0,100>
}

Здесь мы применили новые параметры: parallel и point_at. Один имитирует большой и отдалённый источник света, вроде Солнца или Луны (в сцене – Луна), испускающий пучок параллельных лучей. Второй указывает точку, на которую падает луч из центра источника, задавая таким образом направление света (источник можно вращать, как и любой другой объект, с помощью модификатора rotate, меняя направление освещения; иногда так удобнее).

Большая часть лаборатории будет затоплена водой: создадим водную поверхность, использовав объект plane (плоскость):

plane {
	 y, -.5
	 material {water}
}

Плоскость задана вектором нормали и числом, задающим сдвиг плоскости вдоль нормали от начала координат. Чтобы плоскость стала видимой, ей назначен материал water из файла tower_textures.inc. Теперь определим факел:

#declare brand = union {
	 #declare len = 3.5;
	 cylinder {
		 0, len*y, 0.12
		 texture { brand_metal }
	 }
	 cone {
		 len*y, 0.12,
		 (len+.7)*y, .3
		 texture { brand_metal }
	 }
	 light_source {
		 (len+1.1)*y,
		 color rgb <1, .5, .2>*2
	 }
}

Ещё один новый объект – cone (конус) – задан двумя парами обязательных параметров: вектором, определяющим положение центра торца, и радиусом. Если в одной из пар радиус равен 0 – получаем обычный конус, если оба радиуса ненулевые – усечённый.

Конус и цилиндр создают корпус светильника; добавив в объединение источник света, мы заставляем факел светить. Переменная len определяет длину ручки факела. Заполним сцену объектами:

union {
	 object { transmitting
		 translate <1.5,4.5,0>
	 }
	 object { stock
		 texture { stock_wood }
		 translate -z
	 }
	 object { stock
		 texture { stock_wood }
		 translate z
	 }
	 object { runway
		 texture { floor_wood }
		 translate -2*x
	 }
	 object { brand
		 translate <0,0, -3>
	 }
	 rotate 45*y
	 translate 10*z
}

Пристроим на сцену группу объектов, определённых в файле tower_shapes.inc: transmitting – шестерни, созданные на прошлом уроке; stock – опора, на которой они установлены; brand – только что созданный факел; runway – помост, на котором все предметы стоят в центре водоёма. Сразу назначим предопределённые текстуры.

Поместим в сцену стены:

object { walls
	 texture { stonework }
}

Объекты размещены; отрисовав сцену, вы увидите, что вышло.

Да будет цвет!

Скучные однотонные поверхности? Сейчас добавим текстур.

Все объекты на рендере, кроме шестерён (для них текстура была заранее определена), имеют монотонный серый окрас. Это копии простой серой текстуры. Давайте сделаем ее более красочной!

Начнём со стены. Откройте файл tower_textures.inc и найдите строчку #declare stonework = texture{ def }, назначающую текстуру кладки переменной stonework. Кладка состоит из двух материалов – камня и раствора. Для их имитации понадобятся две дополнительные текстуры: камень темнее и более блестящий, чем раствор. Удалим слово def из определения текстуры и создадим текстуру камня, вписав внутри текстуры stonework следующее:

	 pigment { color rgb <.2,.21,.2>}
	 finish {
		 specular .1
		 roughness .003
	 }
	 normal {
		 crackle
		 bump_size -1
	 }
}

Мы используем новый модификатор – normal, для имитации выступающих поверхностей камней. Он ведёт себя как обычная карта нормалей, создавая иллюзию неровной поверхности (можете создать реально выступающие булыжники, используя изоповерх­ности, изученные на первом уроке). Сrackle – тип паттерна, используемого для имитации узора; он выглядит аналогично текстуре voronoy в Blender, создавая мозаику, похожую на каменную кладку. bump_size задаёт высоту выступов; отрицательные значения этого параметра меняют местами выступы и впадины, заставляя камни выглядеть выступающими внутрь помещения.

Для имитации раствора создадим простую серую текстуру:

#declare sw_mortar = texture {
	 pigment { color rgb <.53,.53,.53> }
}

Теперь совместим две текстуры в одном материале, применив специальный модификатор – карту текстур (texture_map). Она используется аналогично знакомому модификатору color_map, чередующему цвета в зависимости от значений паттерна. Главное отличие карты текстур – возможность чередовать текстуры и прочие свойства поверхности (интенсивность бликов и диффузного отражения, нормали). Создадим карту текстур, используя паттерн crackle:

crackle
scale 4

t exture_map {

	 [.06 sw_mortar]
	 [.06 stone]
}

Между паттерном и картой текстур стоит модификатор scale, увеличивающий узор паттерна. Создание текстуры стены закончено.

Наломаем дров

Попробуем изобразить деревянный помост и опоры шестерён. Найдите в файле tower_textures.inc строчку #declare stock_wood = texture{def}, удалите def и начните создавать пигмент:

pigment{
	 wood
	 rotate 3*y

В основе пигмента лежит паттерн wood (дерево) – он создаёт узор типа годичных колец древесного ствола, для имитации каковых и предназначен. Правда, эти кольца идеально ровные, без всяких сучков и извивов, и для реалистичности придётся внести в узор хаос. Воображаемое бревно бесконечно большое, его серд­цевина совпадает с осью Z; поворт на вокруг оси Y чуть нарушит симметрию, добавив натурализма. Для более основательного перемешивания применим знакомый модификатор warp:

warp {
	 turbulence <1,1,0>
	 octaves 3
	 lambda 1.5
	 omega .3
}

Единственное новое для нас – вектор <1,1,0> в качестве параметра turbulence. Как вы, надеюсь, помните с предыдущего урока, turbulence задаёт дистанцию начального смещения текстуры, а вектор регулирует величины смещений по разным осям. Текущие значения разрешают пертурбации только в плоскости XY, т. е. «поперёк» воображаемого бревна, что создаст множество узелков.

Сожмем «бревно» с боков и растянем вдоль оси Z, уменьшив ширину годичных колец и превратив узелки в веретенообразные волны натурального узора древесины модификатором scale:

scale <.1, .1, 3>

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

Реальные брусья – это выпиленные из бревна куски древесины, а мы уже соорудили ствол бесконечного виртуального дерева; осталось нарезать его на фрагменты. Снова применим warp:

Текстуры полностью изменили изображение!

warp {
	 repeat y
	 offset 10*z
	 flip <1,1,0>
}

Модификатор берет новые параметры и не вносит случайный шум в текстуру, а по­вторяет её через определённые интервалы с небольшими изменениями. Вектор, принимаемый параметром repeat, задаёт направление, в котором будет повторяться текстура, и размер повторяемой области. Длина его произвольна, но он обязательно должен совпа­дать с одной из осей! Offset – смещение по­вторяемых фрагментов от предыдущих.

Повтор идентичных участ­ков не реа­листичнее цельного бревна – сдвигая текстуру при каждом повторе, мы добьёмся большего натурализма. Направление сдвига может быть любым. Flip зеркально отражает каждый фрагмент относительно предыдущего по осям с ненулевым значением передаваемого вектора. Повернём модифицированный паттерн на 90° вокруг оси Y и применим карту цветов:

rotate 90*y
color_map {
	 [.4 color rgb <.9,1,.8>*.25]
	 [.55 color rgb <1,.9,.8>*.35]
}

В завершение, сымитируем блики:

finish {
	 specular .1
	 roughness .1
}

На стыках деталей имеются щели; издали они похожи на тёмные полосы. Смоделируем их на нашей текстуре, добавив после фигурной скобки, закрывающей описание текстуры, ещё одну текстуру:

texture {
	 pigment {
		 gradient .5*y
		 color_map {
			 [0 color rgbt 0]
			 [.051 color rgbt <0,0,0,1>]
		 }
	 }
}

Расположение текстур друг за другом создаст многослойную [layered] текстуру – это способ чередования свойств поверхности материала, альтернативный карте текстур. Текстура, определённая первой, будет фоном; все последующие текстуры должны иметь прозрачные участки, сквозь которые видны предыдущие. Многослойную текстуру можно представить как стопку «прозрачек». Пигмент текстуры, определённой поверх древесины, использует паттерн gradient – плавный переход значений от 0 до 1 вдоль указанного вектора. На дистанции, равной вектору, будет единица, затем идет плавный спад до нуля на дистанции, равной удвоенному вектору, потом снова начинается спад – и так до бесконечности.

Карта цветов создаёт узкую тёмную полоску вблизи нулевого значения. Цвет задан четырехмерным вектором; четвёртый компонент – величина пропускания (transmit), или прозрачность участка. Итак, большая часть второй текстуры абсолютно прозрачна. Займёмся текстурой помоста. Просто скопируйте описание текстуры опор шестерён и вставьте вместо texture{ def } в строке #declare floor_wood = texture{ def }. Затем нам потребуется внести кое-какие изменения: на помосте, лежащем горизонтально, текстура должна повторяться в другом направлении, и доски, из которых набран пол, будут чуть шире. Для этого во втором модификаторе warp первой текстуры заменим значение параметра repeat на 1.5*x, offset – на 20*z, а во второй текстуре – gradient на .75*z.

Блики

Осталась отделка водной глади и ручки факела. Для факела –

#declare brand_metal = texture{
	 pigment{ color rgb <.96,.98,1> }
	 finish {
		 diffuse .01
		 ambient 0
		 specular .9
		 roughness .01
		 metallic
		 reflection { .9 metallic }
	 }
}

Параметр reflection [отражение] добавлен в секцию finish для имитации зеркальной металлической поверхности, отражающей окружающие предметы. Число внутри описания этого параметра определяет долю света, отражаемого поверхностью; ключевое слово metallic окрашивает отражение в цвет металла.

Текстура воды должна выглядеть следующим образом:

#declare water = material{
	 texture{
		 pigment { color rgb .1 }
		 finish {
			 diffuse .01
			 specular .85
			 roughness .0005
			 reflection {.9 fresnel}
		 }
		 normal {
			 ripples
			 frequency 30
			 bump_size .2
			 translate -.5*<1,1,0>
			 scale 40
		 }
	 }
	 interior { ior 1.333 }
} 

Это даже не текстура, а материал [material]–модификатор, объединяющий в блок две различные для POV-Ray сущности объектов - текстуру [texture] и интерьер [interior]. Текстуры задают свойства поверхности – бесконечно тонкой оболочки объектов, интерьеры – оптические свой­ства внутри объёма. В секции finish при описании параметров отражения имеется ключевое слово fresnel, означающее реалистичный расчёт отражения в зависимости от угла, под которым видна поверхность. Эта опция работает, только если известен коэффициент преломления материала, задаваемый при помощи параметра ior внутри секции interior. В секции normal использован паттерн ripples, имитирующий рябь на воде; параметр frequency задаёт число волн на единичной дистанции. По умолчанию, рябь – это результат интерференции волн от десяти источников в кубе со стороной в одну единицу; модификатор смещён и масштабирован, чтобы эффект занял всю доступную площадь.

С текстурами покончено, ура! Запустите рендер, чтобы увидеть, насколько радикальны изменения. Если что-то не сработает, обратитесь к файлу tower_textures_final.inc за готовыми текстурами.

Тёплый свет огня

Теперь свет как в катакомбах, а не операционной.

Яркий свет факела режет глаз – освещён огромный объём без малейшего признака затухания, а свет обязан затухать пропорционально квадрату расстояния от источника. В файле tower.pov настроим светильник в факеле, добавив в его описание строки

fade_power 2
fade_distance 11

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

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

looks_like {
	 sphere {
		 0, .3
		 scale 2*y
		 texture {
			 finish {
				 diffuse 0
				 ambient <1, .5, .2>*4
			 }
			 pigment {rgb 1}
		 }
	 }
}

Опция looks_like [англ. «выглядит как»] позволяет задать объект, изображающий источник света; у нас это вытянутая сфера. Чтобы сделать сферу видимой, ей присвоена простая текстура. Параметры diffuse и ambient в секции finish задают степени отражения направленного и рассеянного освещения соответ­ственно. Направленное освещение создаётся источниками света (light_source) и приводит к появлению на объектах переходов светотени. Рассеянное освещение имитирует свет, отражённый от поверхностей объектов. По умолчанию берется самая простая модель рассеянного освещения, представляющая рассеянный свет однородным по всей сцене. Это не слишком корректно с точки зрения фотореализма, зато позволяет создавать интересные эффекты – в нашем случае, мы сымитировали светящуюся поверхность, назначив очень большую величину отражения рассеянного света. Параметр diffuse сделан нулевым, чтобы избежать появления бликов.

Вот он, наш волшебный фонарь.

Наши тени имеют очень резкие, контрастные края. Смягчим их, применив площадные источники света. Вначале займёмся светом Луны – добавим в описание первого источника света строки

area_light
2*x, 2*y, 3, 3
jitter

Area_light включает имитацию объёмного источника. На следующей строчке первые две величины задают размер излучающей свет плоскости по осям X и Y соответственно. Площадной источник имитируется как массив точечных источников, расположенных на плоскости; следующая пара значений задаёт число строк и колонок в этом массиве. Ключевое слово jitter дополнительно размывает контуры тени, смягчая её.

Добавим в описание источника света на факеле следующее:

area_light
.7*x, .7*y, 4, 4
jitter
circular
orient

Пришла пора смягчить края теней.

Сircular деформирует источник света, делая плоскость не прямоугольной, а круглой; orient поворачивает источник на точку, для которой вычисляется освещённость; а вместе эти опции имити­руют шарообразный источник света.

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

Антиалиасинг

Работа над сценой закончена – осталось только настроить сам рендер. Наверно, вы уже отметили ступенчатость краёв объектов и то, что текстура помоста выглядит некрасивой мешаниной точек. Для борьбы с этими артефактами применяется антиалиасинг.

Скопируйте с диска в папку с вашим проектом файл tower.ini, если вы до сих пор обходились без него. Первым делом убедитесь, что в этом файле в строчке Input_File_Name="<имя файла>" указано имя POV-файла вашей сцены; затем взгляните на следующую строчку Antialias=off, включающую/выключающую антиалиасинг. Замените off на on, активировав функцию. Следующий параметр, Sampling_Method, переключает режимы сглаживания. Если он равен 1, то применяется обычный антиалиасинг, при котором пиксель разбивается на множество сэмплов, и их усреднённое значение присваивается пикселю. Число сэмплов одинаково для всех пикселей и равно квадрату параметра Antialias_Depth. Если Sampling_Method равен 2, используется рекурсивный антиалиасинг. В этом режиме пиксель разбивается на 4 части, если различие между частями больше, чем величина Antialias_Threshold (порог антиалиасинга), и каждая часть снова разбивается. Операция повторяется до тех пор, пока разница между сэмплами не станет меньше порога или пока число рекурсивных разбиений не превысит величину Antialias_Depth. Данный метод позволяет гибко регулировать число сэмплов, в зависи­мости от сложности поверхности, проецируемой на пиксель, экономя вычислительные ресурсы без ущерба для каче­ства финального изображения.

Антиалиасинг убрал все дефекты.

Выберем второй метод антиалиасинга, присвоив двойку параметру Sampling_Method; Antialias_Depth будет равно двум, Antialias_Threshold равен 0.01. Запускаем рендер командой povray tower.ini. Теперь придется подождать довольно долго – возможно, час или более, если у вас не самый мощный компьютер – но наградой за терпение будет чистая картинка без артефактов.

На этом наше шапочное знакомство с POV-Ray закончено. За  пределами рассмотрения осталась масса полезных функций: имитация дифракции и дисперсии с помощью карт фотонов, реалистичный расчёт рассеянного осве­щения, сплайновые поверхности вращения и много чего ещё. Надеюсь, что нам удастся заняться этим в по­следующем цикле уроков, полностью посвящённых POV-Ray.

Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию