您的位置:首页 > 编程语言 > Qt开发

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

2017-11-24 18:25 369 查看

一,简述

        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中对应的就是两个类QOpenGLWidget和QOpenGLFunctions,只需要继承他们就可以了。

class QOPenWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
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_OBJECT
public:
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;

//着色器程序ID
unsigned 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);
//绑定VAO
glBindVertexArray(VAO);

//绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//把顶点数组复制到VBO
glBufferData(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);

//解除绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
//解除绑定EBO
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//解除绑定VAO
glBindVertexArray(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();
/
4000
/ 关闭文件处理器
vShaderFile.close();
fShaderFile.close();
// 转换数据流到string
vertexCode = 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 core
layout (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 core
out vec4 FragColor;
in vec3 ourColor;

void main()
{
FragColor = vec4(ourColor, 1.0);
}

五,显示效果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OpenGL shader qt