目录
相关文章
OpenGL系列之一:OpenGL第一个程序
OpenGL系列之二:绘制三角形
OpenGL系列之三:三角形顶点增加颜色
OpenGL系列之四:绘制四边形
OpenGL系列之五:绘制点和线
OpenGL系列之六:绘制立方体
OpenGL系列之七:纹理贴图
OpenGL系列之八:立方体纹理贴图
OpenGL系列之九:glsl着色器语言
实现效果
实现步骤
首先大家可以先了解下VAO、VBO、EBO是什么,我感觉下面这篇文章挺不错的大家可以参考下:
https://blog.csdn.net/weixin_44179561/article/details/124275761
1.封装VAO
基本都是固定的,封装起来以后可以复用
CCOpenGLVAO.h
#ifndef CCOPENGLES_CCOPENGLVAO_H
#define CCOPENGLES_CCOPENGLVAO_H
#include "CCGLPrimitivesDef.h"
class CCOpenGLVAO {
public:
CCOpenGLVAO();
~CCOpenGLVAO();
void Bind();
void Release();
void Create();
private:
GLuint m_vaoId;
};
#endif //CCOPENGLES_CCOPENGLVAO_H
CCOpenGLVAO.cpp
#include "CCOpenGLVAO.h"
CCOpenGLVAO::CCOpenGLVAO()
{
}
CCOpenGLVAO::~CCOpenGLVAO()
{
glDeleteVertexArrays(1,&m_vaoId);
}
void CCOpenGLVAO::Create()
{
glGenVertexArrays(1, &m_vaoId);
}
void CCOpenGLVAO::Bind()
{
glBindVertexArray(m_vaoId);
}
void CCOpenGLVAO::Release()
{
glBindVertexArray(0);
}
2.封装VBO、EBO
这两个封装在一个里了,就是类型不一样
CCOpenGLBuffer.h
#ifndef CCOPENGLES_CCOPENGLBUFFER_H
#define CCOPENGLES_CCOPENGLBUFFER_H
#include "CCGLPrimitivesDef.h"
class CCOpenGLBuffer {
public:
enum Type{
VertexBuffer = 0x8892, // GL_ARRAY_BUFFER
IndexBuffer = 0x8893, // GL_ELEMENT_ARRAY_BUFFER
PixelPackBuffer = 0x88EB, // GL_PIXEL_PACK_BUFFER
PixelUnpackBuffer = 0x88EC // GL_PIXEL_UNPACK_BUFFER
};
enum UsagePattern
{
StreamDraw = 0x88E0, // GL_STREAM_DRAW
StreamRead = 0x88E1, // GL_STREAM_READ
StreamCopy = 0x88E2, // GL_STREAM_COPY
StaticDraw = 0x88E4, // GL_STATIC_DRAW
StaticRead = 0x88E5, // GL_STATIC_READ
StaticCopy = 0x88E6, // GL_STATIC_COPY
DynamicDraw = 0x88E8, // GL_DYNAMIC_DRAW
DynamicRead = 0x88E9, // GL_DYNAMIC_READ
DynamicCopy = 0x88EA // GL_DYNAMIC_COPY
};
CCOpenGLBuffer(CCOpenGLBuffer::Type type,CCOpenGLBuffer::UsagePattern usage);
~CCOpenGLBuffer();
void Bind();
void Release();
void Create();
void SetBufferData(const GLvoid *data, GLsizeiptr size);
private:
CCOpenGLBuffer::Type m_bufferType;
GLuint m_buffID;
GLsizeiptr m_buffSize;
CCOpenGLBuffer::UsagePattern m_usage;
};
#endif //CCOPENGLES_CCOPENGLBUFFER_H
CCOpenGLBuffer.cpp
#include "CCOpenGLBuffer.h"
CCOpenGLBuffer::CCOpenGLBuffer(CCOpenGLBuffer::Type type,CCOpenGLBuffer::UsagePattern usage)
{
m_buffSize = 0;
m_usage = usage;
m_bufferType = type;
}
CCOpenGLBuffer::~CCOpenGLBuffer()
{
glDeleteBuffers(1, &m_buffID);
}
void CCOpenGLBuffer::Create()
{
glGenBuffers(1, &m_buffID);
}
void CCOpenGLBuffer::Bind()
{
glBindBuffer(m_bufferType, m_buffID);
}
void CCOpenGLBuffer::Release()
{
glBindBuffer(m_bufferType, 0);
}
void CCOpenGLBuffer::SetBufferData(const GLvoid *data, GLsizeiptr size)
{
if (size > m_buffSize) {
m_buffSize = size;
glBufferData(m_bufferType, size, data, m_usage);
} else {
glBufferSubData(m_bufferType, 0, size, data);
}
}
3.编写glsl
vertex.vert
#version 300 es
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec2 a_uv;
uniform mat4 u_mat;
out vec2 o_uv;
void main(void)
{
o_uv = a_uv;
gl_Position = u_mat * vec4(a_position,1.0);
}
fragment.frag
#version 300 es
precision mediump float;
uniform sampler2D utexture;
in vec2 o_uv;
out vec4 fragColor;
void main(void)
{
fragColor = texture(utexture,o_uv);
}
4.使用VAO、VBO、EBO缓存数据
这里封装在一个函数里,函数里的顶点数据和索引数据都是立方体的
/**
* 先加载VAO VBO EBO等缓存数据
*/
void CCRender::setupRenderingObject()
{
//顶点数据
const CCFloat5 cubeVertexs[] = {
{ -1.0,-1.0, 1.0 , 0.0, 0.0 },
{ -1.0, 1.0, 1.0 , 0.0, 1.0 },
{ 1.0, -1.0, 1.0 , 1.0, 0.0 },
{ 1.0, 1.0, 1.0 , 1.0, 1.0 },
{ 1.0,-1.0, -1.0, 0, 0 },
{ 1.0, 1.0, -1.0, 0, 1 },
{ -1.0,-1.0, -1.0, 1, 0 },
{ -1.0, 1.0, -1.0, 1, 1 },
{ -1.0, -1.0, -1.0, 0, 0 },
{ -1.0, 1.0, -1.0, 0, 1 },
{ -1.0, -1.0, 1.0, 1, 0 },
{ -1.0, 1.0, 1.0, 1, 1 },
{ 1.0,-1.0, 1.0, 0, 0 },
{ 1.0, 1.0, 1.0, 0, 1 },
{ 1.0, -1.0, -1.0, 1, 0 },
{ 1.0, 1.0, -1.0, 1, 1 },
{ -1.0, 1.0, 1.0, 0, 0 },
{ -1.0, 1.0, -1.0, 0, 1 },
{ 1.0, 1.0, 1.0, 1, 0 },
{ 1.0, 1.0, -1.0, 1, 1 },
{ -1.0, -1.0, -1.0, 0, 0 },
{ -1.0, -1.0, 1.0, 0, 1 },
{ 1.0, -1.0, -1.0, 1, 0 },
{ 1.0, -1.0, 1.0, 1, 1 }
};
//索引数据
const short cubeIndexs[]= {
0, 1, 2, 2, 1, 3,
4, 5, 6, 6, 5, 7,
8, 9, 10, 10, 9,11,
12,13,14, 14,13,15,
16,17,18, 18,17,19,
20,21,22, 22,21,23,
};
ccVAO.Create();
ccVAO.Bind();
ccVBO->Create();
ccVBO->Bind();
ccVBO->SetBufferData(cubeVertexs,sizeof(cubeVertexs));
ccEBO->Create();
ccEBO->Bind();
ccEBO->SetBufferData(cubeIndexs,sizeof(cubeIndexs));
//数据的位置
int offset = 0;
ccOpenGlShader.SetAttributeBuffer(0,GL_FLOAT, (void *)offset, 3, sizeof(CCFloat5));
ccOpenGlShader.EnableAttributeArray(0);
//由于数据类型为float,而uv数据的在第四第五的位置,因此需要偏移3个
offset += 3 * sizeof(float);
ccOpenGlShader.SetAttributeBuffer(1,GL_FLOAT, (void *)offset, 2, sizeof(CCFloat5));
ccOpenGlShader.EnableAttributeArray(1);
ccVAO.Release();
ccVBO->Release();
ccEBO->Release();
}
5.绘制立方体
最后我们进行绘制即可
/**
* 画立方体
*/
void CCRender::drawCube() {
m_angle += 0.05f;
glm::mat4x4 objectMat;
glm::mat4x4 objectTransMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3));
glm::mat4x4 objectRotMat = glm::rotate(glm::mat4(1.0f),m_angle,glm::vec3(1.0f, 1.0f, 1.0) );
glm::mat4x4 objectScaleMat = glm::scale(glm::mat4(1.0f),glm::vec3(0.3f, 0.2f, 0.3) );
glm::mat4 projMat = glm::perspective(glm::radians(60.0f), (float)9/(float)18, 0.1f, 1000.0f);
objectMat = projMat* objectTransMat * objectScaleMat* objectRotMat ;
ccOpenGlShader.Bind();
ccOpenGlShader.SetUniformValue("u_mat",objectMat);
ccVAO.Bind();
for(int i=0; i<6; i++){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,ccTexture.m_texID[i]);
int offset = i * 6 * sizeof(unsigned short);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,(void *)offset);
glBindTexture(GL_TEXTURE_2D,0);
}
ccOpenGlShader.Release();
ccVAO.Release();
}
6.补充说明
设置顶点数据的时候,之前是根据glsl里的变量名来设置的,现在变成了location:
ccOpenGlShader.SetAttributeBuffer(0,GL_FLOAT, (void *)offset, 3, sizeof(CCFloat5));
ccOpenGlShader.EnableAttributeArray(0);
ccOpenGlShader.SetAttributeBuffer(1,GL_FLOAT, (void *)offset, 2, sizeof(CCFloat5));
ccOpenGlShader.EnableAttributeArray(1);
这里的location为0和1是与glsl中的location对应的:
这里的话我尝试使用像之前那样用名字来设置,但是不显示,不知道是不是设置了缓存数据的原因,具体的话我也不大清楚,如果有明白的同学可以留言告诉下,然后是fragment.frag中的uniform sampler2D utexture;
这个变量没有传也可以使用,这里应该是默认就使用了绑定Texture时指定的Texture了