【问题标题】:Texture Cache not rendering into Frame buffer Object in iOS纹理缓存未渲染到 iOS 中的帧缓冲区对象
【发布时间】:2015-02-12 15:44:23
【问题描述】:

我一直在努力从 OpenGL 获取屏幕截图,然后在屏幕上渲染相同的内容。为此,我创建了两个帧缓冲区。 1 用于渲染(ratinaFramebuffer),1 用于使用苹果纹理缓存绘图(textureFramebuffer)。使用以下代码创建两者(变量名除外)。

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];

【问题讨论】:

  • 因此您绑定并绘制到纹理帧缓冲区并从中获取图像,这似乎可以工作,但随后您切换到视图绑定的名声缓冲区,清除它并将其呈现给似乎然后再次按预期工作。您实际上在哪里将纹理绘制到视图绑定帧缓冲区(ratinaFramebuffer)?只需将纹理绑定到先前设置的活动纹理,而不是将其绘制到任何地方。要绘制它,您需要与绘制任何其他纹理相同的过程。
  • 感谢 Matic Oblak 的回答,我添加了以下代码 glVertexPointer(3, GL_FLOAT, 0, vertices); glTexCoordPointer(2, GL_FLOAT, 0, 坐标); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);它显示了纹理,谢谢。但问题是,它在动画框中显示,而不是完整的屏幕,我该怎么做,请建议

标签: ios opengl-es glkview


【解决方案1】:

当您绘制到单独的帧缓冲区时,您可以将纹理附加到它,最终您可以有效地绘制到纹理本身。绘制完成后,您可以像使用其他任何纹理一样使用纹理,包括将其绘制到主屏幕缓冲区。

这样做时您应该检查几点:

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

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

【讨论】:

    【解决方案2】:

    问题已解决,因为我是 openGL 的新手,而且我没有绘制屏幕帧缓冲区,我是通过在屏幕调用中的渲染中使用以下代码来完成的。如果有人需要在初学者级别查看该内容,请发布

    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);
    

    虽然,这显示了纹理,但在另一个帧缓冲区中绘制的一个小框中。尽管顶点和坐标是完整的屏幕,但它不会绘制到完整的屏幕。对此进行调查,如果我发现将对其进行编辑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-24
      • 2023-03-06
      • 1970-01-01
      • 2011-05-14
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多