glClear()不适用于某些机器

时间:2018-02-14 06:52:10

标签: macos opengl fbo

我有一个带有FBO的OpenGL上下文,除了glClear()之外,我的所有简单绘图操作都能正常工作。我可以绘制纹理和矩形,但glClear()拒绝做任何事情。 glGetError()不会返回任何错误。

我这样调用glClear():

glRectd(0, 0, 1024, 1080);  // I see the results of this call
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // This does nothing

请注意,使用glClear()的代码在某些Mac上可以正常工作,但在其他Mac上则不行,所以也许我已经很幸运了,我需要以不同的方式设置上下文或其他设置。任何建议将不胜感激!

编辑:这与将纹理从FBO绘制到另一个上下文有关。在那之后,glClear()停止工作。

编辑2:我现在将它复制到一个小型Xcode项目中,我非常确定我已经得出结论,所有内容都适用于NVIDIA显卡但不适用于集成的Intel Iris卡。我很快就会发布测试代码。

编辑3:代码。我试图尽量减少它,但仍然有点大量。

//
// On the NVIDIA card, we'll see the video switch between red and green.
// On the Intel Iris, it will get stuck on blue because of "break" code below.
//

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    // Initialize the view to white
    [self clearContext:_view.openGLContext.CGLContextObj toRed:1 green:1 blue:1 alpha:1];

    // FBO context
    fbo = [[WTFBOContext alloc] initWithWidth:_view.frame.size.width height:_view.frame.size.height shareContext:_view.openGLContext];

    // Clear the FBO context (and thus texture) to solid blue
    [self clearContext:fbo.oglCtx.CGLContextObj toRed:0 green:0 blue:1 alpha:1];

    // These calls "break" the FBO on Intel Iris chips
    {
        CGLContextObj cgl_ctx = _view.openGLContext.CGLContextObj;

        glEnable(GL_TEXTURE_RECTANGLE_EXT);
        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, fbo.texture);
        glBegin(GL_QUADS);
        glEnd();
    }

    __block int r = 0;

    [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        r = 1 - r;

        // Clear the FBO context (and thus texture) to solid red or green
        [self clearContext:fbo.oglCtx.CGLContextObj toRed:r green:1 - r blue:0 alpha:1];

        [self drawTexture:fbo.texture
                 fromRect:_view.frame
                toContext:_view.openGLContext.CGLContextObj
                   inRect:_view.frame
                  flipped:NO
                 mirrored:NO
                 blending:NO
                withAlpha:1.0];
    }];
}

- (void) clearContext:(CGLContextObj) cgl_ctx
                toRed:(GLfloat) red
                green:(GLfloat) green
                 blue:(GLfloat) blue
                alpha:(GLfloat) alpha
{
    glClearColor(red, green, blue, alpha);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glFlush();
}

- (void) drawTexture:(GLuint) tname
            fromRect:(CGRect) fromRect
           toContext:(CGLContextObj) cgl_ctx
              inRect:(CGRect) inRect
             flipped:(BOOL) flipped
            mirrored:(BOOL) mirrored
            blending:(BOOL) blending
           withAlpha:(GLfloat) withAlpha
{
    glEnable(GL_TEXTURE_RECTANGLE_EXT);

    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tname);

    GLint vp[4];
    glGetIntegerv(GL_VIEWPORT, vp);

    GLdouble left, right, bottom, top;

    if (flipped)
    {
        bottom = vp[1] + vp[3];
        top = vp[1];
    }
    else
    {
        bottom = vp[1];
        top = vp[1] + vp[3];
    }

    if (mirrored)
    {
        left = vp[0] + vp[2];
        right = vp[0];
    }
    else
    {
        left = vp[0];
        right = vp[0] + vp[2];
    }

    glMatrixMode (GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity ();
    glOrtho (left, right, bottom, top, -1, 1);
    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();

    GLboolean wasBlending = glIsEnabled(GL_BLEND);

    if (blending)
    {
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    }
    else
        glDisable(GL_BLEND);

    // Texures are multiplied by the current color.
    glColor4f(withAlpha, withAlpha, withAlpha, withAlpha);

    glBegin(GL_QUADS);
    glTexCoord2f(fromRect.origin.x, fromRect.origin.y);
    glVertex2i(inRect.origin.x, inRect.origin.y);
    glTexCoord2f(fromRect.origin.x, fromRect.origin.y + fromRect.size.height);
    glVertex2i(inRect.origin.x, inRect.origin.y + inRect.size.height);
    glTexCoord2f(fromRect.origin.x + fromRect.size.width, fromRect.origin.y + fromRect.size.height);
    glVertex2i(inRect.origin.x + inRect.size.width, inRect.origin.y + inRect.size.height);
    glTexCoord2f(fromRect.origin.x + fromRect.size.width, fromRect.origin.y);
    glVertex2i(inRect.origin.x + inRect.size.width, inRect.origin.y);
    glEnd();

    glMatrixMode (GL_PROJECTION);
    glPopMatrix();

    if (wasBlending)
        glEnable(GL_BLEND);
    else
        glDisable(GL_BLEND);

    glFlush();

    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
}

支持文件:

@interface WTFBOContext : NSObject
{
    GLuint framebuffer;
}

@property (nonatomic, retain) NSOpenGLContext *oglCtx;
@property (nonatomic, retain) NSOpenGLPixelFormat *oglFmt;
@property (nonatomic) GLuint texture;
@property (nonatomic, readonly) NSUInteger width;
@property (nonatomic, readonly) NSUInteger height;

- (id)initWithWidth:(NSUInteger)width height:(NSUInteger)height shareContext:(NSOpenGLContext *)shareContext;

// We take ownership of the texture
- (void)setTexture:(GLuint)texture;

- (BOOL)isComplete;

@end

@implementation WTFBOContext

- (id)initWithWidth:(NSUInteger)width height:(NSUInteger)height shareContext:(NSOpenGLContext *)shareContext
{
    self = [super init];

    _width = width;
    _height = height;

    NSOpenGLPixelFormatAttribute attributes[] = {
        NSOpenGLPFANoRecovery,
        NSOpenGLPFAAccelerated,
        NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
        (NSOpenGLPixelFormatAttribute)0};

    self.oglFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
    self.oglCtx = [[NSOpenGLContext alloc] initWithFormat:self.oglFmt shareContext:shareContext];

    CGLContextObj cgl_ctx = self.oglCtx.CGLContextObj;

    glGenFramebuffersEXT(1, &framebuffer);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);

    [self _makeTexture];

    glViewport(0, 0, _width, _height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, _width, 0, _height, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    return self;
}

- (void)dealloc
{
    CGLContextObj cgl_ctx = self.oglCtx.CGLContextObj;

    glDeleteTextures(1, &_texture);
}

- (void)_makeTexture
{
    CGLContextObj cgl_ctx = self.oglCtx.CGLContextObj;

    GLuint texture;
    glGenTextures(1, &texture);

    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA8, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    self.texture = texture;
}

- (void)setTexture:(GLuint)tex
{
    CGLContextObj cgl_ctx = self.oglCtx.CGLContextObj;

    if (_texture > 0)
        glDeleteTextures(1, &_texture);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, tex, 0);

    if (!self.isComplete)
        NSLog(@"glFramebufferTexture2DEXT");

    _texture = tex;
}

- (BOOL)isComplete
{
    CGLContextObj cgl_ctx = self.oglCtx.CGLContextObj;

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);

    GLuint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

    return status == GL_FRAMEBUFFER_COMPLETE_EXT;
}

@end

0 个答案:

没有答案