I'm going to show pixel data on opengl view.
But I can't see anything, only can see the empty pink gl screen.
Please check my codes and let me know what it is wrong.
#implementation GLView
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
// Do OpenGL Core Animation layer setup
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!context || ![EAGLContext setCurrentContext:context]
|| ![self createFramebuffers])
return nil;
}
return self;
}
- (BOOL)createFramebuffers
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
// Onscreen framebuffer object
glGenFramebuffers(1, &viewFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
glGenRenderbuffers(1, &viewRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
NSLog(#"Backing width: %d, height: %d", backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(#"Failure with framebuffer generation");
return NO;
}
return YES;
}
- (void)setDisplayFramebuffer;
{
if (context)
{
// [EAGLContext setCurrentContext:context];
if (!viewFramebuffer)
[self createFramebuffers];
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
// glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
glViewport(0, 0, backingWidth, backingHeight);
}
}
- (BOOL)presentFramebuffer;
{
BOOL success = FALSE;
if (context)
{
// [EAGLContext setCurrentContext:context];
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER];
}
return success;
}
and in viewcontroller
m_glView = [[GLView alloc] initWithFrame:CGRectMake(0, 0, m_viewPlayer.frame.size.width, m_viewPlayer.frame.size.height)];
[m_viewPlayer addSubview:m_glView];
[self loadVertexShader:#"DirectDisplayShader" fragmentShader:#"DirectDisplayShader" forProgram:&m_directDisplayProgram];
and in timer loop
CMSampleBufferRef buf = [m_trackOutput copyNextSampleBuffer];
if (buf == nil)
return;
[self processFrame:buf]; // draw frame to opengl view
CFRelease(buf);
- (void)processFrame:(CMSampleBufferRef)sampleBuffer
{
if (m_videoFrameTexture)
glDeleteTextures(1, &m_videoFrameTexture);
// Get a CMSampleBuffer's Core Video image buffer for the media data
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// Lock the base address of the pixel buffer
CVPixelBufferLockBaseAddress(imageBuffer, 0);
CGFloat width = CVPixelBufferGetWidth(imageBuffer);
CGFloat height = CVPixelBufferGetHeight(imageBuffer);
// Create a new texture from the camera frame data, display that using the shaders
glGenTextures(1, &m_videoFrameTexture);
glBindTexture(GL_TEXTURE_2D, m_videoFrameTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Using BGRA extension to pull in video frame data directly
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(imageBuffer));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(imageBuffer));
[self drawFrame];
// glDeleteTextures(1, &videoFrameTexture);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}
- (void)drawFrame
{
[m_glView setDisplayFramebuffer];
[self drawCapturedScreen];
[m_glView presentFramebuffer];
}
- (void)drawCapturedScreen
{
glUseProgram(m_directDisplayProgram);
glBindTexture(GL_TEXTURE_2D, m_videoFrameTexture);
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
// Update attribute values.
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
float m_fScale = 1.0f; //
GLfloat kRate = 1.0f/m_fScale;
GLfloat kX = (1.0-kRate)/2;
GLfloat kY = (1.0-kRate)/2;
GLfloat kS = kX+kRate;
GLfloat kT = kY+kRate;
{
{
GLfloat textureVertices[] = {
kS, kT,
kS, kY,
kX, kT,
kX, kY,
};
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
}
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
Have you managed to render anything in OpenGL so far? I would suggest breaking what you're doing down into smaller steps and get those working first. First try rendering just using GL_POINTS and see if you can get anything and then build up from there. Make your shaders as simple as possible too to check for issues there. You should try to get the bare minimum rendering working and then build up the complexity (for example, after points try lines, then triangles, then textured triangles). By breaking down the rendering you can isolate what's causing the draw call to not show anything.
Related
In an OpenGL ES app I'm working on, when i use glReadPixels to get pixel but got empty buffer.now i don't know what's wrong in my code。Thanks for any help.
- (void)setTextureImage:(UIImage *)image {
self.textureID = [self createTextureWithImage:image];
CAEAGLLayer *layer = [[CAEAGLLayer alloc] init];
layer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
layer.contentsScale = [[UIScreen mainScreen] scale];
layer.opaque = NO;
[self.layer addSublayer:layer];
[self bindRenderLayer:layer];
}
- (void)bindRenderLayer:(CALayer <EAGLDrawable> *)layer {
glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
[self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
renderBuffer);
}
- (GLint)drawableWidth {
GLint backingWidth;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
return backingWidth;
}
- (GLint)drawableHeight {
GLint backingHeight;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
return backingHeight;
}
above sample code just part of display texture and it's works fine. The renderBuffer and framebuffer is property of my class.
sample get pixel code here, buffer is empty after use glReadPixels? Is anything I missed to setup?
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
// I'm try to use one or both of the bind method but not worked
//glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
NSInteger dataLength = self.drawableWidth * self.drawableHeight * 4;
GLubyte *buffer = (GLubyte *)malloc(dataLength * sizeof(GLubyte));
glReadPixels(0,
0,
self.drawableWidth,
self.drawableHeight,
GL_RGBA,
GL_UNSIGNED_BYTE,
buffer);
I found a solution. When you set CAEAGLLayer's drawableProperties like this:
layer.drawableProperties = #{
kEAGLDrawablePropertyRetainedBacking: #(YES),
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
};
kEAGLDrawablePropertyRetainedBacking = YES makes it so you can get the buffer when finshed rendering.
i use CADisplayLink render-loop callback to render a serial of image textures with openGLes.
after CADisplayLink's first callback called, i just get these error output
Failed to bind EAGLDrawable: <CAEAGLLayer: 0x946bb40> to GL_RENDERBUFFER 2
Failed to make complete framebuffer object 8cd6
i setup the renderBuffer&frameBuffer and call glFramebufferRenderbuffer in controller's viewDidLoad stage, the return of glCheckFramebufferStatus is fine in that stage.
this is the code I'm using.
//GLKViewController.m
typedef struct {
GLKVector3 positionCoords;
GLKVector2 textureCoords;
}SceneVertex;
static const SceneVertex vertices[] =
{
{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}}, // lower left corner
{{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f}}, // lower right corner
{{-1.0f, 1.0f, 0.0f}, {0.0f, 1.0f}}, // upper left corner
{{ 1.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
};
#interface myViewController () //glkViewController
#property (nonatomic) GLuint renderBuffer;
#property (nonatomic) GLuint frameBuffer;
#property (nonatomic) GLuint glBuffer;
#property (nonatomic) int renderWidth;
#property (nonatomic) int renderHeight;
#property(strong, nonatomic) CADisplayLink* displayLink;
#property(strong, nonatomic) EAGLContext* context;
#end
#implementation myViewController
-(void)setupBuffers
{
glGenFramebuffers(1, &_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glGenRenderbuffers(1, &_renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
[self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.view.layer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, _renderBuffer);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_renderWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_renderHeight);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
NSLog(#"AAfailed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
glGenBuffers(1,&_glBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _glBuffer);
glBufferData(
GL_ARRAY_BUFFER, // Initialize buffer contents
sizeof(vertices), // Number of bytes to copy
vertices, // Address of bytes to copy
GL_STATIC_DRAW); // Hint: cache in GPU memory
}
-(void)loadView
{
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
self.view = [[myView alloc] initWithFrame:[[UIScreen mainScreen] bounds] context:_context];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[EAGLContext setCurrentContext:self.context];
[self setupBuffers];
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(render)];
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
_displayLink.frameInterval = 1;
}
- (void)render
{
myView *view = (myView*)self.view;
NSData *image = [view getOneImage]; //if nil, return or sleep®et;
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, _renderWidth, _renderHeight);
GLuint texture = -1;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexImage2D(
GL_TEXTURE_2D, 0, /* target, level */
GL_RGB, /* internal format */
_renderWidth, _renderHeight, 0, /* width, height, border */
GL_RGB, GL_UNSIGNED_BYTE, /* external format, type */
image.bytes /* pixels */
);
glBindBuffer(GL_ARRAY_BUFFER,_glBuffer);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, // Identifies the attribute to use
3, // number of coordinates for attribute
GL_FLOAT, // data is floating point
GL_FALSE, // no fixed point scaling
sizeof(SceneVertex), // total num bytes stored
NULL+offsetof(SceneVertex, positionCoords));
glBindBuffer(GL_ARRAY_BUFFER, _glBuffer);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, // Identifies the attribute to use
2, // number of coordinates for attribute
GL_FLOAT, // data is floating point
GL_FALSE, // no fixed point scaling
sizeof(SceneVertex), // total num bytes stored per vertex
NULL+offsetof(SceneVertex, textureCoords));
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 1, 4);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
[_context presentRenderbuffer:GL_RENDERBUFFER];
glFlush();
glDeleteTextures(1, &texture);
}
#end
//GLKView
#implementation myView
+ (Class)layerClass {
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame context:(EAGLContext *)context
{
self = [super initWithFrame:frame];
if (self) {
self.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
self.context = context;
CAEAGLLayer *layer= (CAEAGLLayer *)self.layer;
self.images = [[NSMutableArray alloc] init];
layer.opaque = YES;
layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
}
return self;
}
#end
//APPDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [[QCPViewController alloc]init];
[self.window makeKeyAndVisible];
return YES;
}
This occurs when you try to draw an openGL view that isn't currently on screen. In my case, the view wasn't installed in the current size class in my storyboard.
If you are using storyboards, double check that the view is installed in the current size class
Select the open GL view in the storyboard
Go to the Attributes inspector
Verify the view is installed in all size classes like below
I'm experiencing the same thing. I'm creating and adding the SCNView on a callback from CADisplayLink. It is very laggy, it is not visible and the error shows up in console. When I just say dispatch_async(dispatch_get_main_queue(), ^{ /* code */ }); Then everything is fine.
Its about picking a 3d object using color-picking. I draw my mesh (update: Which resides in a static header file and is displayed fine to the screen in the same project) to a new offscreen framebuffer and then I use glReadPixels to identify if the user touched it.
Following the code from the project opengles_ch10_1 from the book "Learning OpenGLES for iOS" by Erik M.Buck, I wrote the following code which always prints to nslog the color 0,0,0 for the picked (by tapping) pixel.
My code is:
- (IBAction) tapGesture:(id)sender
{
if ([(UITapGestureRecognizer *)sender state] == UIGestureRecognizerStateEnded) {
CGPoint tapLocation = [(UITapGestureRecognizer *)sender locationInView:self.view];
int tt = [self findMeshByPoint:tapLocation];
//NSLog( #"tap value: %i", tt );
}
}
- (NSUInteger)findMeshByPoint:(CGPoint)point
{
//In openGL the y axis starts from the bottom of the screen
point.y = self.view.bounds.size.height - point.y;
GLKView *glView = (GLKView *)self.view;
NSAssert([glView isKindOfClass:[GLKView class]],
#"View controller's view is not a GLKView");
// Make the view's context current
[EAGLContext setCurrentContext:glView.context];
glBindVertexArrayOES(0);
// self.effect.constantColor = GLKVector4Make( 1.0f, //This should be meshId/255.0f
if(0 == _glVertexAttributeBufferID)
{
GLuint glName;
glGenBuffers(1, // STEP 1
&glName);
glBindBuffer(GL_ARRAY_BUFFER, // STEP 2
glName);
glBufferData( // STEP 3
GL_ARRAY_BUFFER, // Initialize buffer contents
sizeof(parparit51OBJVertices), parparit51OBJVertices,
GL_STATIC_DRAW); // Hint: cache in GPU memory
_glVertexAttributeBufferID = glName;
}
else
{
glBindBuffer(GL_ARRAY_BUFFER,
_glVertexAttributeBufferID);
}
//glEnableVertexAttribArray(TETerrainPositionAttrib);
glEnableVertexAttribArray( GLKVertexAttribPosition );
if(0 == _program)
{
[self loadShadersWithName:#"UtilityPickTerrainShader"];
[self buildFBO];
NSAssert(0 != _program,
#"prepareOpenGL failed to load shaders");
}
glUseProgram(_program);
// Pre-calculate the mvpMatrix
GLKMatrix4 modelViewProjectionMatrix2 =
GLKMatrix4Multiply(
self.effect.transform.projectionMatrix,
self.effect.transform.modelviewMatrix);
// Standard matrices
glUniformMatrix4fv(uniforms[UtilityPickTerrainMVPMatrix], 1, 0,
modelViewProjectionMatrix2.m);
// glUniform2fv(uniforms[UtilityPickTerrainDimensionFactors], 1,
// &_temp1 ); //self.factors.v); //I removed this from the shaders
glUniform1f(uniforms[UtilityPickTerrainModelIndex],
1.0f ); // self.modelIndex / 255.0f);
glBindFramebuffer(GL_FRAMEBUFFER, _pickFBO);
glViewport(0, 0, 512, 512);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12 * sizeof(GLfloat), 0);
NSLog( #"******* 7" );
[self.effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, sizeof(parparit51OBJVertices) / sizeof(Vertex));
NSLog( #"******* 7.5" );
const GLfloat width = [glView drawableWidth];
const GLfloat height = [glView drawableHeight];
NSAssert(0 < width && 0 < height, #"Invalid drawble size");
// Get info for picked location
const GLKVector2 scaledProjectionPosition = {
point.x / width,
point.y / height
};
NSLog( #"******* 8" );
GLubyte pixelColor[4]; // Red, Green, Blue, Alpha color
GLint readLocationX = MIN((512 - 1),
(512 - 1) * scaledProjectionPosition.x);
GLint readLocationY = MIN((512 - 1),
(512 - 1) * scaledProjectionPosition.y);
glReadPixels(readLocationX,
readLocationY,
1,
1,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixelColor);
NSLog(#"pixelColor[0]=%i, pixelColor[1]=%i, pixelColor[2]=%i", pixelColor[0], pixelColor[1], pixelColor[2] );
// Restore OpenGL state that pickTerrainEffect changed
glBindFramebuffer(GL_FRAMEBUFFER, 0); // default frame buffer
glViewport(0, 0, width, height); // full area of glView
return 0;
}
-(void) buildFBO
{
if ( 0 == _pickFBO )
{
GLuint colorTexture;
// Create a texture object to apply to model
glGenTextures(1, &colorTexture);
glBindTexture(GL_TEXTURE_2D, colorTexture);
// Set up filter and wrap modes for this texture object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
// Allocate a texture image we can render into
// Pass NULL for the data parameter since we don't need to
// load image data. We will be generating the image by
// rendering to this texture.
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
512,
512,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL);
GLuint depthRenderbuffer;
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
512, 512);
glGenFramebuffers(1, &_pickFBO);
glBindFramebuffer(GL_FRAMEBUFFER, _pickFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, colorTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
GL_FRAMEBUFFER_COMPLETE)
{
NSLog(#"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
//+++tbd+++UtilityPickTerrainEffectDestroyFBO(fboName);
return;
}
//#ifdef DEBUG
// { // Report any errors
GLenum error = glGetError();
if(GL_NO_ERROR != error)
{
NSLog(#"GL Error: 0x%x", error);
}
// }
//#endif
}
}
Your error is that you are trying to access a Null Pointer -- you are almost certainly passing an array that you never actually initialized to your GLKEffect or giving it to OpenGL with a bufferData call, given that the error is occurring inside of prepareToDraw or glDrawArrays. There are several possible explanations for this that I can see, though I can't confirm any of them, since the relevant information is how you allocate the data that you are using either in perpareToDraw or in glDrawArrays.
The first is that "parparit51OBJVertices" might be allocated on the heap dynamically (are you calling malloc or the like? How do you specify the size of the array), in which case your calls to sizeof will be returning incorrect values (0 I think) which might lead to the EXEC_BAD_ACESS.
The other part of this that seems suspect is that you are calling glDrawArrays and passing in the number of vertices, but before that you bind a VBO for indices -- at best this is wasted work, since glDrawArrays will ignore the indices. Worse, if you are trying to draw an OBJ, as your variable name implies, then likely there is a considerable amount of geometry you aren't drawing at all, so even if you fix your EXEC_BAD_ACCESS problem you still will be getting bad results.
I had a BAD_ACCESS error.
I solved this by removing the code which handles the indices:
if(0 == _indexBufferID)
{
// Indices haven't been sent to GPU yet
// Create an element array buffer for mesh indices
glGenBuffers(1, &_indexBufferID);
NSAssert(0 != _indexBufferID,
#"Failed to generate element array buffer");
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof( parparit51OBJIndices ),
parparit51OBJIndices,
GL_STATIC_DRAW);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferID);
}
Now I still need to understand why the code updated above always print 0,0,0 for any picked pixel.
I'm developing an iOS openGL ES application.
I'm doing the usual EAGLView / ES2Render stuff.
On startup, frambuffer creation succeeds, using the following code:
- (BOOL) createFramebuffers
{
[EAGLContext setCurrentContext:_mainContext];
// [ A ] On-screen
// 1. Framebuffer
glGenFramebuffers(1, &_mainFramebuffer);
bindFramebuffer(_mainFramebuffer);
// 2. Color buffer
glGenRenderbuffers(1, &_mainColorbuffer);
bindRenderbuffer(_mainColorbuffer);
// Adjust size to view's layer:
CAEAGLLayer* layer = (CAEAGLLayer*)[_view layer];
if (![_mainContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]) {
// something went horribly wrong
NSLog(#"-[ES2Renderer createFramebuffers]: Failed to obtain renderbuffer storage from layer!");
return NO;
}
// Query new size:
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
// Attach to color:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _mainColorbuffer);
// 3. Depth buffer
glGenRenderbuffers(1, &_depthBuffer);
bindRenderbuffer(_depthBuffer);
if (_useStencilBuffer) {
// Depth + Stencil
// Allocate storage:
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
// Attach to depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
// Attach to stencil:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
}
else{
// Depth only
// Allocate storage:
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
// Attachto depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
}
// 4. Validate the set:
GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSLog(#"-[ES2Renderer createFramebuffers]: Failed to make complete framebuffer object: %#",
[self stringFromFramebufferStauts:framebufferStatus]);
return NO;
}
// [ B ] Off-screen (Render-to-texture)
// 1. Framebuffer
glGenFramebuffers(1, &_transFramebuffer);
bindFramebuffer(_transFramebuffer);
// 2. Depth buffer
glGenRenderbuffers(1, &_transDepthBuffer);
bindRenderbuffer(_transDepthBuffer);
if (_useStencilBuffer) {
// Allocate storage:
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
// Attach to depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _transDepthBuffer);
// Attach to stencil:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _transDepthBuffer);
}
else{
// Allocate storage
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
// Attach to depth:
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _transDepthBuffer);
}
// 3. Textures (color buffers)
GLuint* texPtrs[2] = {&_transTexture1, &_transTexture2};
for (NSUInteger i=0; i < 2; i++) {
GLuint* texPtr = texPtrs[i];
// Create:
glGenTextures(1, texPtr);
// Bind:
bindTexture2D(*texPtr);
// Configure for pixel-aligned use:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Allocate storage:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _backingWidth, _backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Attach:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texPtr, 0);
framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// Validate:
if ( framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSLog(#"-[ES2Renderer createFramebuffers]: Failed to make complete framebuffer object: %#",
[self stringFromFramebufferStauts:framebufferStatus]);
return NO;
}
}
// Final State:
bindFramebuffer(_mainFramebuffer);
bindRenderbuffer(_mainColorbuffer);
bindTexture2D(0);
NSLog(#"-[ES2Renderer createFramebuffers] Succeeded.");
return YES;
}
Soon after, UIView's -layoutSubviews is called and I in turn execute -resizeFromLayer::
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
// [ A ] On screen framebuffer
bindFramebuffer(_mainFramebuffer);
// 1. Resize color buffer
bindRenderbuffer(_mainColorbuffer);
if (![_mainContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]) {
// Something went wrong
return NO; // <-- SECOND TIME ON, THIS HAPPENS
}
// Query new size:
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
// 2. Resize depth buffer
bindRenderbuffer(_depthBuffer);
if (_useStencilBuffer) {
// (Depth & Stencil)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
}
else{
// (Depth only)
glRenderbufferStorage(GL_FRAMEBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
}
// ...Validate:
GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSLog(#"-[ES2Renderer resizeFromLayer:]: Failed to make complete framebuffer object: %#",
[self stringFromFramebufferStauts:glCheckFramebufferStatus(GL_FRAMEBUFFER)]);
return NO;
}
// [ B ] Off screen (render-to-terxture) framebuffer
bindFramebuffer(_transFramebuffer);
// 1. Resize depth buffer
bindRenderbuffer(_transDepthBuffer);
if (_useStencilBuffer) {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, _backingWidth, _backingHeight);
}
else{
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, _backingWidth, _backingHeight);
}
// 2. Resize textures
GLuint* texPtrs[2] = {&_transTexture1, &_transTexture2};
for (NSUInteger i=0; i < 2; i++) {
GLuint* texPtr = texPtrs[i];
// Bind:
bindTexture2D(*texPtr);
// Configure for pixel-aligned use:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Allocate storage:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _backingWidth, _backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Attach:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texPtr, 0);
// Validate:
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
// Something went wrong!
NSString* statusString = [self stringFromFramebufferStauts:glCheckFramebufferStatus(GL_FRAMEBUFFER)];
NSLog(#"-[ES2Renderer resizeFromLayer:]: Failed to make complete framebuffer object: %#", statusString);
return NO;
}
}
bindFramebuffer(_mainFramebuffer);
bindRenderbuffer(_mainColorbuffer);
// Pass new ortho projection to shaders
[self initializeModelViewMatrix];
[self initializeSpriteProgram];
// Set new viewport
glViewport(0, 0, _backingWidth, _backingHeight);
NSLog(#"-[ES2Renderer resizeFromLayer:]: Succeeded.");
return YES;
}
Nothing of what I'm doing is special. I have a separate framebuffer to render scene transitions, with two textures to attach to color, and depth.
The second time -renderbufferStorage:fromDrawable: is called (-layoutSubviews -> resizeFromLayer:), it invariably fails (returns NO); Calling glGetError() right before that results in no error, but calling it right after returns GL_INVALID_OPERATION.
If I ignore this and proceed, glGetRenderbufferParameteriv() still gets me the right width and height (640 and 1136, respectively, on an iPhone 5), but glCheckFramebufferStatus() will return GL_FRAMEBUFFER_UNSUPPORTED.
Alternatively, I skipped the above resizeFromLayer: and replaced it with this:
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
[self destroyFramebuffers];
return [self createFramebuffers];
}
...but the same error persists (-renderStorage:fromDrawable: fails; this time inside -createFramebuffers).
For now, I just return YES (my app only supports portrait, so no screen size change actually ever happens), but I really want to fix it because one day I'll need to support landscape, etc...
Another possible reason is that the size of your layer is too large. In addition make sure you are using a new framebuffer and renderbuffer each time. And you have destroyed your old ones before creating new ones.
You can delete them like this
if let displayFramebuffer = self.displayFramebuffer {
var temporaryFramebuffer = displayFramebuffer
glDeleteFramebuffers(1, &temporaryFramebuffer)
self.displayFramebuffer = nil
}
if let displayRenderbuffer = self.displayRenderbuffer {
var temporaryRenderbuffer = displayRenderbuffer
glDeleteRenderbuffers(1, &temporaryRenderbuffer)
self.displayRenderbuffer = nil
}
One possible reason that renderbufferStorage:fromDrawable: is failing is that the _mainContext is not the current context at that time. Even though it may seem that no other context could have stolen the 'current' status, I recommend calling [EAGLContext setCurrentContext:_mainContext] before any gl or EAGL code that operates on objects associated with that context (e.g. at the beginning of the resizeFromLayer: method).
Josh Bernfeld's answer inspired me. I check the size of MyView and the bounds of it is CGRect.zero. And the same with the CAEAGLLayer.
For me, init MyView with a nonzero CGRect solved the problem.
Hope it works for you.
I am working on a test app from RosyWriter demo, by the original code, when we take the 1920*1080 dimension videos, actually we can only see the 1620*1080 region in preview(with the aspect ratio 4/3, 960*640), I want to modify the code to display all content of the video (window size should be 960*540), with black frames up and down the view. I can figure out that the codes below achieved this result:
- (CGRect)textureSamplingRectForCroppingTextureWithAspectRatio:(CGSize)textureAspectRatio toAspectRatio:(CGSize)croppingAspectRatio
{
CGRect normalizedSamplingRect = CGRectZero;
CGSize cropScaleAmount = CGSizeMake(croppingAspectRatio.width / textureAspectRatio.width, croppingAspectRatio.height / textureAspectRatio.height);
CGFloat maxScale = fmax(cropScaleAmount.width, cropScaleAmount.height);
CGSize scaledTextureSize = CGSizeMake(textureAspectRatio.width * maxScale, textureAspectRatio.height * maxScale);
if ( cropScaleAmount.height > cropScaleAmount.width ) {
normalizedSamplingRect.size.width = croppingAspectRatio.width / scaledTextureSize.width;
normalizedSamplingRect.size.height = 1.0;
}
else {
normalizedSamplingRect.size.height = croppingAspectRatio.height / scaledTextureSize.height;
normalizedSamplingRect.size.width = 1.0;
}
// Center crop
normalizedSamplingRect.origin.x = (1.0 - normalizedSamplingRect.size.width)/2.0;
normalizedSamplingRect.origin.y = (1.0 - normalizedSamplingRect.size.height)/2.0;
return normalizedSamplingRect;
}
- (void)displayPixelBuffer:(CVImageBufferRef)pixelBuffer
{
if (frameBufferHandle == 0) {
BOOL success = [self initializeBuffers];
if ( !success ) {
NSLog(#"Problem initializing OpenGL buffers.");
}
}
if (videoTextureCache == NULL)
return;
// Create a CVOpenGLESTexture from the CVImageBuffer
size_t frameWidth = CVPixelBufferGetWidth(pixelBuffer);
size_t frameHeight = CVPixelBufferGetHeight(pixelBuffer);
CVOpenGLESTextureRef texture = NULL;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
videoTextureCache,
pixelBuffer,
NULL,
GL_TEXTURE_2D,
GL_RGBA,
frameWidth,
frameHeight,
GL_BGRA,
GL_UNSIGNED_BYTE,
0,
&texture);
if (!texture || err) {
NSLog(#"CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
return;
}
glBindTexture(CVOpenGLESTextureGetTarget(texture), CVOpenGLESTextureGetName(texture));
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferHandle);
// Set the view port to the entire view
glViewport(0, 0, renderBufferWidth, renderBufferHeight);
//NSLog(#"render width:%d height:%d",renderBufferWidth,renderBufferHeight);
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
// The texture vertices are set up such that we flip the texture vertically.
// This is so that our top left origin buffers match OpenGL's bottom left texture coordinate system.
CGRect textureSamplingRect = [self textureSamplingRectForCroppingTextureWithAspectRatio:CGSizeMake(frameWidth, frameHeight) toAspectRatio:self.bounds.size];
GLfloat textureVertices[] = {
CGRectGetMinX(textureSamplingRect), CGRectGetMaxY(textureSamplingRect),//0.078125, 1.0
CGRectGetMaxX(textureSamplingRect), CGRectGetMaxY(textureSamplingRect),//0.921875, 1.0
CGRectGetMinX(textureSamplingRect), CGRectGetMinY(textureSamplingRect),//0.078125, 1.0
CGRectGetMaxX(textureSamplingRect), CGRectGetMinY(textureSamplingRect),//0.921875, 0.0
};
// Draw the texture on the screen with OpenGL ES 2
[self renderWithSquareVertices:squareVertices textureVertices:textureVertices];
//[oglContext presentRenderbuffer:GL_RENDERBUFFER];
glBindTexture(CVOpenGLESTextureGetTarget(texture), 0);
// Flush the CVOpenGLESTexture cache and release the texture
CVOpenGLESTextureCacheFlush(videoTextureCache, 0);
CFRelease(texture);
}
I think I must modify the textureSamplingRect and textureVertices part to get my effects, but I am newbie for the opengl es, so, could anyone pls figure out how to do this in detail?