将IOSurface支持的纹理转换为GL_TEXTURE_2D

时间:2016-07-13 20:46:00

标签: macos opengl textures scenekit iosurface

我想用mipmapping渲染IOSurface纹理。

我正在OpenGL生成一个IOSurface纹理,如下所示:

let error = CGLTexImageIOSurface2D(context.cglContextObj!, 
GLenum(GL_TEXTURE_RECTANGLE_ARB),GLenum(GL_RGBA), GLsizei(width), GLsizei(height),
GLenum(GL_BGRA), GLenum(GL_UNSIGNED_INT_8_8_8_8_REV), surface!, 0)

使用简单的片段着色器渲染它:

#version 120
uniform sampler2DRect texture;
varying vec2 texCoord;
uniform vec2 size;

void main(){
    vec4 tex = texture2DRect(texture, texCoord*size);
    gl_FragColor = tex;
}

这很好用。但不幸的是,纹理不是mipmap,并且在较小的尺寸下观看时非常有颗粒/像素化。经过进一步研究,似乎不仅IOSurface支持的纹理仅限于GL_TEXTURE_RECTANGLE_ARB目标,它们也不支持mipmapping。

奥莱特。所以我最好的选择似乎是:

  1. GL_TEXTURE_RECTANGLE_ARB纹理复制到GL_TEXTURE_2D纹理
  2. 为此新纹理生成mipmap
  3. 请注意我在Mac上开发,它不支持OpenGL 4.3,所以我不能在这里使用方便的glCopyImageSubData。相反,我将基于此答案的第1步的方法基于How to copy texture1 to texture2 efficiently?

    我的完整代码现在看起来像这样:

    if !hasCreatedTexture {
        glGenTextures(1, &texture);
        glGenTextures(1, &arbTexture);
        glGenFramebuffers(1, &fbo)
        hasCreatedTexture = true
    }
    glEnable(GLenum(GL_TEXTURE_RECTANGLE_ARB))
    glBindTexture(GLenum(GL_TEXTURE_RECTANGLE_ARB), arbTexture)
    
    let error = CGLTexImageIOSurface2D(context.cglContextObj!, GLenum(GL_TEXTURE_RECTANGLE_ARB), GLenum(GL_RGBA), GLsizei(width), GLsizei(height), GLenum(GL_BGRA), GLenum(GL_UNSIGNED_INT_8_8_8_8_REV), surface!, 0)
    
    
    glBindFramebuffer(GLenum(GL_FRAMEBUFFER), fbo);
    glFramebufferTexture2D(GLenum(GL_READ_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0),
                               GLenum(GL_TEXTURE_RECTANGLE_ARB), arbTexture, 0);
    glFramebufferTexture2D(GLenum(GL_DRAW_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT1),
                               GLenum(GL_TEXTURE_2D), texture, 0);
    glDrawBuffer(GLenum(GL_COLOR_ATTACHMENT1));
    glBlitFramebuffer(0, 0, GLint(width), GLint(height), 0, 0, GLint(width), GLint(height), GLbitfield(GL_COLOR_BUFFER_BIT), GLenum(GL_NEAREST));
    glBindTexture(GLenum(GL_TEXTURE_2D), texture)
    

    我更改了着色器以支持GL_TEXTURE_2D

    #version 120
    uniform sampler2D texture;
    varying vec2 texCoord;
    
    void main(){
        vec4 tex = texture2D(texture, texCoord);
        gl_FragColor = tex;
    }
    

    这就是我被困的地方。图像全黑,我不知道为什么它不起作用。

    我试着像这样查看像素数据:

    var pixelData = UnsafeMutablePointer<GLubyte>(allocatingCapacity: Int(width * height * 4))
    
    glGetTexImage(GLenum(GL_TEXTURE_2D), 0, GLenum(GL_BGRA),
    GLenum(GL_UNSIGNED_INT_8_8_8_8_REV), pixelData)
    print(NSData(bytes: pixelData, length: 50000).description)
    

    它全是零。我的方法是否有问题,或者该问题是否与处理IOSurface支持的纹理特别相关?

1 个答案:

答案 0 :(得分:2)

最后使用以下方法解决了这个问题:

func createMipTexture() {
    guard let surface = self.surface else { return }
    glBindTexture(GLenum(GL_TEXTURE_2D), texture);
    glEnable(GLenum(GL_TEXTURE_2D))

    guard let address = IOSurfaceGetBaseAddress(surface) as UnsafeMutableRawPointer? else { return }
    IOSurfaceLock(surface, .readOnly, nil)
    glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(width), GLsizei(height), 0,  GLenum(GL_BGRA), GLenum(GL_UNSIGNED_INT_8_8_8_8_REV), address)
    IOSurfaceUnlock(surface, .readOnly, nil);
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAX_LEVEL), 100)
    glHint(GLenum(GL_GENERATE_MIPMAP_HINT), GLenum(GL_NICEST));
    glGenerateMipmap(GLenum(GL_TEXTURE_2D))
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_REPEAT);
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_REPEAT);
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR);
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR_MIPMAP_LINEAR);
}