OpenGL环境配置(基于Qt窗口)

来源:互联网 发布:网络水军是什么 编辑:程序博客网 时间:2024/05/17 22:47

一,简述

        OPenGL的环境配置由很多种,比如glut和glu,glfw和glad,glew和freeglut等,网上教程都有讲到,这些配置基本上都需要一个窗口库和OpenGL扩展库(用于管理函数指针的)。带领我入门的教程就LearnOpenGL,这是一个对初学者十分友好的教程,基于OpenGL3.3来讲解的,使用的环境就是glfw和glad组合。

        但在随后的实际项目中界面比较复杂,在不同窗口间数据传输,控件交互等操作,glfw库就显得有点小了,最后选择Qt来作为界面库使用。

        为了和LearnOpenGL教程对应起来,需要搭建一个只使用Ot的界面,而不用它封装好的OpenGL类。写OpenGL程序是还是以LearnOpenGL中面向过程的风格。

二,环境版本

vs2013 + Qt5.5 + OpenGL3.3

三,方法

        和一般的环境配置一样,也需要一个三维绘图窗口和一个用于管理函数指针的库,在Qt中对应的就是两个类QOpenGLWidgetQOpenGLFunctions,只需要继承他们就可以了。

class QOPenWidget : public QOpenGLWidget, protected QOpenGLFunctions{Q_OBJECTpublic:QOPenWidget(QWidget *parent = 0);~QOPenWidget();private:void initializeGL();/*写渲染前的配置信息*/void resizeGL(int w, int h);/*窗口变化*/void paintGL();/*写渲染循环的内容*/};

        注意QOpenGLFunctions是基于OpenGL ES 2.0的API,如果想用任意版本的原生OPenGL,需要用的一个类QAbstractOpenGLFunctions,它有很多子类,对应不同版本的OpenGL。如图这是Qt文档中的说明。


        对于本示例来说使用的是3.3版,继承的类就是QOpenGLFunctions_3_3_Compatibility类。其他可按自己需要的版本来继承。下面来个完整的示例。

四,源码

QOPenWidget.h

#ifndef QOPENWIDGET_H#define QOPENWIDGET_H#include <qopenglwidget.h>#include <qopenglfunctions_3_3_compatibility>#include <qopenglfunctions_4_3_compatibility>#include <QOpenGLShaderProgram>#include <QOpenGLBuffer>#include <qopenglvertexarrayobject.h>#include <qpushbutton.h>#include <qtimer.h>#include <string>#include <fstream>#include <sstream>#include <iostream>class QOPenWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Compatibility{Q_OBJECTpublic:QOPenWidget(QWidget *parent = 0);~QOPenWidget();private:void initializeGL();void resizeGL(int w, int h);void paintGL();//加载着色器程序void CompileShader(unsigned int *id, const char* vertexPath, const char* fragmentPath, const char* geometryPath = NULL);private://缓存对象unsigned int VBO, VAO, EBO;//着色器程序IDunsigned int ID;//定时器QTimer timer;};#endif 

QOPenWidget.cpp

#include "QOPenWidget.h"#include <iostream>#include <qtimer.h>#include<ctime>#include <string.h>QOPenWidget::QOPenWidget(QWidget *parent) :QOpenGLWidget(parent){setUpdateBehavior(QOpenGLWidget::NoPartialUpdate);connect(&timer, SIGNAL(timeout()), this, SLOT(update()));timer.start(0);}QOPenWidget::~QOPenWidget(){}void QOPenWidget::initializeGL(){initializeOpenGLFunctions();//初始化glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glEnable(GL_DEPTH_TEST);//开启深度缓存//添加着色器CompileShader(&ID,"texture.vs", "texture.fs");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    };glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);//绑定VAOglBindVertexArray(VAO);//绑定VBOglBindBuffer(GL_ARRAY_BUFFER, VBO);//把顶点数组复制到VBOglBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 位置属性glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 颜色属性glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);//解除绑定VBOglBindBuffer(GL_ARRAY_BUFFER, 0);//解除绑定EBO//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);//解除绑定VAOglBindVertexArray(0);}void QOPenWidget::resizeGL(int w, int h){glViewport(0, 0, w, h);}void QOPenWidget::paintGL(){glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);//激活着色器glUseProgram(ID);//绑定顶点缓存对象glBindVertexArray(VAO);//开始绘制glDrawArrays(GL_TRIANGLES, 0, 3);//解除绑定glBindVertexArray(0);}//加载着色器程序void QOPenWidget::CompileShader(unsigned int *id, const char* vertexPath, const char* fragmentPath, const char* geometryPath){std::string vertexCode;std::string fragmentCode;std::string geometryCode;std::ifstream vShaderFile;std::ifstream fShaderFile;std::ifstream gShaderFile;// 打开文件vShaderFile.open(vertexPath);fShaderFile.open(fragmentPath);std::stringstream vShaderStream, fShaderStream;// 读取文件的缓冲内容到数据流中vShaderStream << vShaderFile.rdbuf();fShaderStream << fShaderFile.rdbuf();// 关闭文件处理器vShaderFile.close();fShaderFile.close();// 转换数据流到stringvertexCode = vShaderStream.str();fragmentCode = fShaderStream.str();if (geometryPath != NULL){gShaderFile.open(geometryPath);std::stringstream gShaderStream;gShaderStream << gShaderFile.rdbuf();gShaderFile.close();geometryCode = gShaderStream.str();}const char* vShaderCode = vertexCode.c_str();const char* fShaderCode = fragmentCode.c_str();// 2. 编译着色器unsigned int vertex, fragment;int success;char infoLog[512];// 顶点着色器vertex = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex, 1, &vShaderCode, NULL);//编译着色器glCompileShader(vertex);//检测编译时错误glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//如果编译错误进入语句if (!success){//获取错误信息glGetShaderInfoLog(vertex, 512, NULL, infoLog);//打印错误std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;}//片元着色器fragment = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment, 1, &fShaderCode, NULL);glCompileShader(fragment);//检测错误glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success){//获取错误原因glGetShaderInfoLog(fragment, 512, NULL, infoLog);//打印std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;}//几何着色器unsigned int geometry;if (geometryPath != nullptr){const char * gShaderCode = geometryCode.c_str();geometry = glCreateShader(GL_GEOMETRY_SHADER);glShaderSource(geometry, 1, &gShaderCode, NULL);glCompileShader(geometry);}// 着色器程序*id = glCreateProgram();glAttachShader(*id, vertex);glAttachShader(*id, fragment);if (geometryPath != nullptr)glAttachShader(*id, geometry);glLinkProgram(*id);//检测错误glGetProgramiv(*id, GL_LINK_STATUS, &success);if (!success){//获取错误信息glGetProgramInfoLog(ID, 512, NULL, infoLog);std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;}// 删除着色器,它们已经链接到我们的程序中了,已经不再需要了glDeleteShader(vertex);glDeleteShader(fragment);if (geometryPath != nullptr)glDeleteShader(geometry);}

着色器

texture.vs

#version 330 corelayout (location = 0) in vec3 aPos;   layout (location = 1) in vec3 aColor; out vec3 ourColor; void main(){    gl_Position = vec4(aPos, 1.0);    ourColor = aColor; }

texture.fs

#version 330 coreout vec4 FragColor;  in vec3 ourColor;void main(){    FragColor = vec4(ourColor, 1.0);}

五,显示效果



原创粉丝点击