opengl - 我可以使用 OpenGL 进行离屏渲染吗?

标签 opengl 3d rendering render off-screen

这个问题在这里已经有了答案:





How to use GLUT/OpenGL to render to a file?

(5 个回答)


8年前关闭。




我想尝试制作一个简单的程序,该程序采用 3D 模型并将其渲染为图像。有什么方法可以使用 OpenGL 渲染图像并将其放入保存图像而不是显示图像的变量中?我不想看到我正在渲染的内容,我只想保存它。有没有办法用 OpenGL 做到这一点?

最佳答案

我假设您知道如何使用 OpenGL 将内容绘制到屏幕上,并且您编写了诸如 之类的函数。 drawStuff 这样做。

首先,您必须决定最终渲染的大小;我在这里选择一个正方形,大小为 512x512。您也可以使用不是 2 的幂的大小,但为了简单起见,我们暂时使用这种格式。有时 OpenGL 对这个问题很挑剔。

const int width = 512;
const int height = 512;

然后你需要三个对象来创建一个离屏绘图区域;正如 user1118321 所说,这称为帧缓冲区对象。
GLuint color;
GLuint depth;
GLuint fbo;

FBO存储一个颜色缓冲区和一个深度缓冲区;您的屏幕渲染区域也有这两个缓冲区,但您不想使用它们,因为您不想绘制到屏幕上。要创建 FBO,您只需执行一次类似以下操作,例如在启动时:
glGenTextures(1, &color);
glBindTexture(GL_TEXTURE_2D, color);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);

glGenRenderbuffers(1, &depth);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

首先,创建一个存储像素颜色的内存区域,然后创建一个存储像素深度(在计算机图形学中用于删除隐藏表面),最后将它们连接到 FBO,它基本上包含对两者的引用。以第一个 block 为例,有 6 个调用:
  • glGenTextures 为纹理创建名称; OpenGL 中的名称只是一个整数,因为字符串效率太低。
  • glBindTexture 将纹理绑定(bind)到目标,即 GL_TEXTURE_2D ;指定相同目标的后续调用将对该纹理进行操作。
  • 第 3、4 和 5 次调用特定于被操作的目标,您应该引用 OpenGL 文档以获取更多信息。
  • 最后一次调用 glBindTexture 将纹理与目标解除绑定(bind)。因为在某些时候你会将控制权交给你的 drawStuff 函数,这反过来会进行大量的 OpenGL 调用,您现在需要清除工作区,以避免干扰您创建的对象。

  • 要从屏幕渲染切换到屏幕外渲染,您可以在程序的某处使用 bool 变量:
    if (offscreen)
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    else
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
    drawStuff();
    
    if (offscreen)
        saveToFile();
    

    所以,如果 离屏真实 你真的想要 drawStuff 干扰转发 ,因为您希望它在其上渲染场景。

    函数 saveToFile 负责加载渲染结果并将其转换为文件。这在很大程度上取决于您使用的操作系统和语言。例如,在带有 C 的 Mac OS X 上,它将类似于以下内容:
    void saveImage()
    {
        void *imageData = malloc(width * height * 4);
    
        glBindTexture(GL_TEXTURE_2D, color);
        glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
    
        CGContextRef contextRef = CGBitmapContextCreate(imageData, width, height, 8, 4 * width, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), kCGImageAlphaPremultipliedLast);
        CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);
        CFURLRef urlRef = (CFURLRef)[NSURL fileURLWithPath:@"/Users/JohnDoe/Documents/Output.png"];
        CGImageDestinationRef destRef = CGImageDestinationCreateWithURL(urlRef, kUTTypePNG, 1, NULL);
        CGImageDestinationAddImage(destRef, imageRef, nil);        
        CFRelease(destRef);
    
        glBindTexture(GL_TEXTURE_2D, 0);
    
        free(imageData);
    }
    

    关于opengl - 我可以使用 OpenGL 进行离屏渲染吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14785007/

    相关文章:

    browser - Blender 与 Unity

    c++ - Dev C++ 中的过剩错误 "redeclaration of C++ built-in type ` short'”

    opengl - 在同一阶段使用多个着色器仍然是一个坏主意吗?

    c++ - 带有聚光灯的 OpenGL 中的阴影映射会产生不寻常的效果

    matlab - 有没有办法控制 Matlab 的 3D 查看器中的失真?

    image - Matlab 中图像的 3D 图

    directx - 点 Sprite 的缩放 (Direc3D 9)

    android-studio - Android Studio 的渲染问题

    c++ - OpenGL:无法渲染三角形

    .net - System.Windows.Media.DrawingVisual.RenderOpen() 一段时间后出错