Разработка приложения для визуализации трехмерных сцен с использованием карт освещения и динамического освещения
Общая характеристика игровых движков, история их создания и совершенствования, современное состояние и перспективы. Сущность и значение шейдерных эффектов, программирование данных программ. Механизм и этапы разработки 3D-приложения, его тестирование.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 16.06.2011 |
Размер файла | 2,2 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
(6)
Если вы не знакомы с матричной формой записи, принятой в OpenGL, у вас может возникнуть вопрос, почему эти матрицы идут в обратном порядке. Ведь вначале нужно применить матрицу, обратную к относящейся к камере матрице проекции модели, а матрица трансляция (или смещения) на одну вторую применяется последней. В чем дело? В действительности все очень просто. OpenGL действует матрицей (М) на координату (Т) в обратном порядке. Поэтому чтобы представлять порядок преобразований, применяющихся к координатам, следует читать выражения справа налево:
(7)
К сожалению, для большинства теневых текстур, созданных по технологии shadow mapping допускает алиасинг - резкие границы теней. Современные видео-карты имеют встроенные методы для понижения алиасинга на простых текстурах: а именно mipmapping и anisotropic filtering. Эти методы не подходят к стандартным теневым картам, так как они могут изменить глубину соседних пикселей, которая хранится в компоненте цвета текстуры.
Для вычисления теней в общих сценах и борьбы с алиасинг используется процентная Близкая Фильтрация (Percentage Closer Filtering, PCF) обеспечивает решение проблемы алиасинга карты теней. Ключевой момент в том, что корректный алгоритм фильтрации нуждается в выявление результатов срав-нения глубин, вместо их фильтрации. Это совершается выборочно семплированием карты теней, таким образом, требуя множество семплов для уничтожения помех.
Карты глубин хранит распределение глубин каждого пикселя вместо единой глубины. Как результат, PCF может быть сделан как препроцесс.
Однако, карта глубин не подлежит реализации на аппаратном уровне по двум причинам: каждый пиксель должен кодироваться как кусочно-линейная функция, используя большое количество данных, а кроме того, процедура усреднения двух распределений не нулевая.
Тусклость карты теней кодируется распределением глубин, используется фиксированное количество сохранённых пикселей. Каждый пиксель хранит функция в карте глубин, функция эта создаётся из фиксированного набора точек. Таким образом, алгоритм имеет преимущество в скорости.
Альтернативное решение проблемы алиасинга карты теней это изменение проекции карты теней. Этот подход рассматривается в adaptive shadow maps, perspective shadow maps, light space perspective shadow maps и trapezoidal shadow maps.
2. Проектирование 3D-приложения
Для проектирования 3D-приложения необходима библиотека классов, которая облегчает процесс разработки такого рода приложений. Такую библиотеку классов также часто называют «3D движком», Над разработкой «3D движка» работают многие коммерческие фирмы с большим штатом программистов в течение длительного времени, но все эти «3D движки» закрыты или являются очень дорогостоящими. В связи с тем, что мы не обладаем большими финансовыми и штатными резервами и также ограничены во времени, будем проектировать собственный «3D движок» c минимальным достаточным набором функций.
2.1 Постановка задачи
Цель данной работы - разработка 3D-приложения на основе библиотеки классов. Разработанная библиотека классов должна предоставлять пользова-телю следующий перечень возможностей:
- выводить, управлять Windows - окнами
- подключать / отключать графическую библиотеку, в нашем случае - OpenGL
- обрабатывать действия пользователя, например нажатие клавиш и перемещение мыши
- уметь манипулировать математикой основных 3d данных:
1) вектора разной размерности (2,3,4 компонентные),
2) матрицы (3,4 разрядные),
3) кватернионы
4) углы Эйлера, а также их взаимное преобразование, а именно переход из углов Эйлера в матрицу и наоборот
- загружать / выгружать текстуры (файловые изображения)
- уметь создавать базовые модели плоскость, куб, сфера, торус
- уметь загружать / выгружать произвольные 3d-модели
- загружать шейдеры
- передавать данные в шейдер
- задавать материалы к загруженным 3d-моделям
- работа с внеэкранными буферами
3D движок сложная структура и может быть представлена в виде, как показано на рис. 2.1. Причем заметим, что подсистемы расчета физики и подсистема воспроизведения звука не обязательны для нашего минимального 3D движка, поэтому мы их опустим, а подсистемы пользовательского ввода и подсистема вывода графики необходимы.
Рисунок 2.1 Общая схема 3D-движка
Модуль Камера предназначен для создания и управления камерой наблюдателя в нашем проектируемом 3d мире
Модуль Текстуры предназначен загрузки изображений и преобразований ее формат OpenGL. В нашей программе мы используем TGA формат для загрузки изображения, как один из наиболее распространенный.
Модуль шейдеры предназначен компиляции, отладки, подключение к программе, а также передачи из программы в шейдер параметров
Модуль внеэкранный буфер предназначен
Модуль 3d математика предназначен манипулировать математикой основных 3d данных:
1) вектора разной размерности (2,3,4 компонентные),
2) матрицы (3,4 разрядные),
3) кватернионы
4) углы Эйлера, а также их взаимное преобразование, а именно переход из углов Эйлера в матрицу и наоборот
Модуль Справочная информация предназначен для вывода справочной информации о ходе работы приложения (какая видео карта, как откомпилировались шейдеры и т.д.) это нужно для быстрого анализа ошибок приложения при запуске на других компьютерах и отличной от используемой видеокарты.
Модуль OpenGL API функции необходим для описания и подключений функций OpenGL и его расширений
Модуль приложения предназначен для создания окна windows и инициализации контекста OpenGL. В данной разработке мы используем OpenGL версии 3.3.
Модуль 3d модель предназначен создания базовых примитивов базовые модели плоскость, куб, сфера, торус, а также произвольных моделей в формате bin. Модель в формате bin представляет собой бинарный файл, в котором записан массив мешей, где каждый меш описывается следующими паромерами:
- общее количество данных
- массив данных, в формате (вершина, текстурная координата, нормаль)
- количество индексов
массив индексов
Модуль материалы предназначен для описания структуры материала, а также передачи данных в шейдер. Считаем, что материал описывается такими параметрами:
Свечение материала
Фоновое освещение материла
Рассеянный свет источника света
Отраженный свет источника света
Модуль тени предназначен для описания алгоритмов построения теней от 3d объектов
Модуль освещение предназначен для описания, создания ми управления источниками света, а также передачи данных в шейдер. В данной работе мы будем использовать направленный источник света. Считаем, что свет описывается следующими параметрами:
Свечение источника света
Фоновое освещение источника света
Рассеянный свет источника света
Отраженный свет источника света
Позиция источника света
Направление источника света
Проекционная матрица источника света
2.2 Архитектура 3D-приложения с использованием проектируемого 3D движка
Решение задачи проектирование 3D-приложения с 3D движком существенно сокращает время разработки, а также облегчает понимание работы 3D приложения и сводится к созданию и вызову соответствующих классов и модулей в основной программе.
3. Реализация 3D-приложения
В данном разделе представлен и расписан алгоритм добавления тени для 3D объектов на основе теневой карты (shadow map) с фрагметнтами программного кода и шейдерами. Весь программный код 3D - приложения приведен в приложениях А, Б, В, Г, Д соответственно
3.1 Обобщенный алгоритм работы 3d-программы
Обобщенный алгоритм работы 3d-программы представлен на рис. 3.1 и состоит из 8 шагов.
1. Ввод исходных данных
На данном этапе вводиться ширина и высота окна визуализирующий наш 3d мир. Это способность очень важна, если мы хотим демонстрировать нашу программу на разных типах визуализации информации - монитор, проектор, плазменный телевизор.
Также здесь вводятся модели для рисования
Источники света
Текстуры
Материалы
Дополнительный буфер
2. Инициализируется Windows-окно и контекст OpenGL 3.3.
3. Обработка очереди сообщений Windows-окна
4. Обработка ввода с клавиатуры пользователя
5. Рисование кадра 3D-приложения
6. Пересчет кадра 3D-приложения
7. Проверка условий работает ли 3D-приложение
8. Деинициализация Windows-окна и контекста OpenGL 3.3
Рисунок 3.1 Обобщенный алгоритм работы 3d-программы
3.2 Рисование кадра 3d-приложения
Рисование кадра 3D-приложения представляет собой двух этапный алгоритм (рис. 3.2) и состоит следующих этапов:
- рисование сцены в текстуру тени.
- рисование итогового изображения вместе с тенью
Рисунок 3.2 Алгоритм рисования кадра 3D-приложения
Подробный алгоритм рисование сцены в текстуру тени представлен на рис. 3.3 и состоит в свою очередь из 6 этапов, а подробный алгоритм рисование итогового изображения вместе с тенью рисунок 8 соответственно.
Рисование сцены в текстуру тени
Для получения теневой карты нам необходимо получить буфер глубины сцены относительно положения и направления источника освещения. Мы используем направленный источник освещения, чтобы получить буфер глубины сцены для такого источника нам понадобиться построить две матрицы:
· Матрицу вида (view matrix)
· Матрицу проекции (projection matrix)
Как вы можете заметить, это те же самые матрицы, которые используются в камере, поэтому удобно использовать существующие функции для работы с камерой, чтобы произвести рендер сцены относительно источника освещения.
На каждый источник освещения необходим дополнительный проход рендера сцены, с использованием камеры источника освещения. В данном случаи у нас используется только один источник освещения, поэтому понадобиться только один дополнительный проход рендера.
Рисунок 3.3 Алгоритм рисования сцены в текстуру тени
Стоит также отметить, что для направленного источника освещения используется не перспективная матрица проекции, а ортогональная, ее построение выглядит следующим образом:
const mat4 OrthoProjection (float left, float right,
float bottom, float top,
float zNear, float zFar)
{
const float tx = - (right + left) / (right - left),
ty = - (top + bottom) / (top - bottom),
tz = - (zFar + zNear) / (zFar - zNear);
return mat4 (2 / (right - left), 0, 0, tx,
0, 2 / (top - bottom), 0, ty,
0, 0, -2 / (zFar - zNear), tz,
0, 0, 0, 1);
}
Теневая карта использует буфер глубины (depth buffer), для того, чтобы определить, находится ли пиксель в прямой видимости источника освещения, либо он чем-то загорожен.
Одним из полезных свойств построения теневой карты является то, что ее построение не зависит от сложности геометрии на сцене, необходимо лишь получить буфер глубины для каждого из обсчитываемых источников освещения.
Для того, чтобы получить буфер глубины, нам необходимо:
Создать текстуру для хранения буфера глубины
Создать Framebuffer Object (FBO) и привязать к нему текстуру
Настроить камеру и выполнить рендер сцены в созданный FBO
Начнем по порядку, для начала создадим текстуру для хранения буфера глубины, делается это следующим образом:
// функция создания текстуры для хранения буфера глубины
GLuint TextureCreateDepth (GLsizei width, GLsizei height)
{
GLuint texture;
// запросим у OpenGL свободный индекс текстуры
glGenTextures (1, &texture);
// сделаем текстуру активной
glBindTexture (GL_TEXTURE_2D, texture);
// установим параметры фильтрации текстуры - линейная фильтрация
glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_MAG_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);
// необходимо для использования depth-текстуры как shadow map
glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
// соаздем «пустую» текстуру под depth-данные
glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
// проверим на наличие ошибок
OPENGL_CHECK_FOR_ERRORS();
return texture;
}
// создадим текстуру для хранения буфера глубины
GLuint depthTexture = TextureCreateDepth (DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_HEIGHT);
Отдельно стоит сказать про размеры текстуры для хранения буфера глубины, часто, для использования этой текстуры как теневой карты, берут удвоенный размер окна, в которое происходит рендер. Но это совсем не обязательное требование, размер надо подбирать исходя из задачи.
Далее нам необходимо создать и настроить FBO, рендер сцены мы будем осуществлять с его использованием, создание FBO выглядит следующим образом:
// Framebuffer Object (FBO) для рендера в него буфера глубины
GLuint depthFBO = 0;
// переменная для получения состояния FBO
GLenum fboStatus;
// создаем FBO для рендера глубины в текстуру
glGenFramebuffers (1, &depthFBO);
// делаем созданный FBO текущим
glBindFramebuffer (GL_FRAMEBUFFER, depthFBO);
// отключаем вывод цвета в текущий FBO
glDrawBuffer (GL_NONE);
glReadBuffer (GL_NONE);
// указываем для текущего FBO текстуру, куда следует производить рендер глубины
glFramebufferTexture (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);
// проверим текущий FBO на корректность
if ((fboStatus = glCheckFramebufferStatus (GL_FRAMEBUFFER))!= GL_FRAMEBUFFER_COMPLETE)
{
LOG_ERROR («glCheckFramebufferStatus error 0x % X\n», fboStatus);
return false;
}
// возвращаем FBO по-умолчанию
glBindFramebuffer (GL_FRAMEBUFFER, 0);
После создания FBO и привязки к нему текстуры мы можем выполнить рендер всей сцены с использованием этого FBO:
// установим активный FBO
glBindFramebuffer (GL_FRAMEBUFFER, depthFBO);
// размер вьюпорта должен совпадать с размером текстуры для хранения буфера глубины
glViewport (0, 0, DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_HEIGHT);
// отключаем вывод цвета
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// включаем вывод буфера глубины
glDepthMask (GL_TRUE);
// очищаем буфер глубины перед его заполнением
glClear (GL_DEPTH_BUFFER_BIT);
// отключаем отображение внешних граней объекта, оставляя внутренние
glCullFace (GL_FRONT);
// выполним рендер сцены с использованием шейдерной программы и камеры источника освещения
RenderScene (depthProgram, lightCamera);
Во-первых, необходимо пояснить, что при заполнении буфера глубины нет никакой необходимости обрабатывать цвет пикселя, нам необходимо узнать только его глубину по отношению к источнику освещения.
Во-вторых, рендер внутренних граней объекта помогает избежать некоторых артефактов при использовании теневой карты. Однако данный способ подходит только для замкнутых выпуклых объектов, именно такие мы и используем в этом уроке.
В-третьих, рендер сцены мы производим с использованием специальной шейдерной программы, в этой программе мы можем отключить все лишние расчеты, оставив только необходимые для получения глубины.
В минимальном варианте вершинный шейдер для такой шейдерной программы выглядит следующим образом:
layout (location = VERT_POSITION) in vec3 position;
// параметры преобразований
uniform struct Transform
{
mat4 modelViewProjection;
} transform;
void main(void)
{
// переводим координаты вершины в однородные
gl_Position = transform.modelViewProjection * vec4 (position, 1.0);
}
Т.к. нас интересует только глубина фрагментов, а не их цвет, то фактически фрагментный шейдер может быть пустым:
void main(void)
{
}
Рисования итогового изображения вместе с тенью
Рисунок 3.4 Алгоритм рисования итогового изображения вместе с тенью
Как уже отмечалось ранее, смыл использования теневой карты заключается в определении является ли определенный фрагмент (пиксель) в тени другого фрагмента. Проверить мы это можем при рендере сцены, используя дополнительную матрицу источника освещения.
С помощью матрицы источника освещения мы переводим координаты вершины объекта из мировой системы координат, сначала в пространство источника освещения, а после в текстурные координаты карты глубины. Получить эту матрицу, используя камеру источника освещения, мы можем следующим образом:
void CameraSetupLightMatrix (GLuint program, const Camera &camera)
{
// матрица сдвига текстурных координат
static const mat4 bias (
0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 0.5f, 0.5f,
0.0f, 0.0f, 0.0f, 1.0f
);
// расчитаем необходимые матрицы
mat4 view = GLFromEuler (camera.rotation) * GLTranslation (-camera.position);
mat4 viewProjection = bias * camera.projection * view;
// передадим матрицу источника освещения в шейдерную программу
glUniformMatrix4fv (glGetUniformLocation(program, «transform.light»), 1, GL_TRUE, viewProjection.m);
}
Комментарий по поводу матрицы bias. Сначала мы получаем видовую матрицу источника освещения view, она переводит координаты вершины из мирового пространства координат в пространство координат источника освещения. Затем, используя проекционную матрицу, мы переводим координаты в однородные. Однако, известно что однородные координаты лежат в диапазоне [-1, 1], а нам необходимо получить текстурные координаты, которые лежат в диапазоне [0, 1], именно для этого используется матрица bias. Трансформация этой матрицы равносильна операции a * 0.5 + 0.5 для каждого элемента трансформируемого вектора.
В результате, используя матрицу источника освещения, мы можем перевести координаты вершины из мирового пространства в текстурные координаты карты глубины в вершинном шейдере:
layout (location = VERT_POSITION) in vec3 position;
layout (location = VERT_TEXCOORD) in vec2 texcoord;
layout (location = VERT_NORMAL) in vec3 normal;
// параметры преобразований
uniform struct Transform
{
mat4 model;
mat4 viewProjection;
mat4 light;
mat3 normal;
vec3 viewPosition;
} transform;
// параметры точеченого источника освещения
uniform struct Light
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
} light;
// параметры для фрагментного шейдера
out Vertex
{
vec2 texcoord;
vec4 smcoord;
vec3 normal;
vec3 lightDir;
vec3 viewDir;
} Vert;
void main(void)
{
// переведем координаты вершины в мировую систему координат
vec4 vertex = transform.model * vec4 (position, 1.0);
// передадим в фрагментный шейдер некоторые параметры
// вычисляем текстурные координаты вершины на карте глубины
Vert.smcoord = transform.light * vertex;
// передаем текстурные координаты
Vert.texcoord = texcoord;
// передаем нормаль в мировой системе координат
Vert.normal = transform.normal * normal;
// передаем направление на источник освещения
Vert.lightDir = vec3 (light.position);
// передаем направление от вершины к наблюдателю в мировой системе координат
Vert.viewDir = transform.viewPosition - vec3 (vertex);
// переводим координаты вершины в однородные
gl_Position = transform.viewProjection * vertex;
}
Используя полученные координаты и теневую карту мы можем найти глубину фрагмента относительно камеры источника освещения. Обладая информацией о глубине фрагмента относительно камеры источника освещения и относительно камеры наблюдателя мы можем сравнить эти два значения и узнать, находится ли этот фрагмент в тени другого в пространстве источника освещения.
GLSL 3.30 обладает двумя возможностями, которые облегчают нам получение требуемой информации о фрагментах:
Самплер sampler2DShadow
Функция textureProj
Использование специального текстурного самплера sampler2DShadow позволяет изменить логику работы некоторых функций для работы с текстурой, а использование функции textureProj позволяет получить значение текселя текстуры с коррекцией текстурных координат. При передаче в функцию textureProj в качестве текстурных координат 3х компонентного вектора для получения текселя она использует первые два компонента деленные на третий. Это позволит нам получить корректное значение карты глубины с учетом глубины фрагмента относительно камеры источника освещения.
При создании текстуры для хранения значений глубины мы использовали специальный параметр:
glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
Использование этого параметра позволяет производить автоматический тест на затенение (shadow test), это происходит когда мы вызываем функцию textureProj. В случае если глубина фрагмента с координатами smccord больше чем в текстуре глубины depthTexture функция textureProj вернет 1.0, иначе она вернет 0.0. Итоговый фрагментый шейдер:
// текстурный самплер карты глубины
uniform sampler2DShadow depthTexture;
// параметры точеченого источника освещения
uniform struct Light
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
} light;
// параметры материала
uniform struct Material
{
sampler2D texture;
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 emission;
float shininess;
} material;
// параметры полученные из вершинного шейдера
in Vertex
{
vec2 texcoord;
vec4 smcoord;
vec3 normal;
vec3 lightDir;
vec3 viewDir;
} Vert;
layout (location = FRAG_OUTPUT0) out vec4 color;
void main(void)
{
// нормализуем полученные данные для коррекции интерполяции
vec3 normal = normalize (Vert.normal);
vec3 lightDir = normalize (Vert.lightDir);
vec3 viewDir = normalize (Vert.viewDir);
// коэффициент затенения
float shadow = textureProj (depthTexture, Vert.smcoord);
// добавим собственное свечение материала
color = material.emission;
// добавим фоновое освещение
color += material.ambient * light.ambient;
// добавим рассеянный свет
float NdotL = max (dot(normal, lightDir), 0.0);
color += material.diffuse * light.diffuse * NdotL;
// добавим отраженный свет
float RdotVpow = max (pow(dot (reflect(-lightDir, normal), viewDir), material.shininess), 0.0);
color += material.specular * light.specular * RdotVpow;
// вычислим итоговый цвет пикселя на экране с учетом текстуры
color *= texture (material.texture, Vert.texcoord) * shadow;
}
Для сглаживания краев тени в используется техника Percentage Closer Filtering (PCF). Данная техника заключается в том, что производится несколько тестов на затенение в окрестностях искомого фрагмента и для затенения используется среднее значение этих тестов, таким образом, граница тени будет более «мягкой».
Относительно описанного выше фрагментного шейдера эту технику можно использовать так:
// сглаживание границы тени, используем PCF с выборкой 3x3
float PCF (in vec4 smcoord)
{
float res = 0.0;
res += textureProjOffset (depthTexture, smcoord, ivec2 (-1, - 1));
res += textureProjOffset (depthTexture, smcoord, ivec2 (0, - 1));
res += textureProjOffset (depthTexture, smcoord, ivec2 (1, - 1));
res += textureProjOffset (depthTexture, smcoord, ivec2 (-1, 0));
res += textureProjOffset (depthTexture, smcoord, ivec2 (0, 0));
res += textureProjOffset (depthTexture, smcoord, ivec2 (1, 0));
res += textureProjOffset (depthTexture, smcoord, ivec2 (-1, 1));
res += textureProjOffset (depthTexture, smcoord, ivec2 (0, 1));
res += textureProjOffset (depthTexture, smcoord, ivec2 (1, 1));
return (res / 9.0);
}
// коэффициент затенения
float shadow = PCF (Vert.smcoord);
3.3 Пересчет кадра 3d-приложения
В связи с тем, что мы используем не статический, а динамический источник света а также динамическую камеру наблюдения и объекты, необходимо заново рассчитывать основные параметры для камеры, источника света и объектов. Алгоритм пересчета всех этих параметров представлен на рисунке 3.5. Блок 1 и 2 отвечают за изменение параметров объектов и их реализация выглядит:
// зададим углы поворота куба с учетом времени
if ((torusRotation[0] += 30.0f * (float) deltaTime) > 360.0f)
torusRotation[0] -= 360.0f;
if ((torusRotation[1] += 15.0f * (float) deltaTime) > 360.0f)
torusRotation[1] -= 360.0f;
if ((torusRotation[2] += 7.0f * (float) deltaTime) > 360.0f)
torusRotation[2] -= 360.0f;
// зададим матрицу вращения куба
meshes[1].rotation = GLFromEuler (torusRotation[0],
torusRotation[1],
torusRotation[2]);
meshes[2].rotation =GLFromEuler (-torusRotation[0],
torusRotation[1],
- torusRotation[2]);
Рисунок 3.5. Алгоритм пересчета кадра 3D-приложения
Блок 3 и 4 отвечают за изменение параметров наблюдателя и их реализация выглядит:
// вращаем камеру
CameraRotate (mainCamera, (float) deltaTime * rotateDelta[1], (float) deltaTime * rotateDelta[0], 0.0f);
// двигаем камеру
CameraMove (mainCamera, (float) deltaTime * moveDelta[0]*5, 0.0f, (float) deltaTime * moveDelta[1]*5);
rotateDelta[0] = rotateDelta[1] = 0;
moveDelta[0] = moveDelta[1] = 0;
Блок 5 и 6 отвечают за изменение источника света и их реализация выглядит:
// движение источника света
decLightPos = false;
if (directionalLight.position[0] < -50)
if (directionalLight.position[0] > 50)
decLightPos = true;
if (decLightPos)
directionalLight.position += vec3 (-deltaTime*2, 0, 0);
else
directionalLight.position += vec3 (deltaTime*2, 0, 0);
CameraLookAt (lightCamera, directionalLight.position, vec3 (0,0,0), vec3_y);
meshes[4].position = directionalLight.position;
meshes[4].position += vec3 (2,2,2);
4. Тестирование реализации 3d приложения
Тестирование реализации 3D приложения будем производить на разных настройках карт теней. Изменять будем проекционную матрицу. Как известно из предыдущих разделов проекционная матрица задается функцией OrthoProjection (float left, float right, float bottom, float top, float zNear, float zFar).
Будем пропорционально увеличивать left, right, bottom, top для тестов 1-3, а для тестов 4 и 5 ZNear соотвествестно.
Тест 1
Значение параметров
left = -10.0f, right = 10.0f,
bottom = -10.0f, top = 10.0f,
zNear = 0.0f, zFar = 100.0
Рисунок 4.1 Результат теста 1
Тест 2
Значение параметров
left = -50.0f, right = 50.0f,
bottom = -50.0f, top = 50.0f,
zNear = 0.0f, zFar = 100.0
Рисунок 4.2 Результат теста 2
Тест 3
Значение параметров
left = -100.0f, right = 100.0f,
bottom = -100.0f, top = 100.0f,
zNear = 0.0f, zFar = 100.0
Рисунок 4.3 Результат теста 3
Тест 4
Значение параметров
left = -10.0f, right = 10.0f,
bottom = -10.0f, top = 10.0f,
zNear = 20.0f, zFar = 100.0
Результат теста 4 при параметрах -10.0f, 10.0f, -10.0f, 10.0f, 20.0f, 100.0f
Рисунок 4.4 Результат теста 4
Тест 5
Значение параметров
left = -10.0f, right = 10.0f,
bottom = -10.0f, top = 10.0f,
zNear = 60.0f, zFar = 100.0
Результат теста 5 при параметрах -10.0f, 10.0f, -10.0f, 10.0f, 60.0f, 100.0f
Рисунок 4.5 Результат теста 5
Исходя из тестов можно сделать следующие выводы:
1. При увеличении параметры left, right, bottom, top происходит уменьше-ние доли занимаемой сцены в карте теней.
2. Уменьшение доли занимаемой сцены в карте теней ведет к ухудшению качества тени
3. Увеличение параметра zNear при неизменном zFar и left, right, bottom, top ведет к увеличению четкости карты теней и следовательно качеству теней в итоговом изображении.
5. Технико-экономическое обоснование
5.1 Концепция экономического обоснования
Целью технико-экономического обоснования дипломной работы является разработка плана организации исследований выполняемых работ, обобщение организационно-экономических показателей и получение оценок эффективности проекта. Индустрия компьютерных игр, графические редакторы для дизайнеров и специалистов в области мультимедиа, навигационные программы и визуализация ландшафта местности, применяемая для разведки и освоения полезных ископаемых - все эти области требуют всё больших затрат оперативной памяти и ресурсов процессора для всё более качественных эффектов и детальной прорисовки моделируемых объектов в режиме реального времени. В свою очередь, рынок и научно-технический прогресс не стоит на месте, предлагая всё новые технологии и эффекты. В данном случае речь пойдёт о динамичес-ком освещении, ему и посвящена данная работа.
Для технико-экономического обоснования НИР выделены сле-дующие этапы:
- определение трудоемкости проводимых в ходе дипломного проектирования работ и составление календарного плана выпол-нения работ;
- составление сметы затрат на проведение работ;
- оценка эффективности дипломной работы.
В конце технико-экономического обоснования будут сделаны выводы о научно-технических результатах данной дипломной Ра-боты.
5.2 Трудоемкость и календарный план выполнения работы
Все необходимые действия по выполнению данной НИР производились в составе научного сотрудника и инженера-программиста на кафедре МОЭВМ.
5.3 Смета затрат на проведение работ
Калькуляция себестоимости разработки осуществляется по следующим статьям:
- материалы;
- расходы на оплату труда;
- отчисления на социальные нужды;
- накладныерасходы;
- прочие прямые расходы.
Затраты на израсходованные материалы приведены в таблице 5.3.1.
Таблица 5.3.1 Затраты на материалы
Материал |
Количество, шт. |
Стоимость единицы, руб. |
Стоимость, руб. |
|
Ч/б картридж для принтера |
1 |
1800 |
1800 |
|
Бумага размера A4 для принтера, пачка |
1 |
150 |
150 |
|
Комплектканцелярских принадлежностей |
1 |
- |
60 |
|
USBflash-накопительемкостью на 2 Гб |
1 |
1 |
299 |
|
Транспортные расходы |
7-10% от общих затрат на материалы |
- |
231 |
|
ИТОГО: |
2540 |
Основная и дополнительная заработные платы непосредст-венных исполнителей проекта рассчитываются на основании трудо-емкости выполнения работ научным сотрудником Тр и инженером-программистом Ти, ставок научного сотрудника Др и инженера-программиста Ди и величины процента дополнительной заработной платы (12%):
Тр = 13 чел.-дн.;
Ти = 52 чел.-дн.;
Др = 24000 руб./мес.;
Ди = 12000 руб./мес.
Основная заработная плата исполнителей Сзо рассчитывается по формуле:
(1)
где число 22 - норматив рабочих дней в месяце.
Сзо = (13 Ч 24000 + 52Ч12000) = 42 545 руб.
Дополнительная заработная плата - заработная плата за неотработанное время, как правило, это «отпускные». Дополнительная заработная плата исполнителей Сдоп. рассчитывается по формуле:
(2)
где число 0,12 - ставка дополнительной заработной платы.
Сдоп. = 42 545 Ч 0,12 = 5 105 руб.
Величина расходов на оплату труда составляет 47650 руб.
Рассчитаем величину отчислений во внебюджетные фонды. Она рассчитывается по формуле:
(3)
где Сзо - величина заработной платы; Hвф - суммарный процент отчислений во внебюджетные фонды составляет 26,2%.
Свф=42 545* 26,2/100 = 11 147 руб.
К прочим прямым расходам отнесем плату за Internet, приведенную для рабочего места на основе использованного Internet-трафика, а также абонентскую плату за телефон по данным кафедры, и сведем их к таблице 6.3.2.
Так как все работы по исследованию производились ни личном компьютере, то нет необходимости считать амортизационные отчисления для персональных компьютеров кафедры проведения исследовательских работ.
Таблица 6.3.2 Расходы, относящиеся к статье «Прочие прямые расходы»
Наименование |
Сумма, руб. |
|
Плата за Internet |
1100 |
|
Абонентская плата за телефон |
200 |
|
ИТОГО: |
1300 |
К накладным расходам мы отнесем затраты на управление и организацию выполнения работ.
Накладные расходы составляют 20% от оплаты труда и выплат во внебюджетные фонды:
(4)
где Сзо - величина заработной платы; Свф - величина отчислений во внебюджетные фонды.
Снр = (42 545+11 147) * 0,2 = 10 738 руб.
Рассчитаем общую себестоимость проекта, для чего все предыдущие вычисления сведем в одну таблицу 5.3.3.
Таблица 5.3.3 Смета затрат на проведение НИР
Наименование статьи расходов |
Сумма, руб. |
|
Материалы |
2 540 |
|
Расходы на оплату труда |
47650 |
|
Внебюджетные фонды |
11 147 |
|
Прочие прямые расходы |
1 300 |
|
Накладные расходы |
10 738 |
|
Итого: |
73375 |
5.4 Комплексная оценка эффективности внедрения программы
Разработанный программный продукт можно использовать в качестве обучающего материала на кафедре МОЭВМ в течении года, что принесет экономию средств в размере 32000 р.
Вышеуказанная сумма получилась после того, как было взято общее количество занятий в год и подсчитаны расходы на материалы (на бумагу и другие канцтовары).
Коэффициент эффективности (32000/73375= 0.415) или 43.6%. Таким образом, средства будут окуплены примерно через два года, или более точно (100/43.6=2. года).
Заключение
Разработана и реализована архитектура библиотеки классов, способная отрисовывать любые трехмерные сцены с использованием основных алгоритмов обработки. В библиотеке реализованы следующие алгоритмы 3D-графики: освещение объекта (равномерное, диффузное, бликовое), текстурирование, Shadow Mapping, вывод в квадрат любой текстуры, создание и управление навигацией камеры, загрузка и визуализация сложных 3D моделей, настройка материалов, загрузка, выгрузка и передача данных в шейдеры. Создано демонстрационное приложение с использованием этой библиотеки. Кроме того, данный набор библиотек может служить основой для разработки коммерческой системы моделирования, а само приложение может быть использовано в качестве учебного материала по дисциплине компьютерная графика.
Список использованных источников
Горнаков С.Г. DirectX 9: «Уроки программирования на С++». - СПб.: БХВ-Петербург, 2005. - 400 с.
Программирование игр на платформе XNA [Электронный ресурс]. - Режим доступа: http://www.xnadev.ru свободный.
Luna, Frank D. Introduction to 3D game programming with DirectX 9.0. - Wordware Publishing, Inc, 2003. - 421 p.
ixbt.com [Электронный ресурс]. - Режим доступа: http://www.ixbt.com свободный.
Blinn, James F. Simulation of Wrinkled Surfaces // Computer Graphics, Vol. 12 (3), pp. 286-292, SIGGRAPH-ACM (August 1978).
Dempski, Kelly and Viale, Emmanuel, Advanced Lighting and Materials with Shaders // Wordware Publishing Inc., 2005, 361 p.
Программирование игр [Электронный ресурс]. - Режим доступа: http://www.gamedev.ru свободный.
Nitschke B. Professional XNA Game Programming: For Xbox 360 and Windows - Wrox Press, 2007. - 504 p.
Krishnamurthy and Levoy, Fitting Smooth Surfaces to Dense Polygon Meshes // SIG-GRAPH 1996.
Guardado, Juan, NVIDIA, GPU Gems, 2004 by NVIDIA Corporation.
Pharr, Matt and Fernando, Randima, NVIDIA, GPU Gems 2: Programming Techniques for High-Performance Graphics and General-Purpose Computation, 2005, by Addison-Wesley Professional, 880 p.
Cook, Robert L., Shade trees // Proceedings of the 11th annual conference on Computer graphics and interactive techniques, p. 223-231, January 1984, SIGGRAPH-ACM.
Phong, Bui-Tuong, Illumination for computer generated images // Comm. ACM 18, 6 (June 1975) 311-317.
Blinn, James F., Models of Light Reflection for Computer Synthesized Pictures // Computer Graphics, Vol. 11, No. 2, July, 1977, 192-198.
Krishnamurthy and Levoy, Fitting Smooth Surfaces to Dense Polygon Meshes // SIG-GRAPH 1996
Cohen et al., Appearance-Preserving Simplification // SIGGRAPH 1998
Cignoni et al., A general method for recovering attribute values on simplifed meshes // IEEE Visualization 1998
Oliveira, Manuel M.; Bishop, Gary; McAllister, David, Relief texture mapping // International Conference on Computer Graphics and Interactive Techniques archive, proceedings of the 27th annual conference on Computer graphics and interactive techniques, Pages: 359 - 368, 2000.
Kaneko, T., et al., Detailed Shape Representation with Parallax Mapping // In Proceedings of ICAT 2001, pp. 205-208, 2001.
Crow, F., Shadow algorithms for computer graphics, // SIGGRAPH, vol. 11, 242-248, 1977.
Roth, Scott D., Ray Casting for Modeling Solids // Computer Graphics and Image Processing 18: 109-144, doi:10.1016/0146-664X(82) 90169, February 1982.
Jensen, Realistic Image Synthesis Using Photon Mapping // AK Peters, July 2001.
Williams, Lance; Casting curved shadows on curved surfaces // SIGGRAPH-ACM, Volume 12, Issue 3 (August 1978), pp: 270 - 274., 1978.
Spencer, Greg; Shirley Peter; Zimmerman, Kurt; Greenberg, Donald P.; Physically-based glare effects for digital images // SIGGRAPH: 325. doi:10.1145/218380.218466., 1995.
Debevec, Paul E. and Malik Jitendra, Recovering High Dynamic Range Radiance Maps from Photographs // SIGGRAPH, 1997.
Размещено на Allbest.ru
Подобные документы
Программирование приложения с использованием библиотеки OpenGL и функции для рисования геометрических объектов. Разработка процедуры визуализации трехмерной сцены и интерфейса пользователя. Логическая структура и функциональная декомпозиция проекта.
курсовая работа [1,1 M], добавлен 23.06.2011Функциональные возможности библиотеки OpenGL. Разработка процедуры визуализации трехмерной сцены, интерфейса пользователя и подсистемы управления событиями с целью создания приложения для построения динамического изображения 3D-модели объекта "Самолет".
курсовая работа [1,7 M], добавлен 28.06.2011Программирование с использованием библиотеки ОреnGl: возможности, работа с матрицами, синтаксист команд, освещение, спецификация материалов, создание эффекта тумана. Разработка визуализации трехмерной сцены. Информационное и программное обеспечение.
курсовая работа [39,2 K], добавлен 23.06.2011Этапы разработки и отладки приложения "Помощь почтальону". Составление сопроводительной документации. Выбор средств и методов программирования. Анализ проектных данных. Особенности создания базы данных, СУБД. Тестирование созданного программного продукта.
контрольная работа [2,5 M], добавлен 17.12.2014Создание, изучение и разработка приложение на Android. Среда разработки приложения DelphiXE5. Установка и настройка среды программирования. Этапы разработки приложения. Инструменты для упрощения конструирования графического интерфейса пользователя.
курсовая работа [1,6 M], добавлен 19.04.2017Общая характеристика и анализ требований к разрабатываемому приложению, функциональные особенности и сферы практического применения. Проектирование базы данных и выбор системы управления ею. Тестирование приложения и выбор языка программирования.
дипломная работа [791,8 K], добавлен 10.07.2017Автоматизация системы снятия показаний счетчиков энергии. Разработка базы данных и клиентского приложения для структур жилищно-коммунального хозяйства, занимающихся составлением квитанций. Описание предметной области. Тестирование клиентского приложения.
курсовая работа [953,3 K], добавлен 01.09.2016Разработка клиент-серверного приложения, позволяющего взаимодействовать друг с другом с использованием доступа к базам данных. Проектирование связи сервера с базой данных с помощью технологии ODBC. Разработка интерфейса программы, ее тестирование.
курсовая работа [352,0 K], добавлен 24.08.2016Современное состояние рынка мобильных приложений. Основные подходы к разработке мобильных приложений. Обоснование выбора целевой группы потребителей приложения. Этапы проектирования и разработки мобильного приложения для операционной системы Android.
курсовая работа [987,1 K], добавлен 27.06.2019Визуальная разработка приложений баз данных. Характеристика визуальных компонентов среды разработки Builder 6.0, используемых в данном приложении. Программная реализация приложения, разработка форм и вкладок. Тестирование приложения, листинг программы.
курсовая работа [3,1 M], добавлен 28.03.2011