点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,可以点个在看,让它可以帮助到更多老铁~
原教程地址:
https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/
程序参考地址:
https://blog.csdn.net/z136411501/article/details/79834381
这里介绍第二种方法,使用QOpenGLFunctions_3_3_Core类对象,Core类其实是一种Qt对OpenGL特定版本的包装类对象,可以直接使用该版本OpenGL的所有函数。
效果图如下:
代码和之前比“几乎”没变,只是把所有gl开头的函数都换成了
m_core->gl ******来调用了。
头文件如下:
#include
#include
class MyGLWidget : public QOpenGLWidget
{
Q_OBJECT
public:
MyGLWidget();
~MyGLWidget();
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
//顶点缓冲对象 Vertex Buffer Object,VBO,教程中第一个出现的OpenGL对象
GLuint VBO;
GLuint VAO;
GLuint EBO;
GLuint m_shaderProgram; //着色器程序对象
QOpenGLFunctions_3_3_Core *m_core;
这里我们不再继承 QOpenGLExtraFunctions,对gl相关函数的调用则是通过m_core进行。
源文件如下:
//着色器语言GLSL(OpenGL Shading Language)编写的顶点着色器
static const char *vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"void main(){\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n\0";
//着色器语言GLSL(OpenGL Shading Language)编写的片段着色器
static const char *fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main(){\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
#if 0
#define TRIANGLE
#elif 1
#define RECTANGLE
#endif
MyGLWidget::MyGLWidget()
{
}
MyGLWidget::~MyGLWidget()
{
}
void MyGLWidget::initializeGL()
{
m_core = QOpenGLContext::currentContext()->versionFunctions();//获取上下文
//着色器部分
GLuint vertexShader = m_core->glCreateShader(GL_VERTEX_SHADER); //创建顶点着色器对象
m_core->glShaderSource(GLuint(vertexShader), 1, &vertexShaderSource, nullptr); //着色器源码附加到着色器对象
m_core->glCompileShader(GLuint(vertexShader)); //编译
int is_success; //检查是否编译成功,未成功则需返回错误
char infoLog[512];
m_core->glGetShaderiv(GLuint(vertexShader), GL_COMPILE_STATUS, &is_success);
if (!is_success)
{
m_core->glGetShaderInfoLog(GLuint(vertexShader), 512, nullptr, infoLog);
qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << infoLog ;
}
GLuint fragmentShader = m_core->glCreateShader(GL_FRAGMENT_SHADER); //创建片段着色器对象,与顶点着色器相似
m_core->glShaderSource(GLuint(fragmentShader), 1, &fragmentShaderSource, nullptr);
m_core->glCompileShader(GLuint(fragmentShader));
m_core->glGetShaderiv(GLuint(fragmentShader), GL_COMPILE_STATUS, &is_success);
if (!is_success)
{
m_core->glGetShaderInfoLog(GLuint(fragmentShader), 512, nullptr, infoLog);
qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED" << infoLog;
}
m_shaderProgram = m_core->glCreateProgram(); //创建着色器程序对象
m_core->glAttachShader(m_shaderProgram, GLuint(vertexShader));
m_core->glAttachShader(m_shaderProgram, GLuint(fragmentShader));
m_core->glLinkProgram(m_shaderProgram); //之前编译的着色器附加到程序对象上
m_core->glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &is_success);//检查是否编译成功,未成功则需返回错误
if (!is_success) {
m_core->glGetProgramInfoLog(m_shaderProgram, 512, nullptr, infoLog);
qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog ;
}
m_core->glDeleteShader(vertexShader); //着色器对象链接到程序对象以后,删除着色器对象
m_core->glDeleteShader(fragmentShader);
//VAO,VBO数据部分
#ifdef TRIANGLE
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
#else //绘制矩形
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = { // 注意索引从0开始!
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
#endif
//两个参数,第一个为需要创建的缓存数量。第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
m_core->glGenVertexArrays(1, &VAO);
m_core->glGenBuffers(1, &VBO); //顶点缓冲对象处理
m_core->glGenBuffers(1, &EBO);
m_core->glBindVertexArray(VAO);
m_core->glBindBuffer(GL_ARRAY_BUFFER, VBO); //使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上
//之前定义的顶点数据复制到缓冲的内存中
m_core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
#ifdef RECTANGLE
m_core->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
m_core->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
#endif
//glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)
m_core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
m_core->glEnableVertexAttribArray(0); //以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的
m_core->glBindBuffer(GL_ARRAY_BUFFER, 0);
m_core->glBindVertexArray(0);
}
void MyGLWidget::resizeGL(int w, int h)
{
m_core->glViewport(0, 0, w, h);
}
void MyGLWidget::paintGL()
{
m_core->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
m_core->glClear(GL_COLOR_BUFFER_BIT);
m_core->glUseProgram(m_shaderProgram); //激活程序对象
m_core->glBindVertexArray(VAO);
#ifdef TRIANGLE
m_core->glDrawArrays(GL_TRIANGLES, 0, 3);
#else //绘制矩形
m_core->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
#endif
// glUseProgram(0);
}
小结:
对于程序中 文字解释的排版欢迎大家多提出宝贵的意见,感谢!
最后,如需完整工程可在公众号后台留言
学不可以已