Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2633

.pdf
Скачиваний:
6
Добавлен:
07.01.2021
Размер:
54.26 Mб
Скачать

Делее проделаем аналогичные операции с клавишей 'F':

if(keys['F'] && !fp)

// Клавиша 'F' нажата?

{

 

fp=TRUE;

// fp равно TRUE

filter+=1;

// значение filter увеличивается на один

if(filter>2)

// Значение больше чем 2?

filter=0;

// Если так, то установим filter в 0

}

 

}

 

if (!keys['F'])

// Клавиша 'F' отжата?

{

 

fp=FALSE;

// Если так, то fp равно FALSE

}

Если клавиша нажата, и она не удерживается, или она не была нажата до этого, тогда присваивается значение переменной fp равное истине, что значит клавиша 'F' нажата и удерживается. При этом увеличится значение переменной filter. Если filter больше чем 2 (т.е. texture[3], которой не существует), значение переменной texture сбрасывается назад в ноль.

Если так, то происходит уменьшение значения переменной z. Если эта переменная уменьшается, куб будет двигаться вглубь экрана, поскольку используется glTranslatef (0.0f, 0.0f, z) в процедуре

DrawGLScene.

В следующих четырех строках проверяется, нажата ли клавиша

'Page up':

 

if (keys[VK_PRIOR])

// Клавиша 'Page Up' нажата?

{

 

z-=0.02f;

// Если так, то сдвинем вглубь экрана

}

 

Далее проверяется, нажата ли клавиша 'Page down': if (keys[VK_NEXT]) // Клавиша 'Page Down' нажата?

{

z+=0.02f;

}

Если так, то увеличивается значение переменной z и куб смещается к наблюдателю, поскольку используется glTranslatef (0.0f, 0.0f, z) в процедуре DrawGLScene.

Далее проверяются клавиши курсора:

if (keys[VK_UP])

// Клавиша стрелка вверх нажата?

{

 

xspeed-=0.01f;

// Если так, то уменьшение xspeed

}

 

83

if (keys[VK_DOWN])

// Клавиша стрелка вниз нажата?

{

 

xspeed+=0.01f;

// Если так, то увеличение xspeed

}

 

if(keys[VK_RIGHT])

// Клавиша стрелка вправо нажата?

{

 

yspeed+=0.01f;

// Если так, то увеличение yspeed

}

 

if (keys[VK_LEFT])

// Клавиша стрелка влево нажата?

{

 

yspeed-=0.01f;

// Если так, то уменьшение yspeed

}

 

if(keys[VK_F1])

// Клавиша 'F1' нажата?

{

 

keys[VK_F1]=FALSE;

// Если так, то создание Key FALSE

KillGLWindow();

// Уничтожение текущего окна

fullscreen=!fullscreen;

// Переключение между режимами

Полноэкранный/Оконный

 

// Повторное создание нашего окна OpenGL

if (!CreateGLWindow("Урок NeHe Текстуры, Свет & Обработка

Клавиатуры",640,480,16,fullscreen))

{

 

return 0; // Выход, если окно не создано

}

 

}

 

}

 

}

 

}

 

// Сброс

 

KillGLWindow();

// Уничтожение окна

return (msg.wParam);

// Выход из программы

}

 

При нажатии клавиш влево или вправо – xspeed увеличивается или

уменьшается, при вверх или вниз – yspeed увеличивается или уменьшается. Чем дольше удерживается одна из клавиш курсора, тем, быстрее куб вращается в соответствующем направлении.

Здесь появляется новая функция KillGLWindow, которая корректно уничтожает окно и все что с ним связано. Код KillGLWindow, который необходимо разместить сразу за функцией InitGL:

GLvoid KillGLWindow(GLvoid)

// Правильное уничтожение окна

{

 

if (fullscreen)

// Полноэкранный режим?

84

{

ChangeDisplaySettings(NULL,0); // Переход в режим разрешения

рабочего стола

 

 

ShowCursor(TRUE);

// Показать указатель мыши

}

 

 

if (hRC)

// Существует контекст рендеринга?

{

 

 

if (!wglMakeCurrent(NULL,NULL))

// Можно ли освободить DC

и RC контексты?

 

 

{

MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

}

 

if (!wglDeleteContext(hRC))

// Можно ли уничтожить RC?

{

 

MessageBox(NULL,"Release Rendering Context Failed.",

"SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

}

 

 

hRC=NULL;

// Установление RC в NULL

}

 

 

if (hDC && !ReleaseDC(hWnd,hDC))

// Можно ли уничтожить

DC?

 

 

{

 

 

MessageBox(NULL,"Release Device Context ailed.","SHUTDOWN

ERROR",

 

 

MB_OK | MB_ICONINFORMATION);

 

hDC=NULL;

// Установление DC в NULL

}

 

 

if (hWnd && !DestroyWindow(hWnd))

// Можно ли

уничтожить окно?

 

 

{

 

 

MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN

ERROR",MB_OK |MB_ICONINFORMATION);

hWnd=NULL;

// Установление hWnd в NULL

}

 

 

if (!UnregisterClass("OpenGL",hInstance))

{

MessageBox(NULL,"Could Not Unregister Class.",

"SHUTDOWN ERROR",MB_OK |MB_ICONINFORMATION);

hInstance=NULL;

// Устанавление hInstance в NULL

}

 

}

 

85

В данном примере реализовано создание и оперирование объектами из четырехугольников с высококачественным, реалистичным наложением текстур, а также, преимущества каждого из трех фильтров

(рис.10-11).

Рис. 10. Наложение реалистичной текстуры

Рис. 11. Вращение куба с текстурой

Контрольные вопросы

1.Каково назначение переменной filter?

2.В чем сущность типа текстуры GL_NEAREST?

3.Что такое мип-наложение текстур в OpenGL?

86

4. Каким образом происходит освобождения памяти изображения текстуры?

2.9.Эффект смешивание цветов смежных пикселей

Впроекте рассмотрим эффект смешивания или, иначе комбинирование цвета данного пикселя, который должен быть выведен

спикселем, уже находящемся на экране.

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

#include <windows.h>

 

//Заголовочный файл для Windows

#include <stdio.h>

 

// Заголовочный файл для стандартного

ввода/вывода

 

 

#include <gl\gl.h>

 

// Заголовочный файл для библиотеки

OpenGL32

 

 

#include <gl\glu.h>

 

// Заголовочный файл для для

библиотеки GLu32

 

 

#include <gl\glaux.h>

 

// Заголовочный файл для библиотеки

GLaux

 

 

HDC hDC=NULL;

// Приватный контекст устройства GDI

HGLRC hRC=NULL; // Постоянный контекст рендеринга

HWND hWnd=NULL;// Содержит дискриптор нашего окна

HINSTANCE hInstance;

// Содержит экземпляр приложения

Bool keys[256];

// Массив для процедуры обработки

клавиатуры

 

 

bool active=TRUE;

// Флаг активности окна, по умолчанию

TRUE

 

 

bool fullscreen=TRUE; // Флаг полноэкранного режима, по

умолчанию полный экран

 

boolblend;

// Смешивание НЕТ/ДА? (НОВОЕ)

boollight;

// Освещение Вкл./Выкл.

boollp;

// L Нажата?

boolfp;

// F Нажата?

boolbp;

// B Нажата? ( Новое )

GLfloatxrot;

// Вращение вдоль оси X

GLfloatyrot;

// Вращение вдоль оси Y

GLfloat xspeed;

// Скорость вращения вдоль оси X

GLfloat yspeed;

// Скорость вращения вдоль оси X

GLfloatz=-5.0f;

// Глубина в экран.

// Задаем параметры освещения

87

GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };

GLfloat LightDiffuse[]={ 1.0f, 1.0f, 1.0f, 1.0f };

GLfloat LightPosition[]={ 0.0f, 0.0f, 2.0f, 1.0f };

GLuint filter;

// Используемый фильтр для текстур

GLuint texture[3];

// Хранит 3 текстуры

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Объявление для WndProc

Далее изменяется LoadGLTextures().

Строка texture1=auxDIBImageLoad ("Data/create.bmp"), изменяется на строку ниже. Используется текстура окрашенного стекла вместо текстуры куба:

// Загрузка текстуры стекла (МОДИФИЦИРОВАННО) texture1 = auxDIBImageLoad("Data/glass.bmp");

Далее дополняется InitGL(). Первая строка задает яркость для отрисовки объекта, равную полной яркости с альфой 50 % (непрозрачность). Это означает, когда включается смешивание, объект будет на 50% прозрачный. Вторая строка задает тип смешивания:

glColor4f(1.0f,1.0f,1.0f,0.5f);

// Полная яркость, 50% альфа

(НОВОЕ)

 

 

glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Функция

смешивания для непрозрачности, базирующаяся на значении

альфы(Новая строка)

 

 

Далее, в самом конце кода:

 

 

if (keys[VK_LEFT])

// Нажата левая стрелка?

{

 

 

yspeed-=0.01f;

// уменьшаем скорость

}

 

 

Под вышеупомянутым

кодом добавляются строки ниже.

Отслеживается нажатие ‘B’. Если было нажатие, компьютер проверит, включено ли смешивание. Если смешивание задано, компьютер выключает его. И наоборот, если смешивание выключено, включает его:

if (keys['B'] && !bp)

 

{

 

bp=TRUE;

 

blend = !blend;

// Инвертируем blend

if(blend) // blend TRUE?

 

{

 

glEnable(GL_BLEND);

// Включаем смешивание

glDisable(GL_DEPTH_TEST); // Выключаем тест глубины

}

else

{

88

glDisable(GL_BLEND);

// Выключаем смешивание

glEnable(GL_DEPTH_TEST);

// Включаем тест глубины

}

 

}

 

if (!keys['B'])

// ’B’ отжата?

{

 

bp=FALSE;

// Тогда bp возвращает ложь

}

В результате работы программы получен эффект смешивания в цветов смежных пикселей (рис 12,13).

Рис. 12. Наложение текстуры с эффектом смешивания

89

Рис. 13. Текстурированный куб, который имеет 100% прозрачность

Контрольные вопросы

1.Какая функция задает значение параметра прозрачности

альфа?

2.Каково назначение функции glBlendFunc(GL_SRC_ALPHA,GL_ONE)?

3.Какие параметры имеет функция glColor4f() и за что отвечает каждый параметр?

4.В чем отличие функций glColor4f() и glColor3f()?

2.10. Передвижение изображений в 3D

Цель проекта – реализация перемещения изображений (bitmap) по экрану в 3D, удаляя, черные пиксели (pixels) из изображения (используя смешивание), дополнение цветности в черно-белые текстуры и создание простой анимации путём смешивания различных цветных текстур вместе.

Данный пример так же основывается на коде первого проекта инициализации окна. Для начала необходимо описать новые переменные в начале программы:

#include <windows.h>

// Заголовочный файл для Windows

#include <stdio.h>

// Заголовочный файл для стандартного

ввода/вывода

 

#include <gl\gl.h>

// Заголовочный файл для библиотеки

OpenGL32

 

#include <gl\glu.h>

// Заголовочный файл для для

библиотеки GLu32

 

#include <gl\glaux.h>

// Заголовочный файл для библиотеки

GLaux

 

HDC hDC=NULL;

// Служебный контекст GDI устройства

HGLRChRC=NULL;

// Постоянный контекст для

визуализации

 

HWNDhWnd=NULL;

// Содержит дескриптор для окна

HINSTANCEhInstance;

// Содержит данные для нашей

программы

 

boolkeys[256];

// Массив, использующийся для

сохранения состояния клавиатуры

boolactive=TRUE;

// Флаг состояния активности

приложения (по умолчанию: TRUE)

90

boolfullscreen=TRUE; // Флаг полноэкранного режима (по умолчанию: полноэкранное)

Логические переменные twinkle и tp могут принимать значения TRUE (истина) или FALSE (ложь). Twinkle будет говорить о включении/выключении эффекта twinkle. Tp используется для определения состояния клавиши 'T' (была ли нажата или нет). Если нажата, то tp=TRUE, иначе tp=FALSE:

BOOLtwinkle;

// Twinkling Stars (Вращающиеся звезды)

BOOLtp;

// 'T' клавиша нажата?

Переменная num хранит информацию о количестве звезд, которые рисуются на экране. Она определена как константа. Это значит, в коде программы её значение неизменно. Причина, по которой она определяется как константа, в том, что невозможно переопределить (увеличить/уменьшить) массив:

constnum=50; // Количество рисуемых звезд

На данном этапе создается структура (structure) – совокупность простых данных (переменных, и т.д.) сгруппированных по какому-либо признаку в одну группу. В программе необходимо хранить цепочку

звезд:

 

typedef struct

// Создание структуры для звезд

{

 

int r, g, b;

// Цвет звезды

GLfloat dist;

// Расстояние от центра

GLfloat angle;

// Текущий угол звезды

}

 

stars;

// Имя структуры – Stars

stars star[num];

// Создание массива 'star' длинной 'num', где

элементом является структура 'stars'

Известно, что каждая звезда имеет 3 значения для цвета, и все эти значения целые числа: 3-я строчка: int r,g,b задаёт эти значения. Одно для красного (red) (r), одно для зелёного (green) (g), и одно для голубого (blue) (b). Необходимо, чтобы каждая звезда имела разное расстояние от центра экрана, и была расположена на одном из 360 углов от центра. Для этого создаётся переменная типа число с плавающей точкой (floating point value), которая называется dist. Она означает расстояние. 5-ая строчка создаёт переменную того же типа с именем angle. Она будет отвечать за угол звезды.

Далее задается переменная для хранения расстояния от наблюдателя до звезд (zoom), и какой будет начальный угол(tilt):

GLfloatzoom=-15.0f;

// Расстояние от наблюдателя до звезд

GLfloat tilt=90.0f;

// Начальный угол

GLfloatspin;

// Для вращения звезд

91

GLuintloop;

// Используется для цикло

GLuinttexture[1];

// Массив для одной текстуры

LRESULTCALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); // Объявления для WndProc

Также создается переменная spin, которая будет вращать звезды по оси z, и это будет выглядеть как вращение вокруг их текущей позиции.

Loop – это переменная, которая используется в программе для обрисовки всех 50-ти звезд, и texture[1] будет использоваться для хранения одной черно-белой текстуры, которая загружается. Если необходимо использовать больше текстур, можно увеличить длину массива, с одного до нужной длины.

Сразу же за переменными необходимо добавить код для загрузки текстур. Можно использовать тот же код что был в предыдущих проектах. Изображение, которое будет использоваться в данном примере называется star.bmp. Производится генерация только одной текстуры, используя glGenTextures(1, &texture[0]). Текстура будет иметь линейную фильтрацию (linear filtering):

AUX_RGBImageRec *LoadBMP(char *Filename) // Функция для

загрузки bmp файлов

 

{

 

FILE *File=NULL;

// Переменная для файла

if (!Filename)

// Проверка правильности переданного

имени

 

{

 

return NULL;

// Если неправильное имя, то возвращение

NULL

 

}

 

File=fopen(Filename,"r"); // Открытие и проверка на наличие

файла

 

if (File)

// Файл существует?

{

 

fclose(File);

// Если да, то закрытие файла, загрузка

его с помощью библиотеки AUX, возвращая ссылку на изображение return auxDIBImageLoad(Filename);

}

// Если загрузить не удалось или файл не найден, то возврат NULL return NULL;

}

Эта часть кода загружает изображение (описанным выше кодом) и

конвертирует в текстуру:

 

int LoadGLTextures()

// Функция загрузки изображения и

конвертирования в текстуру

 

92

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]