OpenGL: Основы. (Часть 1)



Скачать 149.83 Kb.
Дата25.11.2012
Размер149.83 Kb.
ТипДокументы
OpenGL: Основы. (Часть 1)
Знакомство.
OpenGL является одним из ведущих и популярных графических API, разработанный SGI . OpenGL разрабатывался как многоплатформенный, открытый и быстрый графический API. Многие графические пакеты используют OpenGL для вывода трёхмерной графики. Многие известные игры, такие как Quake, Serious Sam и наш отечественный ИЛ-2 Штурмовик, также написаны под OpenGL.
Почти все современные графические акселераторы могут аппаратно поддерживать OpenGL, что позволяет выводить графику в реальном времени.
В этом уроке мы познакомимся с основами OpenGL, и научимся делать приложения, работающие с этой графической библиотекой в операционной среде Windows.
OpenGL представляет собой набор функций, при помощи которых можно выводить 2-х и 3-х мерные графические примитивы, управлять ими, их свойствами, способами вывода и пр.
Заголовочные файлы, которые могут понадобиться для работы с OpenGL, обычно находятся в папке GL, расположенной в стандартной папке Include.
Объявление стандартных функций OpenGL находится в файле gl.h, поэтому ваш файл исходного кода, содержащий функции OpenGL, должен включать gl.h:
#include



Кроме того, линковщику нужно указать статические библиотеки, с внешними функциями. Например, для функций, объявленных в gl.h, необходимо добавить в проект opengl32.lib.
Инициализация.
В OpenGL нет встроенных функций для инициализации OpenGL. Это связано с тем, что OpenGL является независимым от платформы графическим API. Инициализацию обеспечивает операционная среда.
Существует несколько функций по работе с OpenGL, которые представляет Windows API.
Перед тем как проинициализировать наше приложение, мы должны определить какими свойствами будет обладать наше приложение и каким способом будет выводиться графика.
Обычно в трёхмерных играх каждый видимый кадр строится заново. То есть, в каждом кадре полностью перерисовывается вся видимая графика. Построение кадра может происходить следующим образом. Сначала весь кадр очищается, а потом последовательно выводятся трёхмерные графические объекты. Такое действие происходит несколько раз в секунду. Количество этих перерисовок в секунду называют FPS (frames per second).
Понятно, что если мы будем стирать и рисовать в видимой части экрана, то мы будем видеть мигание и мерцание наших рисующихся и стирающихся объектов.
Чтобы не было этого неприятного эффекта, пользуются следующим способом. Весь кадр полностью строят в невидимой части видеопамяти адаптера. Эту часть называют Back Buffer . После того, как все графические объекты выведены, вся эта невидимая часть копируется в видимую область видеопамяти, называемую Front Buffer . Если ваше приложение выводит графику на весь экран, а не в окно, то можно избежать копирования буфера, переключая указатель на видимую часть в видео памяти. Такой эффект называют Flip. Видно, что он работает быстрее, чем копирование буфера.

Мы будем строить пример оконного приложения.
Окно, в котором будет выводиться графика под OpenGL должно иметь два дополнительных стиля WS_CLIPSIBLINGS и WS_CLIPCHILDREN. Эти стили можно установить либо во время создания окна в функции CreateWindow(), либо функцией из Windows API - SetWindowLong(), если окно уже создано.
Согласно нашему примеру , для того чтобы установить эти стили, нами созданную функцию CreateMainWindow() необходимо вызвать с true в параметре bIsOpenGL.
Для устройства контекста окна необходимо выставить описатель пиксельного формата.
Это можно сделать при помощи объекта структуры PIXELFORMATDESCRIPTOR. Тут вы указываете, например, сколько бит необходимо выделить под каждое значение цвета, под буфер глубины и т.д.
Рассмотрим функции, работающие с PIXELFORMATDESCRIPTOR.
На самом деле, вы не всегда можете установить точно все параметры PIXELFORMATDESCRIPTOR для текущего режима по вашему желанию. Другими словами, вы можете рекомендовать те или иные параметры, система, выберет наиболее подходящий формат по вашим пожеланиям.

Итак, сначала создадим объект типа PIXELFORMATDESCRIPTOR, полностью заполненный нулевыми значениями.
PIXELFORMATDESCRIPTOR pfd = {0};

Для работы с этим объектов всегда нужно выставлять поля nSize значением равным размеру всей структуры и nVersion (версия) - со значением равным 1.
Также необходимо выставить требуемые флаги в dwFlags. Поскольку мы собираемся выводить графические объекты в окно, то нужно выставить флаг PFD_DRAW_TO_WINDOW. Далее, говорим, что буфер кадра поддерживает вывод через OpenGL - PFD_SUPPORT_OPENGL, и, так как мы используем два буфера (Back и Front), устанавливаем флаг PFD_DOUBLEBUFFER. Итак:
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;

В поле iPixelType выставим PFD_TYPE_RGBA. Это означает, что цвет для пикселя представляется в виде RGBA (цветовые компоненты: R - красный, G - зелёный, B - голубой и A - альфа). Кроме этого бывает ещё индексное представление, которое мы не будем рассматривать вообще.
Дальше выставляем желаемые параметры. Например: глубину цвета (cColorBits) - 32 бит.
Заполнив все необходимы поля, мы делаем запрос на выбор самого подходящего формата. Это делается функцией ChoosePixelFormat(). Эта функция либо возвращает подобранный для указанного контекста устройства индекс формата, либо возвращает ноль.
Если формат был успешно подобран, нужно его выставить функцией SetPixelFormat().
Чтобы узнать, какие именно значения устанавливаются для формата, то есть получить описание полей структуры PIXELFORMATDESCRIPTOR, пользуются функцией DescribePixelFormat()
Итак, построим функцию, инициализирующую пиксельный формат для устройства контекста:
int

InitPixelFormat(HDC hdc)

{

int

pixelformat;

PIXELFORMATDESCRIPTOR pfd = {0};

pfd.nSize =

sizeof

(PIXELFORMATDESCRIPTOR);

pfd.nVersion = 1;

pfd.dwFlags = PFD_SUPPORT_OPENGL |

PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;

pfd.iPixelType = PFD_TYPE_RGBA;

pfd.cColorBits = 32;

if

(!(pixelformat = ChoosePixelFormat(hdc, &pfd)))

{

//Error: ChoosePixelFormat failed

return

0;

}

if

(!SetPixelFormat(hdc, pixelformat, &pfd))

{

//Error: SetPixelFormat failed"

return

0;

}

return

1;

}

Если удалось установить пиксельный формат, то теперь нужно создать просчитывающий контекст (rendering context) OpenGL. Это делается вызовом функции wglCreateContext(). Далее, созданный контекст выставляется текущим функцией wglMakeCurrent().
Теперь вы можете пользоваться функциями OpenGL.
По окончанию работы с OpenGL, например, в конце работы приложения, нужно освободить занятые ресурсы: освободить контекст, вызвав wglMakeCurrent() с параметром ноль для идентификатора контекста OpenGL и разрушить этот контекст функцией wglDeleteContext().
Итак, мы теперь можем построить код, позволяющий работать нам с OpenGL:
Файл OpenGL.h


// OpenGL.h

// Объявление внешних функций

#ifndef

_OpenGL_h_

#define

_OpenGL_h_

int

InitOpenGL(HWND hWnd);

void

ReleaseOpenGL();

#endif

//_OpenGL_h_

Файл OpenGL.cpp


// OpenGL.cpp

// http://www.gamedev.ru

// Урок: http://www.gamedev.ru/coding/11203.shtml

// Автор: Sergey Watkin (wat@gamedev.ru)

#include



#include



#include

"OpenGL.h"

int

InitPixelFormat(HDC hdc);

void

InitSettings();

namespace

{

HWND hWnd;

HDC hDC;

HGLRC hRC;

}

int

InitOpenGL(HWND _hWnd)

{

hWnd = _hWnd;

hDC = GetDC(hWnd);

if

(!InitPixelFormat(hDC))

return

0;

hRC = wglCreateContext(hDC);

wglMakeCurrent(hDC, hRC);

InitSettings();

return

1;

}

void

InitSettings()

{

}

void

ReleaseOpenGL()

{

if

(hRC)

{

wglMakeCurrent(hDC, 0);

wglDeleteContext(hRC);

hRC = 0;

}

if

(hDC)

{

ReleaseDC(hWnd, hDC);

hDC = 0;

}

}

int

InitPixelFormat(HDC hdc)

{

int

pixelformat;

PIXELFORMATDESCRIPTOR pfd = {0};

pfd.nSize =

sizeof

(PIXELFORMATDESCRIPTOR);

pfd.nVersion = 1;

pfd.dwFlags = PFD_SUPPORT_OPENGL |

PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;

pfd.iPixelType = PFD_TYPE_RGBA;

pfd.cColorBits = 32;

if

(!(pixelformat = ChoosePixelFormat(hdc, &pfd)))

{

//Error: ChoosePixelFormat failed

return

0;

}

if

(!SetPixelFormat(hdc, pixelformat, &pfd))

{

//Error: SetPixelFormat failed"

return

0;

}

return

1;

}

Кроме того, если вы пользуетесь кодом для своего приложения, описанным здесь , то не забудьте добавить в него:
В начале:
#include

"OpenGL.h"

Функцию CreateMainWindow() вызвать с true для параметра bIsOpenGL.
В функции Init() вызвать:
InitOpenGL(hWndMain);

А в функции ReleaseAll() вызвать:
ReleaseOpenGL();

OpenGL: Основы. (Часть 2)
Типы в OpenGL.
В OpenGL переопределены стандартные типы, включая встроенные. Это сделано для переносимости программного кода на другие платформы. В принципе, нет ничего сложного, чтобы запомнить эти типы и их значения.
Например, тип GLint соответствует стандартному int:
typedef int

GLint;

аналогично:
typedef unsigned int

GLuint;

typedef float

GLfloat;

typedef double

GLdouble;

typedef void

GLvoid;

и т.д.
Эти типы объявлены в GL.h. Имена всех этих типов начинаются с GL. Рекомендуется с функциями OpenGL использовать эти типы.
Функции OpenGL.
Многие функции OpenGL - вариации друг друга, различаясь только типами данных и их аргументами. Конечно же, этого не было бы, если бы OpenGL изначально был сделан для языков, поддерживающих перегрузку функций, таких как C++.
Чтобы не было путаницы в именах функций, ввели несколько договорённостей (правил), по которым строится имя функции OpenGL.
Во-первых, все имена функций OpenGL начинаются с приставки gl. Например,
glBegin();

glEng();

Во-вторых, если набор функций имеют одинаковый смысл и различаются только количеством и типами параметров, то имя таких функций записывают в виде:
glОбщая_часть_имени_функции[n][type],

где n - количество параметров, type - тип параметров.
Например:
glVertex2d(1.0, 0.5);

// 2d означает: 2 параметра типа GLdouble

glVertex3f(1.0f, 0.5f, 0.0f);

// 3f означает: 3 параметра типа GLfloat

glColor3ub(127, 0, 255);

// 3ub означает: 3 параметра типа GLubyte

Ниже в таблице приведены значения сокращений для type:
i

GLint

ui

GLuint

f

GLfloat

d

GLdouble

s

GLshort

us

GLushort

b

GLbyte

ub

GLubyte

v

массив

В различных документациях по OpenGL, чтобы не перечислять все функции одного семейства, принято записывать только имя общей части всех функций семейства и в конце ставить звёздочку "*". Например, функции, задающие координаты вершин записывают так:
glVertex*

Дополнительные сведения об OpenGL.
Команды OpenGL интерпретируются моделью client/server.
Код приложения (client) выдаёт команды, которые интерпретируются и обрабатываются.
OpenGL (server) может оперировать или не оперировать на компьютере как клиент. Сервер может содержать несколько контекстов OpenGL. Клиент может подключаться к любому из этих контекстов.
Оконная система выделяет буфер кадра (frame buffer). Она определяет, какая часть буфера кадра модели может быть доступна в данное время для OpenGL, и уведомляет OpenGL, как эти порции структурированы. Поэтому OpenGL не имеет команд, конфигурирующих буфер кадра или инициализирующие OpenGL.
Дополнительные библиотеки.
Помимо функций OpenGL и функций, предоставляемых операционной системой, часто для работы с OpenGL используют дополнительные библиотеки.
Библиотеки не вносят каких-либо новых возможностей в сам OpenGL. Их назначение, это упрощение кода. Библиотеки избавляют от написания программистами часто встречаемых функций.
Дополнительные библиотеки рекомендуется использовать крайне осторожно. Проблемы могут возникнуть при переносе вашего кода на другую платформу. Обычно их используют для небольших и тестовых программ. В крупных проектах от этих библиотек отказываются, оставляя предпочтение чистому OpenGL.
Наиболее известные библиотеки:
OpenGL Utility Library (glu)
Утилитная библиотека glu предоставляет функции, работающие с матрицами, с координатными системами, с кривыми и поверхностями NURBS и т.п.
Эта библиотека поставляется почти со всеми реализациями OpenGL, в частности с MS Visual C++.
Для того чтобы её использовать, нужно в исходном файле включить заголовочный файл glu.h:
#include



и включить для линковки статическую библиотеку glu32.lib в ваш проект.
Имена функций в этой утилитной библиотеки начинаются на glu, например,
gluPerspective();

OpenGL Auxiliary Library (glaux)
Вспомогательная библиотека glaux содержит функции, создающие простые трёхмерные геометрические объекты, такие как сфера, куб, параллелепипед, цилиндр, конус и пр., функции, загружающие изображения из файлов, функции, работающие с окном вывода графики и т.д.
Эта библиотека используется реже, и описание функций не включено в MSDN. Файлы для работы с библиотекой также поставляются с MS Visual C++.
Для того чтобы её использовать, нужно в исходном файле включить заголовочный файл glaux.h:
#include



и включить для линковки статическую библиотеку glaux.lib в ваш проект.
Имена функций в этой утилитной библиотеки начинаются на aux, например,
auxSolidCube();

OpenGL Utility Toolkit (GLUT)
Независимый от оконной операционной системы инструмент для создания OpenGL программ. Предоставляет простую реализацию оконного интерфейса. Эта библиотека освобождает от инициализационных подготовок приложения, может генерировать геометрические объекты и пр.
Для того чтобы её использовать, нужно в исходном файле включить заголовочный файл glut.h и включить для линковки статическую библиотеку glut32.lib в ваш проект.
Кроме того, у вас должна быть динамически подключаемая библиотека glut32.dll.

OpenGL: Основы. (Часть 3)
Вывод кадра.
Мы уже говорили, что почти всегда в трёхмерных играх за одну секунду несколько раз полностью строится кадр. Другими словами, всегда, когда программа свободна от обработки сообщений системы, нужно вызывать некую функцию, назовём её DrawFrame(), которая будет каждый раз выводить все объекты в кадре.
Следуя нашему примеру построения приложения, видно, что эта функция должна вызываться из функции OnIdle().
// Функция, вызывающаяся при пустой очереди сообщений

void

OnIdle()

{

DrawFrame();

}

Какие общие действия должны произойти в функции DrawFrame()? Сначала, нужно очистить невидимый буфер (Back buffer), вывести все объекты в этот буфер и сделать невидимый буфер - видимым.
Для очистки используется функция glClear(). Этой функцией очищают несколько типов буферов, нас интересует тот, в котором хранится цветовое изображение (color buffer). Поэтому функцию glClear будем вызывать с параметром GL_COLOR_BUFFER_BIT.
Чтобы back buffer сделать видимым, в нашем случае это означает копирование содержимого этого буфера в видимую часть видеопамяти, используют функцию из Windows API - SwapBuffers().
Итак, что мы можем добавить в наш код. Поскольку функция DrawFrame() должна быть видна из main.cpp, включающей #include "OpenGL.h", то необходимо добавить объявление DrawFrame() в файл OpenGL.h.
Реализация функции DrawFrame() (добавить в OpenGL.cpp):
void

DrawObjects()

{

}

void

DrawFrame()

{

glClear(GL_COLOR_BUFFER_BIT);

DrawObjects();

SwapBuffers(hDC);

}

Функцию DrawObjects()оставьте пока с пустым телом, после будем её использовать в наших примерах по выводу графических примитивов.
Графические примитивы
Существует несколько типов примитивов: точки, линейные сегменты и полигоны.
В функциях, отвечающих за вывод примитивов, нужно указывать, какие именно примитивы будут выводиться, указывая соответствующий режим. Например, для вывода точек, выставляется режим GL_POINTS, для вывода линий - GL_LINES, а для треугольников - GL_TRIANGLES. Помимо этого, есть специальные режимы, использующиеся для удобства и оптимизации. Например, GL_QUADS - выводятся четырёх вершинные примитивы, GL_TRIANGLE_STRIP - выводится цепочка треугольников, у которой каждый следующий треугольник имеет общее ребро с предыдущим и т.д.
Все примитивы описываются вершинами.
Вершины.
Вершина представляет собой данные, используемые для вывода примитивов. Этими данными могут быть вершинные координаты, цвет вершины, нормаль, текстурные координаты и рёберные флаги.
Вывод примитивов последовательностью вершинных функций.
Это самый старый способ вывода вершин, реализованный в OpenGL.
Примитив задаётся отдельными функциями для каждой вершины между функциональными скобками glBegin() и glEnd().
Режим, отвечающий за тип примитива, выставляется в функции glBegin(). Например:
glBegin(GL_TRIANGLES);

означает, что мы будем выводить треугольники, задавая каждый из них тремя вершинами.
Функции glVertex* - задают координаты вершины, которые в свою очередь описывают форму геометрического объекта. При выполнении такой функции, другие данные вершины, такие как вектор нормали и цвет, берутся из установленных ранее "текущих" значений.
Пример. Задаём три (3) координаты типа GLfloat (f) для вершины:
glVertex3f(0.5f, 1.0f, 0.0f);

Пример:
void

DrawObjects()

{

glBegin(GL_TRIANGLES);

glVertex3f(-0.5f, -0.5f, 0.0f);

glVertex3f( 0.5f, 0.5f, 0.0f);

glVertex3f(-0.5f, 0.5f, 0.0f);

glEnd();

}

Эта функция выведет простейший полигон - треугольник, каждая вершина которого задаётся glVertex3f(). Ещё раз обратите внимание, что все функции glVertex* находятся между glBegin() и glEnd().
Текущие значения некоторых данных для вершин можно выставить следующими функциями:
glColor* - задаёт цвет RGBA вершины вместе с условиями освещённости.
glNormal* - задаёт вектор нормали, соответствующий отдельной вершине.
glTexCoord* - задаёт текущие текстурные координаты для вершины.
Текущие значения для вершины выставляются до вызова glVertex*.
Пример:
void

DrawObjects()

{

glBegin(GL_TRIANGLES);

glColor3ub(255,0,0);

// красный

glVertex3f(-0.5f, -0.5f, 0.0f);

glVertex3f( 0.5f, 0.0f, 0.0f);

glColor3ub(0,0,255);

// синий

glVertex3f(-0.5f , 0.5f, 0.0f);

glEnd();

}

Эта функция рисует треугольник с двумя красными вершинами и одной синей.


Вывод примитивов, используя массивы.
Этот метод отправляет на просчёт сразу пачку вершинных данных. То есть вершинные параметры, такие как координаты, нормали и цвета вершин, задаются не отдельными функциями OpenGL для каждой вершины, а отдельными массивами координат, нормалей и пр. Этот метод обычно работает быстрее и более удобен, когда вы работаете с объектами с большим количеством вершин.
Указание OpenGL на массивы происходит отдельными функциями, сам вывод тоже происходит отдельной функцией.
К примеру, выведем опять тот же треугольник.
Имеем массив вершин:
GLfloat pVerts[]= {-0.5f, -0.5f, 0.0f,

0.5f, 0.0f, 0.0f,

-0.5f , 0.5f, 0.0f};

здесь последовательно расположено по три координаты для трёх вершин.
Установка массива для вершинных координат происходит функцией glVertexPointer():
glVertexPointer(3, GL_FLOAT, 0, pVerts);

Первый параметр в этой функции говорит, сколько координат идёт на одну вершину, возможные значения - 2,3,4. Второй параметр отвечает за тип координат. Третий параметр равен шагу в байтах между данными с координатами для каждой вершины. 0 в нашем случае означает, что координаты лежат плотно друг за другом. Четвёртый параметр - собственно сам указатель на массив с координатами.
Кроме того, что мы выставили указатель на массив, необходимо выставить состояние для OpenGL, означающее, что мы будем использовать указатель на массив вершин. Это состояние выставляется функцией glEnableClientState().
glEnableClientState(GL_VERTEX_ARRAY);

Аналогичным образом вы можете выставлять указатели на массивы для других вершинных данных. И не забывайте включать соответствующее состояние. Если вам не нужен для какого-то объекта, какой-то из установленных массивов, вы можете его просто отключить, убрав состояние функцией glDisableClientState().
Включённое состояние остаётся включённым, до тех пор, пока вы его не выключите. То есть, если у вас последовательно идёт вывод нескольких объектов, содержащих свои, к примеру, вершинные массивы, достаточно одного включения состояние для всех объектов перед выводом первого объекта.
Если мы хотим, чтобы объект выводился, используя координаты из массива, но имел, например, один общий цвет для всех вершин, то не нужно строить массив с одинаковыми значениями цвета. Пользуйтесь уже известной вам функцией glColor*().
Рассмотрим теперь одну из функций, отвечающих за вывод примитива с использованием выставленных массивов.
glDrawArrays()
Выводит примитивы по данным в массивах.
glDrawArrays(mode, first, count);

mode - режим, отвечающий за тип примитива,
first - индекс вершины, с которой мы будем выводить объект,
count - количество вершин.
В нашем случае - для одного треугольника используем 3 вершины.
glDrawArrays(GL_TRIANGLES,0,3);

Обратите внимание, что эта функция должна вызываться вне пары glBegin() и glEnd().
Пример:
void

DrawObjects()

{

static

GLfloat pVerts[]= {-0.5f, -0.5f, 0.0f,

0.5f, 0.0f, 0.0f,

-0.5f , 0.5f, 0.0f};

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3,GL_FLOAT,0,pVerts);

glColor3ub(255,0,0);

// красный

glDrawArrays(GL_TRIANGLES,0,3);

}

Индексные примитивы.
Позже, в OpenGL в версии 1.1 ввели дополнительный метод для вывода на экран. Этот метод позволяет работать с индексным заданием геометрических объектов для вывода на просчёт адаптера.
Что это означает? Почти все полигональные модели имеют треугольники с общими вершинами. И обычно, таких вершин большое количество. Ясно, что хранить и использовать копии одинаковых вершин расточительно.
Рассмотрим простейший пример.


Имеем три соседних треугольника с общими вершинами. Для первого и второго треугольника - общие вершины 1 и 2, для второго и третьего - 2,3. Вершина 2 общая для всех треугольников.
Если бы мы не использовали индексный способ задания объекта, то нам понадобилось бы задать для вывода этих треугольников 9-ть вершин (по три для каждого треугольника).
Однако можно задать только 5-ть вершин, используя массивы для координат и прочих вершинных данных, а сами треугольники выводить, указывая индексы, соответствующие расположению вершинных данных в массивах.
То есть

для первого треугольника индексы будут - 0,1,2

для второго - 1,3,2

для третьего - 2,3,4
Рассмотрим одну из функций для работы с индексами.
glArrayElement()
glArrayElement( index );

Эта функция используется внутри пары glBegin() и glEnd(). Собственно ей мы и задаём индексы. А массивы с данными о самих вершинах устанавливаются ранее.
Пример:
void

DrawObjects()

{

static

GLfloat pVerts[]= {-0.5f, 0.0f, 0.0f,

-0.25f,-0.4f, 0.0f,

0.0f, 0.0f, 0.0f,

0.25f,-0.4f, 0.0f,

0.5f, 0.0f, 0.0f};

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3,GL_FLOAT,0,pVerts);

glBegin(GL_TRIANGLES);

glColor3ub(255,0,0);

// красный

glArrayElement(0);

glArrayElement(1);

glArrayElement(2);

glColor3ub(0,255,0);

// зеленый

glArrayElement(1);

glArrayElement(3);

glArrayElement(2);

glColor3ub(0,0,255);

// синий

glArrayElement(2);

glArrayElement(3);

glArrayElement(4);

glEnd();

}

Этот пример выводит три цветных треугольника.
Однако индексы также можно задавать массивом и выводить объект одним вызовом без пары glBegin() и glEnd().
Это можно сделать функцией:
glDrawElements()
glDrawElements(mode, count, type, indices);

Здесь

mode - как всегда выставляет режим типа полигонов,

count - количество индексов, берущихся из массива,

type - тип элементов в индексном массиве, может принимать значения: GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT или GL_UNSIGNED_INT. Обычно под индексы используют unsigned short.

indices - указатель на массив с индексами. Заметьте, что этот указатель можно расценить, как указатель на элемент, с которого будет происходить расчёт объекта. То есть вы можете поставить указатель на любой элемент в массиве.
Для ясности новый пример:
void

DrawObjects()

{

static

GLfloat pVerts[]= {-0.5f, 0.0f, 0.0f,

-0.25f,-0.4f, 0.0f,

0.0f, 0.0f, 0.0f,

0.25f,-0.4f, 0.0f,

0.5f, 0.0f, 0.0f};

static

GLushort pInds[] =

{ 0,1,2 , 1,3,2 , 2,3,4 };

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3,GL_FLOAT,0,pVerts);

glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_SHORT, pInds);

}

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

Похожие:

OpenGL: Основы. (Часть 1) iconOpengl игорь Тарасов Часть I основы OpenGL
С тех пор библиотека завоевала огромную популярность и была интегрирована со множеством языков и систем разработки приложений. Вы...
OpenGL: Основы. (Часть 1) iconJava Opengl (jogl) библиотека, представляющая собой прямую привязку функций
Является реализацией спецификации jsr-231 (Java Bindings to OpenGL). Отмечена независимым сообществом opengl org
OpenGL: Основы. (Часть 1) icon1. Библиотека OpenGL
На данный момент в Windows существует два стандарта для работы с трёхмерной графикой: OpenGL, являющийся стандартом де-факто для...
OpenGL: Основы. (Часть 1) iconЛабораторная работа №2. Задание полигональных моделей объектов. Трехмерная визуализация с использованием OpenGL
Цель работы: ознакомиться с основным способом задания полигональных моделей – методом тиражирования сечений; ознакомиться со средствами...
OpenGL: Основы. (Часть 1) iconМатематика часть 3 Основы интегрального исчисления
Математика. Учебное пособие. Часть Основы интегрального исчисления. – Уфа: Уфимск гос акад экон и сервиса, 2006. – 45 с
OpenGL: Основы. (Часть 1) iconЗакон республики татарстан о внесении изменения в бюджетный кодекс республики татарстан принят
Татарстана, 2004, n 4-5; 2005, n 6 (II часть), n 10 (I часть), n 12 (IV часть); 2006, n 6 (I часть), n 12 (I часть); 2007, n 8, n...
OpenGL: Основы. (Часть 1) iconОсновы творческой деятельности журналиста Часть IV. Аналитическая журналистика Часть V. Художественная публицистика
«Îñíîâû òâîð÷åñêîé äåÿòåëüíîñòè æóðíàëèñòà. ×àñòü IV. Аналитическая журналистика. Часть V. Художественная публицистика». – Ì.: ÈÌÏÝ...
OpenGL: Основы. (Часть 1) iconРеферат «Применение OpenGL»

OpenGL: Основы. (Часть 1) iconУчебно-методический комплекс дисциплины основы творческой деятельности журналиста Часть IV. Аналитическая журналистика Для студентов факультета журналистики
Учебно-методический комплекс дисциплины «Основы творческой деятельности журналиста». Часть IV: Аналитическая журналистика / авт сост....
OpenGL: Основы. (Часть 1) iconУчебно-методический комплекс дисциплины Основы творческой деятельности журналиста Часть V художественная публицистика Для студентов факультета журналистики
Учебно-методический комплекс дисциплины «Основы творческой деятельности журналиста». Часть V: Художественная публицистика. – М.:...
Разместите кнопку на своём сайте:
ru.convdocs.org


База данных защищена авторским правом ©ru.convdocs.org 2016
обратиться к администрации
ru.convdocs.org