Автор работы: Пользователь скрыл имя, 11 Декабря 2011 в 07:50, дипломная работа
Задача моделирования фотореалистичной воды в реальном времени является одной из классических задач компьютерной графики. Это связано с тем, что вода является сложным природным объектом, и ее внешний вид зависит от многих факторов таких, как окружающий мир или положение наблюдателя. Поэтому очень важно знать основные факторы, влияющие на поведение и внешний вид воды. Но в различных ситуациях поведение воды может очень сильно различаться, поэтому нужно выделять категории эффектов, характерные для каждого случая (в основном, это относится только к физическому поведению поверхности воды).
1. Введение 3
1.1 Обзор публикаций 4
1.2 Постановка задачи 6
2. Имитация поведения поверхности воды 7
2.1 Выбор типа сетки для представления поверхности воды 7
2.2 Волновое уравнение поверхности 8
3. Имитация оптических эффектов 12
3.1 Оптические свойства воды 12
3.2 Создание текстур 13
3.3 Проекционное текстурирование 15
3.4 Отсечение объектов 16
3.5 Цвет воды 17
4. Описание приложения 19
4.1 HLSL – высокоуровневый язык шейдеров 19
4.2 Рендеринг в текстуру (Render To Texture) 21
4.3 Руководство пользователя 21
5. Заключение 23
6. Список литературы 24
рис.16
Принцип работы метода
проецирования текстуры
Здесь
используется метод проекционного
текстурирования. Данный метод заключается
в том, что для каждой точки
поверхности вычисляется
рис.17Различия
в системах отсчета
для пространств текстуры
и экрана
Поэтому
для правильного наложения
matProjectTex = matView * matProjec t * matRemapping.
Данное преобразование координат применяется к вершине поверхности воды в вершинном шейдере:
float4 vProjTex = mul( vPos, matProjectTex );
Затем текстурные координаты вычисляются на основе полученного результата в пиксельном шейдере:
float2 vTexCoord = vProjTex.xy / vProjTex.w;
После этого можно производить выборку из проецируемой текстуры на основе полученных координат.
В процессе создания карт отражения и преломления необходимо отсекать “лишние” объекты или части сцены, которые не должны отражаться или преломляться. Есть два широко распространенных способа сделать такое отсечение в процессе рендеринга сцены: User Clip Planes и Oblique Frustum Culling.
Первый способ – User Clip Planes. Данный механизм позволяет установить несколько плоскостей отсечения, в результате чего вывод точек возможен только в части пространства, ограниченной этими плоскостями. Но есть одна проблема: если использовать фиксированный графический конвейер, то уравнение плоскости отсечения должно быть задано в мировом пространстве, а в случае программируемого конвейера – в том же пространстве, что и вершины на выходе. Это оказывается очень неудобным в том случае, когда в процессе работы производится частое переключение с одного конвейера на другой (при отрисовке различных материалов и объектов).
В связи с этим часто применяется другой способ, который оказывается более удобным за счет своей простоты и отсутствия вышеописанных проблем (Oblique Frustum Culling). Идея этого метода состоит в преобразовании матрицы проекции таким образом, что ближняя отсекающая плоскость переводится в плоскость водной поверхности, а это нам и нужно.
Но после отсечения возникает другая проблема, которая касается объектов, пересекающихся с водной поверхностью. Все дело в том, что в результате последующего искажения текстур на границе между водой и данными объектами будут видны “разрывы”. Чтобы избежать этого, наилучшим способом является специальный метод маски изображения. Он дает почти идеальный результат. Ни один из других алгоритмов не сможет полностью устранить артефакты.
Суть метода заключается в следующем: мы выводим всю сцену только в Z-буфер, при этом буфер кадра заполнен белым цветом. Затем мы рисуем воду черным цветом, не очищая Z-буфер. Таким образом, часть воды, скрытая за другими объектами, не выводится. В итоге мы получаем черно-белую текстуру, в которой все объекты, кроме воды, закрашены белым цветом. Это и есть наша “маска”, которая позволяет определить, где на экране вода, а где перекрывающие ее сплошные объекты.
Теперь, когда есть маска, можно использовать ее в процессе искажения текстур отражения и преломления в шейдере водной поверхности следующим образом: если искаженные координаты соответствуют области с черным цветом, то все нормально; если же точка с этими координатами оказывается в области с белым цветом, то нужно использовать исходные координаты без искажений. Все эти операции можно записать следующим образом:
float4 vReflectRefractTexCoord = saturate(vTexCoord
+ vOffset);
float mask1 = tex2D(MaskSampler, vReflectRefractTexCoord.xy).r;
float mask2 = tex2D(MaskSampler, vReflectRefractTexCoord.zw).r;
float3 reflection = tex2D(ReflectSampler, vReflectRefractTexCoord.xy);
float3 reflection2 = tex2D(ReflectSampler, vTexCoord.xy);
float3 refraction = tex2D(RefractSampler, vReflectRefractTexCoord.zw);
float3 refraction2 = tex2D(RefractSampler, vTexCoord.zw);
reflection = lerp(reflection, reflection2, mask1);
refraction
= lerp(refraction, refraction2, mask2);
Таким образом, можно легко устранить возникающие артефакты. При этом скорость работы приложения практически не изменяется, что говорит о высокой эффективности метода. Этот метод является расширением метода из [9], расширение предложено Рябчиковым А.В.
В
простейшем случае цвет точки водной
поверхности можно вычислить
на основе смешивания текстур отражения
и преломления с помощью
рис.18 Сравнение приближений формулы Френеля
На
рисунке показана разница между
двумя способами приближения
формулы Френеля (вертикальная ось
соответствует степени
Здесь n1 и n2 – коэффициенты преломления соответствующих сред, - угол между нормалью и направлением взгляда. Для воздуха и воды .
Обычно используется первая формула, причем считается , хотя второй способ аппроксимации дает меньшую погрешность при вычислении коэффициента Френеля. А иногда используется линейная зависимость , но это приводит к еще большей ошибке по сравнению с (1).
Таким образом, с помощью следующей формулы вычисляется конечный цвет воды в данной точке (производится линейная интерполяция между двумя значениями с помощью коэффициента Френеля):
color = lerp(RefractionColor, ReflectionColor, Fresnel)
Если остановится на этом, то получится, что вода абсолютно прозрачна. Для большей реалистичности нужно учитывать оттенок воды, который влияет на цвет преломляемых объектов. Одним из способов реализации этого эффекта (и наиболее правильным) является вывод объектов с учетом тумана при создании карты преломления. В этом случае получится, что цвет воды зависит от глубины в каждой точке.
Есть и более простой метод, но он дает менее реалистичный результат. Можно просто задать 2 оттенка воды – один для отраженных, а другой для преломленных объектов, и перед смешиванием цветов, взятых из соответствующих текстур, умножить их соответственно на эти оттенки. В этом случае цвет дна не будет зависеть от глубины, но иногда этот способ очень удобен за счет своей простоты.
Также, можно считать, что оттенок зависит от угла зрения на воду: чем меньше угол между нормалью к поверхности и вектором зрения, тем темнее цвет воды, и наоборот. Таким образом, можно интерполировать значение цвета в пределах двух крайних значений и применять его к каждой точке.
Базовое приложение использует DXUT framework. В качестве основы берется готовая 3D сцена, содержащая небольшой кратер для воды (ландшафт) и небесный купол (skybox) на основе кубической карты окружения. В приложение изначально было встроено управление камерой (camera) и вводом (input). Весь аппарат моделирования водной поверхности содержится в классах NXWaterCore и NXWater.
Класс NXWaterCore содержит необходимые для работы матрицы, а именно, матрицу отражения m_mReflect; матрицу, которая преобразует координаты точек пространства экрана в текстурные координаты, m_mTex. Так же уровень воды и уровни, необходимые для отражения/преломления и методы для работы с ними.
Класс NXWater отвечает за триангуляцию и визуализацию водной поверхности.
Приложение создано в среде Visual Studio 2005 с использованием расширения DirectX SDK 9.0с (2006).
Шейдер - это микропрограмма на языке низкого уровня (как ассемблер), исполняющаяся на графическом процессоре видеокарты (GPU) и обрабатывающая поток данных, а это значит, что у шейдерной программы есть "вход" и есть "выход", а "посередине" - набор команд, выполняющих обработку. Под "потоком данных" подразумевается информация о координатах вершин полигонов, освещении каждой вершины, нормалях, текстурных координатах, и т.п., непрерывно поступающая блоками в шейдерную программу.
Шейдеры полностью программируемы и позволяют нам реализовать техники, которые отсутствуют в фиксированном конвейере функций. В результате количество доступных техник значительно расширяется.
Написание шейдеров на низкоуровневом языке очень трудоемко и неудобно, поскольку даже для реализации простых эффектов приходится писать достаточно большое количество кода, что, в свою очередь, мешает пониманию и изменению кода. Но возникновение языков высокого уровня программирования шейдеров (HLSL / GLSL) сделало процесс написания шейдеров максимально простым и удобным, т.к. появилась возможность разработки шейдеров на языке высокого уровня, похожем на С.
Программируемые HLSL-шейдеры используют компилятор HLSL, чтобы сгенерировать ассемблерный код по исходному высокоуровневому коду. Таким образом, данный язык позволяет программировать шейдеры на алгоритмическом уровне.
Графический эффект обычно состоит из нескольких компонентов: вершинный и/или пиксельный шейдер, список режимов устройства, которые должны быть установлены, и один или несколько проходов визуализации. Кроме того, часто для графических эффектов желательно наличие механизма обработки сбоев, позволяющего эффекту выполняться на различных видеокартах (то есть, необходимо наличие нескольких версий эффекта, которые реализуют его или пытаются достичь наиболее близкого соответствия реализации, используя возможности установленного оборудования). Ясно, что все эти задачи связаны с одним эффектом. Следовательно, логичным шагом будет попытка объединения всех этих задач в один блок.
Каркас эффектов Direct3D предоставляет подобный механизи для объединения связанных с визуальным эффектом задач в один файл эффекта. Такая реализация эффектов имеет ряд преимуществ. Во-первых, она позволяет нам менять реализацию эффекта без перекомпиляции исходного кода приложения. Это делает процесс обновления эффектов гораздо проще, независимо от того, вызван ли он исправлением обнаруженных ошибок, или усовершенствованиями, связанными с появлением нового оборудования. Во-вторых, мы объединяем все компоненты эффекта в одном файле.
Файл эффекта состоит из одной или нескольких техник (techniques). Техникой называется конкретный способ реализации спецэффекта. Другими словами, файл эффекта описывает один или несколько способов реализации одного и того же спецэффекта. Зачем надо несколько различных реализаций одного и того же эффекта? Дело в том, что установленное на компьютере оборудование может не поддерживать определенную реализацию эффекта. Следовательно необходимо реализовать несколько версий одного и того же эффекта, ориентированных на различное оборудование.
Информация о работе Моделирование и визуализация водных поверхностей