Bladeren bron

feat: 添加顶点数组和顶点缓存的抽象

nicetry12138 1 jaar geleden
bovenliggende
commit
1b1d28fa21

+ 55 - 1
图形学/OpenGL学习/README.md

@@ -923,4 +923,58 @@ glBindVertexArray(vao);
 
 可以选择使用默认的 VAO 对象,不停的绑定、解绑不同的顶点数据,以此来绘制多个几何图形
 
-也可以选择为每个几何图形
+也可以选择为每个几何图形创建一个 `VAO` 分别绑定不同的顶点数据
+
+如果需要注重开发效率,那么建议每个图元一个 `VAO`;如果每一字节的显存都需要非常小心使用,那么建议全局一个 `VAO`
+
+## 简单封装抽象类
+
+对于一个复杂的模型,会有一个顶点缓冲区,包括模型的每个顶点;可能会有多个索引缓冲区来绘制飞船的部分,因为不同部分可能会是不同材质,比如飞船的舱门可能是金属和玻璃两种材质
+
+```cpp
+// 顶点缓冲区
+class VertexBuffer
+{
+private:
+	GLuint m_RendererID;
+
+public:
+	VertexBuffer(const void* data, GLuint size) {
+    glGenBuffers(1, &m_RendererID);
+    glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);
+    glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
+  }
+	~VertexBuffer();
+
+	void Bind() const;
+	void UnBind() const;
+};
+
+
+// 索引缓冲区
+class IndexBuffer
+{
+private:
+	GLuint m_RendererID;
+	GLuint m_Count;
+
+public:
+	IndexBuffer(const GLuint* data, GLuint count) {
+    GL_CALL(glGenBuffers(1, &m_RendererID));
+    GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
+    GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLuint), data, GL_STATIC_DRAW));
+    m_Count = count;
+  }
+	~IndexBuffer();
+
+	void Bind() const;
+	void Unbind() const;
+
+	inline GLuint GetCount() const { return m_Count; }
+};
+```
+
+然后替换掉 `Application.cpp` 中对应的部分,就算初步完成了顶点、索引缓冲区的抽象
+
+接下来就是抽象顶点数组 `VAO` ,一个顶点数组需要做的就是将一个顶点缓冲区与某种布局绑定在一起
+

+ 8 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/OpenGLStudy.vcxproj

@@ -136,12 +136,20 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="src\IndexBuffer.cpp" />
+    <ClCompile Include="src\Renderer.cpp" />
     <ClCompile Include="src\Application.cpp" />
+    <ClCompile Include="src\VertexBuffer.cpp" />
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Fragment.frag" />
     <None Include="src\Vertex.vert" />
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\IndexBuffer.h" />
+    <ClInclude Include="src\Renderer.h" />
+    <ClInclude Include="src\VertexBuffer.h" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

+ 20 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/OpenGLStudy.vcxproj.filters

@@ -21,6 +21,15 @@
     <ClCompile Include="src\Application.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="src\Renderer.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="src\VertexBuffer.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="src\IndexBuffer.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Vertex.vert">
@@ -30,4 +39,15 @@
       <Filter>src</Filter>
     </None>
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\Renderer.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="src\VertexBuffer.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="src\IndexBuffer.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+  </ItemGroup>
 </Project>

+ 74 - 138
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/Application.cpp

@@ -3,64 +3,9 @@
 #include <iostream>
 #include <fstream>
 
-#define GL_CHECK_ERROR do { LogError(__LINE__); }while(0);
-#define GL_CLEAR_ERROR do { GLClearError(); } while(0);
-
-#define GL_CALL(x) do {			\
-	GLClearError();				\
-	x;							\
-	LogError(__LINE__, #x);		\
-} while (0);					\
-
-const int gWidth = 640;
-const int gHeight = 480;
-
-void render() {
-	glBegin(GL_TRIANGLES);
-	glVertex2f(-0.5f, -0.5f);
-	glVertex2f(0.0f, 0.5f);
-	glVertex2f(0.5f, -0.5f);
-	glEnd();
-}
-
-static void GLClearError() {
-	while (glGetError() != GL_NO_ERROR);
-}
-
-static void LogError(unsigned int Line, const char* functionName = nullptr) {
-	GLuint errorType = glGetError();
-	while (errorType != GL_NO_ERROR){
-		std::cout << __FILE__ << " Line: " << Line << " Function Name: " << functionName << " ";
-		switch (errorType)
-		{
-		case GL_INVALID_ENUM:
-			std::cout << "LogError: " << "GL_INVALID_ENUM" << std::endl;
-			break;
-		case GL_INVALID_VALUE:
-			std::cout << "LogError: " << "GL_INVALID_VALUE" << std::endl;
-			break;
-		case GL_INVALID_OPERATION:
-			std::cout << "LogError: " << "GL_INVALID_OPERATION" << std::endl;
-			break;
-		case GL_INVALID_FRAMEBUFFER_OPERATION:
-			std::cout << "LogError: " << "GL_INVALID_FRAMEBUFFER_OPERATION" << std::endl;
-			break;
-		case GL_OUT_OF_MEMORY:
-			std::cout << "LogError: " << "GL_OUT_OF_MEMORY" << std::endl;
-			break;
-		case GL_STACK_UNDERFLOW:
-			std::cout << "LogError: " << "GL_STACK_UNDERFLOW" << std::endl;
-			break;
-		case GL_STACK_OVERFLOW:
-			std::cout << "LogError: " << "GL_STACK_OVERFLOW" << std::endl;
-			break;
-		}
-
-		__debugbreak();	// 中断函数 编译器强相关函数,gcc 没有
-
-		errorType = glGetError();
-	} 
-}
+#include "Renderer.h"
+#include "VertexBuffer.h"
+#include "IndexBuffer.h"
 
 static GLuint CompiledShader(const std::string& source, GLenum inType) {
 	GLuint id = glCreateShader(inType);
@@ -68,16 +13,16 @@ static GLuint CompiledShader(const std::string& source, GLenum inType) {
 	glShaderSource(id, 1, &src, nullptr);
 	glCompileShader(id);
 
-	// Shader 错误处理
+	// Shader 閿欒�澶勭悊
 	GLint result;
 	glGetShaderiv(id, GL_COMPILE_STATUS, &result);
 	if (result == GL_FALSE) {
 		int length;
 		glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
-		// alloca 在栈上申请内存,不需要 free ,在作用域结束后自动释放
+		// alloca 鍦ㄦ爤涓婄敵璇峰唴瀛橈紝涓嶉渶瑕� free 锛屽湪浣滅敤鍩熺粨鏉熷悗鑷�姩閲婃斁
 		char* msg = (char*)alloca(length * sizeof(char));
 		glGetShaderInfoLog(id, length, &length, msg);
-		std::cout << "Sharder Compile " << (inType == GL_VERTEX_SHADER ? "vertex sharder" : "fragment sharder") << " Faild" << std::endl;
+		std::cout << "Shader Compile " << (inType == GL_VERTEX_SHADER ? "vertex shader" : "fragment shader") << " Fail" << std::endl;
 		std::cout << msg << std::endl;
 		
 		glDeleteShader(id);
@@ -92,12 +37,12 @@ static unsigned int CreateShader(const std::string& vertexShader, const std::str
 	GLuint vs = CompiledShader(vertexShader, GL_VERTEX_SHADER);
 	GLuint fs = CompiledShader(fragmentShader, GL_FRAGMENT_SHADER);
 
-	glAttachShader(program, vs);	// 绑定顶点着色器
-	glAttachShader(program, fs);	// 绑定片段着色器
-	glLinkProgram(program);			// 链接程序,将所有着色器合并为一个可执行的程序
-	glValidateProgram(program);		// 验证程序对象是否可以在当前的 OpenGL 状态下执行
+	glAttachShader(program, vs);	// 缁戝畾椤剁偣鐫€鑹插櫒
+	glAttachShader(program, fs);	// 缁戝畾鐗囨�鐫€鑹插櫒
+	glLinkProgram(program);			// 閾炬帴绋嬪簭锛屽皢鎵€鏈夌潃鑹插櫒鍚堝苟涓轰竴涓�彲鎵ц�鐨勭▼搴�
+	glValidateProgram(program);		// 楠岃瘉绋嬪簭瀵硅薄鏄�惁鍙�互鍦ㄥ綋鍓嶇殑 OpenGL 鐘舵€佷笅鎵ц�
 
-	glDeleteShader(fs);				// 删除着色器对象 因为一旦着色器被链接到程序对象,着色器的代码已经被链接到程序中,所以可以安全地删除着色器对象
+	glDeleteShader(fs);				// 鍒犻櫎鐫€鑹插櫒瀵硅薄 鍥犱负涓€鏃︾潃鑹插櫒琚�摼鎺ュ埌绋嬪簭瀵硅薄锛岀潃鑹插櫒鐨勪唬鐮佸凡缁忚�閾炬帴鍒扮▼搴忎腑锛屾墍浠ュ彲浠ュ畨鍏ㄥ湴鍒犻櫎鐫€鑹插櫒瀵硅薄
 	glDeleteShader(vs);
 
 	return program;
@@ -107,7 +52,7 @@ static GLuint CreateShaderWithFile(const std::string& vertexShaderFilePath, cons
 	std::ifstream ifs;
 	ifs.open(vertexShaderFilePath, std::ios::in);
 	if (!ifs.is_open()) {
-		std::cout << "Compile Shader Faild: Can't Open File" << std::endl;
+		std::cout << "Compile Shader Fail: Can't Open File" << std::endl;
 		return GL_ZERO;
 	}
 
@@ -116,7 +61,7 @@ static GLuint CreateShaderWithFile(const std::string& vertexShaderFilePath, cons
 
 	ifs.open(fragmentShaderFilePath, std::ios::in);
 	if (!ifs.is_open()) {
-		std::cout << "Compile Shader Faild: Can't Open File" << std::endl;
+		std::cout << "Compile Shader Fail: Can't Open File" << std::endl;
 		return GL_ZERO;
 	}
 
@@ -134,9 +79,9 @@ int main(void)
 	if (!glfwInit())
 		return -1;
 
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);					// 设置 OpenGL 主版本为 3
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);					// 设置 OpenGL 主版本为 3
-	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);	// 设置 OpenGL 为 核心
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);					// 璁剧疆 OpenGL 涓荤増鏈�负 3
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);					// 璁剧疆 OpenGL 涓荤増鏈�负 3
+	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);	// 璁剧疆 OpenGL 涓� 鏍稿績
 
 	/* Create a windowed mode window and its OpenGL context */
 	window = glfwCreateWindow(gWidth, gHeight, "Hello World", NULL, NULL);
@@ -159,83 +104,74 @@ int main(void)
 	GLuint vao;
 	glGenVertexArrays(1, &vao);
 	glBindVertexArray(vao);
-
-	float positions[] = {
-		-0.5f, -0.5f,
-		 0.5f, -0.5f,
-		 0.5f, 0.5f,
-		-0.5f,  0.5f,
-	};
-
-	GLuint indeices[] = {
-		0, 1, 2,
-		2, 3, 0
-	};
-
-	unsigned int buffer;
-	glGenBuffers(1, &buffer);
-	glBindBuffer(GL_ARRAY_BUFFER, buffer);
-	glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), positions, GL_STATIC_DRAW);
-
-	GL_CALL(glEnableVertexAttribArray(0));
-	GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));
-	
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
-
-	GLuint ibo;	// index buffer object
-	glGenBuffers(1, &ibo);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
-	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indeices, GL_STATIC_DRAW);
-
-	GLuint shader = CreateShaderWithFile("src/Vertex.vert", "src/Fragment.frag");
-	glUseProgram(shader);
-
-	GLint location = -1;
-	GL_CALL(location = glGetUniformLocation(shader, "u_Color"));
-	GL_CALL(glUniform4f(location, 1, 1, 0, 0));
-
-	// 清除所有绑定关系
-	glBindVertexArray(0);
-	glUseProgram(0);
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-	
-
-	GLfloat r = 0.0f;
-	GLfloat increment = 0.05f;
-	/* Loop until the user closes the window */
-	while (!glfwWindowShouldClose(window))
 	{
-		/* Render here */
-		glClear(GL_COLOR_BUFFER_BIT);  
+		float positions[] = {
+			-0.5f, -0.5f,
+			 0.5f, -0.5f,
+			 0.5f, 0.5f,
+			-0.5f,  0.5f,
+		};
 
-		//render();
+		GLuint indeices[] = {
+			0, 1, 2,
+			2, 3, 0
+		};
 
-		//glDrawArrays(GL_TRIANGLES, 0, 6);
-		//GL_CLEAR_ERROR;
-		//glDrawElements(GL_TRIANGLES, 6, GL_UNIFORM, 0);
-		//GL_CHECK_ERROR; 
+		VertexBuffer vb(positions, sizeof(float) * 2 * 4);
 
-		glBindVertexArray(vao);
-		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
+		GL_CALL(glEnableVertexAttribArray(0));
+		GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));
 
-		r += increment;
-		GL_CALL(glUseProgram(shader));
-		GL_CALL(glUniform4f(location, r, .5f, .5f, 1.0f));
+		IndexBuffer ibo(indeices, 6);
 
-		if (r > 1.0f || r < 0.0f) {
-			increment *= -1;
-		}
+		GLuint shader = CreateShaderWithFile("src/Vertex.vert", "src/Fragment.frag");
+		glUseProgram(shader);
 
-		GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
+		GLint location = -1;
+		GL_CALL(location = glGetUniformLocation(shader, "u_Color"));
+		GL_CALL(glUniform4f(location, 1, 1, 0, 0));
 
-		/* Swap front and back buffers */
-		glfwSwapBuffers(window);
+		// 娓呴櫎鎵€鏈夌粦瀹氬叧绯�
+		glBindVertexArray(0);
+		glUseProgram(0);
+		glBindBuffer(GL_ARRAY_BUFFER, 0);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-		/* Poll for and process events */
-		glfwPollEvents();
+
+		GLfloat r = 0.0f;
+		GLfloat increment = 0.05f;
+		/* Loop until the user closes the window */
+		while (!glfwWindowShouldClose(window))
+		{
+			/* Render here */
+			glClear(GL_COLOR_BUFFER_BIT);
+
+			//glDrawArrays(GL_TRIANGLES, 0, 6);
+			//GL_CLEAR_ERROR;
+			//glDrawElements(GL_TRIANGLES, 6, GL_UNIFORM, 0);
+			//GL_CHECK_ERROR; 
+
+			glBindVertexArray(vao);
+			ibo.Bind();
+
+			r += increment;
+			GL_CALL(glUseProgram(shader));
+			GL_CALL(glUniform4f(location, r, .5f, .5f, 1.0f));
+
+			if (r > 1.0f || r < 0.0f) {
+				increment *= -1;
+			}
+
+			GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
+
+			/* Swap front and back buffers */
+			glfwSwapBuffers(window);
+
+			/* Poll for and process events */
+			glfwPollEvents();
+		}
+		glDeleteProgram(shader);
 	}
-	glDeleteProgram(shader);
 	glfwTerminate();
 	return 0;
 }

+ 25 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/IndexBuffer.cpp

@@ -0,0 +1,25 @@
+#include "IndexBuffer.h"
+#include "Renderer.h"
+
+IndexBuffer::IndexBuffer(const GLuint* data, GLuint count) 
+{
+	GL_CALL(glGenBuffers(1, &m_RendererID));
+	GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
+	GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLuint), data, GL_STATIC_DRAW));
+	m_Count = count;
+}
+
+IndexBuffer::~IndexBuffer()
+{
+	glDeleteBuffers(1, &m_RendererID);
+}
+
+void IndexBuffer::Bind() const
+{
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID);
+}
+
+void IndexBuffer::Unbind() const
+{
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}

+ 19 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/IndexBuffer.h

@@ -0,0 +1,19 @@
+#pragma once
+#include <GL/glew.h>
+
+class IndexBuffer
+{
+private:
+	GLuint m_RendererID;
+	GLuint m_Count;
+
+public:
+	IndexBuffer(const GLuint* data, GLuint count);
+	~IndexBuffer();
+
+	void Bind() const;
+	void Unbind() const;
+
+	inline GLuint GetCount() const { return m_Count; }
+};
+

+ 42 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/Renderer.cpp

@@ -0,0 +1,42 @@
+#include "Renderer.h"
+#include <iostream>
+#include <fstream>
+
+void GLClearError() {
+	while (glGetError() != GL_NO_ERROR);
+}
+
+void LogError(unsigned int Line, const char* functionName) {
+	GLuint errorType = glGetError();
+	while (errorType != GL_NO_ERROR) {
+		std::cout << __FILE__ << " Line: " << Line << " Function Name: " << functionName << " ";
+		switch (errorType)
+		{
+		case GL_INVALID_ENUM:
+			std::cout << "LogError: " << "GL_INVALID_ENUM" << std::endl;
+			break;
+		case GL_INVALID_VALUE:
+			std::cout << "LogError: " << "GL_INVALID_VALUE" << std::endl;
+			break;
+		case GL_INVALID_OPERATION:
+			std::cout << "LogError: " << "GL_INVALID_OPERATION" << std::endl;
+			break;
+		case GL_INVALID_FRAMEBUFFER_OPERATION:
+			std::cout << "LogError: " << "GL_INVALID_FRAMEBUFFER_OPERATION" << std::endl;
+			break;
+		case GL_OUT_OF_MEMORY:
+			std::cout << "LogError: " << "GL_OUT_OF_MEMORY" << std::endl;
+			break;
+		case GL_STACK_UNDERFLOW:
+			std::cout << "LogError: " << "GL_STACK_UNDERFLOW" << std::endl;
+			break;
+		case GL_STACK_OVERFLOW:
+			std::cout << "LogError: " << "GL_STACK_OVERFLOW" << std::endl;
+			break;
+		}
+
+		__debugbreak();	// 中断函数 编译器强相关函数,gcc 没有
+
+		errorType = glGetError();
+	}
+}

+ 20 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/Renderer.h

@@ -0,0 +1,20 @@
+#pragma once
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+#define GL_CHECK_ERROR do { LogError(__LINE__); }while(0);
+#define GL_CLEAR_ERROR do { GLClearError(); } while(0);
+
+#define GL_CALL(x) do {			\
+	GLClearError();				\
+	x;							\
+	LogError(__LINE__, #x);		\
+} while (0);					\
+
+const int gWidth = 640;
+const int gHeight = 480;
+
+// 清除所有错误
+void GLClearError();
+// 输出当前错误
+void LogError(unsigned int Line, const char* functionName = nullptr);

+ 3 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/VertexArray.cpp

@@ -0,0 +1,3 @@
+#include "VertexArray.h"
+#include "VertexBuffer.h"
+#include "IndexBuffer.h"

+ 14 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/VertexArray.h

@@ -0,0 +1,14 @@
+#pragma once
+
+class VertexBuffer;
+class VertexBufferLayout;
+
+class VertexArray
+{
+public:
+	VertexArray();
+	~VertexArray();
+
+	void AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout);
+};
+

+ 24 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/VertexBuffer.cpp

@@ -0,0 +1,24 @@
+#include "VertexBuffer.h"
+#include "Renderer.h"
+
+VertexBuffer::VertexBuffer(const void* data, GLuint size)
+{
+	glGenBuffers(1, &m_RendererID);
+	glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);
+	glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
+}
+
+VertexBuffer::~VertexBuffer()
+{
+	GL_CALL(glDeleteBuffers(1, &m_RendererID));
+}
+
+void VertexBuffer::Bind() const
+{
+	GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
+}
+
+void VertexBuffer::UnBind() const
+{
+	GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
+}

+ 15 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/VertexBuffer.h

@@ -0,0 +1,15 @@
+#pragma once
+#include <GL/glew.h>
+
+class VertexBuffer
+{
+private:
+	GLuint m_RendererID;
+
+public:
+	VertexBuffer(const void* data, GLuint size);
+	~VertexBuffer();
+
+	void Bind() const;
+	void UnBind() const;
+};

+ 0 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/VertexBufferLayout.cpp


+ 36 - 0
图形学/OpenGL学习/src/OpenGLStudy/OpenGLStudy/src/VertexBufferLayout.h

@@ -0,0 +1,36 @@
+#pragma once
+#include <vector>
+#include <GL/glew.h>
+
+struct VertexBufferElement
+{
+	unsigned int type;
+	unsigned int count;
+	bool normalized;
+};
+
+class VertexBufferLayout
+{
+private:
+	std::vector<VertexBufferElement> m_Elements;
+
+public:
+	VertexBufferLayout();
+	~VertexBufferLayout();
+
+	template<typename T>
+	void Push(unsigned int count) {
+		static_assert(false);
+	}
+
+	template<>
+	void Push<float>(unsigned int count) {
+		m_Elements.push_back({GL_FLOAT, count, false});
+	}
+
+	template<>
+	void Push<int>(unsigned int count) {
+		m_Elements.push_back({ GL_UNSIGNED_INT, count, false });
+	}
+};
+