Metodichka по компьютерной графике. Е. А. Снижко, Н. А. Флерова, А. В. Воронцов программирование компьютерной графики с использованием
Скачать 1.31 Mb.
|
Использование текстуры. Этот этап выполняется непосредственно в функции прорисовки сцены. 1) Выбор текстуры для использования (вторичное связывание) Для использования текстуры в программе ее надо сделать активной этот процесс и называется вторичным связыванием. Вторичное связывание, как и первичное, выполняется с помощью функции void glBindTexture (GLenum target, GLuint textureName); target определяет тип текстуры (GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D). Этот параметр должен совпадать с тем, который был при операции первичного связывания. textureNameидентификатор текстуры. Пример вторичного связывания – делает активной текстуру с идентификаторм SingleTex. glBindTexture(GL_TEXTURE_2D, SingleTex); 2) Согласование геометрических и текстурных координат При прорисовке объекта, на который накладывается текстура, необходимо согласовать текстурные координаты с геометрическими. Например при наложении текстуры на 42 прямоугольный объект вы должны отобразить правый верхний угол текстуры в правый верхний угол объекта, правый нижний угол текстуры в правый нижний угол объекта и т.д. Текстурные координаты являются частью данных, связанных с вершинами многоугольника. Для установки текстурных координат используется функция glTexCoord2f(GLfloat s, GLLfloat t); s - определяет горизонтальную текстурную координату t - определяет вертикальнуютекстурную координату Система текстурных координат имеет следующий вид: Пример наложения текстуры с растяжением на прямоугольный объект. glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-1.,-1., 0.); //левый нижний угол glTexCoord2f(1.0, 0.0); glVertex3f( 5.,-1., 0.); //правый нижний угол glTexCoord2f(1.0, 1.0); glVertex3f( 5., 3., 0.); //правый верхний угол glTexCoord2f(0.0, 1.0); glVertex3f(-1., 3., 0.); //левый верхний угол glEnd(); Пример наложения текстуры на треугольник. В данном примере используется только левая нижняя часть текстуры 3.0 5.0 -1.0 -1.0 y x z Вид объекта после наложения текстуры Координаты прямоугольного объекта s t 0.0 0.0 1.0 1.0 0.5 0.5 Вид объекта после наложения текстуры 43 glBegin( GL_TRIANGLES ); glTexCoord2f(0.0, 0.0); glVertex3f(-2.,-1., 0.); //левая нижняя вершина glTexCoord2f(0.5, 0.0); glVertex3f( 2.,-1., 0.); //правая нижняя вершина glTexCoord2f(0.25, 0.5); glVertex3f( 0., 3., 0.); //верхняя вершина glEnd(); Пример мозаичного(тайлового) покрытия текстурой Координаты прямоугольника совпадают с координатами прямоугольника в первом примере. Текстура будет повторена по горизонтальной оси 3 раза, по вертикальной – 2 раза. Для возможности повторения текстуры этот режим должен быть активирован с помощью команд GlTexParametri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GlTexParametri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-1.,-1., 0.); //левый нижний угол glTexCoord2f(3.0, 0.0); glVertex3f( 5.,-1., 0.); //правый нижний угол glTexCoord2f(3.0, 2.0); glVertex3f( 5., 3., 0.); //правый верхний угол glTexCoord2f(0.0, 2.0); glVertex3f(-1., 3., 0.); //левый верхний угол glEnd(); Пример создания с помощь текстур эффекта отражения. Необходимо разрешить OpenGL использовать автоматически сгенерированные координаты. Параметры, с помощью которых эти координаты будут генерироваться, хранятся в текстурном объекте, созданном на втором этапе (см. пункт 2.7). // 1 - разрешаем автогенерацию текстурных координат по оси S // 2 - разрешаем автогенерацию текстурных координат по оси T y x z 2.0 -2.0 -1.0 3.0 3.0 5.0 -1.0 -1.0 y x z Вид объекта после наложения текстуры 44 glEnable(GL_TEXTURE_GEN_S); // 1 glEnable(GL_TEXTURE_GEN_T); // 2 glBegin(GL_QUADS); glVertex3f(-1.,-1., 0.); //левый нижний угол glVertex3f( 5.,-1., 0.); //правый нижний угол glVertex3f( 5., 3., 0.); //правый верхний угол glVertex3f(-1., 3., 0.); //левый верхний угол glEnd(); // 3 - запрещаем автогенерацию текстурных координат по оси S // 4 - запрещаем автогенерацию текстурных координат по оси T glEnable(GL_TEXTURE_GEN_S); // 3 glEnable(GL_TEXTURE_GEN_T); // 4 Задания к лабораторной работе и порядок выполнения. 1. Подготовьте изображение к использованию в качестве текстуры. В качестве изображения выбирается любое изображение, имеющееся на компьютере. При отсутствии таковых изображение создается в графическом редакторе. 2. Создайте текстурный объект. 3. Настройте параметры текстурных объектов, в соответствии с вариантом. Номер_варианта_Вид_объекта_Номер_варианта_Вид_объекта'>Номер_варианта_Увеличивающий_фильтр_Уменьшающий_фильтр_Взаимодействие_с_поверхностью'>Номер варианта Увеличивающий фильтр Уменьшающий фильтр Взаимодействие с поверхностью 1 линейная фильтрация без сглаживания смешивание 2 без сглаживания линейная фильтрация без смешивания 3 мип - мап наложение без сглаживания без смешивания 4 линейная фильтрация линейная фильтрация смешивание 5 мип - мап наложение линейная фильтрация без смешивания 4. Изобразите объект в соответствии с вариантом Номер варианта Вид объекта Номер варианта Вид объекта 1 4 2 5 3 5. Наложите текстуры на созданный геометрический объект. 45 6. Реализуйте изменение параметров текстуры при нажатии клавиш в соответствии с вариантом. Номер варианта Вносимые изменение 1 Установка уменьшающего фильтра в режим линейной фильтрации Вращение объекта вокруг оси Х 2 Разрешение тайлового покрытия текстурой. Изменения количества повторения текстуры Вращение объекта вокруг оси Z. 3 Изменение режима взаимодействия с поверхностью в режим смешивания Вращение текстуры вокруг оси Y. 4 Установка увеличающего и уменьшающего фильтра. Вращение текстуры вокруг оси Z. 5 Создание эффекта зеркального отражения Вращение текстуры вокруг осей X, Y. Контрольные вопросы. 1. Что понимается под термином «текстура»? 2. Каков смысл использования текстур при визуализации? Какому уровню визуализации соответствует текстурирование? 3. Что такое «тексель»? 4. Что представляют собой текстурные координаты? 5. Какие действия необходимо выполнить для наложения текстуры на объект? 6. Какие режимы фильтрации используются при наложении текстур? 7. В чем заключается первичное связывание? 8. Каким образом осуществляется связывание изображения с текстурой? 9. Каким образом при помощи текстур может быть достигнут эффект отражения? 10. Почему необходимо согласование геометрических и текстурных координат? Как это достигается? 46 ПРИЛОЖЕНИЯ. Приложение 1. Минимальный код программы OpenGL на C++. #include // Заголовочный файл для Windows #include // Заголовочный файл для OpenGL32 библиотеки #include // Заголовочный файл для GLu32 библиотеки #include // Заголовочный файл для GLaux библиотеки static HGLRC hRC; // Постоянный контекст рендеринга static HDC hDC; // Приватный контекст устройства GDI BOOL keys[256]; // Массив для процедуры обработки клавиатуры GLvoid InitGL(GLsizei Width, GLsizei Height) // Вызвать после создания // окна GL { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Очистка экрана в черный цвет } GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height) { if (Height==0) // Предотвращение деления на ноль, //если окно слишком мало Height=1; glViewport(0, 0, Width, Height); // Сброс текущей области вывода } GLvoid DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT); // Очистка экрана // Здесь создается рисунок glPointSize(2); glBegin(GL_POINTS); glColor3f(1,0,0); glVertex2f(-0.45,-0.4); // первая точка glColor3f(0,1,0); glVertex2f(0.4,0.4); // вторая точка glColor3f(0,0,1); //третья точка glVertex2f(-0.35,0.4); glEnd(); glLineWidth(3); glBegin(GL_LINE_STRIP); // ломаная линия glColor3f(0.7,0.3,0); glVertex2f(-0.10,0); glVertex2f(1,0.13); glColor3f(0,1,0); glVertex2f(-0.15,0.33); glColor3f(0,0,1); glVertex2f(-0.12,0.35); glEnd(); // здесь закончилось создание рисунка } LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT Screen; // используется позднее для размеров окна GLuint PixelFormat; 47 static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), // Размер этой структуры 1, // Номер версии (?) PFD_DRAW_TO_WINDOW | // Формат для Окна PFD_SUPPORT_OPENGL | // Формат для OpenGL PFD_DOUBLEBUFFER, // Формат для двойного буфера PFD_TYPE_RGBA, // Требуется RGBA формат 16, // Выбор 16 бит глубины цвета 0, 0, 0, 0, 0, 0, // Игнорирование цветовых битов (?) 0, // нет буфера прозрачности 0, // Сдвиговый бит игнорируется (?) 0, // Нет буфера аккумуляции 0, 0, 0, 0, // Биты аккумуляции игнорируются (?) 16, // 16 битный Z-буфер (буфер глубины) 0, // Нет буфера траффарета 0, // Нет вспомогательных буферов (?) PFD_MAIN_PLANE, // Главный слой рисования 0, // Резерв (?) 0, 0, 0 // Маски слоя игнорируются (?) }; switch (message) // Тип сообщения { case WM_CREATE: hDC = GetDC(hWnd); // Получить контекст устройства для окна PixelFormat = ChoosePixelFormat(hDC, &pfd); // Найти ближайшее совпадение для нашего формата пикселов if (!PixelFormat) { MessageBox(0,"Can't Find A SuitablePixelFormat.","Error",MB_OK|MB_ICONERROR); PostQuitMessage(0); // Это сообщение говорит, что программа должна завершиться break; // Предтовращение повтора кода } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) { MessageBox(0,"Can't Set ThePixelFormat.","Error",MB_OK|MB_ICONERROR); PostQuitMessage(0); break; } hRC = wglCreateContext(hDC); if(!hRC) { MessageBox(0, "Can't Create A GLRenderingContext.", "Error",MB_OK|MB_ICONERROR); PostQuitMessage(0); break; } if(!wglMakeCurrent(hDC, hRC)) { MessageBox(0,"Can't activate GLRC.","Error",MB_OK|MB_ICONERROR); PostQuitMessage(0); break; } GetClientRect(hWnd, &Screen); InitGL(Screen.right, Screen.bottom); break; case WM_DESTROY: case WM_CLOSE: ChangeDisplaySettings(NULL, 0); 48 wglMakeCurrent(hDC,NULL); wglDeleteContext(hRC); ReleaseDC(hWnd,hDC); PostQuitMessage(0); break; case WM_KEYDOWN: keys[wParam] = TRUE; break; case WM_KEYUP: keys[wParam] = FALSE; break; case WM_SIZE: ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow) { MSG msg; // Структура сообщения Windows WNDCLASS wc; // Структура класса Windows для установки типа окна HWND hWnd; // Сохранение дескриптора окна wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGL WinClass"; if(!RegisterClass(&wc)) { MessageBox(0, "Failed To Register The WindowClass.", "Error",MB_OK|MB_ICONERROR); return FALSE; } hWnd = CreateWindow("OpenGL WinClass", "First OpenGL program", // Заголовок вверху окна WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, // Позиция окна на экране 640, 480, // Ширина и высота окна NULL, NULL, hInstance, NULL); if(!hWnd) { MessageBox(0,"Window Creation Error.","Error",MB_OK|MB_ICONERROR); return FALSE; } if(!hWnd) { MessageBox(0,"Window Creation Error.","Error",MB_OK|MB_ICONERROR); return FALSE; 49 } ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); SetFocus(hWnd); while (1) { // Обработка всех сообщений while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { return TRUE; } } DrawGLScene(); // Нарисовать сцену SwapBuffers(hDC); // Переключить буфер экрана if (keys[VK_ESCAPE]) SendMessage(hWnd,WM_CLOSE,0,0); // Если ESC - выйти } } Приложение 2. Минимальный код программы для использования OpenGL в программе на Delphi. В приложении приводятся три варианта программ, позволяющих использовать библиотеку OpenGL для графического вывода. Примеры взяты с диска к книге Краснова М.В. «OpenGL в проектах Delphi». 1) Оконное приложение. (часть 1, пример 20) {**********************************************************************} program GLmin; uses Forms, Unit1 in 'Unit1.pas' {frmGL}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TfrmGL, frmGL); Application.Run; end. {**********************************************************************} unit Unit1; interface uses Windows, Messages, Forms, Classes, Controls, ExtCtrls, ComCtrls, StdCtrls, Dialogs, SysUtils, OpenGL; type TfrmGL = class(TForm) 50 procedure FormCreate(Sender: TObject); procedure FormPaint(Sender: TObject); procedure FormDestroy(Sender: TObject); private hrc: HGLRC; // ссылка на контекст воспроизведения end; var frmGL: TfrmGL; implementation {$R *.DFM} {============================================Рисование картинки} procedure TfrmGL.FormPaint(Sender: TObject); begin wglMakeCurrent(Canvas.Handle, hrc); glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета //glBegin(GL_LINES); // glVertex(-0.5,-0.5); // glVertex(0.5,0.5); //glEnd; wglMakeCurrent (0, 0); end; {=============================================Формат пикселя} procedure SetDCPixelFormat (hdc : HDC); var pfd : TPixelFormatDescriptor; nPixelFormat : Integer; begin FillChar (pfd, SizeOf (pfd), 0); nPixelFormat := ChoosePixelFormat (hdc, @pfd); SetPixelFormat (hdc, nPixelFormat, @pfd); end; {==============================================Создание формы} procedure TfrmGL.FormCreate(Sender: TObject); begin SetDCPixelFormat(Canvas.Handle); hrc := wglCreateContext(Canvas.Handle); end; {======================================Конец работы приложения} procedure TfrmGL.FormDestroy(Sender: TObject); begin wglDeleteContext(hrc); end; end. {**********************************************************************} 2) Консольное приложение. (часть 1, пример 21). {**********************************************************************} program OpenGL_min; uses 51 Messages, Windows, OpenGL; const AppName = 'OpenGL_Min'; Var Window : HWnd; Message : TMsg; WindowClass : TWndClass; dc : HDC; hrc : HGLRC; // контекст воспроизведения OpenGL MyPaint : TPaintStruct; // Процедура заполнения полей структуры PIXELFORMATDESCRIPTOR procedure SetDCPixelFormat (hdc : HDC); var pfd : TPixelFormatDescriptor; // данные формата пикселей nPixelFormat : Integer; Begin With pfd do begin nSize := sizeof (TPixelFormatDescriptor); // размер структуры nVersion := 1; // номер версии dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL; // множество битовых флагов, определяющих устройство и интерфейс iPixelType := PFD_TYPE_RGBA; // режим для изображения цветов cColorBits := 16; // число битовых плоскостей в каждом буфере цвета cRedBits := 0; // число битовых плоскостей красного в каждом буфере RGBA cRedShift := 0; // смещение от начала числа битовых плоскостей красного //в каждом буфере RGBA cGreenBits := 0; // число битовых плоскостей зелёного в каждом буфере RGBA cGreenShift := 0; // смещение от начала числа битовых плоскостей зелёного //в каждом буфере RGBA cBlueBits := 0; // число битовых плоскостей синего в каждом буфере RGBA cBlueShift := 0; // смещение от начала числа битовых плоскостей синего //в каждом буфере RGBA cAlphaBits := 0; // число битовых плоскостей альфа в каждом буфере RGBA cAlphaShift := 0; // смещение от начала числа битовых плоскостей альфа //в каждом буфере RGBA cAccumBits := 0; // общее число битовых плоскостей в буфере аккумулятора cAccumRedBits := 0; // число битовых плоскостей красного в буфере аккумулятора cAccumGreenBits := 0; // число битовых плоскостей зелёного в буфере аккумулятора cAccumBlueBits := 0; // число битовых плоскостей синего в буфере аккумулятора cAccumAlphaBits := 0; // число битовых плоскостей альфа в буфере аккумулятора cDepthBits := 32; // размер буфера глубины (ось z) cStencilBits := 0; // размер буфера трафарета cAuxBuffers := 0; // число вспомогательных буферов iLayerType := PFD_MAIN_PLANE;// тип плоскости bReserved := 0; // число плоскостей переднего и заднего плана dwLayerMask := 0; // игнорируется dwVisibleMask := 0; // индекс или цвет прозрачности нижней плоскости dwDamageMask := 0; // игнорируется end; nPixelFormat := ChoosePixelFormat (hdc, @pfd); // запрос системе - поддерживается ли //выбранный формат пикселей SetPixelFormat (hdc, nPixelFormat, @pfd); // устанавливаем формат пикселей в 52 //контексте устройства End; function WindowProc (Window : HWnd; Message, WParam : Word; LParam : LongInt) : LongInt; stdcall; Begin WindowProc := 0; case Message of wm_Create: begin dc := GetDC (Window); SetDCPixelFormat (dc); // установить формат пикселей hrc := wglCreateContext (dc); // создаёт контекст воспроизведения OpenGL ReleaseDC (Window, dc); end; wm_Paint: begin dc := BeginPaint (Window, MyPaint); wglMakeCurrent (dc, hrc); // устанавливает текущий контекст воспроизведения {****** ЗДЕСЬ РАСПОЛАГАЮТСЯ КОМАНДЫ РИСОВАНИЯ OpenGL*********} glClearColor (0.85, 0.75, 0.5, 1.0); // определение цвета фона glClear (GL_COLOR_BUFFER_BIT); // установление цвета фона {************************************************************************} wglMakeCurrent (dc, 0); // перед завершением работы необходимо, // чтобы контекст никем не использовался EndPaint (Window, MyPaint); ReleaseDC (Window, dc); end; wm_Destroy : begin wglDeleteContext (hrc); // удаление контекста воспроизведения DeleteDC (dc); PostQuitMessage (0); Exit; end; end; // case WindowProc := DefWindowProc (Window, Message, WParam, LParam); End; Begin With WindowClass do begin Style := cs_HRedraw or cs_VRedraw; lpfnWndProc := @WindowProc; cbClsExtra := 0; cbWndExtra := 0; hInstance := 0; hCursor := LoadCursor (0, idc_Arrow); lpszClassName := AppName; end; RegisterClass (WindowClass); Window := CreateWindow (AppName, AppName, ws_OverLappedWindow or ws_ClipChildren 53 or ws_ClipSiBlings, // обязательно для OpenGL cw_UseDefault, cw_UseDefault, cw_UseDefault, cw_UseDefault, HWND_DESKTOP, 0, HInstance, nil); ShowWindow (Window, CmdShow); UpdateWindow (Window); While GetMessage (Message, 0, 0, 0) do begin TranslateMessage (Message); DispatchMessage (Message); end; Halt (Message.wParam); end. {**********************************************************************} |