Работа с рендерингом контекстов
Контекст рендеринга является контейнером для получения информации состояния. Когда Вы определяете контекст рендеринга как текущий контекст рендеринга, последующие команды OpenGL изменяют состояние того контекста, объекты, присоединенные к тому контексту или drawable объекту, связанному с тем контекстом. По мере необходимости, когда контекст рендеринга фактически присоединен к drawable объекту, фактические поверхности получения никогда не принадлежат контексту рендеринга, но создаются. Можно присоединить многократные контексты рендеринга к тем же поверхностям получения. Каждый контекст поддерживает свое собственное состояние получения.
Рисование к Окну или Представлению, Рисование на Полный экран и Рисование Вне экрана показывают, как создать контекст рендеринга и присоединить его к drawable объекту. В этой главе описываются усовершенствованные способы взаимодействовать с рендерингом контекстов.
Обновите контекст рендеринга когда изменения средства рендеринга или геометрии
Изменение средства рендеринга может произойти, когда пользователь перетаскивает окно от одного дисплея до другого или когда дисплей присоединен или демонтирован. Изменения геометрии происходят, когда режим отображения изменяется или когда окно изменено или перемещено. Если Ваше приложение использует NSOpenGLView
объект поддержать контекст, это автоматически обновляется. Приложение, создающее пользовательское представление для содержания контекста рендеринга, должно отследить надлежащие системные события и обновить контекст, когда изменяются геометрия или дисплей.
Обновление контекста рендеринга уведомляет его относительно изменений геометрии; это не сбрасывает содержание. Вызов функции обновления обновляет присоединенные drawable объекты и гарантирует, что средство рендеринга должным образом обновляется для любых виртуальных экранных изменений. Если Вы не обновляете контекст рендеринга, можно видеть артефакты рендеринга.
Подпрограмма, что Вы требуете обновление, определяет, как обрабатываются события, связанные со средством рендеринга и изменениями геометрии. Для приложений то использование или подкласс NSOpenGLView
, Какао вызывает update
метод автоматически. Приложения, создающие NSOpenGLContext
объект вручную должен вызвать update
метод NSOpenGLContext
непосредственно. Для полноэкранного приложения Какао, вызывая setFullScreen
метод NSOpenGLContext
гарантирует, чтобы глубина, размер или изменения дисплея взяли влияние.
Ваше приложение должно обновить контекст рендеринга после системного события, но прежде, чем нарисовать к контексту. Если drawable объект изменен, можно хотеть выпустить a glViewport
команда, чтобы гарантировать, что содержание масштабируется должным образом.
Важно, чтобы Вы не обновляли более, чем необходимые контексты рендеринга. Ваше приложение должно реагировать на события системного уровня и уведомления вместо того, чтобы обновить каждый кадр. Например, Вы захотите реагировать на перемещение окна и изменить размеры операций и вывести на экран изменения конфигурации, такие как изменение глубины цвета.
Отслеживание изменений средства рендеринга
Это довольно прямо для отслеживания изменений геометрии, но как прослежены изменения средства рендеринга? Это - то, где понятие виртуального экрана становится важным (см. Виртуальные Экраны). Изменение на виртуальном экране указывает изменение средства рендеринга, изменение в возможности средства рендеринга или обоих. Когда Ваше приложение обнаруживает окно, изменяют размеры события, события перемещения окна, или выводят на экран изменение, это должно проверить на виртуальный экран, изменяют и реагируют на изменение, чтобы гарантировать, что текущее состояние приложения отражает любые изменения в возможностях средства рендеринга.
Каждый специфичный для Apple OpenGL, APIs имеет функцию, возвращающую текущее виртуальное экранное число:
currentVirtualScreen
методNSOpenGLContext
классCGLGetVirtualScreen
функция
Виртуальное экранное число представляет индекс в списке виртуальных экранов, установленных в частности для объекта формата пикселя, используемого для контекста рендеринга. Число уникально для списка, но бессмысленно иначе.
Когда средство рендеринга изменяется, пределы и расширения, доступные OpenGL, могут также измениться. Ваше приложение должно повторно протестировать возможности средства рендеринга и использовать их для выбора его алгоритмов рендеринга соответственно. Посмотрите Определение Возможностей OpenGL, Поддерживаемых Средством рендеринга.
Обновление контекста рендеринга для пользовательского представления какао
Если Вы разделяете на подклассы NSView
вместо того, чтобы использовать NSOpenGLView
класс, Ваше приложение должно обновить контекст рендеринга. Это вследствие незначительных различий между событиями, обычно обработанными NSView
класс и обработанные NSOpenGLView
класс. Какао не вызывает a reshape
метод для NSView
класс, когда размер изменяется, потому что тот класс не экспортирует a reshape
метод для переопределения. Вместо этого необходимо выполнить, изменяют операции непосредственно в Вашем drawRect:
метод, ища изменения в поле зрения ограничивает до рисования содержания. Используя этот подход обеспечивает результаты, которые эквивалентны использованию reshape
метод NSOpenGLView
класс.
Перечисление 7-1 является частичной реализацией пользовательского представления, показывающего, как обработать обновления контекста. update
метод вызывают после перемещения, измените размеры и выведите на экран события изменения и когда поверхностное обновление потребностей. Класс добавляет наблюдателя к уведомлению NSViewGlobalFrameDidChangeNotification
, который отправляется каждый раз, когда NSView
объект, присоединивший поверхности (т.е. NSOpenGLContext
объекты), изменяет размеры, перемещает или изменяет координатные смещения.
Это немного более сложно для обработки изменений в конфигурации дисплея. Для этого необходимо зарегистрироваться для уведомления NSApplicationDidChangeScreenParametersNotification
через NSApplication
класс. Это уведомление отправляется каждый раз, когда конфигурация любого из дисплеев, присоединенных к компьютеру, изменяется (или программно или когда пользователь изменяет настройки в интерфейсе).
Перечисление 7-1 , Обрабатывающее контекст, обновляет для пользовательского представления
#import <Cocoa/Cocoa.h> |
#import <OpenGL/OpenGL.h> |
#import <OpenGL/gl.h> |
@class NSOpenGLContext, NSOpenGLPixelFormat; |
@interface CustomOpenGLView : NSView |
{ |
@private |
NSOpenGLContext* _openGLContext; |
NSOpenGLPixelFormat* _pixelFormat; |
} |
- (id)initWithFrame:(NSRect)frameRect |
pixelFormat:(NSOpenGLPixelFormat*)format; |
- (void)update; |
@end |
@implementation CustomOpenGLView |
- (id)initWithFrame:(NSRect)frameRect |
pixelFormat:(NSOpenGLPixelFormat*)format |
{ |
self = [super initWithFrame:frameRect]; |
if (self != nil) { |
_pixelFormat = [format retain]; |
[[NSNotificationCenter defaultCenter] addObserver:self |
selector:@selector(_surfaceNeedsUpdate:) |
name:NSViewGlobalFrameDidChangeNotification |
object:self]; |
} |
return self; |
} |
- (void)dealloc |
[[NSNotificationCenter defaultCenter] removeObserver:self |
name:NSViewGlobalFrameDidChangeNotification |
object:self]; |
[self clearGLContext]; |
} |
- (void)update |
{ |
if ([_openGLContext view] == self) { |
[_openGLContext update]; |
} |
} |
- (void) _surfaceNeedsUpdate:(NSNotification*)notification |
{ |
[self update]; |
} |
@end |
Параметры контекста изменяют поведение контекста
Контекст рендеринга имеет множество параметров, которые можно установить для удовлетворения потребностям получения OpenGL. Некоторые самые полезные, и часто пропускаемый, параметры контекста обсуждены в этом разделе: интервал подкачки, поверхностная непрозрачность, порядок рисования поверхности и управление заднего размера буфера.
Каждый специфичный для Apple OpenGL APIs обеспечивает подпрограмму для установки и получения параметров контекста рендеринга:
setValues:forParameter:
методNSOpenGLContext
класс берет в качестве параметров список значений и список параметров.CGLSetParameter
функция берет в качестве параметров контекст рендеринга, константа, указывающая опцию и значение для той опции.
Некоторые параметры должны быть позволены для их значений вступить в силу. Справочная документация для параметра указывает, должен ли быть включен параметр. Посмотрите Ссылку класса NSOpenGLContext и Ссылку CGL.
Интервал подкачки позволяет приложению синхронизировать обновления с экранным обновлением
Если интервал подкачки установлен в 0
(значение по умолчанию), буферы подкачиваются как можно скорее, вне зависимости от частоты кадровой развертки монитора. Если интервал подкачки установлен в какое-либо другое значение, буферы подкачиваются только во время вертикали, восстанавливают монитора. Для получения дополнительной информации посмотрите, Синхронизируются с Экранной Частотой обновления.
Можно использовать следующие константы, чтобы указать установку значения интервала подкачки:
Для Какао использовать
NSOpenGLCPSwapInterval
.При использовании API CGL использовать
kCGLCPSwapInterval
как показано в Перечислении 7-2.
Перечисление 7-2 Используя CGL для установки синхронизации
GLint sync = 1; |
// ctx must be a valid context |
CGLSetParameter (ctx, kCGLCPSwapInterval, &sync); |
Поверхностная непрозрачность указывает как смешения поверхности OpenGL с поверхностями позади него
Поверхности OpenGL обычно представляются как непрозрачные. Таким образом цвет фона для пикселей с альфа-значениями 0.0
поверхностный цвет фона. Если Вы устанавливаете значение поверхностного параметра непрозрачности к 0
, тогда содержание поверхности смешивается с содержанием поверхностей позади поверхности OpenGL. Эта работа эквивалентна OpenGL, смешивающемуся с исходным вкладом, пропорциональным исходной альфе и фоновому вкладу, пропорциональному 1
минус исходная альфа. Значение 1
означает, что поверхность непрозрачна (значение по умолчанию); 0
абсолютно прозрачные средние значения.
Можно использовать следующие константы, чтобы указать установку поверхностного значения непрозрачности:
Для Какао использовать
NSOpenGLCPSurfaceOpacity
.При использовании API CGL использовать
kCGLCPSurfaceOpacity
как показано в Перечислении 7-3.
Перечисление 7-3 Используя CGL для установки поверхностной непрозрачности
GLint opaque = 0; |
// ctx must be a valid context |
CGLSetParameter (ctx, kCGLCPSurfaceOpacity, &opaque); |
Порядок рисования поверхности указывает позицию поверхности OpenGL относительно окна
Значение 1
средние значения, что позиция выше окна; значение –1
указывает позицию, которая является ниже окна. Когда у Вас есть перекрывающиеся представления, устанавливая порядок к -1
причины OpenGL для рисования внизу, 1
причины OpenGL для привлечения вершины. Этот параметр полезен для рисования средств управления пользовательским интерфейсом поверх представления OpenGL.
Можно использовать следующие константы, чтобы указать установку поверхности, получающей стоимость заказа:
Для Какао использовать
NSOpenGLCPSurfaceOrder
.При использовании API CGL использовать
kCGLCPSurfaceOrder
как показано в Перечислении 7-4.
Перечисление 7-4 Используя CGL для устанавливания порядка рисования поверхности
GLint order = –1; // below window |
// ctx must be a valid context |
CGLSetParameter (ctx, kCGLCPSurfaceOrder, &order); |
Определение, происходит ли обработка вершины и фрагмента на GPU
CGL обеспечивает два параметра для проверки, использует ли система GPU для обработки: kCGLCPGPUVertexProcessing
и kCGLCPGPUFragmentProcessing
. Для проверки обработки вершины передайте вершину, постоянную CGLGetParameter
функция. Для проверки обработки фрагмента передайте фрагмент, постоянный CGLGetParameter
. Перечисление 7-5 демонстрирует, как использовать эти параметры.
Перечисление 7-5 Используя CGL, чтобы проверить, обрабатывает ли GPU вершины и фрагменты
BOOL gpuProcessing; |
GLint fragmentGPUProcessing, vertexGPUProcessing; |
CGLGetParameter (CGLGetCurrentContext(), kCGLCPGPUFragmentProcessing, |
&fragmentGPUProcessing); |
CGLGetParameter(CGLGetCurrentContext(), kCGLCPGPUVertexProcessing, |
&vertexGPUProcessing); |
gpuProcessing = (fragmentGPUProcessing && vertexGPUProcessing) ? YES : NO; |
Управление Обратным размером буфера
Обычно, задний буфер является тем же размером как окно, или просмотрите это, это вовлечено, и это изменяет размер, когда окно или представление изменяют размер. Для окна, размер которого 720 [×] пиксели, OpenGL назад буферизует, измерен для соответствия. Если окно растет до 1 024 [×] 768 пикселей, например, тогда задний буфер изменен также. Если Вы не хотите это поведение, используйте задний параметр управления размером буфера.
Используя этот параметр фиксирует размер заднего буфера и позволяет системе масштабировать изображение автоматически, когда это перемещает данные в переменный буфер размера (см. рисунок 7-1). Размер заднего буфера остается фиксированным в размере, который Вы устанавливаете независимо от того, изменено ли изображение для отображения больше на экране.
Можно использовать следующие константы, чтобы указать установку размера поддержки поверхности:
При использовании API CGL использовать
kCGLCPSurfaceBackingSize
, как показано в Перечислении 7-6.
Перечисление 7-6 Используя CGL для установки назад управления размером буфера
GLint dim[2] = {720, 480}; |
// ctx must be a valid context |
CGLSetParameter(ctx, kCGLCPSurfaceBackingSize, dim); |
CGLEnable (ctx, kCGLCESurfaceBackingSize); |
Совместное использование рендеринга ресурсов контекста
Контексту рендеринга не принадлежат рисованного объекты, присоединенные к нему, который оставляет открытым опция для совместного использования. Рендеринг контекстов может совместно использовать ресурсы и может быть присоединен к тому же drawable объекту (см. рисунок 7-2), или к различным drawable объектам (см. рисунок 7-3). Вы устанавливаете контекст, совместно использующий — или больше чем с одним drawable объектом или с другим контекстом — в то время, когда Вы создаете контекст рендеринга.
Контексты могут совместно использовать объектные ресурсы и их связанное объектное состояние путем указания совместно используемого контекста во время создания контекста. Совместно используемые контексты совместно используют все объекты текстуры, дисплейные списки, программы вершины, программы фрагмента, и буферизуют объекты, создаваемые прежде и после того, как будет инициироваться совместное использование. Состояние объектов также совместно используется, но не другое состояние контекста, такое как текущий цвет, настройки координаты текстуры, матрица и настройки освещения, состояние растеризации и параметры среды текстуры. Необходимо копировать изменения состояния контекста как требуется, но необходимо установить отдельные объекты только один раз.
При создании контекста OpenGL можно определять другой контекст, объектные ресурсы которого Вы хотите совместно использовать. Все совместное использование является коллегой для пиринга. Когда последний совместно использующий контекст ресурс выпущен, совместно используемые ресурсы считаются на ссылку и таким образом сохраняются, пока явно не выпущено или.
Не каждый контекст может быть совместно использован с любым контекстом. Оба контекста должны совместно использовать тот же профиль OpenGL. Необходимо также гарантировать, чтобы оба контекста совместно использовали тот же набор средств рендеринга. Вы удовлетворяете эти требования путем обеспечения, что каждый контекст использует тот же виртуальный экранный список, с помощью любого из следующих методов:
Используйте тот же объект формата пикселя создать все контексты рендеринга, которые Вы хотите совместно использовать.
Создайте объекты формата пикселя с помощью атрибутов, сужающих выбор к единственному дисплею. Эта практика гарантирует, что виртуальный экран идентичен для каждого объекта формата пикселя.
Установка совместно использованных контекстов рендеринга является очень прямой. Каждый специфичный для Apple OpenGL API предоставляет функциям опцию указать контекст для совместного использования в его подпрограмме создания контекста:
Используйте
share
параметр заinitWithFormat:shareContext:
методNSOpenGLContext
класс. См. Перечисление 7-7.Используйте
share
параметр для функцииCGLCreateContext
. См. перечисление 7-8.
Перечисление 7-7 гарантирует тот же виртуальный экранный список при помощи того же объекта формата пикселя для каждого из совместно используемых контекстов.
Перечисление 7-7 , Настраивающее NSOpenGLContext
объект для совместного использования
#import <Cocoa/Cocoa.h> |
+ (NSOpenGLPixelFormat*)defaultPixelFormat |
{ |
NSOpenGLPixelFormatAttribute attributes [] = { |
NSOpenGLPFADoubleBuffer, |
(NSOpenGLPixelFormatAttribute)nil }; |
return [(NSOpenGLPixelFormat *)[NSOpenGLPixelFormat alloc] |
initWithAttributes:attribs]; |
} |
- (NSOpenGLContext*)openGLContextWithShareContext:(NSOpenGLContext*)context |
{ |
if (_openGLContext == NULL) { |
_openGLContext = [[NSOpenGLContext alloc] |
initWithFormat:[[self class] defaultPixelFormat] |
shareContext:context]; |
[_openGLContext makeCurrentContext]; |
[self prepareOpenGL]; |
} |
return _openGLContext; |
} |
- (void)prepareOpenGL |
{ |
// Your code here to initialize the OpenGL state |
} |
Перечисление 7-8 гарантирует тот же виртуальный экранный список при помощи того же объекта формата пикселя для каждого из совместно используемых контекстов.
Перечисление 7-8 , Настраивающее контекст CGL для совместного использования
#include <OpenGL/OpenGL.h> |
CGLPixelFormatAttribute attrib[] = {kCGLPFADoubleBuffer, 0}; |
CGLPixelFormatObj pixelFormat = NULL; |
Glint numPixelFormats = 0; |
CGLContextObj cglContext1 = NULL; |
CGLContextObj cglContext2 = NULL; |
CGLChoosePixelFormat (attribs, &pixelFormat, &numPixelFormats); |
CGLCreateContext(pixelFormat, NULL, &cglContext1); |
CGLCreateContext(pixelFormat, cglContext1, &cglContext2); |