Глава 8. Компоненты просмотра сцены 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Глава 8. Компоненты просмотра сцены



 

Пришло время поближе познакомиться с вьюверами (viewers) в GLScene. В нашем распоряжении четыре компонента для вывода сцены на экран — это GLSceneViewer , GLFullScreenViewer , GLSDLViewer и GLMemoryViewer . Все они находятся на вкладке GLScene. Первые три используются для вывода изображения, полученного из камеры, на форму. Четвёртый выводит изображение от камеры в память. Далее детально рассказано о каждом из компонентов.

GLSceneViewer

 

У этого вьювера есть интересная особенность: он работает и в design time. Это очень удобно для проектирования трёхмерных сцен, ведь визуальные объекты будут видны на компоненте ещё до запуска откомпилированного файла (правда, не все).

GLFullScreenViewer

 

Для полноэкранного режима используется компонент GLFullScreenViewer. Полноэкранный режим означает, что во время запуска программы панель задач и меню пуск не будут видны. Переход в полноэкранный режим:

GLFullScreenViewer1.UseCurrentResolution;

GLFullScreenViewer1.Active:=True;

Количество FPS можно узнать процедурой GLFullScreenViewer1.Buffer. FramesPerSecond. Если не указывать команду UseCurrentResolution, то установится разрешение Width*Height.

Этот компонент имеет многие события, свойственные форме, поэтому его в большинстве случаев разумно размещать не на форме (которая все равно будет невидима под вьювером, когда он активен), а на невизуальном DataModule (создается в File — New — Data Module).

GLSDLViewer

По завершению работы приложения (точнее сказать, при удалении контекста) возможны утечки памяти из-за использования этого вьювера. Также могут вылетать Access Violation при завершении приложения, работающего с ним.

 

Прежде чем начинать рассказ об этом компоненте, нужно рассказать о так называемых виджетах. Виджет — это набор библиотек для отрисовки пользовательского интерфейса, работы с устройствами ввода-вывода и т. д. Самые популярные виджеты в Linux — gtk и qt, которые предоставляют пользователю более-менее удобный интерфейс, сами же эти виджеты обращаются к X Window System. Компонент GLSDLViewer использует кроссплатформенную библиотеку SDL. Преимущество перед остальными вьюверами заключается в том, что SDL позволяет запускаться консольным приложениям на самых разных платформах (Windows, Linux, MacOS и других), при том, что у пользователя могут не быть установлены ни gtk, ни qt. Для использования этого компонента требуется установить пакет GLS_SDLXXX, где XXX — версия Delphi, и скопировать библиотеку GLScene\Source\GameAPIs\SDL. dll в Windows\system32.

В настоящее время GLSDLViewer устарел и нуждается в глобальной переработки. По этой причине мы не будет описывать работу с ним. Есть стандартная демка Demos\rendering\basicsdl.

GLMemoryViewer

 

GLMemoryViewer используется для рендинга сцены в память. Для использования этого компонента нужна поддержка расширения WGL_ARB_pbuffer extension (в наше врямя она есть почти везде). Стандартная демка, очень неудачно показывающая возможности этого компонента, лежит в Demos\rendering\memviewer. Этот компонент не будет использовать возможности современных компьютеров, где давно уже есть FBO.

Понятие об FPS

 

FPS — Frames Per Second (количество кадров в секунду) — очень важный параметр для определения быстродействия графического проекта. При маленьких значениях FPS игра начинает «идти скриншотами».

Поместите на форму таймер из вкладки System. Задайте у него свойство Interval = 100. В OnTimer введите следующие строки:

Caption:=Format('%.1f FPS', [GLSceneViewer1.FramesPerSecond]);

GLSceneViewer1.ResetPerformanceMonitor;

Первая строчка выводит в заголовке формы количество FPS, вторая делает так, чтобы выводилось не среднее значение FPS, а текущее. Подсчёт FPS в GLScene ведётся при перерисовке хотя бы одного из объектов сцены, если этого не происходит, то выдаётся нулевое значение.

Общие свойства вьюверов

 

Вьюверы в GLScene управляют ключевыми параметрами, влияющими на всю сцену. Например, сглаживанием, вертикальной синхронизацией, освещенией, а так же фоновым цветом, туманом и многим другим. Ниже приведена таблица-описание этих свойств.

Свойство Описание
Camera Ссылка на камеру, с которой будет приходить изображение на GLSceneViewer.
VSync Использование возможно только при наличии расширения WGL_EXT_swap_control. Свойство отвечает за включение и выключение так называемой вертикальной синхронизации. Это синхронизация кадровой частоты в компьютерной игре с частотой вертикальной развёртки монитора. В некоторых случаях убирает артефакты, также убирает подергивания изображения. При этом несколько снижается производительность, иногда довольно значительно. Максимальный FPS с вертикальной синхронизацией приравнивается к частоте обновления монитора.

 

Теперь опишем свойства свойства Buffer. Для понимания многих из них необходимо знать OpenGL, но я старался привести в колонках всё максимально понятно и без знаний OGL.

Свойство Описание
AccumBufferBits Количество бит для буфера аккумулятора. Это специальный буфер, в который при помощи OpenGL-команд заносятся определенные значения цветов. Затем, при необходимости, они могут быть выведены в форме картинки. Хочу подчеркнуть, что свойство AccumBufferBits является устаревшим. Буфер аккумулятора давно уже не используется в OpenGL, поэтому и в GLScene по умолчанию false.
AmbientColor Цвет глобального освещения, который влияет на все объекты сцены, независимо от их материалов.
AntiAliasing Антиалиасинг или сглаживание. Чем выше цифра у значения, тем сильнее (и ресурсоемче) сглаживание. Работает только при поддержке расширения ARB_multisample. CSA режимы поддерживается только на видеокартах nVidia, подробнее о преимуществах режимов Coverage Sample AntiAliasing читайте здесь: developer.nvidia.com/object/coverage-sampled-aa.html
BackgroundColor Фоновый цвет
ColorDepth Глубина цвета
ContextOptions Отвечает за различные опции GL контекста: roDoubleBuffer — обеспечивает двойную буферизацию. Что это такое и с чём едят: .mirgames.ru/articles/opengl/around_gl.html; roStencilBuffer — установка этого свойства помогает избавиться от мерцания очень близкорасположенных треугольников моделей; roTwoSideLighting — обеспечивает двухсторонние освещение; roNoSwapBuffers — если True, то сцена будет просчитываться, но не будет выводится на вьювер; roNoDepthBufferClear — буфер глубины не будет очищаться автоматически при значении True; roForwardContext — будет использоваться OpenGL 1.1.
DepthPrecision Отвечает за точность буфера глубины (или Z-буфера). Что это такое, см. здесь: gamedev.ru/code/terms/ZBuffer. Значение по умолчанию 24 бита, самое высокое.
DepthTest Если True (по умолчанию), то вьювер будет ипользовать тест глубины для объектов.
FaceCulling Определяет отсечение граней. Все модели в OpenGL состоят из граней (faces), и для большей производи-тельности некоторые грани можно не отрисовывать (этот приём называется face culling). Когда face culling включен, то грани с нормалями, направленными от наблюдателя, не отрисовываются.
FogEnabled Включает/выключает туман (см. ниже).
FogEnvironment Содержит настройки тумана.
Lighting Включено ли освещение. Если оно выключено, то учитывается только глобальное (Ambient) освещение.
ShadeModel Используемая модель освещения граней. Задаётся в OpenGL через glShadeModel. smSmooth — метод Гуро или Фонга; smFlat — метод Ламберта.

Разрешения дисплея

 

GLScene позволяет в любой момент времени изменить текущее разрешение экрана. Делается это следующим образом (нужно подключить модуль GLScreen):

var

res: TResolution;

begin

res:=GetIndexFromResolution(640, 480, 32);

SetFullScreenMode(res);

end;

Помимо разрешения мы ещё задали и глубину цветопередачи, обычно она составляет 32 бита. Этот код изменит разрешение не только вьювера, но и рабочего стола и всех приложений (если они видны), но после завершения работы программы будет установлено исходное разрешение.

Возможна такая ситуация: пользователь растягивает форму с игрой на весь экран и видит весь мир, но когда он уменьшает размеры окна, то видит всё меньше игрового пространства. При необходимости исправить это достаточно просто: нужно подгонять масштаб сцены при изменении размера формы.

GLCamera1.FocalLength:=GLCamera1.FocalLength*

Width/Screen.Width;

Порой нужно получить список поддерживаемых видеорежимов, чтобы дать пользователю возможность выбрать наиболее подходящий. Конечно, чем больше разрешение, тем качественнее картинка (если монитор его поддерживает), однако тем больше и нагрузка на систему, причём значительно. Для получения этого списка можно воспользоватсья процедурой ReadVideoModes из модуля GLScreen. Она работает как на Windows, так и на Unix системах. Демонстрация:

var i: integer;

begin

ReadVideoModes;

for i:=0 to vNumberVideoModes-1 do

Memo1.Lines.Add(IntToStr(vVideoModes[i].Width)+' x'+ IntToStr(vVideoModes[i].Height)+' | '+ IntToStr(vVideoModes[i].MaxFrequency)+' | '+ IntToStr(vVideoModes[i].ColorDepth)+
vVideoModes[i].Description);

end;

В поле Width у vVideoModes записана ширина, в поле Height высота, в поле MaxFrequency частота обновления экрана, в ColorDepth глубина цвета, в Description только у одного из разрешений будет записано «default» (то есть это разрешение установлено сейчас), для остальных разрешений оно будет пусто. Если вы программно установили разрешение экрана, отличное от того, которое было установлено на рабочем столе, то ReadVideoModes вернёт, что ни одно разрешение не установлено по умолчанию. Если же вы переустановили разрешение и вам нужно знать его, то просто до или после переустановки запишите это разрешение в переменную.

Диагонали дисплеев

 

В мире распространены мониторы двух видов: с соотношением сторон 4:3 и 16:9. Ниже показана разница между ними. Синий прямоугольник — соотношение 16:9, сиреневый — 4:3.

 

При разработке графических приложений следует учитывать эту существенную разницу. Можно поступить двумя путями. Первый путь — обрезать изображение на мониторах 4:3 сверху и снизу. Подходит только для игровых приложений и позволяет избежать разной области видимости на разных мониторах. Идея следующая: мы получили текущее разрешение монитора, если при делении ширины на высоту получилось число 4/3, то монитор надо обрезать. Обрезание будет проводиться в событии OnCreate формы, чтобы при создании окно уже было обрезано, а также проводиться в событии OnResize, чтобы при изменении размера окна обрезка не сбивалась. Тогда в коде это будет выглядеть следующим образом:

var

WildScreen: boolean;

function IntVectorMake(const x,y,z,w: Integer): TVector4i;

begin

Result[0]:=x;

Result[1]:=y;

Result[2]:=z;

Result[3]:=w;

end;

 

procedure TForm1.FormCreate(Sender: TObject);

var

NewScreenHeight: Integer;

begin

ReadVideoModes;

if vVideoModes[0].Width/vVideoModes[0].Height=4/3 then

begin

WildScreen:=True;

NewScreenHeight:=GLSceneViewer.Width *9 div 16;

GLSceneViewer.Buffer.RenderingContext.Activate;

GLSceneViewer.Buffer.RenderingContext.GLStates.SetViewPort(

IntVectorMake(0,(GLSceneViewer.Height-NewScreenHeight) div 2,

GLSceneViewer.Width,NewScreenHeight));

end;

end;

 

procedure TForm1.FormResize(Sender: TObject);

var

NewScreenHeight: Integer;

begin

if WildScreen then

begin

NewScreenHeight:=GLSceneViewer.Width *9 div 16;

GLSceneViewer.Buffer.RenderingContext.GLStates.SetViewPort(

IntVectorMake(0,(GLSceneViewer.Height-NewScreenHeight) div 2,

GLSceneViewer.Width,NewScreenHeight));

end;

end;

Пояснение. Мы здесь пользуемся тем, что ReadVideoModes записывает установленное по умолчанию разрешение в vVideoModes[0]. Поэтому мы берём значения оттуда. Переменная WideScreen объявлена здесь для того, чтобы лишний раз не проводить деление ширины на высоту. Функция VectorMake объявлена в одном из модулей GLScene, но там используется не тот тип, нам нужен именно TVector4i. Метод SetViewPort имеет четыре параметра;первые два задают координаты точки, от которой будут откладываться ширина (третий параметр) и высота (четвёртый). Реализация обрезания экрана внутри SetViewPort проводится с помощью OpenGL команды glviewport. Совсем недавно в мире стали распространяться так называемые нетбуки, которые имеют соотношение экрана 16:10. Если вы хотите обрезать экран под соотношение 16:10, то вам понадобится модифицировать только проверку соотношения (vVideoModes[0]. Width/vVideoModes[0]. Height=4/3) (подставить 16/10 вместо 4/3) и расчётNewScreenHeight(GLSceneViewer. Width *10 div 16) вместо *9 div 16.

Обрезать экран — не самый красивый вариант, пользователи будут им не очень довольны. Поэтому большинство игр подстраиваются под различные мониторы, например, Napoleon Total War. А некоторые экран всё-таки обрезают, например, GTA Vice City.

Туман

 

GLSceneViewer позволяет задать настройки тумана. Они расположены в свитке GLSceneViewer.Buffer.FogEnvironment. При создании тумана, он будет ложиться равномерно и с неизменяемой плотностью. Это удобно, когда нужен эффект утреннего тумана.

Поместите на форму GLScene и GLSceneViewer. Создайте источник света и камеру, которую установите вьюверу. Свойству GLCamera1. Position.Z присвойте 5. Далее создайте две сферы и расположите их в любом порядке (но чтобы обе были видны). Теперь разверните свойство GLSceneViewer1. Buffer и установите FogEnable = True, после чего разверните FogEnvironment.

Туман включен, теперь выберем подходящий цвет в FogColor. Обычно цвет тумана — оттенок белого, но поскольку у нас серый фон, да и сферы тоже, выберем, например, clrDarkPurple. Теперь обратим внимание на свойство FogEnd. Оно отвечает за то, на какое расстояние туман будет простилаться, чем больше это значение, тем менее затуманенными будут ближайшие объекты, а если объект дальше этого значения, к нему применяется туман максимальной плотности (весь объект становится цвета FogColor — сфера 2 на рисунке). Для нашей сцены свойство слишком велико, уменьшите его до 9. Теперь рассмотрим FogStart. Он определяет, с какого расстояния от камеры туман будет накладываться, поставим 0. Результаты отобразятся прямо в вьювере.

Демка с демонстрацией тумана есть в стандартном наборе по адресу Demos\rendering\fog.

 

Другие свойства тумана:

Свойство Описание
FogDistance Задействуется только при наличии расширения GL_NV_fog_distance. Может принимать значения: fdDefault — OpenGL использует наиболее удобную формулу (самая высокая скорость). fdEyeRadial — использует радиальную — «правильную» систему расчёта (самое лучшее качество) fdEyePlane — рассчитывается с использованием дистанции до плоскости проекции (среднее качество).
FogMode Свойство задаёт способ расчёта тумана. Может быть fmLinear, fmExp2, fmExp. Более подробно о каждом режиме можите прочитать в OpenGL Red Book, но это материал повышенной трудности.

 

В GLScene для создания тумана используется устаревшая команда OpenGL glFog*. Сейчас вместо неё используют шейдеры. Помимо избавления от устаревшего функционала, шейдеры ещё и позволяют создать так называемый объёмный туман (volumetric fog).

В реализации объёмного тумана вам помогут ресурсы www.gamedev.ru и pmg.org.ru. Только для продвинутых пользователей!

 



Поделиться:


Последнее изменение этой страницы: 2016-04-19; просмотров: 707; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.225.149.136 (0.047 с.)