我在同一窗口中显示两个带有自己的GLKViewControllers的GLKView。我能够正确显示内容。一个GLK视图包含一半的ipad窗口,另一半由另一个GLKview包含。我正在使用VBO和IBO来渲染我的对象。我也基于这里描述的colorPicking技术检测对象上的触摸(渲染到屏幕外缓冲区并对对象进行颜色编码): OpenGL ES 2.0 Object Picking on iOS
当我触摸view1中的对象(首先被初始化的对象)时,我的应用程序开始崩溃,所以我试图弄清楚出了什么问题。但是,对view2对象的触摸工作正常。崩溃时(在view1中触摸对象时)的错误是 glerunvertexsubmitARM 。在一些研究中,我发现错误与绑定的错误的veretx或索引缓冲区有关。所以我检查了我的对象的bufferIndex和vertexIndex。初始化我的第一个视图后,我的vertexbuffer和索引缓冲区的句柄再次从索引1开始。 根据我的理解,EAGLcontext对此负责。所以现在当我为我的view2生成新的EAGLContext时,我使用相同的EAGLsharegroup初始化它。这使得我的应用程序不再崩溃,而且我看到第二个视图的句柄不以1开头。根据我对EAGLSharegroup的理解,它负责共享资源,如顶点和索引缓冲区对象。 (VBO和IBO就是我在这里所需要的,它阻止我的应用程序崩溃)
但我根本无法有效地发现我的观点。 它很多次都没有读取任何像素,但有时它会读取。 如果我不触摸第一个视图,触摸第二个视图是完全正常的。 除了共享相同的EAGLsharegroup之外,我不确定还需要做什么。 我在下面发布我的代码。
此外,当我只使用一个视图时,一切都顺利而且很好。
触摸检测
-(NSNumber*)findBarbyPoint:(CGPoint)point {
NSInteger height = ((GLKView *)self.view).drawableHeight;
NSInteger width = ((GLKView *)self.view).drawableWidth;
GLubyte *pixelColor = (GLubyte*)malloc(4*sizeof(GLubyte)*1*1);
int k = 4*1*1;
GLuint colorRenderbuffer;
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER, colorRenderbuffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"Framebuffer status: %x", (int)status);
return 0;
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
self.effect.transform.projectionMatrix = ProjectionMatrix;
//can be in a different function
for(int i=0; i<self.numberofBars ;i++)
{
//Render the object with GLKBaseEffect
iVBarNode *temp = [theBars objectAtIndex:i];
NSLog(@"temp properties %f %f %f %f",temp.color.r, temp.color.g, temp.color.b, temp.position.x);
self.effect.transform.modelviewMatrix = GLKMatrix4Multiply(ViewMatrix,modelMatrix);
self.effect.transform.modelviewMatrix = GLKMatrix4Multiply(self.effect.transform.modelviewMatrix,temp.modelMatrix);
self.effect.constantColor = GLKVector4Make(temp.color.r, temp.color.g, temp.color.b, 1.0);
//bind corresponding buffer before drawing
glBindBuffer(GL_ARRAY_BUFFER, [temp getVertexID]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, [temp getIndexID]);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), BUFFER_OFFSET(12));
[self.effect prepareToDraw];
glDrawElements(GL_TRIANGLES, [temp.bar getIndicesSize], GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribNormal);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
///rendering ends here
CGFloat scale = UIScreen.mainScreen.scale;
glReadPixels(point.x * scale, (height - (point.y * scale)), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelColor);
glDeleteRenderbuffers(1, &colorRenderbuffer);
glDeleteFramebuffers(1, &framebuffer);
for(int i=0; i<k; i=i+4)
{
NSUInteger pixelr = pixelColor[i];NSUInteger pixelg = pixelColor[i+1]; NSUInteger pixelb = pixelColor[i+2];
NSUInteger pixela = pixelColor[i+3];
NSLog(@"read pixel = %d %d %d %d", pixelr, pixelg, pixelb, pixela);
}
return [NSNumber numberWithUnsignedChar:pixelColor[0]];
}
这是我为第二个视图(view2)初始化EAGLContext的方法。
EAGLSharegroup *shareGRp = [[EAGLContext currentContext] sharegroup];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:shareGRp];
下面是生成veretx和索引缓冲区的代码,我将它们保存在带有类函数的实用程序类中,以生成我的VBO和IBO的句柄。
+ (GLuint) createBufferFromArray:(GLfloat*)array size:(int)size {
// set up buffer to store array
GLuint bufferIndex;
glGenBuffers(1, &bufferIndex);
glBindBuffer(GL_ARRAY_BUFFER, bufferIndex);
// Copy data from local memory
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(size* sizeof(GLfloat)), array, GL_STATIC_DRAW);
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
NSLog(@"Error creating buffer %i. glError: 0x%04X", bufferIndex, err);
}
NSLog(@"bufferIndex=%d", bufferIndex);
return bufferIndex;
}
+ (GLuint) createBufferFromElementArray:(GLushort*)array size:(int)size {
// set up buffer to store array
GLuint bufferIndex;
glGenBuffers(1, &bufferIndex);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferIndex);
// Copy data from local memory
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(size * sizeof(GLushort)), array, GL_STATIC_DRAW);
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
NSLog(@"Error creating buffer %i. glError: 0x%04X", bufferIndex, err);
}
NSLog(@"bufferIndex=%d", bufferIndex);
return bufferIndex;
}