关于OpenGL实现VBO绘制的旗帜飘扬的作业的一个小思路
遇到一个问题,要求我用VBO画的旗帜有飘扬的动态,进一步,VBO绘制的图像怎么用曲面细分着色器。
下面是思路:
把VBO先绘制到帧缓冲里,然后保存成纹理
用纹理绘制的形式,使用曲面细分添加控制点
曲面细分评估里加入sin()函数即可
程序在有N卡的电脑上不显示不知道为什么
把VBO转换成纹理的函数
void convertTrianglesToFBOTexture(GLuint vbo,const int numTriangles,GLuint &textureId)
{
int textureWidth;
int textureHeight;
GLuint fbo;
// 创建临时顶点着色器和片段着色器源码
const char* vertexShaderSource = R"(
#version 430 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec3 fargcolor;
uniform mat4 proj_matrix;
uniform mat4 mv_matrix;
void main()
{
gl_Position = proj_matrix * mv_matrix * vec4(position, 1.0);
fargcolor = color;
}
)";
const char* fragmentShaderSource = R"(
#version 430 core
out vec4 color; // 声明color变量
in vec3 fargcolor;
void main()
{
color=vec4(fargcolor,1.0);
}
)";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 检查顶点着色器编译是否成功
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
char infoLog[512];
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "顶点着色器编译失败!\n" << infoLog << std::endl;
glDeleteShader(vertexShader);
return;
}
// 编译片段着色器
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 检查片段着色器编译是否成功
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
// 编译失败,处理错误
char infoLog[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "段着色器编译失败!\n" << infoLog << std::endl;
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return;
}
// 创建渲染程序并关联着色器
GLuint shaderProgramTmp = glCreateProgram();
glAttachShader(shaderProgramTmp, vertexShader);
glAttachShader(shaderProgramTmp, fragmentShader);
glLinkProgram(shaderProgramTmp);
// 检查渲染程序链接是否成功
glGetProgramiv(shaderProgramTmp, GL_LINK_STATUS, &success);
if (!success)
{
// 链接失败,处理错误
char infoLog[512];
glGetProgramInfoLog(shaderProgramTmp, 512, NULL, infoLog);
std::cout << "链接失败!\n" << infoLog << std::endl;
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgramTmp);
return;
}
// 绑定VBO并获取顶点数据
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float* vertexData = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
// 初始化最小和最大坐标为第一个顶点的坐标
float minX = vertexData[0];
float minY = vertexData[1];
float maxX = vertexData[0];
float maxY = vertexData[1];
// 遍历顶点数据,找到最小和最大坐标
for (int i = 0; i < numTriangles; i++)
{
float x = vertexData[i * 6];
float y = vertexData[i * 6 + 1];
if (x < minX)
minX = x;
if (x > maxX)
maxX = x;
if (y < minY)
minY = y;
if (y > maxY)
maxY = y;
}
textureWidth = 1200;
textureHeight = 800;
//cout << "纹理宽度 " << textureWidth << "\n纹理高度 " << textureHeight << "\n";
// 创建帧缓冲对象
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// 创建纹理对象
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureWidth, textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
//创建渲染缓冲对象
//可参考https://zhuanlan.zhihu.com/p/109107214
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, textureWidth, textureHeight);
//封装了24位的深度和8位的模板缓冲
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
// 检查帧缓冲是否完整
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &textureId);
return ;
}
// 绑定帧缓冲并渲染三角形到纹理
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, textureWidth, textureHeight);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgramTmp);
GLuint mvtmp,ptmp;
glm::mat4 vMatmp = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -18));
glm::mat4 pMatmp = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);//透视投影矩阵
ptmp = glGetUniformLocation(shaderProgramTmp, "proj_matrix");
mvtmp = glGetUniformLocation(shaderProgramTmp, "mv_matrix");
//vMat = glm::mat4(1.0f);
glUniformMatrix4fv(mvtmp, 1, GL_FALSE, glm::value_ptr(vMatmp));
glUniformMatrix4fv(ptmp, 1, GL_FALSE, glm::value_ptr(pMatmp));
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 设置顶点属性指针,包括位置和颜色
glVertexAttribPointer(0, 3, GL_FLOAT, false, 6 * sizeof(float), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 绘制三角形(包括矩形和五个五角星)
glDrawArrays(GL_TRIANGLES, 0, 156);
// 解绑帧缓冲
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//删除临时顶点着色器、片段着色器和渲染程序
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgramTmp);
//return textureId;
}
今天终于验收完成计图的实验啦!
好好复习考试吧
作者:qbning
-------------------------------------------
个性签名:曾经的我们空有一颗望海的心,却从没为前往大海做过真正的努力
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!