为什么我需要在drawInRect中调用glClear?

时间:2014-12-23 02:07:47

标签: ios iphone opengl-es glkit

我有一个简单的GLKViewController,我将屏幕设为白色:

- (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);
}

为什么?为什么必须在drawInRect中调用glClear而不是glClearColor?

1 个答案:

答案 0 :(得分:4)

GPU上下文包含许多值,这些值在更改之前一直保留。其中一个是清晰的颜色,由4个浮动值组成。无论何时设置这些值,它们都将保持为相同的值,并且可以重复使用,直到您再次更改它们为止。

因此,可以在创建和设置上下文后随时设置清晰颜色。 glClear将使用此值将颜色绑定缓冲区组件(像素)设置为此值。为此,必须至少绑定一个帧缓冲区。

调用glClear中的viewDidLoad可能有效,也可能无效,因为此调用需要绑定帧缓冲区,因此它知道要清除哪个缓冲区以前设置的颜色。 “可能或可能不是有效”我的意思是因为你正在使用来自GLKit的便利类,你实际上无法控制甚至不知道这些类正在使用的管道。在您调用该函数时,您不知道您的缓冲区是否已绑定或甚至已创建。如果您手动创建了这个,您将创建一个上下文,创建一个帧缓冲区并附加渲染缓冲区,然后您可以清除这些缓冲区,并且所有缓冲区都按预期工作。

因此,glClear方法可以随时调用drawRect,有时甚至可以多次调用glClearColor。此调用产生的结果与使用openGL设置的颜色绘制完整缓冲区大小rect相同,不同之处在于它在char buffer[width][height][4]绘制管道中跳过几个步骤时加快了您可以清除颜色缓冲区(例如深度缓冲区)。

您清除的渲染缓冲区最好呈现为像素的二维数组或glViewport,因为它通常有4个颜色分量(RGBA)。缓冲区数据再次被保留,并且可以反复重绘,您可以使用glClear绘制到不同的平静点或甚至呈现某个部分。如果清除每个并条机上的缓冲区调用,则意味着您需要重新绘制所有元素,这通常是这种情况,但如果您想继续绘制缓冲区,则必须跳过清除调用。例如,如果您想在每次用户点击屏幕时绘制一个圆圈,您将跳过清除呼叫。但在这种情况下你也想丢失定时器(显示链接)来继续调用draw方法,当用户点击屏幕时你只是画圆圈并将缓冲区呈现给屏幕,没有理由继续刷新它

那为什么你需要拨打drawInRect中的GLKView?你没有,你可以随时调用它和任何你想要的方法,你需要确保你有正确的上下文集和正确的帧缓冲区绑定。虽然我同意如果您无法直接访问这些元素(在您的情况下使用{{1}}),这可能是一个问题。