2014-12-23 1 views
1

У меня есть простой GLKViewController где я сделал экран белый:Зачем мне нужно звонить glClear в drawInRect?

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 

    GLKView *view = (GLKView *)self.view; 
    view.context = self.context; 

    [EAGLContext setCurrentContext:self.context]; 

    glClearColor(1, 1, 1, 1); 
    glClear(GL_COLOR_BUFFER_BIT); 
} 

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { 
} 

Это не работает, однако.

Но, если я перееду вызов glClear к drawInRect, то он работает:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { 
    glClear(GL_COLOR_BUFFER_BIT); 
} 

Почему? Зачем нужно вызывать glClear в drawInRect, но glClearColor нет?

+0

Возможный дубликат [Есть ли разница между glClearColor (0.0,0.0.0.0.0.0) и glClear (COLOR \ _BUFFER \ _BIT)?] (Http: // stackoverflow.com/questions/4296126/is-there-a-difference-between-glclearcolor0-0-0-0-0-0-0-0-and-glclearcolor-bu) –

+0

@ 0xSina: Я не знаком с вашим кодом , но я подозреваю, что проблема - это количество раз, которое вызывается каждой из этих функций. Первое звучит как нечто, которое будет вызываться один раз при инициализации (фреймбуфер может даже не иметь конечных размеров а эта точка), а второй используется для делегирования чертежа из GLKview. Обычно вы хотите очищать буфер цветов каждый раз, когда вы рисуете, поэтому вызов его в 'drawInRect' имеет смысл на нескольких уровнях. –

ответ

3

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

Таким образом, прозрачный цвет можно установить в любое время после создания и установки контекста. Это значение будет использоваться glClear, чтобы установить компоненты буфера, связанные с цветом (пиксели), на это значение. Для этого для работы буфер кадров должен быть связан как минимум.

Вызов glClear в viewDidLoad может быть или недействительным, так как для этого вызова необходим буфер кадра, который должен быть привязан, чтобы он знал, какой буфер очистится до ранее установленного цвета. Под «может быть или не быть допустимо» я имею в виду, поскольку вы используете классы удобства из GLKit, у вас действительно нет контроля или даже идеи о конвейере, который используют эти классы. В то время, когда вы вызываете эту функцию, вы не представляете, связан ли ваш буфер или даже создан. Если вы создали это вручную, вы создадите контекст, создаете буфер кадров и присоединяете буферы визуализации, тогда вы можете очистить эти буферы, и все работает как ожидалось.

Так что glClear можно назвать в любое время и в некоторых случаях даже несколько раз в методе drawRect. Результатом этого вызова является то же самое, что и рисование полного размера размера буфера с цветом, установленным glClearColor, разница в том, что он намного быстрее, поскольку он пропускает несколько шагов в конвейере вывода openGL плюс вы можете очистить больше, чем цветной буфер (например, буфера глубины).

Буфер визуализации, который вы очищаете, может быть лучше всего представлен как 2-мерная матрица пикселей или что-то вроде char buffer[width][height][4], поскольку он имеет 4 цветовых компонента (RGBA). Буферные данные снова сохраняются и могут быть перерисованы снова и снова, вы можете рисовать на разные стороны или даже представлять определенную часть, используя glViewport. Если вы очищаете буфер при каждом обращении кадра кадра, это означает, что вам нужно будет снова перерисовать все элементы, что обычно имеет место, но если вы хотите продолжать рисовать материал в буфер, вы должны пропустить ясный вызов. Например, если вы хотите нарисовать круг каждый раз, когда пользователь нажимает на экран, вы пропускаете ясный вызов. Но в этом случае вы также захотите потерять таймер (ссылку на изображение), чтобы продолжить вызов метода draw, когда пользователь набирает экран, вы просто рисуете круг и представляете буфер на экране, нет причин продолжать его обновлять ,

Для чего вам нужно позвонить в glClear в drawInRect? Вы не можете, вы можете назвать его в любой момент и любой метод, который вам нужен, все, что вам нужно, чтобы убедиться, что у вас есть правильный набор контекстов и правильный буфер буфера. Хотя я согласен, это может быть проблемой, если у вас нет прямого доступа к этим элементам, которые в вашем случае используют GLKView.

+0

Благодарим вас за подробный ответ. Я понимаю это сейчас. – 0xSina