Несколько текстурных изображений, смешанных на трехмерной поверхности
Как компьютерные игры делают свое дело? Я буду использовать карту высот для геометрии (хотя позже я ее оптимизирую), но мне интересно, какой метод лучше всего подходит, например, для "рисования" моего грунта; повсюду трава, грязные дорожки здесь и там, гравий внутри городов и плавные переходы между материалами каждого типа.
Я просто использую огромную предварительно запеченную текстуру? Это кажется очень неэффективным, когда я могу использовать существующие текстуры. Так тогда я использую огромную альфа-карту для каждой существующей текстуры? В теории это звучит нормально для меня, но как мне на самом деле поступить так и каковы последствия? Я действительно не знаю, с чего начать, и мои поиски в Google не очень эффективны.
Я бы предпочел не привязывать текстуру к сетке (т. Е. Пространство (0,0) - это трава, пространство (0,2) - это грязь, пространство (0,1) - это переход трава-грязь); Я бы предпочел произвольно рисовать так, чтобы это выглядело более убедительно. Конечно, это был бы легкий путь, но это слишком большая жертва в качестве графики и "реалистичности".
Я в основном просто ищу теорию и варианты здесь. Я использую OpenGL, так что если вы можете дать советы, касающиеся способов работы OpenGL и функций, о которых я, возможно, никогда не слышал, это было бы замечательно.
Просто для пояснения, Oblivion - хорошая ссылка на то, что я ищу. Я не знаю, какова геометрия земли (карта высот, статические 3D-модели и т. Д.), Но их рельеф имеет разные типы грунтов и плавные переходы между ними, о чем я говорю. Вот пример изображения, обратите внимание, как булыжник сливается с травой, нереально, но плавно: http://www.elitistsnob.com/images/Oblivion%202006-05-21%2008-38-25-15.jpg
Кроме того, я думаю, что читал об этом в одной из книг "Game Programming Gems", но в то время я не обращал на это особого внимания, и теперь, когда лето, у меня нет доступа к библиотеке моего университета, чтобы проверить! Я сейчас ищу оглавления и буду редактировать, если найду, но я все равно не смогу прочитать его до середины августа.
РЕДАКТИРОВАТЬ: А, чувак, в Game Programming Gems 7 есть глава 5.8 под названием "Отображение больших текстур для рендеринга ландшафта на открытом воздухе", которая звучит как то, что мне нужно, но в библиотеке моего U даже нет этой книги! Я не мог найти ничего подобного в других книгах Game Programming Gems, хотя у пары было несколько статей по геометрии местности.
6 ответов
Недавно я написал небольшой движок рендеринга ландшафта в OpenGL, который делает нечто похожее на то, о чем вы говорите. Технику, которую я использую, лучше всего описать как разбрызгивание текстуры.
Я использую пять текстур для достижения этой цели. Четыре из этих текстур являются детальными текстурами: трава, камень, вода и песок. Эти текстуры имеют небольшую текстуру 512х512, и они выложены плиткой по всей местности. Пятая текстура - это микскарта. Mixmap - это гигантская текстура, которая покрывает всю местность, в моем случае это 4096x4096.
MixMap
Этот микскарта использует все 4 цветовых канала (r,g,b,a), чтобы описать, сколько текстур детали отображать в этом конкретном месте. Я использую канал красного цвета, чтобы определить, насколько непрозрачен песок, зеленый - для травы, синий - для воды, а альфа - для камня. Этот микскарт рассчитывается на основе карты высот при инициализации, и я использую высоты для определения этих значений. Например, ближе к уровню моря я в основном хочу воды, поэтому я установил высокое значение в синем канале и низкие значения в других каналах. Когда я поднимаюсь выше в горы, я устанавливаю альфа-цветовой канал на высокое значение, так как я хочу много текстуры камня, но я устанавливаю все остальные цветовые каналы на более низкие значения.
Фрагмент шейдера
Затем этот микскарт используется в фрагментном шейдере, где я беру эти цветовые каналы микскарты и использую их для объединения текстур деталей. Вот код GLSL, который я использую для фрагментного шейдера:
uniform sampler2D alpha;
uniform sampler2D grass;
uniform sampler2D water;
uniform sampler2D rock;
uniform sampler2D sand;
uniform float texscale;
varying vec3 normal, lightDir ;
void main()
{
// Get the color information
vec3 alpha = texture2D( alpha, gl_TexCoord[0].st ).rgb;
vec3 texSand = texture2D( sand, gl_TexCoord[0].st * texscale ).rgb;
vec3 texGrass = texture2D( grass, gl_TexCoord[0].st * texscale ).rgb;
vec3 texWater = texture2D( water, gl_TexCoord[0].st * texscale ).rgb;
vec3 texRock = texture2D( rock, gl_TexCoord[0].st * texscale ).rgb;
// Mix the colors together
texSand *= mixmap.r;
texGrass = mix(texSand, texGrass, mixmap.g);
texWater = mix(texGrass, texWater, mixmap.b);
vec3 tx = mix(texWater, texRock, mixmap.a);
// Lighting calculations
vec3 dl = gl_LightSource[0].diffuse.rgb;
vec3 al = gl_LightSource[0].ambient.rgb;
vec3 n = normalize(normal);
vec3 d = tx * (dl * max( dot ( n, lightDir), 0.0 ) + al );
// Apply the lighting to the final color
vec4 finalColor = vec4( min(d, 1.0), 1.0);
gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor);
}
Равномерная текстовая шкала - это значение, которое определяет, сколько раз текстуры деталей будут выкладываться по поверхности. При более высоких значениях текстуры деталей выглядят более четкими, рискуя сделать их более повторяющимися.
Предварительная выпечка наверняка не является неэффективной. на самом деле он наиболее эффективен, потому что ваш исполняемый код не должен делать никаких смешиваний или других вычислений. это просто делает текстуру. Конечно, динамические методы предлагают упрощение набора инструментов и больше опций.
Кажется, ID заставил одну большую "мегатекстуру" (мы говорим 32K^2-128K^2) работать в QuakeWars.
Об этом есть интересный вопрос с Кармаком в
http://web.archive.org/web/20080121072936/http://www.gamerwithin.com/?view=article&article=1319&cat=2
(оригинальная ссылка кажется мертвой в настоящее время, но не делает вышеупомянутую ссылку, потому что кажется, что SO имеет проблемы со ссылками на Интернет-архив; они хорошо выглядят в предварительном просмотре редактирования, а затем ломаются на главной странице).
Одним из стандартных способов, используемых, например, в движке источника (hl2), является создание альфа на каждую вершину для смешивания двух материалов. Материалы обычно состоят как минимум из альбедо и карты нормалей. В исходном механизме допускается только 2 материала на материал "текстуры текстуры", что является своего рода дерьмовым.
Если вам нужно более двух материалов, вы должны смоделировать их, текстурируя различные смещения разными текстурами, следя за тем, чтобы каждая отдельная плитка содержала не более двух материалов.
Наличие альфа-канала на вершину, а не на пиксель, выглядит довольно плохо. Как вы заметили в Oblivion, вы получите, например, булыжники, плавно переходящие в песок. Есть исправление для этого дефекта; Вы используете другую текстуру, которая модулирует альфа на пиксельную основу, так что трещины между булыжниками легко заполняются песком, но вершины булыжников остаются на уровне почти 1,0 альфа, пока интерполированная вершина альфа не станет почти 0 для булыжника. материал. Это может сделать переход действительно красивым, а не просто уродливым мазком.
Вы также можете использовать текстуру с низким разрешением, которая содержит альфы (но все же намного выше, чем 1 альфа на вершину). Текстуры мозаичного трейна могут иметь размер 2048x2048, но текстура, используемая для их смешивания, не требует разрешения на пиксель. Текстура 256x256 8 бит на тексель занимает всего 96 кБ с картами MIP.
Как правило, переходные области создаются заранее, хотя некоторые вещи можно делать с альфа-каналами и смешиванием текстур.
Вы не можете убежать от плитки, но, может быть, если вы используете базовую текстуру, которая создает небольшой шум на земле, похоже, что нет плитки...
использовать базовую текстуру с такими же координатами текстуры альфа-текстуры. Базовая текстура может быть чем угодно.. Сателлитная картинка или текстура травы. Она идеально подойдет, если она связана с вашей земной формой.
and try to use seamless textures for your grass, rock textures... it does not solve but makes it look as there is no problem