QT+OpenGL从顶点着色器传递颜色数据给片元着色器
QT+OpenGL基础:
- QT+OpenGL创建一个三角形并动态改变三角形颜色
- OpenGL中的VAO、VBO、EBO
- QT+OpenGL 使用VAO、VBO、EBO结合绘制一个正方形
- QT+OpenGL使用一组顶点绘制两个三角形
- QT+OpenGL通过两个VAO来管理两个三角形
- QT+Opengl使用两个Shader绘制两个不同颜色的三角形
- QT+OpenGL从顶点着色器传递颜色数据给片元着色器
- QT+OpenGL简单纹理贴图
- QT+OpenGL纹理与颜色混合
- Qt+OpenGL混合两个纹理,并可以改变纹理透明度
一、概述
目的:
1.定义顶点数据和颜色数据,并将颜色数据通过顶点着色器传递给片元着色器
2.对定义的三角形动态进行:平移、颠倒、镜像
二、示例代码
1.定义顶点坐标和颜色值。此处颜色和顶点是放到一块的。需要告知GPU如何解析数据,如:哪些是顶点,哪些是颜色数据
float vertices[] = { // 位置 // 颜色 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下 -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 顶部 };
2.定义顶点着色器和片元着色器
//顶点着色器 #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; uniform float mX; uniform float mY; uniform float mXT; out vec3 ourColor; void main(void) { gl_Position = vec4(aPos.x*mX+mXT,aPos.y*mY,aPos.z,1.0f); ourColor = aColor; }
//片元着色器 #version 330 core out vec4 FragColor; in vec3 ourColor; void main(void) { FragColor = vec4(ourColor,1.0f); }
3.编译、链接顶点着色器及片元着色器
GLuint BaseOpenGLWindow::buildAttachShaderAndReturnProgramId(QString vertexResPath, QString fragmentResPath) { //编译顶点着色器和片元着色器 GLuint vertexShader = getShaderId(GL_VERTEX_SHADER, vertexResPath); GLuint fragmentShader = getShaderId(GL_FRAGMENT_SHADER, fragmentResPath); GLuint programId = glCreateProgram(); glAttachShader(programId, vertexShader); glAttachShader(programId, fragmentShader); glLinkProgram(programId); getLinkProgramErrorInfo(programId); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return programId; }
//小程序 programId = buildAttachShaderAndReturnProgramId(":/QtForOpenCV4Tool/shader/vertex_color.vert", ":/QtForOpenCV4Tool/shader/vertex_color.frag");
4.创建VAO、VBO,把VBO挂到VAO上,并将顶点数据一次性Copy到GPU中,方便后续使用(效率高)
glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); //创建VBO并创建存放顶点数据的内存 glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
5.告知显卡如何解析顶点数据(顶点和颜色)
//位置数据(参数1:位置对应aPos,参数2:顶点个数,参数3:顶点数据类型,参数4:是否标准化处理,false,参数5:步长,这里一行有6个数据交替,所以这里写6,参数6:偏移量) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0);//启用第一个顶点,即aPos //颜色数据(参数1:位置对应aColor,参数5:步长同上,参数6:偏移量,这里颜色数据和顶点数据之间隔了3个float,所以是3*sizeof(float)) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1);//启用第二个顶点即aColor
6.顶点着色器定义了三个uniform变量
uniform float mX; uniform float mY; uniform float mXT;
可以通过这三个值从CPU把数据传递给GPU
GLint mLocation = glGetUniformLocation(programId, "mX"); glUniform1f(mLocation, mX); GLint mLocation1 = glGetUniformLocation(programId, "mY"); glUniform1f(mLocation1, mY); GLint mLocation2 = glGetUniformLocation(programId, "mXT"); glUniform1f(mLocation2, mXT);
7.绘制出想要的三角形
void GLColorDataFromVertexWindow::paintGL() { glUseProgram(programId); GLint mLocation = glGetUniformLocation(programId, "mX"); glUniform1f(mLocation, mX); GLint mLocation1 = glGetUniformLocation(programId, "mY"); glUniform1f(mLocation1, mY); GLint mLocation2 = glGetUniformLocation(programId, "mXT"); glUniform1f(mLocation2, mXT); switch (type) { case 1: { mX = -1.0f; GLint mLocation = glGetUniformLocation(programId, "mX"); glUniform1f(mLocation, mX); break; } case 2: { mY = -1.0f; GLint mLocation = glGetUniformLocation(programId, "mY"); glUniform1f(mLocation, mY); } break; case 3: { mXT = 0.25f; GLint mLocation = glGetUniformLocation(programId, "mXT"); glUniform1f(mLocation, mXT); } break; } glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); }
8.增加点击事件动态给mX、mY、mXT赋值,从而改变三角形的状态
void GLColorDataFromVertexWindow::changeTriStatus(int type) { this->type = type; mY = 1.0f; mX = 1.0f; mXT = 0.0f; update(); } QHBoxLayout* hLayout = new QHBoxLayout(this); QPushButton* btnRed = new QPushButton(this); btnRed->setText("Y轴颠倒"); QPushButton* btnGreen = new QPushButton(this); btnGreen->setText("X轴颠倒"); QPushButton* btnBlue = new QPushButton(this); btnBlue->setText("X轴平移"); hLayout->addWidget(btnRed); hLayout->addWidget(btnGreen); hLayout->addWidget(btnBlue); hLayout->setAlignment(Qt::AlignTop); connect(btnRed, &QPushButton::clicked, [=]() { changeTriStatus(1); }); connect(btnGreen, &QPushButton::clicked, [=]() { changeTriStatus(2); }); connect(btnBlue, &QPushButton::clicked, [=]() { changeTriStatus(3); });
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2023-08-22 ARouter源码再分析
2013-08-22 Android调用系统的发邮件功能
2013-08-22 Android向手机通讯录中的所有的联系人(包括SIM卡),向手机通讯录中插入联系人