我有一个带有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