Работа с рендерингом контекстов

Контекст рендеринга является контейнером для получения информации состояния. Когда Вы определяете контекст рендеринга как текущий контекст рендеринга, последующие команды OpenGL изменяют состояние того контекста, объекты, присоединенные к тому контексту или drawable объекту, связанному с тем контекстом. По мере необходимости, когда контекст рендеринга фактически присоединен к drawable объекту, фактические поверхности получения никогда не принадлежат контексту рендеринга, но создаются. Можно присоединить многократные контексты рендеринга к тем же поверхностям получения. Каждый контекст поддерживает свое собственное состояние получения.

Рисование к Окну или Представлению, Рисование на Полный экран и Рисование Вне экрана показывают, как создать контекст рендеринга и присоединить его к drawable объекту. В этой главе описываются усовершенствованные способы взаимодействовать с рендерингом контекстов.

Обновите контекст рендеринга когда изменения средства рендеринга или геометрии

Изменение средства рендеринга может произойти, когда пользователь перетаскивает окно от одного дисплея до другого или когда дисплей присоединен или демонтирован. Изменения геометрии происходят, когда режим отображения изменяется или когда окно изменено или перемещено. Если Ваше приложение использует NSOpenGLView объект поддержать контекст, это автоматически обновляется. Приложение, создающее пользовательское представление для содержания контекста рендеринга, должно отследить надлежащие системные события и обновить контекст, когда изменяются геометрия или дисплей.

Обновление контекста рендеринга уведомляет его относительно изменений геометрии; это не сбрасывает содержание. Вызов функции обновления обновляет присоединенные drawable объекты и гарантирует, что средство рендеринга должным образом обновляется для любых виртуальных экранных изменений. Если Вы не обновляете контекст рендеринга, можно видеть артефакты рендеринга.

Подпрограмма, что Вы требуете обновление, определяет, как обрабатываются события, связанные со средством рендеринга и изменениями геометрии. Для приложений то использование или подкласс NSOpenGLView, Какао вызывает update метод автоматически. Приложения, создающие NSOpenGLContext объект вручную должен вызвать update метод NSOpenGLContext непосредственно. Для полноэкранного приложения Какао, вызывая setFullScreen метод NSOpenGLContext гарантирует, чтобы глубина, размер или изменения дисплея взяли влияние.

Ваше приложение должно обновить контекст рендеринга после системного события, но прежде, чем нарисовать к контексту. Если drawable объект изменен, можно хотеть выпустить a glViewport команда, чтобы гарантировать, что содержание масштабируется должным образом.

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

Отслеживание изменений средства рендеринга

Это довольно прямо для отслеживания изменений геометрии, но как прослежены изменения средства рендеринга? Это - то, где понятие виртуального экрана становится важным (см. Виртуальные Экраны). Изменение на виртуальном экране указывает изменение средства рендеринга, изменение в возможности средства рендеринга или обоих. Когда Ваше приложение обнаруживает окно, изменяют размеры события, события перемещения окна, или выводят на экран изменение, это должно проверить на виртуальный экран, изменяют и реагируют на изменение, чтобы гарантировать, что текущее состояние приложения отражает любые изменения в возможностях средства рендеринга.

Каждый специфичный для Apple OpenGL, APIs имеет функцию, возвращающую текущее виртуальное экранное число:

Виртуальное экранное число представляет индекс в списке виртуальных экранов, установленных в частности для объекта формата пикселя, используемого для контекста рендеринга. Число уникально для списка, но бессмысленно иначе.

Когда средство рендеринга изменяется, пределы и расширения, доступные 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 обеспечивает подпрограмму для установки и получения параметров контекста рендеринга:

Некоторые параметры должны быть позволены для их значений вступить в силу. Справочная документация для параметра указывает, должен ли быть включен параметр. Посмотрите Ссылку класса 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 [&#215;] пиксели, OpenGL назад буферизует, измерен для соответствия. Если окно растет до 1 024 [&#215;] 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);
Рисунок 7-1  фиксированный размер назад буферизует и переменный передний буфер размера
A fixed size back buffer and variable size front buffer

Совместное использование рендеринга ресурсов контекста

Контексту рендеринга не принадлежат рисованного объекты, присоединенные к нему, который оставляет открытым опция для совместного использования. Рендеринг контекстов может совместно использовать ресурсы и может быть присоединен к тому же drawable объекту (см. рисунок 7-2), или к различным drawable объектам (см. рисунок 7-3). Вы устанавливаете контекст, совместно использующий — или больше чем с одним drawable объектом или с другим контекстом — в то время, когда Вы создаете контекст рендеринга.

Контексты могут совместно использовать объектные ресурсы и их связанное объектное состояние путем указания совместно используемого контекста во время создания контекста. Совместно используемые контексты совместно используют все объекты текстуры, дисплейные списки, программы вершины, программы фрагмента, и буферизуют объекты, создаваемые прежде и после того, как будет инициироваться совместное использование. Состояние объектов также совместно используется, но не другое состояние контекста, такое как текущий цвет, настройки координаты текстуры, матрица и настройки освещения, состояние растеризации и параметры среды текстуры. Необходимо копировать изменения состояния контекста как требуется, но необходимо установить отдельные объекты только один раз.

Рисунок 7-2  Совместно используемые контексты, присоединенные к тому же drawable объекту
Shared contexts attached to the same drawable object

При создании контекста OpenGL можно определять другой контекст, объектные ресурсы которого Вы хотите совместно использовать. Все совместное использование является коллегой для пиринга. Когда последний совместно использующий контекст ресурс выпущен, совместно используемые ресурсы считаются на ссылку и таким образом сохраняются, пока явно не выпущено или.

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

Рисунок 7-3  Совместно используемые контексты и больше чем один drawable объект
Shared contexts and more than one drawable object

Установка совместно использованных контекстов рендеринга является очень прямой. Каждый специфичный для Apple OpenGL API предоставляет функциям опцию указать контекст для совместного использования в его подпрограмме создания контекста:

Перечисление 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);