#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
//顶点着色器源码
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
//片段着色器源码
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
Widget::Widget(QWidget *parent) :
QOpenGLWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::initializeGL()
{
initializeOpenGLFunctions();
GLuint vertexShader; // 顶点着色器
vertexShader = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);// 参数二为需要编译的着色器源码数量
glCompileShader(vertexShader);
createShaderError(vertexShader,GL_COMPILE_STATUS,false,"Vertex Shader compiler error");
GLuint fragmentShader;// 片段着色器
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
glCompileShader(fragmentShader);
createShaderError(fragmentShader,GL_COMPILE_STATUS,false,"Fragment Shader compiler error");
m_shaderProgram = glCreateProgram();
glAttachShader(m_shaderProgram,vertexShader);
glAttachShader(m_shaderProgram,fragmentShader);
glLinkProgram(m_shaderProgram);
createShaderError(m_shaderProgram,GL_LINK_STATUS,true,"Program linking failed error");
glUseProgram(m_shaderProgram);//激活程序对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void Widget::resizeGL(int w, int h)
{
//视口变换
glViewport(0,0,(GLsizei)w,(GLsizei)h);
}
void Widget::paintGL()
{
// glEnable(GL_DEPTH_TEST);
//drawTriangles();
drawRect();
}
void Widget::createShaderError(GLuint shader, GLuint flag, bool isProgram, const QString errMessage)
{
GLint success = 0;
GLchar error[1024] = {0};
if (isProgram){
glGetProgramiv(shader,flag,&success);
}
else {
glGetShaderiv(shader,flag,&success);
}
if (success == GL_FALSE){
if (isProgram){
glGetProgramInfoLog(shader,sizeof(error),NULL,error);
}
else {
glGetShaderInfoLog(shader,sizeof(error),NULL,error);
}
}
qDebug() << errMessage << ": " << error;
}
void Widget::drawTriangles()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
glUseProgram(m_shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void Widget::drawRect()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
float vertices[] = {
0.5f, 0.5f, 0.0f, // 右上
0.5f, -0.5f, 0.0f, // 右下
-0.5f, 0.5f, 0.0f, // 左上
-0.5f, -0.5f, 0.0f // 左下
};
unsigned int indices[] = {
0,1,2,//第一个三角形
1,2,3// 第二个三角形
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// 1. 绑定顶点数组对象
glBindVertexArray(VAO);
// 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用
unsigned int EBO;
glGenBuffers(1,&EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
// 4,设置顶点指针属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
glUseProgram(m_shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
}
//#include "widget.h"
//#include "ui_widget.h"
//Widget::Widget(QWidget *parent) :
// QGLWidget(parent),
// ui(new Ui::Widget)
//{
// ui->setupUi(this);
//}
//Widget::~Widget()
//{
// delete ui;
//}
//void Widget::initializeGL()
//{
// //设置widget的坐标和尺寸
// setGeometry(300, 150, 500, 500);
// //设置清除时颜色
// glClearColor(0.0, 0.0, 0.0, 0);
//}
//void Widget::resizeGL(int w, int h)
//{
// //视口变换
// glViewport(0,0,(GLsizei)w,(GLsizei)h);
// //投影变换
// glMatrixMode(GL_PROJECTION);
// glLoadIdentity();
// gluPerspective(40.0,(GLdouble)w/(GLdouble)h,0.1,10000.0);
// //视图变换
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
// gluLookAt(0.0,0.0,15.0,0.0,0.0,0.0,0.0,1.0,0.0);
//}
//void Widget::paintGL()
//{
// //清屏
// glClear(GL_COLOR_BUFFER_BIT);
// //绘制七彩三角形
// glBegin(GL_TRIANGLES);
// glColor3f(1.0,0.0,0.0);
// glVertex3f(-2,0,0);
// glColor3f(0.0,1.0,0.0);
// glVertex3f(2,0,0);
// glColor3f(0.0,0.0,1.0);
// glVertex3f(0,4,0);
// glEnd();
// glFlush();
//}