Преобразуйте структуру NeHe VC OPENGL, переведенную CKER, в версию Delphi.
Я надеюсь, что это будет полезно братьям, которые используют Delphi для изучения OPENGL.
Я не знаю почему, но он не может работать непосредственно в моей среде Delphi, но на других машинах он вроде бы работает нормально.
Моя машина может компилировать и запускать только EXE-файлы.
Спасибо NeHe за предоставление такой хорошей структуры и спасибо CKER за перевод информации VC.
ПРОГРАММА Проект1;
Использование
опенгл,
окна,
Сообщения;
Конст
WND_TITLE = 'Базовая структура OPenGl'; //Название
Вар
//============================================== ==========================
// Каждый OpenGL связан с контекстом затенения. Таблица контекста затенения соединяет все вызовы OpenGL с
// Получаем контекст устройства (таблицу описания устройства) и определяем таблицу описания затенения OpenGL как hRC, чтобы программа могла
// Если достаточно нарисовать окно, необходимо также создать таблицу описания устройств. Таблица описания устройств Windows определяется как hDC,
// DC подключает окно к GDI (интерфейс графического устройства). И RC подключает OpenGL
// в ДЦ.
//============================================== ==========================
h_RC: HGLRC; // Контекст рендеринга (таблица описания затенения).
h_DC: HDC // Контекст устройства (таблица описания устройства)
h_Wnd: HWND // дескриптор окна;
h_Instance: HINST // Экземпляр программы (экземпляр).
клавиши: Array[0..255] Boolean // Массив для клавиатурных процедур;
{$R *.res}
//============================================== =============================
//Сбрасываем размер сцены OpenGL независимо от того, изменился ли размер окна (при условии, что полноэкранный режим не используется).
//Даже если размер окна нельзя изменить (например, в полноэкранном режиме), оно все равно запустится хотя бы один раз————————
//Установим перспективу в начале программы. Размер сцены OpenGL будет установлен в соответствии с размером окна, в котором она отображается.
//============================================== =============================
Процедура glResizeWnd(Width, Height: Integer); //Сбрасываем и инициализируем размер окна GL;
Начинать
If (Height = 0) then // Предотвращаем, чтобы высота была равна 0 и вызывала исключение деления на 0.
Высота := 1;
glViewport(0, 0, Width, Height); //Сбрасываем текущую область просмотра (Viewport);
//Следующие строки настраивают экран перспективы. Это означает, что предметы, находящиеся дальше, кажутся меньшими. Это создает реальность
//Сцена появления. Перспектива здесь рассчитывается как угол обзора 45 градусов в зависимости от ширины и высоты окна. 0,1f, 100,0f — это
//Начальная и конечная точки глубины, которую мы можем нарисовать на сцене.
//glMatrixMode(GL_PROJECTION) указывает, что следующие две строки кода будут влиять на матрицу проекции.
//Матрица проекции отвечает за добавление перспективы в нашу сцену.
//glLoadIdentity() аналогичен сбросу. Он восстанавливает выбранное состояние матрицы в исходное состояние.
//После вызова glLoadIdentity() мы устанавливаем перспективу сцены.
glMatrixMode(GL_PROJECTION); //Выбираем матрицу проекции
glLoadIdentity(); // Сбрасываем матрицу проекции
gluPerspective(45.0, Width / Height, 0.1, 100.0 // Вычисляем пропорции внешнего вида окна
//glMatrixMode(GL_MODELVIEW) указывает, что любое новое преобразование повлияет на матрицу просмотра модели (матрицу наблюдения модели).
//Информация о нашем объекте хранится в матрице наблюдения модели.
glMatrixMode(GL_MODELVIEW); //Выбираем матрицу наблюдения модели
glLoadIdentity(); //Сброс матрицы наблюдения модели
//Если вы еще не понимаете, что означают эти термины, не волнуйтесь.
//Просто знайте, что вам нужно это сделать, если вы хотите получить великолепную перспективную сцену.
Конец;
//============================================== =============================
// Выполняем все настройки для OpenGL. Установите цвет очистки экрана, включите кеш глубины,
// Включаем плавное затенение (сглаживание теней) и т.д. Эта процедура не вызывается до тех пор, пока не будет создано окно OpenGL.
// Этот процесс будет иметь возвращаемое значение. Но инициализация здесь не такая уж и сложная, и о возвращаемом значении пока беспокоиться не приходится.
//============================================== =============================
Процедура glInit();
Начинать
//Устанавливаем цвет, используемый при очистке экрана. Если вы не уверены, как работает цвет, вот краткое объяснение.
//Значения цвета варьируются от 0.0f до 1.0f. 0,0f представляет самую темную ситуацию, а 1,0f — самую яркую.
//Первый параметр после glClearColor — интенсивность красного (красный компонент), второй — зеленый, а третий — синий.
//Максимальное значение также равно 1.0f, что представляет собой самый яркий случай определенного цветового компонента. Последний параметр — это значение Alpha.
//Когда он используется для очистки экрана, не обращайте внимания на четвертое число. Теперь пусть это будет 0,0f.
//Смешивая три основных цвета (красный, зеленый, синий), можно получить разные цвета
//Итак, используйте glClearColor(0.0f,0.0f,1.0f,0.0f), ваш синий цвет, чтобы очистить экран.
//Если вы используете glClearColor(0.5f,0.0f,0.0f,0.0f), для очистки экрана будет использоваться средний красный цвет.
//Не самый яркий (1.0f) и не самый темный (0.0f). Чтобы получить белый фон, все цвета должны быть установлены на максимально яркие (1.0f).
//Если вам нужен черный фон, установите для всех цветов самые темные (0,0f).
glClearColor(0.0, 0.0, 0.0, 0.0); // черный фон;
//Сглаживание теней аккуратно смешивает цвета в полигонах и сглаживает внешний свет.
glShadeModel(GL_SMOOTH); // Включаем сглаживание теней;
//Следующее, что нужно сделать, это буфер глубины. Думайте о буфере глубины как о слое за экраном.
//Буфер глубины постоянно отслеживает, насколько глубоко объект входит в экран. Эта программа на самом деле не использует кэш глубины.
//Но почти все программы OpenGL, отображающие 3D-сцены на экране, используют буферы глубины. Его порядок определяет, какой объект будет нарисован первым.
//Таким образом, вы не рисуете квадрат за кругом на круге. Буфер глубины — очень важная часть OpenGL.
glClearDepth(1.0); //Устанавливаем буфер глубины
glEnable(GL_DEPTH_TEST); // Включить тестирование глубины
glDepthFunc(GL_LESS); // Тип выполненной проверки глубины
//Затем сообщаем OpenGL, что нам нужна наилучшая возможная коррекция перспективы.
//Это очень незначительно повлияет на производительность. Но делает перспективу немного лучше.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Действительно тонкая коррекция перспективы
Конец;
//============================================== =============================
//Весь код рисования. Все, что вы хотите отобразить на экране, появится в этом коде.
//Каждая будущая программа будет добавлять сюда новый код.
//============================================== =============================
Процедура glDraw();
Начинать
glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT // Очистить экран и буфер глубины);
glLoadIdentity(); //Сбрасываем матрицу наблюдения текущей модели
Конец;
Функция WndProc(hWnd: HWND; // дескриптор окна
Сообщение: UINT; // Сообщение окна
wParam: WPARAM // Дополнительный контент сообщения
lParam: LPARAM // Дополнительное содержимое сообщения
): ЛРЕЗУЛЬТАТ;
Начинать
Результат:= 0;
Случай (Msg) // Проверка сообщений Windows
WM_ACTIVATE: // Сообщение об активации окна монитора
Начинать
Конец;
WM_CREATE: // Создать
Начинать
Конец;
WM_CLOSE: // закрываем
Начинать
PostQuitMessage(0); //Отправляем сообщение о выходе
Результат := 0
Конец;
WM_KEYDOWN: // клавиша нажата
Начинать
keys[wParam] := True // Если да, установите TRUE;
Результат:= 0;
Конец;
WM_KEYUP: // Отпускаем клавишу
Начинать
keys[wParam] := False // Если да, установите значение FALSE;
Результат:= 0;
Конец;
WM_SIZE: //Регулировка размера окна OpenGL
Начинать
glResizeWnd(LOWord(lParam), HIWORD(lParam)); //LoWord=Width,HiWord=Height);
Результат:= 0;
Конец;
WM_TIMER: //таймеры
Начинать
Конец;
Else //Позвольте Windows сделать все остальное.
Результат: = DefWindowProc(hWnd, Msg, wParam, lParam); // Передаем все необработанные сообщения в DefWindowProc.
Конец;
Конец;
//============================================== =============================
// Вызывается только перед выходом из программы. Функция состоит в том, чтобы последовательно освободить таблицу контекста окраски, таблицу контекста устройства и дескриптор окна.
// Добавлено много проверок ошибок. Если программе не удастся уничтожить какую-либо часть окна, появится соответствующее сообщение об ошибке.
// окно сообщения,
//============================================== =============================
Процедура glKillWnd (Полноэкранный режим: логическое значение);
Начинать
//Первое, что делается в KillGLWindow() — проверяется, находится ли он в полноэкранном режиме.
//Если да, переключимся обратно на рабочий стол. Окно должно было быть уничтожено до отключения полноэкранного режима,
//Но выполнение этого действия на некоторых видеокартах может привести к сбою рабочего стола. Поэтому лучше сначала отключить полноэкранный режим.
//Это предотвратит сбои рабочего стола и отлично работает как на видеокартах Nvidia, так и на 3dfx!
Если полноэкранный режим, то // В полноэкранном режиме?
Начинать
// Используйте ChangeDisplaySettings(NULL,0) для возврата к исходному рабочему столу.
// Берем NULL в качестве первого параметра,
// Передача 0 в качестве второго параметра заставляет Windows использовать значение, хранящееся в данный момент в реестре
// (разрешение по умолчанию, глубина цвета, частота обновления и т. д.), чтобы эффективно восстановить исходный рабочий стол.
// После переключения обратно на рабочий стол указатель мыши должен снова стать видимым.
ChangeDisplaySettings(devmode(Nil^), 0 // Если да, переключимся обратно на рабочий стол
ShowCursor(True); //Показать мышь
Конец;
//Есть ли у него таблица описания раскрасок (hRC).
Если h_RC > 0 Тогда
//Посмотрим, сможем ли мы его освободить (отделить hRC от hDC).
Если (Не wglMakeCurrent(h_DC, 0)) Тогда
MessageBox(0, «DC и RC не могут быть освобождены!», «Ошибка», MB_OK Или
МБ_ИКОНЕРРОР);
// Можно ли удалить таблицу описания штриховки?
Если (Не wglDeleteContext(h_RC)) Тогда
Начинать
MessageBox(0, «Не удалось удалить таблицу контекстов затенения!», «Ошибка», MB_OK или
МБ_ИКОНЕРРОР);
h_RC:= 0;
Конец;
//Существует ли таблица контекста устройства, и если да, то пытаемся ее освободить.
Если ((h_DC > 0) И (ReleaseDC(h_Wnd, h_DC) = 0)) Тогда
Начинать
MessageBox(0, «Не удалось освободить контекст устройства!», «Ошибка», MB_OK или
МБ_ИКОНЕРРОР);
h_DC: = 0;
Конец;
//Если есть дескриптор окна, вызовите DestroyWindow(hWnd), чтобы попытаться уничтожить окно
Если ((h_Wnd <> 0) И (Не DestroyWindow(h_Wnd))) Тогда
Начинать
MessageBox(0, «Невозможно уничтожить форму!», «Ошибка», MB_OK Или
МБ_ИКОНЕРРОР);
h_Wnd:= 0;
Конец;
//Класс окна выхода из системы
//Это позволяет нам нормально уничтожить окно, а затем открыть другие окна,
//Вы не будете получать сообщения об ошибках, такие как «Класс Windows уже зарегистрирован» (класс окна уже зарегистрирован).
Если (Не UnRegisterClass('OpenGL', hInstance)) Тогда
Начинать
MessageBox(0, «Невозможно выйти из класса окна!», «Ошибка», MB_OK Или
МБ_ИКОНЕРРОР);
hInstance: = 0;
Конец;
Конец;