如何利用Vertex Buffers在OpenGL里画一个三角形

原理是:基于你选定的Shader和Buffer去绘制某个三角形,OpenGL是一种状态机,意思是OpenGL不是一个对象


instead of me just saying draw me a triangle and pass everything that opengl needs to 
know to draw the that triangle it actually knows what it needs to do
OpenGL work draw a triangle and base on which buffer and which shader you have selected, to determine
what triangle get drawn and where and all of that stuff

talk is cheap, show me the code

GLCALL是个人用来检查错误的宏

	unsigned int buffer;
	GLCall(glGenBuffers(1, &buffer));//create an ID :buffer

	//就像 PS 一样在指定层上画画
	GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer));

	//specify the buffer
	GLCall(glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW));

 http://docs.gl/是一个查找OpenGL的好网站,访问的时候把上网策略关了

以glBufferData为例,glBufferData很重要,它负责把绑定的buffer输送到GPU上

如何告诉OpenGLposition中的数据分布?VertexAttrib.

顶点属性 Vertex Attribute 和 shader

Vertex Attribute:

opengl pipeline 的工作方式:提供图形类型给数据,然后存储在GPU上的内存里(内存里包含了我们想要绘制的所有数据)

然后我们使用shader(在GPU上执行的一种程序)读取这部分数据,然后在屏幕上显示下来

有代表性的是,我们实际上绘制图形使用的是一个Vertex buffer (存储在GPU上的一部分内存的 buffer )

当shader 实际上开始读取 Vertex buffer 时,它需要知道 buffer 的布局( buffer 里面有什么)

如果我们不说这个,它只是和c++的其他数据没什么两样

/*glBegin(GL_TRIANGLES);
		glVertex2d(-0.5f, -0.5f);
		glVertex2d(0.0f, 0.5f);
		glVertex2d(0.5f, -0.5f);
		glEnd();*/

float positions[] = {//逆时针绘制

		-0.5f, -0.5f, 
		 0.5f, 0.5f, 
		 0.5f,  -0.5f, 

		 
	};

		//glDrawArrays(GL_TRIANGLES, 0, 6);//从buffer里第*组开始draw,一共*组点

		//GLClearError();
		//Draw Call
		GLCall(glDrawElements(GL_TRIANGLES, 6/* 代表indices里面6个index */, GL_UNSIGNED_INT, nullptr));//因为前面glBindBuffer已经创建绑定所以空指针
		// GL_UNSIGNED_INT 如果被写成了GL_INT,会导致黑屏
		//GLCheckError();
		//ASSERT(GLLogCall());

vertex(顶点)顶点并不总是坐标,可以是别的什么东西,颜色、坐标等等都可以用vertex表示

glVertexAttribPointer() 参数:

stride: the amount of bytes between each vertex 12 for coordinate(index1), 8 for texture(index2), 12 for normal(index3)(bytes) so the stride is 32 bytes(每个属性(比如说坐标)的全部长度)

pointer: 指向属性的指针 coordinate offset = 0 ,texture offset = 12, normal offset = 20
 

!REMEMBER 记得使能vertex Attribute

	//!!!!! REMEMBER!!!!!!!
	GLCall(glEnableVertexAttribArray(0));

  	GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, 0));//2: component count

 参考代码

个人笔记已经同步传至github,如果有问题请赐教

个人邮箱 867027145@qq.com

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>


#define ASSERT(x) if(!(x)) __debugbreak();
#define GLCall(x) GLClearError();\
	x;\
	ASSERT(GLLogCall(#x/* 把函数名当做字符串返回 */, __FILE__, __LINE__))

static void GLClearError()
{
	while (glGetError() != GL_NO_ERROR);
}

static bool GLLogCall(const char* function, const char* file, int line)
{
	while (GLenum error = glGetError())
	{
		std::cout << "[OpenGL Error] (" << error << " )" << function << " " << file << ":" << line << std::endl;
		return false;
	}
	return true;
}



int main(void)
{
	GLFWwindow* window;

	/* Initialize the library */
	if (!glfwInit())
		return -1;

	GLCall(glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3));
	GLCall(glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3));
	GLCall(glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE));
	//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);


	/* Create a windowed mode window and its OpenGL context */
	window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	/* Make the window's context current */
	glfwMakeContextCurrent(window);

		if (glewInit() != GLEW_OK)
		std::cout << "Error!" << std::endl;
	//First you need to create a valid OpenGL rendering context and call glewInit() to initialize the extension entry points. 

	std::cout << glGetString(GL_VERSION) << std::endl;

	float positions[] = {//逆时针绘制

		-0.5f, -0.5f, 
		 0.0f, 0.5f,
		 0.5f,  -0.5f, 
		  
	};//vertex shader 会调用三次

	

	unsigned int buffer;
	GLCall(glGenBuffers(1, &buffer));//create an ID :buffer

	//就像 PS 一样在指定层上画画
	GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer));

	//specify the buffer
	GLCall(glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), positions, GL_STATIC_DRAW));

	//!!!!! REMEMBER!!!!!!!
	GLCall(glEnableVertexAttribArray(0));

  	GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, 0));//2: component count



	/* Loop until the user closes the window */
	while (!glfwWindowShouldClose(window))
	{
		/* Render here */
		glClear(GL_COLOR_BUFFER_BIT);

		


		/*glBegin(GL_TRIANGLES);
		glVertex2d(-0.5f, -0.5f);
		glVertex2d(0.0f, 0.5f);
		glVertex2d(0.5f, -0.5f);
		glEnd();*/

		//glDrawArrays(GL_TRIANGLES, 0, 6);//从buffer里第*组开始draw,一共*组点

		//GLClearError();
		//Draw Call
		GLCall(glDrawElements(GL_TRIANGLES, 6/* 代表indices里面6个index */, GL_UNSIGNED_INT, nullptr));//因为前面glBindBuffer已经创建绑定所以空指针
		// GL_UNSIGNED_INT 如果被写成了GL_INT,会导致黑屏
		//GLCheckError();
		//ASSERT(GLLogCall());



		/* Swap front and back buffers */
		glfwSwapBuffers(window);

		/* Poll for and process events */
		glfwPollEvents();
	}

	glDeleteProgram(shader);

	glfwTerminate();
	return 0;
}

更新:精简无代码注释版

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>

int main(void)
{
	GLFWwindow* window;

	/* Initialize the library */
	if (!glfwInit())
		return -1;

	glewInit();

	/* Create a windowed mode window and its OpenGL context */
	window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	/* Make the window's context current */
	glfwMakeContextCurrent(window);

	if (glewInit() != GLEW_OK)
		std::cout << "Error!" << std::endl;

	std::cout << glGetString(GL_VERSION) << std::endl;

	float positions[6] = {
		-0.5f, -0.5f,
		 0.0f,  0.5f,
		 0.5f, -0.5f
	};



	unsigned int buffer;
	glGenBuffers(1, &buffer);
	glBindBuffer(GL_ARRAY_BUFFER, buffer);
	glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float)/*in bytes*/, positions, GL_STATIC_DRAW);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	/* Loop until the user closes the window */
	while (!glfwWindowShouldClose(window))
	{
		/* Render here */
		glClear(GL_COLOR_BUFFER_BIT);

		glDrawArrays(GL_TRIANGLES, 0, 3);
		
		/* Swap front and back buffers */
		glfwSwapBuffers(window);

		/* Poll for and process events */
		glfwPollEvents();
	}

	glfwTerminate();
	return 0;
	
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值