macos - 将 IOSurface 支持的纹理转换为 GL_TEXTURE_2D

标签 macos opengl textures scenekit iosurface

我想使用 mipmapping 渲染 IOSurface 纹理。

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

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

这很好用。但不幸的是,纹理没有进行纹理贴图,并且当以较小尺寸查看时,纹理非常颗粒化/像素化。经过进一步研究,发现 IOSurface 支持的纹理不仅限于 GL_TEXTURE_RECTANGLE_ARB 目标,而且也不支持 mipmapping。

好吧。所以我最好的选择似乎是:

  1. GL_TEXTURE_RECTANGLE_ARB 纹理复制到 GL_TEXTURE_2D 纹理
  2. 为此新纹理生成 mipmap

请注意,我是在 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 支持的纹理特别相关?

最佳答案

最终使用以下方法实现了此功能:

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

关于macos - 将 IOSurface 支持的纹理转换为 GL_TEXTURE_2D,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38361376/

相关文章:

opengl - GL_ARB_vertex_attrib_binding 和索引绘图

c++ - 以不同的方式转换同一3D空间中的两个对象?

c++ - 为什么法 vector 的顶点属性不起作用?

c++ - 从 sdl 调色板表面创建 OpenGL 纹理 (SDL_PIXELFORMAT_INDEX8)

qt - QPaint 到 QGLFramebufferObject 纹理上?

python - 无法在 Mac OS X 上导入 wx(Python)

swift - 将远程帧缓冲区流式传输到 NSView

r - IPython 笔记本和 rmagic/rpy2 : cannot find module ri2py (OSX 10. 8.5、python 2.7、R 3.1)

mysql - 无法连接到通过 Homebrew 安装的 MySQL @127.0.0.1

cuda - 新的 CUDA 纹理对象——在 2D 情况下获取错误数据