see*_*arp 4 opengl 3d rendering render off-screen
我想尝试制作一个简单的程序,它采用3D模型并将其渲染成图像.有什么方法可以使用OpenGL渲染图像并将其放入一个包含图像而不是显示图像的变量中?我不想看到我正在渲染的东西我只想保存它.有没有办法用OpenGL做到这一点?
我假设您知道如何使用OpenGL将内容绘制到屏幕上,并且您编写了一个像drawStuff这样的函数来执行此操作.
首先,您必须决定最终渲染的大小; 我在这里选择一个方块,大小为512x512.您也可以使用不是2的幂的大小,但为了简单起见,我们暂时坚持这种格式.有时OpenGL对这个问题很挑剔.
const int width = 512;
const int height = 512;
Run Code Online (Sandbox Code Playgroud)
然后,您需要三个对象才能创建一个屏幕外绘图区域; 这称为帧缓冲区对象,如user1118321所述.
GLuint color;
GLuint depth;
GLuint fbo;
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
首先,您创建一个存储像素颜色的存储区域,而不是存储像素深度的存储区域(在计算机图形中用于移除隐藏的表面),最后将它们连接到FBO,FBO基本上都包含对两者的引用.以第一个块为例,有6个调用:
要从屏幕渲染切换到屏幕外渲染,您可以在程序中的某处使用布尔变量:
if (offscreen)
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawStuff();
if (offscreen)
saveToFile();
Run Code Online (Sandbox Code Playgroud)
所以,如果屏幕外是真的,你实际上想让drawStuff干扰fbo,因为你希望它在它上面渲染场景.
函数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);
}
Run Code Online (Sandbox Code Playgroud)