Студопедия — Наложение текстуры
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Наложение текстуры






Текстурирование позволяет наложить изображение на многоугольник и вывести этот многоугольник с нало­женной на него текстурой, соответствующим образом преобразо­ванной. OpenGL поддерживает одно- и двумер­ные текстуры и различные способы нало­жения (применения) текстуры.

Для использования текстуры надо сначала разрешить одно- или двумерное текстуриро­вание при помощи ко­манд glEnable(GL_TEXTURE1D) или glEnable(GL_TEXTURE_2D).

Для задания двумерной текстуры служит процедура

glTexlmage2D(GLenum target, GLint level, GLint component,

GLsizei width, GLsizei height, GLint border, GLenum format,

GLenum type, const GLvoid *pixels).

Параметр target зарезервирован для будущего использования и в текущей версии OpenGL должен быть равен GL_TEXTURE_2D. Параметр level используется в том слу­чае, если задается несколько разрешений данной тек­стуры. При ровно одном разрешении он должен быть равным нулю.

Следующий параметр – component – целое число от 1 до 4, показывающее, какие из RGBA-компонент выбраны для использования. Значение 1 выбирает компоненту R, зна­чение 2 выбирает R и А компоненты, 3 соответствует R, G и В, а 4 соответствует компо­нентам RGBA.

Параметры width и height задают размеры текстуры, border задает размер границы (бор­тика), обычно равный нулю. Как параметр width, так и параметр height, должны иметь вид 2n + 2b, где n – целое число, a b – значение параметра border. Максимальный размер текстуры зависит от реализации OpenGL, но он не менее 64 на 64.

При текстурировании OpenGL поддерживает использование пирамидального фильтрования (mip-mappping). Для этого необходимо иметь текстуры всех промежуточ­ных размеров, являющихся степенями двух, вплоть до 1х1, и для каждого такого разре­шения вызвать glTexImage2D с соответствующими параметрами level, width, height и image. Кроме того, необходимо задать способ фильтрования, который будет применяться при выводе текстуры.

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

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

glTexParameteri(GL_TEXTURE_2D, GLenum p1, GLenum p2),

где параметр p1 показывает, задается ли фильтр для сжатия или для растяжения тек­стуры, принимая значение GL_TEXTURE_MIN_FLITER или GL_TEXTURE_MAG_FILTER.. Параметр p2 задает способ фильтрования.

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

glTexCoord{1 2 3 4}{s i f d}[v](TYPE coord,...).

Этот вызов задаёт значения индексов текстуры для последующей команды gIVertex.

Если размер грани больше, чем размер текстуры, то для циклического повторения тек­стуры служат команды

gITexParameteri(GL_TEXTURE_2D,GL_TEXTURE_S_WRAP, GL_REPEAT)

gITexParameteri(GL_TEXTURE_2D,GL_TEXTURE_T_WRAP, GL_REPEAT)

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

gIMatrixMode(GL_TEXTURE);

gIRotatef(...};

gIMatrixMode(GL_MODELV1EW);

При выводе текстуры OpenGL может использовать линейную интерполяцию (аффинное текстурирование) или же точно учитывать перспективное искажение. Для задания точ­ного текстурирования служит команда

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST).

Если качество не играет большой роли, а нужна высокая скорость рендеринга, то в ка­честве последнего аргу­мента следует использовать константу GL_FASTEST.

Описанный выше способ работ с текстурами используется в OpenGL версии 1.0. В бо­лее новых версиях OpenGL, начиная с версии 1.1, введены дополнительные функции, по­вышающие удобство работы с текстурами. В OpenGL 1.0 процедуру glTexImage2D необ­ходимо вызывать всякий раз, когда нужно сменить текущую тек­стуру. Это достаточно медленный способ. В OpenGL 1.1 имеется возможность присваивать имена текстурам и за­тем сменять текущую текстуру только указанием имени новой текстуры, без повторной её загрузки в память про­цедурой glTexImage2D.

Имя текстуры представляет собой уникальное значение типа GLuint. Перед использова­нием текстуры необхо­димо присвоить ей имя. Имена текстур можно сгенерировать при помощи процедуры

glGenTextures(GLsizei n, GLuint *textures).

Параметр n определяет количество текстур, для которых необходимо сгенерировать имена. Параметр textures является указателем на массив переменных типа GLuint, со­стоящим из n элементов. После вызова процедуры ка­ждый элемент массива будет со­держать уникальное имя текстуры, которое затем может быть использовано при работе с текстурами.

Для выбора текущей (активной) текстуры используется функция

glBindTexture(GLenum target, GLuint texture).

Параметр target определяет тип текстуры (одномерная – GL_TEXTURE_1D или двумерная – GL_TEXTURE_2D). На практике более часто используются двумерные тек­стуры, которые представляют собой обычные двумерные изображения. Параметр texture определяет имя текстуры, которую необходимо сделать ак­тивной.

После того, как установлена активная текстура, можно вызвать процедуру glTexImage2D и задать параметры текстуры, а также сами её тексели. После вызова про­цедуры

glTexImage2D текстура готова к применению.

Для того чтобы наложить текстуру на объект или многоугольник достаточно установить активную текстуру (процедура glBindTexture) и определить текстурные координаты при помощи процедуры glTexCoord.

Достоинство использования функций OpenGL 1.1 для работы с текстурами заключается не только в более высо­ком быстродействии по сравнению с использованием процедуры glTexImage2D, но и в повышенном удобстве ра­боты с текстурами.

 

 

Вначале мы добавим две переменные для хранения угла вращения каждого объекта. Мы сделаем это вначале программы. Посмотрите ниже, я добавил две строки после объявления переменной BOOL keys[256]. В этих строках объявляются две переменные с плавающей запятой, которые мы можем использовать для очень точного поворота объектов. Числа с плавающей запятой учитывают значения меньше единицы. Вместо использования 1, 2, 3 для угла, мы можем использовать 1.1, 1.7, 2.3 или даже 1.015 для точности. Вы увидете, что числа с плавающей запятой неотемлимая часть программирования на OpenGL.

#include <windows.h> // Заголовочный файл для Windows
#include <gl\gl.h> // Заголовочный файл для OpenGL32 библиотеки
#include <gl\glu.h> // Заголовочный файл для GLu32 библиотеки
#include <gl\glaux.h> // Заголовочный файл для GLaux библиотеки

static HGLRC hRC; // Постоянный контекст рендеринга
static HDC hDC; // Приватный контекст устройства GDI

BOOL keys[256]; // Массив для процедуры обработки клавиатуры

GLfloat rtri; // Угол для треугольник
GLfloat rquad; // Угол для четырехугольника

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

GLvoid DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Очистка экрана
// и буфера глубины
glLoadIdentity(); // Сброс просмотра
glTranslatef(-1.5f,0.0f,-6.0f); // Сдвиг в глубь экрана и влево

Следующая строка новая. glRotatef(Angle,Xtrue,Ytrue,Ztrue) отвечает за вращения объекта вдоль оси. Вы многое получите от использования этой команды. Угол некоторое число (обычно переменная), которое задает насколько Вы хотите повернуть объект. Xtrue, Ytrue и Ztrue или 0.0f или 1.0f. Если один из параметров равен 1.0f, OpenGL будет вращать объект вдоль соответствующей оси. Поэтому если Вы имеете glRotatef(10.0f,0.0f,1.0f,0.0f), объект будет поварачиваться на 10 градусов по оси Y. Если glRotatef(5.0f,1.0f,0.0f,1.0f), объект будет поварачиваться на 5 градусов по обеим осям X и Z.

Чтобы лучше понять вращения по осям X, Y и Z я объясню это на примерах.

Ось X - предположим Вы работаете за токарным станком. Заготовка перемещается слева направо (также как ось X в OpenGL). Заготовка вращается вокруг оси X. Также мы вращаем что-то вокруг оси X в OpenGL.

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

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

В следующей строке кода, если rtri равно 7, мы будем вращать на 7 градусов по оси Y (слева направо). Вы можете поэксперементировать с кодом. Изменяйте от 0.0f до 1.0f, и от 1.0f до 0.0f вращение треугольника по осям X и Y одновременно.

glRotatef(rtri,0.0f,1.0f,0.0f); // Вращение треугольника по оси Y

Следующая секция кода не изменена. Здесь будет нарисован закрашенный сглаженный треугольник. Треугольник будет нарисован с левой стороны экрана, и будет вращаться по оси Y слева направо.

glBegin(GL_TRIANGLES); // Начало рисования треугольника
glColor3f(1.0f,0.0f,0.0f); // Верхняя точка - красная
glVertex3f(0.0f, 1.0f, 0.0f); // Первая точка
glColor3f(0.0f,1.0f,0.0f); // Левая точка - зеленная
glVertex3f(-1.0f,-1.0f, 0.0f); // Вторая
glColor3f(0.0f,0.0f,1.0f); // Правая - синия
glVertex3f(1.0f,-1.0f, 0.0f); // Третья
glEnd(); // Конец рисования

Посмотрите на код ниже, там мы добавим вызов glLoadIdentity(). Мы сделаем это для инициализации просмотра. Что будет если мы не сбросим просмотр? Если мы сдвинули объект после вращения, Вы получите очень неожиданные результаты. Поскольку оси вращаются, они будут указывать не в тех направлениях, о каких Вы думаете. Поэтому если мы сдвинулись влево по оси X (для установки треугольника), мы можем переместить квадрат в глубь экрана или вперед, в зависимости от того как много мы вращали по оси Y. Попробуйте убрать glLoadIdentity() и вы поймете о чем я говорю. Квадрат будет вращаться вокруг своей оси X, но и вокруг центра координат синхронно вращению треугольника.

Так как сцена сброшена, поэтому X идет слева направо, Y сверху вниз, Z от нас и далее. Теперь мы перемещаем. Как Вы видите мы сдвигаем на 1.5 вправо, вместо 3.0, как мы делали в последнем уроке. Когда мы сбрасываем экран, наш фокус перемещается в центр экрана, это означает, что мы находимся не 1.5 единицы слева, мы вернулись в 0.0. Поэтому мы не должны сдвигаться на 3.0 единицы вправо (если бы не было сброса), мы должны только сдвинуться от центра вправо на 1.5 единицы.

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

glLoadIdentity();
glTranslatef(1.5f,0.0f,-6.0f); // Сдвиг вправо на 1.5
glRotatef(rquad,1.0f,0.0f,0.0f); // Вращение по оси X

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

glColor3f(0.5f,0.5f,1.0f); // Синий цвет
glBegin(GL_QUADS); // Начнем
glVertex3f(-1.0f, 1.0f, 0.0f); // Верх лево
glVertex3f(1.0f, 1.0f, 0.0f); // Верх право
glVertex3f(1.0f,-1.0f, 0.0f); // Низ право
glVertex3f(-1.0f,-1.0f, 0.0f); // Низ лево
glEnd(); // Окончим

Следующие две строки новые. Думайте о rtri и rquad как о контейнерах. Вначале нашей программы мы сделали контейнеры (GLfloat rtri и GLfloat rquad). Когда мы построили контейнеры они были пусты. В первой строке ниже ДОБАВЛЯЕМ 0.2 в контейнер. Если мы проверим значение контейнера rtri после этой секции кода, мы увидим что оно увеличилось на 0.2. Контейнер rquad уменьшиться на 0.15. Если мы проверим значение контейнера rquad после этой секции кода, мы увидим что оно уменьшилось на 0.15. Отрицательные значения вращения приводят к тому, что объект вращается в противоположную сторону. Как если бы значения были положительные.

Попробуйте изменить + на - в строке ниже и объект будет вращаться в другом направлении. Попробуйте изменить значение с 0.2 до 1.0. С увеличением значения объект будет вращаться быстрее. С уменьшением значения будет вращаться медленее.

rtri+=0.2f; // Увеличение переменной вращения для треугольника
rquad-=0.15f; // Уменьшение переменной вращения для квадрата
}

 

glPushMatrix, glPopMatrix (…attrib)

glPushAttrib(GL_COLOR_BUFFER_BIT or GL_CURRENT_BIT or GL_LIGHTING_BIT or GL_TEXTURE_BIT); glPushAttrib() сохраняет все атрибуты, указанные битами в параметре mask, помещая их в стек атрибутов. glPopAttrib() восстанавливает значения тех переменных состояния, которые были сохранены командой glPushAttrib().

Функции glPushMatrix и glPopMatrix предназначены для помещения матриц в стек и извлечения из него.

void glPushMatrix( void ); void glPopMatrix( void );






Дата добавления: 2015-10-19; просмотров: 623. Нарушение авторских прав; Мы поможем в написании вашей работы!



Композиция из абстрактных геометрических фигур Данная композиция состоит из линий, штриховки, абстрактных геометрических форм...

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

ТЕОРЕТИЧЕСКАЯ МЕХАНИКА Статика является частью теоретической механики, изучающей условия, при ко­торых тело находится под действием заданной системы сил...

Теория усилителей. Схема Основная масса современных аналоговых и аналого-цифровых электронных устройств выполняется на специализированных микросхемах...

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

Билиодигестивные анастомозы Показания для наложения билиодигестивных анастомозов: 1. нарушения проходимости терминального отдела холедоха при доброкачественной патологии (стенозы и стриктуры холедоха) 2. опухоли большого дуоденального сосочка...

Сосудистый шов (ручной Карреля, механический шов). Операции при ранениях крупных сосудов 1912 г., Каррель – впервые предложил методику сосудистого шва. Сосудистый шов применяется для восстановления магистрального кровотока при лечении...

Обзор компонентов Multisim Компоненты – это основа любой схемы, это все элементы, из которых она состоит...

Кран машиниста усл. № 394 – назначение и устройство Кран машиниста условный номер 394 предназначен для управления тормозами поезда...

Приложение Г: Особенности заполнение справки формы ву-45   После выполнения полного опробования тормозов, а так же после сокращенного, если предварительно на станции было произведено полное опробование тормозов состава от стационарной установки с автоматической регистрацией параметров или без...

Studopedia.info - Студопедия - 2014-2024 год . (0.008 сек.) русская версия | украинская версия