前言
- 本节绘制一个矩形
- 矩形=两个三角形,因为openGL中都是用三角形(常用词三角化)来填充
- 两个三角形 = 6个点。数组中会有重复数组
6点绘制 | 4点绘制 |
---|---|
![]() | ![]() |
一、使用六点绘制
- 6个点vertices
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,
-0.5f,-0.5f,0.0f,
-0.5f,0.5f,0.0f
};
- 重新绑定VAO,调用drawArray
glClearColor(0.f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,6);
解释:
1.glUseProgram(shaderProgram); - 是必备6个渲染器
2.glBindVertexArray(VAO)-将VAO重新绑定[VBO自动也加载上来了]
3.glDrawArrays – 画Arrays (VAO)
解释 VAO 和 VBO
1.VAO才是对象
2.VBO仅仅显存缓冲
3.非填充模式
设置填充模式 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
二、 EBO,使用四个点绘制
- 概念
EBO (Element Buffer object) == Index Buffer Object
防止传入太多顶点, - 四个顶点
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//左上
}; //只有四个点了
//EBO
unsigned int indices[]={
0,1,3, //右上三角形 右上 - 右下 - 左上
1,2,3 //左下三角形 右下 - 左下-左上
}
- 绘制EBO时
glDrawElement(GL_TRIANGLES,6,GL_UNSIGNED_INT,0/*indices*/)
三角形,6个索引,是int索引
当没有绑定EBO时,可以直接使用indices变量
- 新建EBO、设置EBO数据
GLuint EBO;
glGenBuffers(1,&EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
- 一些概念说明
1)Buffer-用来向目标类型中传送数据,并不是严格意义的对象
2)两种buffer
buffer | 说明 |
---|---|
GL_ARRAY_BUFFER | 就是顶点数组buffer(简单名称改为 Array–buffer) |
GL_ELEMENT_ARRAY_BUFFER | 序号数组buffer |
- 新建EBO代码
glGenBuffer(GL_ARRAY_BUFFER /GL_ELEMENT_ARRAY_BUFFER)
glBindBuffer(类型,VBO/EBO);
glBufferData(GL_ARRAY_BUFFER /GL_ELEMENT_ARRAY_BUFFER)
必须指定类型,就是因为一个函数可以操作多种类型,必须走内部的switch
传入的数据是indices
GL_STATIC_DRAWA说明这个数据不长变,并且用来绘制的
- VBO操作时,直接被VAO记录了指针位置了
- EBO操作时,直接被VAO记录了地址
- 区别 VBO解绑,不影响VAO
- EBO解绑,VAO就找不到了
从下图看,VAO才是真的对象,Buffer-仅仅是无法自解释的数据
三、代码
#include "axbopenglwidget.h"
#include <QOpenGLFunctions_3_3_Core>
#include <QDebug>
AXBOpenGLWidget::AXBOpenGLWidget(QWidget *parent):
QOpenGLWidget(parent)
{
}
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.0f);\n"
"}\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";
GLuint VBO, VAO,EBO;
//float vertices[]={
// -0.5f,-0.5f,0.0f,
// 0.5f,-0.5f,0.0f,
// 0.0f,0.5f,0.0f
//};
//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,
// -0.5f,-0.5f,0.0f,
// -0.5f,0.5f,0.0f
// };
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//左上
}; //只有四个点了
//EBO
unsigned int indices[]=
{
0,1,3, //右上三角形 右上 - 右下 - 左上
1,2,3 //左下三角形 右下 - 左下-左上
};
unsigned int shaderProgram;
void AXBOpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
//绑定VBO和VAO对象
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
//如果data不是空的,则使用此数据初始化数据存储,跨域内存-显存
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//告知显卡如何解析缓冲力的属性值
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
//开启VAO管理第一个属性值
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,0);
glGenBuffers(1,&EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
glBindVertexArray(0);
//渲染器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader,1 ,&vertexShaderSource,NULL); // 相当于bind
glCompileShader(vertexShader);
int success; char infoLog[512];
glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(vertexShader,512,NULL,infoLog);
qDebug()<<"Error "<< infoLog;
}
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader ,1 ,&fragmentShaderSource,NULL); // 相当于bind
glCompileShader(fragmentShader );
glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(fragmentShader,512,NULL,infoLog);
qDebug()<<"Error "<< infoLog;
}
shaderProgram= glCreateProgram(); // 只有一种program 不用类型了
glAttachShader(shaderProgram,vertexShader);
glAttachShader(shaderProgram,fragmentShader);
glLinkProgram(shaderProgram); //就是设置了
glGetShaderiv(shaderProgram,GL_LINK_STATUS,&success);
if(!success)
{
glGetProgramInfoLog(shaderProgram,512,NULL,infoLog);
qDebug()<<"Error "<< infoLog;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
}
void AXBOpenGLWidget::resizeGL(int w, int h)
{
Q_UNUSED(w);
Q_UNUSED(h);
}
void AXBOpenGLWidget::paintGL()
{
glClearColor(0.f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
//glDrawArrays(GL_TRIANGLES,0,6);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
}