OpenGL:使用FBO为渲染对象并从GPU取出存图
程序员文章站
2022-07-04 11:37:34
...
OpenGL 使用FBO为渲染对象并从GPU取出存图的代码
#include "gl/glew.h"
#include "gl/glut.h"
#include <fstream>
#define isize 512
const char* vertexShaderSource = "#version 460 \n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 460 \n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n\0";
void saveToBMP24(void* packBuffer, const std::string& img);
int main(int argc, char** argv)
{
argc;argv;
//初始化窗口以及渲染上下文
//创建viewport
int iViewportIndex = 0;
float fv4Viewport[4] = {0.0f,0.0f,512.0f,512.0f};
glViewportIndexedfv(iViewportIndex, fv4Viewport);
//创建FBO绑定的纹理
GLuint texName;
glGenTextures(1, &texName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, GLint(0), GL_RGBA, isize, isize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
//创建FOB
GLuint FramebufferName;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texName, 0);
//三角形的三个顶点数据
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
//创建VAO VBO
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//初始化program,shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//清背景
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
//设置绘制buffer,数组形式设置
GLuint a[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, a);
glUseProgram(shaderProgram);
//绑定VAO
glBindVertexArray(VAO);
//绘制三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
//备份
int iOldPixelPackAlignment(1);
glGetIntegerv(GL_PACK_ALIGNMENT, &iOldPixelPackAlignment);
//设置新的对齐
glPixelStorei(GL_PACK_ALIGNMENT, 1);
//绑定fbo,读取数据
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferName);
glReadBuffer(GL_COLOR_ATTACHMENT0);
void* pImage = new char[isize * isize * 4];
glReadPixels(0, 0, isize, isize,
GL_RGBA, GL_UNSIGNED_BYTE, pImage);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
//存图 bmp格式
saveToBMP24(pImage, "/usr/sss1.bmp");
return 0;
}
void saveToBMP24(void* packBuffer, const std::string& img)
{
using namespace std;
//读入一个bmp格式文件,创建头用,todo:尺寸和位数对应
fstream in("/usr/123.bmp", ios_base::in | ios_base::binary);
if (!in)
{
return;
}
char bmpHeader[54] = { 0 };
in.read(bmpHeader, sizeof(bmpHeader));
char* pBuffer = new char[isize * isize *3];
in.read(pBuffer, isize * isize * 3);
in.close();
fstream out(img.c_str(), ios_base::out | ios_base::binary | ios_base::trunc);
if (!out)
{
in.close();
delete[] pBuffer;
return;
}
//RGB数据拷贝,A丢弃
for (size_t i = 0; i < isize*isize; i++)
{
int num = i * 4;
int numI = i * 3;
pBuffer[numI] = ((char*)packBuffer)[num + 2];
pBuffer[numI+1] = ((char*)packBuffer)[num + 1];
pBuffer[numI+2] = ((char*)packBuffer)[num ];
}
*((int*)&bmpHeader[0x12]) = isize;
*((int*)&bmpHeader[0x16]) = isize;
//bmp对齐
int totals = (isize) * 3;
while (totals % 4 != 0)
++totals;
totals = totals * (isize);
out.write(bmpHeader, sizeof(bmpHeader));
out.write(pBuffer, totals);
out.close();
delete[]pBuffer;
}
上一篇: C# linq的使用
下一篇: iperf3使用方法简介