2015-02-11 128 views
0

我一直在努力从OpenGL获取屏幕截图,然后在屏幕上渲染相同的图像。为此我创建了两个帧缓冲区。 1用于渲染(ratinaFramebuffer)和1用于使用苹果纹理缓存绘图(textureFramebuffer)。同时使用下面的代码创建(变量名称除外)。纹理缓存没有渲染到iOS中的帧缓冲区对象

glGenFramebuffers(1, &ratinaFramebuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, ratinaFramebuffer); 

glGenRenderbuffers(1, &ratinaColorRenderbuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, ratinaColorRenderbuffer); 
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer]; 

glGenRenderbuffers(1, &ratinaDepthRenderbuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, ratinaDepthRenderbuffer); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ratinaDepthRenderbuffer); 

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ; 
if(status != GL_FRAMEBUFFER_COMPLETE) 
{ 
    NSLog(@"failed to make complete framebuffer object %x", status); 
} 

这里是我的渲染代码看起来像

glBindTexture(GL_TEXTURE_2D, 0); 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 

// Clear content 
glBindFramebuffer(GL_FRAMEBUFFER, ratinaFramebuffer); 
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 

glBindFramebuffer(GL_FRAMEBUFFER, textureFramebuffer); 
glViewport(0, 0, self.frame.size.width, self.frame.size.height); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// Start drawing 
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 
glEnable(GL_BLEND); 

static int nColor = 104; 


glClearColor(0, (++nColor & 0xff)/255.0, 55.0/255.0, 1.0); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glEnable(GL_DEPTH_TEST); 

CC3GLMatrix *projection = [CC3GLMatrix matrix]; 
float h = 4.0f * self.frame.size.height/self.frame.size.width; 
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10]; 
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix); 

CC3GLMatrix *modelView = [CC3GLMatrix matrix]; 
[modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)]; 
_currentRotation += displayLink.duration * 90; 
[modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, 0)]; 
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix); 

// 1 
glViewport(0, 0, self.frame.size.width, self.frame.size.height); 

glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); 

// 2 
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3)); 

glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7)); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, _floorTexture); 
glUniform1i(_textureUniform, 0); 

// 3 
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0); 

glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer2); 

glActiveTexture(GL_TEXTURE0); // unneccc in practice 
glBindTexture(GL_TEXTURE_2D, _fishTexture); 
glUniform1i(_textureUniform, 0); // unnecc in practice 

glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix); 

glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3)); 
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7)); 

glDrawElements(GL_TRIANGLE_STRIP, sizeof(Indices2)/sizeof(Indices2[0]), GL_UNSIGNED_BYTE, 0); 


// Get the image 
CGImageRef cgImage = NULL; 
UIImage *screenImageimage = nil; 
OSStatus res = CreateCGImageFromCVPixelBuffer(renderTarget,&cgImage); 
if (res == noErr) 
{ 
    screenImageimage = [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationUp]; 

} 

在这一点上,图像是完全被拉入质感。但是当我尝试以使其在屏幕上,同样的质地,它是没有得到拉:(。它显示了蓝色,我在鲜明的色彩,但没有别的都给予。

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ratinaFramebuffer); 
glBindTexture(GL_TEXTURE_2D, 0); 
glClearColor(0, 255/255.0, 255/255.0, 1.0); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glEnable(GL_DEPTH_TEST); 

glViewport(0, 0, self.frame.size.width, self.frame.size.height); 


glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, renderTexture); 


// Display the buffer 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, ratinaColorRenderbuffer); 
[_context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
+0

所以,你绑定并绘制到纹理帧缓冲区,并从它得到的图像似乎工作,但然后你切换到视图绑定的名望缓冲区,清除它,并呈现给视图,似乎然后再按预期工作。你真的在哪里绘制纹理视图绑定帧缓冲区(ratinaFramebuffer)?简单地绑定纹理会将所需的纹理设置为之前设置的活动纹理,但不会将其绘制到任何位置。要绘制它,您将需要与绘制任何其他纹理相同的过程。 – 2015-02-11 17:43:03

+0

感谢您的回答Matic Oblak,我添加了下面的代码glVertexPointer(3,GL_FLOAT,0,顶点); glTexCoordPointer(2,GL_FLOAT,0,coordinates); glDrawArrays(GL_TRIANGLE_STRIP,0,4); 它显示了质感,谢谢。但问题是,它是在动画框中显示的,而不是完整的屏幕,我怎么做,请建议 – 2015-02-12 07:18:33

回答

0

问题得到解决,如我是新来的OpenGL和我没有绘制画面的帧缓冲,我做到了在屏幕上调用render使用下面的代码。只是发表如果有人需要看,在beginer水平

GLfloat  coordinates[] = { 0, 1, 
           1, 1, 
           0, 0, 
           1, 0 }; 

GLfloat  width = self.frame.size.width, 
      height = self.frame.size.height; 

GLfloat  vertices[] = { -width/2 + point.x, -height/2 + point.y, 0.0, 
          width/2 + point.x, -height/2 + point.y, 0.0, 
          -width/2 + point.x, height/2 + point.y, 0.0, 
          width/2 + point.x, height/2 + point.y, 0.0 }; 

glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture)); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

glVertexPointer(3, GL_FLOAT, 0, vertices); 
glTexCoordPointer(2, GL_FLOAT, 0, coordinates); 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

虽然,这显示纹理,但在一个小框中绘制在另一个帧缓冲区中,尽管顶点和共同点都是完整的屏幕,但并没有绘制完成屏幕。如果我找到了,将会编辑这个。

1

当你绘制到单独的帧缓冲区时,你可以附加一个纹理到最后你可以有意识地绘制到纹理本身。完成此绘图后,您可以像使用其他绘图一样将纹理绘制到主屏幕缓冲区中。

有这样做的时候,你应该检查几点:

  • 切换
  • 您必须根据绑定的帧缓冲区设置视当切换
  • 时不要忘记重新绑定帧缓冲区
  • 可能您可能需要清除缓冲区
  • 可能纹理仅在缓冲区的一部分上绘制,例如在1024x1024纹理上绘制600x600屏幕。在这种情况下,您需要生成范围[0,600/1024]中的顶点坐标以绘制正确的部分。这可以通过比较来自纹理边界帧缓冲区的视口值和纹理大小来检查。

很难说你现在失去了什么,但现在最好的办法是检查视口。除此之外,如果您只是绘制全屏幕纹理,则不需要将主缓冲区复杂化。您可以禁用该矩阵,并简单地使用默认的[-1,1]坐标系。

相关问题