class VertexBuffer
{
public:
GLuint m_ID=0;
GLfloat* m_Data=0;
size_t m_Size=0;
VertexBuffer() {};
VertexBuffer(float* data, size_t size);
~VertexBuffer() { if(m_ID>0) glDeleteBuffers(1, &m_ID); };
void create(float* data, size_t size)
{
m_Data = data; m_Size = size;
glGenBuffers(1, &m_ID); Bind(); glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
}
void Bind() const { glBindBuffer(GL_ARRAY_BUFFER, m_ID); }
void Unbind() const { glBindBuffer(GL_ARRAY_BUFFER, 0); }
};
class IndexBuffer
{
public:
GLuint m_ID=0;
GLuint* m_Data = 0;
size_t m_Size = 0;
int m_Count = 0;
IndexBuffer() { }
IndexBuffer(unsigned int* data, size_t size) { create(data, size); }
void create(unsigned int* data, size_t size)
{
m_Data = data; m_Size = size; m_Count = (int)(m_Size / sizeof(GLuint));
glGenBuffers(1, &m_ID); Bind(); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
}
~IndexBuffer() { if (m_ID > 0) glDeleteBuffers(1, &m_ID); };
void Bind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ID); }
void Unbind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); }
};
struct VertexBufferAttribute
{
GLuint offset; // offset/start position in stride
GLuint type; // data type
GLuint count; // data count
GLuint size; // count * sizeof(type)
};
class VertexArray
{
public:
GLuint m_ID = 0;
std::vector<VertexBufferAttribute> m_Attributes;
GLuint m_Stride = 0;
VertexArray() { glGenVertexArrays(1, &m_ID); Bind(); }
~VertexArray() { if (m_ID > 0) glDeleteVertexArrays(1, &m_ID); }
void Bind() const { glBindVertexArray(m_ID); }
void Unbind() const { glBindVertexArray(0); }
template<typename T>
void Push(GLuint count) { }
template<>
void Push<GLfloat>(GLuint count)
{
GLuint size = sizeof(GLfloat) * count; m_Attributes.push_back({ m_Stride, GL_FLOAT, count, size }); m_Stride += size;
}
template<>
void Push<GLuint>(GLuint count)
{
GLuint size = sizeof(GLuint) * count; m_Attributes.push_back({ m_Stride, GL_UNSIGNED_INT, count, size }); m_Stride += size;
}
void SetAttributes()
{
int location = 0;
for (auto& a : m_Attributes)
{
glVertexAttribPointer(location, a.count, a.type, GL_FALSE, m_Stride, (void*)(uint64_t)a.offset);
glEnableVertexAttribArray(location);
location++;
}
}
};
class Shader
{
public:
GLuint m_ID = 0;
std::map<const char*, GLint> m_Uniforms;
Shader() { }
~Shader() { if (m_ID > 0) glDeleteProgram(m_ID); }
GLuint Compile(const char* source, GLenum type)
{
GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, 0); glCompileShader(shader);
int success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success)
{
int len; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); char* info = (char*)malloc(len * sizeof(char));
glGetShaderInfoLog(shader, len, &len, info); printf("compile shader error: %s\n\nshader source: %s\n", info, source); free(info);
glDeleteShader(shader); return -1;
}
return shader;
}
GLuint CreateProgram(const char* vertex_shader_source, const char* fragment_shader_source)
{
GLint64 vertex_shader = Compile(vertex_shader_source, GL_VERTEX_SHADER); if (vertex_shader < 0) throw std::invalid_argument("vertex_shader_source compile fail");
GLint64 fragment_shader = Compile(fragment_shader_source, GL_FRAGMENT_SHADER); if (fragment_shader < 0) throw std::invalid_argument("fragment_shader_source compile fail");
m_ID = glCreateProgram(); glAttachShader(m_ID, (GLuint)vertex_shader); glAttachShader(m_ID, (GLuint)fragment_shader); glLinkProgram(m_ID); // glValidateProgram(program);
int success; glGetProgramiv(m_ID, GL_LINK_STATUS, &success); if (!success)
{
int len; glGetProgramiv(m_ID, GL_INFO_LOG_LENGTH, &len); char* info = (char*)malloc(len * sizeof(char));
glGetProgramInfoLog(m_ID, len, &len, info); printf("link shader program error: %s\n", info); free(info);
throw std::invalid_argument("shader source compile and link fail.");
}
// glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); // keep source for debug
return m_ID;
}
void GetUniforms(std::vector<const char*> names)
{
Bind();
for (auto& name : names)
{
auto location = m_Uniforms[name] = glGetUniformLocation(m_ID, name);
if (location < 0) { printf("error when getting uniform location by name %s\n", name); throw std::invalid_argument("get uniform fail."); }
}
}
void Bind() const { glUseProgram(m_ID); }
void Unbind() const { glUseProgram(0); }
};
class SceneCombine_red : public Scene
{
public:
SceneCombine_red(float ww, float wh)
{
this->ww = ww; this->wh = wh;
float vertexes[] = {
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 0 右下角
0.5f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 1 中左点
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 2 左下脚
-0.5f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 3 中右点
-0.3f, 0.2f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // 4 顶方块左下
0.8f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // 5 顶方块左上
-0.3f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // 6 顶方块右下
0.8f, 0.2f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, // 7 顶方块右上
};
unsigned int indices[] = {
0, 1, 2,
0, 1, 3,
4, 5, 6,
4, 5, 7,
};
m_VertexShaderSource = (char*)"#version 460 core\n"
"layout(location=0) in vec4 a_Position;\n"
"layout(location=1) in vec4 a_Color;\n"
"uniform mat4 u_Mvp;\n"
"out vec4 v_Color;\n"
"void main()\n"
"{\n"
" gl_Position = a_Position; v_Color=a_Color; \n"
"}\n\0";
m_FragmentShaderSource = (char*)"#version 460 core\n"
"out vec4 FragColor;\n"
"in vec4 v_Color;\n"
"void main()\n"
"{\n"
" FragColor = v_Color;\n"
"}\n\0";
m_VB.create(vertexes, sizeof(vertexes));
m_VA.Push<float>(3); // position
m_VA.Push<float>(4); // color
m_IB.create(indices, sizeof(indices));
m_VA.SetAttributes();
m_VA.Unbind();
m_Shader.CreateProgram(m_VertexShaderSource, m_FragmentShaderSource);
//m_Shader.GetUniforms({ u_Mvp });
//m_Proj = glm::ortho(0.0f, ww, 0.0f, wh, -1.0f, 1.0f); // the values are the edges of vertexes positions
//m_Model = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
//m_View = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
//m_Mvp = m_View * m_Model * m_Proj; //glUniformMatrix4fv(m_Shader.m_Uniforms[u_Mvp], 1, GL_FALSE, &m_Mvp[0][0]);
}
void Bind() override
{
m_Shader.Bind(); m_VA.Bind();
}
void Render() override
{
glDrawElements(GL_TRIANGLES, m_IB.m_Count, GL_UNSIGNED_INT, nullptr);
}
void RenderSettings() override
{
}
const char* u_Mvp = "u_Mvp";
const char* u_Color = "u_Color";
};
OpenGL C++ 基本框架 - VBO, IBO, VAO, Shader, Scene
最新推荐文章于 2024-03-15 22:22:30 发布