QT学习(17):QT中OpenGL的简单使用

OpenGL渲染管线:
0、顶点数据:CPU将顶点数据传入GPU,包括顶点的坐标、颜色、法向量、纹理坐标等。
1、顶点着色器Vertex Shader:加工顶点数据,把顶点坐标进行平移、旋转、缩放等各种变换操作,修改各种顶点数据,比如纹理坐标,法向量等。
2、图元装配:将顶点装配成指定图元的形状,
3、几何着色器:生成新的顶点,修改输出的图元类型
4、光栅化:将几何数据转换为像素
5、片段着色器Fragment Shader:计算像素颜色
6、测试:筛选像素,丢弃部分像素
7、混合:表现物体透明度

QOpenGLWidget 类:
QOpenGLWidget 类是用于渲染 OpenGL 图形的Widget。
QOpenGLWidget提供了显示集成到Qt应用程序中的OpenGL图形的功能。它使用起来非常简单:让你的类继承自它,并像使用任何其他QWidget一样使用子类,此外还可以选择使用和标准OpenGL渲染命令。

QOpenGLWidget 提供了三个方便的虚函数,可以在子类中重新实现这些函数以执行典型的 OpenGL 任务:

  • paintGL()-渲染 OpenGL 场景。每当需要更新widget时调用。
  • resizeGL()-设置OpenGL的viewport、投影projection等。每当widget调整大小时调用(以及首次显示widget时,因为所有新创建的widget都会自动获得resize事件)。
  • initializeGL()-设置 OpenGL 资源和状态。在第一次调用paintGL()或resizeGL()之前调用一次。

一、顶点数据和着色器程序
顶点数组vertices:四个顶点数据,每一行对应一个顶点,有八个float数值,分别为坐标(3),颜色(3),纹理(2)。

float vertices[] = {
        // positions          // colors           // texture coords
         0.9f,  0.9f, 0.0f,   1.0f, 0.5f, 0.0f,   1.0f, 1.0f, // top right
         0.9f, -0.9f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        -0.9f, -0.9f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        -0.9f,  0.9f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
    };

索引数组indices:实现顶点的复用。0,1,3对应顶点数组中第一行、第二行、第四行,为一个三角形,1,2,3同理,两个三角形即一个矩形。

unsigned int indices[] = {  // note that we start from 0!
    0, 1, 3,  // first Triangle
    1, 2, 3   // second Triangle
};

顶点着色器程序:从顶点数据中直接接收输入,需要为输入提供一个额外的layout标识,这样才能链接到顶点数据。

#version 330 core
layout (location = 0) in vec3 aPos;//位置变量的属性位置值为 0 
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
        gl_Position = vec4(aPos, 1.0);
        ourColor = aColor;
        TexCoord = vec2(aTexCoord.x,1- aTexCoord.y);
}

片段着色器程序:需要生成一个最终输出的颜色–vec4颜色输出变量。
out和in用来在着色器程序中传递数据,uniform全局可见、变量唯一、一直保存。

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

// texture sampler
uniform sampler2D texture1;

void main()
{FragColor = texture2D(texture1, TexCoord);}

二、重写initializeGL()
VAO,Vertex Array Object顶点数组,一个元素对应一个顶点属性
VBO,Vertex Buffer Objects顶点缓冲区,一个元素对应一个顶点数据

glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);//分配 GPU 里的显存

VAO绑定,将该VAO中的数据提交给vertex shader
VBO绑定,GL_ARRAY_BUFFER为全局变量buffer(显存中),可以通过glVertexAttribPointer规定读写buffer的方式。

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把数据从主存传到分配的显存
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);

glVertexAttribPointer:把对应的顶点属性存储到当前绑定的VAO的对应元素中,第六个参数指针表示位置数据在缓冲中起始位置的偏移量。
glEnableVertexAttribArray:将索引对应的属性状态置为enabled,此时着色器读取值才能生效。

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

绑定顶点着色器和片段着色器

shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/vshader.glsl");
shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/fshader.glsl");
shaderProgram.link();

纹理绑定

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture); //绑定纹理
//设置纹理包装参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	
//将“纹理换行”设置为默认换行
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//设置纹理过滤参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

纹理生成

int width, height, nrChannels;
unsigned char *data  = stbi_load("D:\\qtproject\\untitled\\1.jpeg",&width,&height,&nrChannels,0);
//unsigned char *data  = stbi_load("brickwall.jpg",&width,&height,&nrChannels,0);
if(data)
{
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
	glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
	qDebug() << "Failed to load texture" ;
}
stbi_image_free(data);

三、重写paintGL()

glClearColor(0.1f, 0.9f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram.bind();
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);//使用索引时的绘制方式

参考:
https://zhuanlan.zhihu.com/p/392128223
https://blog.csdn.net/weixin_42126427/article/details/122807819
https://zhuanlan.zhihu.com/p/108077199
https://zhuanlan.zhihu.com/p/56693625

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值