Е. А. Снижко, Н. А. Флерова
![]()
|
Контрольные вопросы 1. Что понимается под термином «текстура»? 2. Каков смысл использования текстур при визуализации? Какому уровню визуализации соответствует текстурирование? 3. Что такое «тексель»? 4. Что представляют собой текстурные координаты? 5. Какие действия необходимо выполнить для наложения текстуры на объект? 6. Какие режимы фильтрации используются при наложении текстур? 7. В чем заключается первичное связывание? 8. Каким образом осуществляется связывание изображения с текстурой? 9. Каким образом при помощи текстур может быть достиг- нут эффект отражения? 10. Почему необходимо согласование геометрических и тек- стурных координат? Как это достигается? 71 П Р И Л О Ж Е Н И Е 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); // третья точка 72 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; 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, // Главный слой рисования 73 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; 74 } GetClientRect(hWnd, &Screen); InitGL(Screen.right, Screen.bottom); break; case WM_DESTROY: case WM_CLOSE: ChangeDisplaySettings(NULL, 0); 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); 75 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; } ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); SetFocus(hWnd); while (1) { // Обработка всех сообщений while(PeekMessage(&msg, NULL,0,0, PM_NOREMOVE)) 76 { 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. {************************************************} 77 unit Unit1; interface uses Windows, Messages, Forms, Classes, Controls, ExtCtrls, ComCtrls, StdCtrls, Dialogs, SysUtils, OpenGL; type TfrmGL = class(TForm) 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); 78 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 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; // режим для // изображения цветов 79 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); 80 // запрос системе - поддерживается ли // выбранный формат пикселей SetPixelFormat (hdc, nPixelFormat, @pfd); // устанавливаем формат пикселей в // контексте устройства 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); // удаление // контекста воспроизведения 81 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 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. {************************************************} 3. Пример рисования на поверхности визуального ком - понента ( пример 10, часть 2). {************************************************} program Dots; uses Forms, 82 Unit1 in 'Unit1.pas' {frmGL}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TfrmGL, frmGL); Application.Run; end. {************************************************} unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, OpenGL; type TfrmGL = class(TForm) 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); glViewPort (0, 0, ClientWidth, ClientHeight); // область вывода glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета glPointSize (20); // размер точек glColor3f (1.0, 0.0, 0.5); // текущий цвет примитивов glBegin (GL_POINTS); // открываем командную скобку glVertex2f (-1, -1); glVertex2f (-1, 1); 83 glVertex2f (0, 0); glVertex2f (1, -1); glVertex2f (1, 1); glEnd; // закрываем командную скобку SwapBuffers(Canvas.Handle); // содержимое буфера - на экран wglMakeCurrent(0, 0); Canvas.Brush.Color := clGreen; Canvas.Ellipse (10, 10, 50, 50); end; {================================== Формат пикселя } procedure SetDCPixelFormat (hdc : HDC); var pfd : TPixelFormatDescriptor; nPixelFormat : Integer; begin FillChar (pfd, SizeOf (pfd), 0); pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER; 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. {*************************************************} 84 П Р И Л О Ж Е Н И Е 3 Особенности использования массивов OpenGL в среде Delphi За основу взято оконное приложение из приложения 2. Простейший случай использования массивов – векторная форма команд. Массив содержащий координаты одной точки, может быть за- дан в виде Var point : Array [0..2] of GLfloat = (0.0, 0.0, 0.0); Векторная форма команды рисования точки glVertex3fv использует в качестве параметра адрес массива: glBegin(GL_POINTS); glVertex3fv(@point); glEnd; Для изображения нескольких точек массив должен быть двумер- ным, например массив из трех точек: Var point : Array [1..3,0..2] of GLfloat = ((0.5, 0.5, 0.5),(0.8,-0.8,0),(-0.8,0.5,1)); Нарисовать точки можно с помощью следующего кода: glBegin(GL_POINTS); for i:=1 to 3 do glVertex3fv(@point[i]); glEnd; Аналогично можно использовать массив для задания цветов. Для использования массивов вершин и цветов библиотеки OpenGL необходимо выполнить следующие действия. 1. Объявить переменную типа массив в разделе Var модуля или включить массивы координат и (или) цветов в класс окна OpenGL. Тип элементов массива должен поддерживаться библиотекой OpenGL, жела- тельно использовать тип GLFloat: type TfrmGL = class(TForm) procedure FormCreate(Sender: TObject); procedure FormPaint(Sender: TObject); procedure FormDestroy(Sender: TObject); private hrc: HGLRC; 85 Vertex : Array [0..3, 0..1] of GLFloat; // содержит плоские координаты четырех точек Colors : Array [0..3, 0..2] of GLFloat; // содержит соответствующие вершинам значения RGB procedure Init; end; 2. В раздел implementation добавить заголовки следующих проце- дур и объявить константы: procedure glVertexPointer ( size: GLint; atype: GLenum; stride: GLsizei; data: pointer); stdcall; external OpenGL32; procedure glColorPointer (size: GLint; atype: GLenum; stride: GLsizei; data: pointer); stdcall; external OpenGL32; procedure glDrawArrays (mode: GLenum; first: GLint; count: GLsizei); stdcall; external OpenGL32; procedure glEnableClientState (aarray: GLenum); stdcall; external OpenGL32; procedure glDisableClientState (aarray: GLenum); stdcall; external OpenGL32; procedure glArrayElement (i: GLint); stdcall; external OpenGL32; const GL_VERTEX_ARRAY = $8074; GL_COLOR_ARRAY = $8076; 3. Инициализировать массивы необходимо до их использования, например в процедуре TfrmGL.Init: procedure; begin Vertex[0][0]:=-0.9; Vertex[0][1]:=-0.9; Colors[0][0]:=0.1; Colors[0][1]:=0.5; Colors[0][2]:=0.85; end; 4. В процедуре прорисовки окна . А. Создать указатель на массив вершин и массив цветов: 86 glVertexPointer(2, GL_FLOAT, 0, @Vertex); // создает указатель на массив вершин glColorPointer(3, GL_FLOAT, 0, @Colors); // создает указатель на массив цветов Б. Разрешить режимы использования массивов: glEnableClientState(GL_VERTEX_ARRAY); // включает режим использование массива вершин glEnableClientState(GL_COLOR_ARRAY); // включает режим использование массива цветов В. Нарисовать объект (набор однотипных объектов). Г. Отменить режимы использования массивов: // выключение режимов glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); Объект может быть нарисован с помощью команд glArrayElement или glDrawArrays. Первая команда рисует объект на основе отдельных точек, пере- числив элементы массива в нужном порядке. Команды заключаются в командные скобки с указанием типа примитива: glBegin (GL_POLYGON); // рисует полигон // на основе четырех точек в заданном порядке glArrayElement(0); glArrayElement(1); glArrayElement(2); glArrayElement(3); glEnd; Вторая команда не требует командных скобок. Тип примитива яв- ляется параметром команды. Вершины используются в том порядке, в котором они хранятся в массиве: glDrawArrays(GL_POLYGON, 0, 4); // рисует полигон по четырем вершинам glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // рисует ленту треугольников // на основе массива координат // с цветами , определенными в массиве цветов 87 П Р И Л О Ж Е Н И Е 4 Ссылки на Интернет-ресурсы по использованию библиотек OpenGL в программировании графики http://www.opengl.org http://gl.satel.ru http://www.sgi.com/software/opengl www.opengl.org.ru/ opengl.gamedev.ru/ www.codenet.ru/progr/opengl/ nehe.gamedev.net/ www.rsdn.ru/article/opengl/ogltut2.xml www.citforum.ru/programming/opengl/index.shtml talk.mail.ru/forum/fido7.ru.opengl pmg.org.ru/nehe/ www.firststeps.ru/mfc/opengl/opengl1.html www.bib.com.ua/cat_art28.html Библиографический список 1. Боресков А. Графика трехмерной компьютерной игры на основе OpenGL. М.: Диалог-МИФИ, 2005. 2. Гашников М. и др. Методы компьютерной обработки изображений. М.: Физматлит, 2001. 3. Павлидис Т. Алгоритмы машинной графики и обработка изображе- ний. М.: Радио и связь. 1986. 4. Петров М. Компьютерная графика: Учебник для вузов. СПб.: Пи- тер, 2002. 5. Рейбоу В. Компьютерная графика. Энциклопедия. СПб.: Питер, 2002. 6. Роджерс Д. Алгоритмические основы машинной графики. М.: Мир, 1989. 7. Снижко Е. Компьютерная геометрия и графика: Конспект лекций. СПб.: БГТУ, 2005. 8. Шикин Е., Боресков А. Компьютерная графика. Динамика, реали- стические изображения. М.: Диалог-МИФИ, 1985. 9. Шикин Е., Боресков А. Компьютерная графика. Полигональные модели. М.: Диалог-МИФИ, 2005. 10. Эйнджел Э. Интерактивная компьютерная графика. Вводный курс на базе OpenGl. М.: Изд. дом «Вильямс», 2001. 11. Херн Д., Бейкер М. Компьютерная графика и стандарт OpenGL. М.: Изд. дом «Вильямс», 2005. О Г Л А В Л Е Н И Е П р е д и с л о в и е .................................................................................. 3 Лабораторная работа № 1. Подключение библиотек; контекст устройства, контекст воспроизведения; общий вид программы........ 4 Лабораторная работа № 2. Примитивы OpenGL, основные прие- мы построения двумерных объектов................................................ 17 Лабораторная работа № 3. Использование массивов вершин. Преобразования координат................................................................ 28 Лабораторная работа № 4. Трехмерные построения. Буфер глу- бины. Видовые параметры. Параллельная и перспективная проекции ............................................................................................ 34 Лабораторная работа № 5. Квадрик-объекты. Камера ...................... 40 Лабораторная работа № 6. Освещение .............................................. 48 Лабораторная работа № 7. Текстуры: режимы фильтрации, режи- мы взаимодействия текстуры с объектом, автоматическая гене- рация текстурных координат............................................................. 58 П р и л о ж е н и е 1. Минимальный код программы OpenGL на C++.. 71 П р и л о ж е н и е 2. Минимальный код программы для использо- вания OpenGL в программе на Delphi. .............................................. 76 П р и л о ж е н и е 3. Особенности использования массивов OpenGL в среде Delphi ..................................................................................... 84 П р и л о ж е н и е 4. Ссылки на Интернет-ресурсы по использова- нию библиотек OpenGL в программировании графики.................... 87 Библиографический список ................................................................... 87 Снижко Елена Александровна, Флерова Наталья Владими- ровна, Воронцов Артем Валерьевич Программирование компьютерной графики с использованием библиотеки ОpenGL Редактор Г.М. Звягина Подписано в печать 15.06.2006. Формат бумаги 60х84/16. Бумага документная. Печать трафаретная. Усл. печ. л. 5,175 . Тираж 250 экз. Заказ № Балтийский государственный технический университет Типография БГТУ 190005, С.-Петербург, 1-я Красноармейская ул., д.1 |