OpenGL для начинающих

Для ортогональной этого делать не надо - центр и так где-то перед нами.Другой способ задавать перспективную проекцию - это воспользоваться gluPerspective. Примечание: чем меньше расстояние между плоскостями отсечения, тем быстрее все считается. 05 Текструры============Текстуру сначала надо загрузить и получить ее идентификатор (хендл). перед созданием объекта текстура выбирается по своему идентификатору(делается текущей) и автоматом прилепляется к объекту (GLUquadricObj).

uses
 OpenGL;
...
var
 Texture: glUint;
...
// функция для установки текущей текстуры по идентификатору texture
// в openGL.pas ее почему то нет :(, потому импортируем
procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32;
...
// Где-то вначале программы, перед использованием glDraw
LoadTexture('1.bmp', Texture);
...
{------------------------------------------------------------------}
{ Создание объектов под отрисовку }
{------------------------------------------------------------------}
procedure glDraw();
var
 Obj : GLUquadricObj;
begin
 ...
 // 1-ый вариант
 glBindTexture(GL_TEXTURE_2D, Texture); // устанавливаем текущую текстуру Texture
 Obj:=gluNewQuadric;
 gluQuadricTexture(Obj, GL_TRUE); // при создании объекта наложить текущую текстуру
 gluSphere(Obj, 100, 25, 25); // создать сферу R = 100, детализация - 25х25
 ...
или так
 ...
 // 2-ой вариант
 glBindTexture(GL_TEXTURE_2D, Texture); // устанавливаем текущую текстуру Texture
 // Рисуем фигуру, на которую наложится текстура при помощи glTexCoord2f
 glBegin(GL_QUADS);
  glNormal3f( 0.0, 0.0, 1.0);
  // 1-я точка текстуры + 1-я точка объекта
  glTexCoord2f(0.0, 0.0);
  glVertex3f(-100.0, -100.0, 0.0);
  // 3-я точка текстуры + 2-я точка объекта
  glTexCoord2f(1.0, 0.0);
  glVertex3f( 100.0, -100.0, 0.0);
  // 3-я точка текстуры + 3-я точка объекта
  glTexCoord2f(1.0, 1.0);
  glVertex3f( 100.0, 100.0, 0.0);
  // 1-я точка текстуры + 1-я точка объекта
  glTexCoord2f(0.0, 1.0);
  glVertex3f(-100.0, 100.0, 0.0);
 glEnd();
При этом должен быть разрешен режим наложения текстур (по умолчанию - отключен) glEnable(GL_TEXTURE_2D); Примечание:Функция MyOpenGL.glLoadTexture поддерживает загрузку только 8 и 24-битных изображений. Дополнительноwww.ru-coding.com/ogl_1_5.php06 Unit MyOpenGL.pas====================
unit MyOpenGL;
interface
uses windows, OpenGL;
procedure glOnResize(Width, Height : Integer);
procedure glInit(Wnd: hWND);
procedure glKill(Wnd: hWND);
procedure glDraw();
procedure glLoadTexture(Filename: String; var Texture: GLuint);
implementation
procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32;
function gluBuild2DMipmaps(Target: GLenum; Components, Width, Height: GLint; Format, atype: GLenum; Data: Pointer): GLint; stdcall; external glu32;
procedure glGenTextures(n: GLsizei; var textures: GLuint); stdcall; external opengl32;
procedure SetDCPixelFormat(DC: hDC); forward;
var
 DC: hDC; // контекст устройства
 RC: hGLRC; // контекст воспроизведения
 Texture: GLuint; // хэндл текстуры
 Angle: Integer = 0; // угол поворота сферы
{------------------------------------------------------------------}
{ Обработчик на изменение размеров окна }
{------------------------------------------------------------------}
procedure glOnResize(Width, Height: Integer);
begin
 if (Height = 0) then Height := 1; // Предупреждаем деление на 0
 glViewport(0, 0, Width, Height); // Устанавливаем область отображения
  // на все окно
 // Настройка матрицы проекции
 glMatrixMode(GL_PROJECTION); // Выбираем матрицу проекции
 glLoadIdentity(); // Устанавливаем ее единичной
 // Устанавливаем тип проеции - Ортогональный
 glOrtho(-Width div 2, Width div 2, -Height div 2, Height div 2, -800, 800);
 // Настройка видовой матрицы
 glMatrixMode(GL_MODELVIEW); // Выбираем матрицу проекции
 glLoadIdentity(); // Устанавливаем ее единичной
end;
{------------------------------------------------------------------}
{ Инициализация OpenGL }
{------------------------------------------------------------------}
procedure glInit(Wnd: hWND);
const
 // Константы, задающие свойства материала фигур
 mat1_amb : array [0..2] of Single = (0.2, 0.2, 0.2);
 mat1_dif : array [0..2] of Single = (0.8, 0.8, 0.0);
 mat1_spec: array [0..2] of Single = (0.6, 0.6, 0.6);
 mat1_shininess = 10;
 // Константы для источника света
 light_pos : array [0..3] of glFloat = (100.0, 100.0, 0.0, 1.0);
 light_amb : array [0..3] of glFloat = (0.6, 0.6, 0.6, 1.0);
 light_dif : array [0..3] of glFloat = (1.0, 1.0, 1.0, 1.0);
 light_spec : array [0..3] of glFloat = (1.0, 1.0, 1.0, 1.0);
 light_spot_direction : array [0..3] of glFloat = (1.0, 1.0, 1.0, 1.0);
 // Цвет тумана
 fogColor: array [0..3] of GLfloat = (0, 1.0, 0, 1.0);
var
 fogMode: GLint;
begin
 // Инициализация контекста воспроизведения OpenGL
 DC := GetDC(Wnd); // Получить контекст устройства для окна
 SetDCPixelFormat(DC); // Установить формата пикселов
 RC := wglCreateContext(DC); // создать новый контекст воспроизведения
 wglMakeCurrent(DC,RC); // Установить его текущим
 // Свойства материала для режима glEnable(GL_COLOR_MATERIAL)
 glMaterialfv(GL_FRONT, GL_AMBIENT, @mat1_amb);
 glMaterialfv(GL_FRONT, GL_DIFFUSE, @mat1_dif);
 glMaterialfv(GL_FRONT, GL_SPECULAR, @mat1_spec);
 glMaterialf (GL_FRONT, GL_SHININESS,mat1_shininess);
 // Свойства источника света GL_LIGHT1 для режима glEnable(GL_LIGHTING)
 // Стандартный источник одна команда: glEnable(GL_LIGHT0);
 glLightfv(GL_LIGHT1, GL_POSITION,@light_pos);
 glLightfv(GL_LIGHT1, GL_AMBIENT, @light_amb); // направленность
 glLightfv(GL_LIGHT1, GL_DIFFUSE, @light_dif); // рассеивание
 glLightfv(GL_LIGHT1, GL_SPECULAR, @light_spec);
 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, @light_spot_direction);
 // разрешить источник света GL_LIGHT1
 glEnable(GL_LIGHT1);
 // Свойства тумана для режима glEnable(GL_FOG)
 fogMode := GL_EXP; // GL_EXP2, GL_LINEAR
 glFogi(GL_FOG_MODE, fogMode); // установить режим
 glFogfv(GL_FOG_COLOR, @fogColor); // цвет тумана
 glFogf(GL_FOG_DENSITY, 0.002); // плотность - 0.2%
 glHint(GL_FOG_HINT, GL_DONT_CARE); // GL_NICEST, GL_FASTEST.
 glClearColor(0.0, 0.0, 0.2, 1.0); // Установить цвет фона - синий
 glClearDepth(1.0); // Очистить буфер глубины
 glDepthFunc(GL_LESS); // Тип теста глубины
 glShadeModel(GL_SMOOTH); // плавное цветовое сглаживание

 // glEnable(..) - включить режим, glDisable(..) - отключить
 glEnable(GL_LIGHTING); // разрешить осещенность
 //glEnable(GL_FOG); // разрешить тумана
 glEnable(GL_DEPTH_TEST); // разрешить тест глубины, с использованием
  // функции определенной в glDepthFunc
 glEnable(GL_NORMALIZE); // разрешить нормали (различение передней
  // и задней сторон плоских объектов)
 glEnable(GL_COLOR_MATERIAL); // разрешить использование материалов на объектах
 glEnable(GL_TEXTURE_2D); // разрешить наложение текстур
 //glEnable(GL_BLEND); // разрешить смешивание (напр. прозрачность)
  // не совместимо с glEnable(GL_DEPTH_TEST)
 glLoadTexture('1.bmp', Texture); // загружаем текстуру
end;
{------------------------------------------------------------------}
{ Завершение работы с OpenGL }
{------------------------------------------------------------------}
procedure glKill(Wnd: hWND);
begin
 wglMakeCurrent(DC, 0);
 wglDeleteContext(RC);
 ReleaseDC(Wnd, DC);
end;

{------------------------------------------------------------------}
{ Создание объектов под отрисовку }
{------------------------------------------------------------------}
procedure glDraw();
var
 Obj: GLUquadricObj;
begin
 // очистка Экрана и буфера глубины
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 glMatrixMode(GL_MODELVIEW); // Переключаемся на видовую матрицу
 glLoadIdentity; // Сбрасываем все преобразования
 // Пример рисования разноцветного треугольника
 glBegin(GL_POLYGON);
 glColor(0.0, 0.5, 0.0, 0.0); // Цвет 1-ой вершины
 glVertex3F(-50, -sqrt(3)*50, 0); // 1-я вершина
 glColor(0.5, 0.0, 0.0, 0.0); // Цвет 2-ой вершины
 glVertex3F(-100, -sqrt(3)*100, 0); // 2-я вершина
 glColor(0.0, 0.0, 0.5, 0.0); // Цвет 3-ей вершины
 glVertex3F(-125, -sqrt(3)*100, 0); // 3-я вершина
 glEnd;
 // Следующая фигура будет нарисована повернутой
 // Поворачиваем сферу так, чтобы северный полюс на текстуре
 // смотрел в нужную сторону
 glRotate(-90, 0.0, 1.0, 0.0);
 glRotate(60, 1.0, 0.0, 0.0);
 // здесь поворот сферы вокруг оси
 glRotate(-Angle, 0.0, 0.0, 1.0);
 // Пример рисования сферы
 glColor(1.0, 1.0, 1.0, 0.5); // установить цвет объекта
 glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Функция смешивания для непрозрачности,
  // базирующаяся на значении альфы
  // Отрабатывает только при glEnable(GL_BLEND)
 glBindTexture(GL_TEXTURE_2D, Texture); // установить текущую текстуру Texture
 Obj:=gluNewQuadric;
 gluQuadricTexture(Obj, GL_TRUE); // разрешить наложить текущую текстуру на
  // создаваемый объект
 gluSphere(Obj, 100, 25, 25); // создать сферу R = 100, детализация - 25х25
 gluDeleteQuadric(Obj); // Освобождаем память
 Angle := (Angle + 5) mod 360;
 // Выводим на экран подготовленную сцену
 SwapBuffers(DC);
end;
{------------------------------------------------------------------}
{ Выбор приемлемого формата точки для данного DC }
{------------------------------------------------------------------}
procedure SetDCPixelFormat(DC: hDC);
var
 pfd: TPixelFormatDescriptor;
 nPixelFormat: Integer;
begin
 FillChar(pfd, SizeOf(pfd), 0);
 with pfd do
 begin
  nSize := sizeof(pfd);
  nVersion := 1;
  dwFlags := PFD_DRAW_TO_WINDOW or
  PFD_SUPPORT_OPENGL or
  PFD_DOUBLEBUFFER;
  iPixelType := PFD_TYPE_RGBA;
  cColorBits := 16;
  cDepthBits := 64;
  iLayerType := PFD_MAIN_PLANE;
  end;
 nPixelFormat := ChoosePixelFormat(DC, @pfd);
 SetPixelFormat(DC, nPixelFormat, @pfd);
end;
{------------------------------------------------------------------}
{ Загрузка 8 или 24-битного bmp-файла текстуры }
{------------------------------------------------------------------}
procedure glLoadTexture(Filename: String; var Texture: GLuint);
type BitmapHeader=
  record
  FH: BitmapFileHeader;
  IH: BitmapInfoHeader;
  end;
var
 ColorTable: array of TRGBQuad;
 Data: array of Byte;
 RGBData: array of TRGBTriple;
 Bmp: BitmapHeader;
 tmp, i, L: Cardinal;
 F: hFile;
begin
 F := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
 if F = INVALID_HANDLE_VALUE then
  begin
  MessageBox(0,PChar('File '+ FileName + ' not found'), 'glLoadTexture',0);
  exit;
  end;
 ReadFile(F, Bmp, sizeof(BitmapHeader),tmp, nil );
 L := Bmp.IH.biWidth * Bmp.IH.biHeight;
 SetLength(RGBData, L);
 case Bmp.IH.biBitCount of
  8:
  begin
  SetLength(ColorTable, round(exp(Bmp.IH.biBitCount*Ln(2))));
  ReadFile(F, ColorTable[0], SizeOf(TRGBQuad) * round(exp(Bmp.IH.biBitCount*Ln(2))), tmp, nil);
  SetLength(Data, L);
  ReadFile(F, Data[0], SizeOf(Byte) * L, tmp, nil);
  for i := 0 to L - 1 do
  begin
  RGBData[L - i - 1].rgbtRed := ColorTable[Data[i]].rgbBlue;
  RGBData[L - i - 1].rgbtGreen := ColorTable[Data[i]].rgbGreen;
  RGBData[L - i - 1].rgbtBlue := ColorTable[Data[i]].rgbRed;
  end;
  end;
  24:
  begin
  SetLength(Data, L * 3);
  ReadFile(F, Data[0], SizeOf(Byte) * L * 3, tmp, nil);
  for i := 0 to L - 1 do
  begin
  RGBData[L - i - 1].rgbtRed := Data[3 * i];
  RGBData[L - i - 1].rgbtGreen := Data[3 * i + 1];
  RGBData[L - i - 1].rgbtBlue := Data[3 * i + 2];
  end;
  end;
  else MessageBox(0, 'Format not support', 'glLoadTexture', 0);
  end; { end case}
 CloseHandle(F);
 // Далее код из BMP.pas от Jan Horn
 glGenTextures(1, Texture);
 glBindTexture(GL_TEXTURE_2D, Texture);
 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); {Texture blends with object background}
 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); {Texture does NOT blend with object background}
 {
  Select a filtering type. BiLinear filtering produces very good results with little performance impact
  GL_NEAREST - Basic texture (grainy looking texture)
  GL_LINEAR - BiLinear filtering
  GL_LINEAR_MIPMAP_NEAREST - Basic mipmapped texture
  GL_LINEAR_MIPMAP_LINEAR - BiLinear Mipmapped texture
 }

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); { only first two can be used }
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); { all of the above can be used }
 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Bmp.IH.biWidth, Bmp.IH.biHeight, GL_RGB, GL_UNSIGNED_BYTE, RGBData);
 // Use when not wanting mipmaps to be built by openGL
 // glTexImage2D(GL_TEXTURE_2D, 0, 3, Bmp.IH.biWidth, Bmp.IH.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, RGBData);
end;
end.
07 Собранный пример VCL=======================На форме таймер, в проект включен MyOpenGL.pas. В той же папке лежит 8 или 24-битный bmp-фаил.
unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, MyOpenGL;
type
 TForm1 = class(TForm)
  Timer1: TTimer;
  procedure FormDestroy(Sender: TObject);
  procedure FormResize(Sender: TObject);
  procedure Timer1Timer(Sender: TObject);
  procedure FormCreate(Sender: TObject);
 private
  { Private declarations }
 public
  { Public declarations }
 end;
var
 Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormDestroy(Sender: TObject);
begin
 glKill(Form1.Handle);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
 glOnResize(Form1.ClientWidth,Form1.ClientHeight);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 glDraw();
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
 glInit(Form1.Handle);
 glOnResize(Form1.ClientWidth,Form1.ClientHeight);
end;
end.
08 Собранный пример WinApi==========================В той же папке лежит 8 или 24-битный bmp-файл.
program a;
uses
 windows,
 messages,
 MyOpenGL in 'MyOpenGL.pas';
var
 MainWnd: hWND;
function WindowProc(Wnd: HWND; Msg: Integer; wParam: wParam; lParam:lParam):lResult;stdcall;
begin
 case Msg of
  WM_DESTROY:
  begin
  glKill(MainWnd);
  postquitmessage(0);
  Result := 0;
  exit;
  end;
  WM_TIMER:
  begin
  glDraw(); // Рисуем сцену
  Result := 0;
  end;
  WM_SIZE:
  begin
  // В lParam содержатся размеры клиентской области ;-)
  glOnResize(loWord(lParam), hiWord(lParam));
  Result := 0;
  end;
  else
  Result := DefWindowProc(Wnd, Msg, wParam, lParam);
 end;
end;
var
 Mesg: TMsg;
 wc : TWndClassEx;
begin
 wc.cbSize := sizeof(wc);
 wc.style := CS_HREDRAW or CS_VREDRAW;
 wc.lpfnWndProc := @WindowProc;
 wc.cbClsExtra := 0;
 wc.cbWndExtra := 0;
 wc.hInstance := hInstance;
 wc.hIcon := LoadIcon(0, IDI_WINLOGO);
 wc.hCursor := LoadCursor(0, IDC_ARROW);
 wc.hbrBackground := COLOR_BTNFACE+2;
 wc.lpszMenuName := nil;
 wc.lpszClassName := 'aWnd';
 RegisterClassEx(wc);
 // Создаем окно 400х400
 MainWnd := CreateWindowEx (0, 'aWnd', 'MyOpenGL', WS_OVERLAPPEDWINDOW or WS_VISIBLE, 100, 100, 400, 400, 0, 0, hInstance, nil);
 // Создаем контекст воспроизведения OpenGL и его параметры
 glInit(MainWnd);
 // Задаем матрицы OpenGL для размера окна 400х400
 glOnResize(400, 400);
 // Устанавливаем таймер 10мс для перерисовки сцены
 SetTimer(MainWnd, 1, 10, nil);
 while GetMessage(Mesg, 0, 0, 0) do
 begin
  TranslateMessage(Mesg);
  DispatchMessage(Mesg);
 end;
end.

Очень сильно помогло для вывода текста. Спасибо.

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...