入门OpenGL - 旋转的立方体

#include "PGLFW.h"

#include 
#include 
#include 
using namespace std;




//--------------------------------------------------------------------------------------------- 回调

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	PGLFW::Instance()->setWidth(width);
	PGLFW::Instance()->setHeight(height);
	glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
}

//---------------------------------------------------------------------------------------------

PGLFW* PGLFW::Instance()
{
	static PGLFW ins;
	return &ins;
}


PGLFW::PGLFW()
	: m_Width(1024)
	, m_Height(768)
{

}

PGLFW::~PGLFW()
{
	//释放资源
	glfwTerminate();
}


bool PGLFW::initWindow()
{
	//[01] 初始化OpenGL上下文环境
	glfwInit();

	//[02] 选择版本 3.3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

	//[03] 选择OpenGL为核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//[04] 创建窗体
	m_Window = glfwCreateWindow(m_Width, m_Height, "My First OpenGL Window", nullptr, nullptr);
	if (m_Window == nullptr) {
		cout << "failed to create glfw window" << endl;

		//释放资源
		glfwTerminate();

		return false;
	}

	//[05] 创建完窗体后通知GLFW将我们的上下文设置为当前线程的主上下文
	glfwMakeContextCurrent(m_Window);


	cout << "success to create glfw window" << endl;

	return true;

}

bool PGLFW::initGLAD()
{
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return false;
	}

	/*
	* 在我们开始渲染之前还有一件重要的事情要做,
	* 我们必须告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport),这样OpenGL才只能知道怎样根据窗口大小显示数据和坐标。
	* 我们可以通过调用glViewport函数来设置窗口的维度
	*
	* 函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)
	*
	* 我们实际上也可以将视口的维度设置为比GLFW的维度小,这样子之后所有的OpenGL渲染将会在一个更小的窗口中显示,
	* 这样子的话我们也可以将一些其它元素显示在OpenGL视口之外。
	*
	* OpenGL幕后使用glViewport中定义的位置和宽高进行2D坐标的转换,将OpenGL中的位置坐标转换为你的屏幕坐标。
	* 例如,OpenGL中的坐标(-0.5, 0.5)有可能(最终)被映射为屏幕中的坐标(200,450)。
	* 注意,处理过的OpenGL坐标范围只为-1到1,因此我们事实上将(-1到1)范围内的坐标映射到(0, 800)和(0, 600)。
	*
	*/
	glViewport(0, 0, m_Width, m_Height);


	/*
	* 然而,当用户改变窗口的大小的时候,视口也应该被调整。我们可以对窗口注册一个回调函数(Callback Function),它会在每次窗口大小被调整的时候被调用。
	* 当窗口被第一次显示的时候framebuffer_size_callback也会被调用。对于视网膜(Retina)显示屏,width和height都会明显比原输入值更高一点。
	*
	* 我们还可以将我们的函数注册到其它很多的回调函数中。
	* 比如说,我们可以创建一个回调函数来处理手柄输入变化,处理错误消息等。我们会在创建窗口之后,渲染循环初始化之前注册这些回调函数。
	*/
	glfwSetFramebufferSizeCallback(m_Window, framebuffer_size_callback);



	return true;
}

void PGLFW::initShader()
{
	std::string _vertexCode("");
	std::string _fragCode("");

	std::ifstream _vShaderFile;
	std::ifstream _fShaderFile;

	_vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	_fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	try
	{
		_vShaderFile.open("Shader/vertex.glsl");
		_fShaderFile.open("Shader/fragment.glsl");

		std::stringstream _vShaderStream;
		std::stringstream _fShaderStream;

		_vShaderStream << _vShaderFile.rdbuf();
		_fShaderStream << _fShaderFile.rdbuf();

		_vertexCode = _vShaderStream.str();
		_fragCode = _fShaderStream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::string errStr = "read shader fail";
		std::cout << errStr << std::endl;
	}

	const char* _vShaderStr = _vertexCode.c_str();
	const char* _fShaderStr = _fragCode.c_str();

	//shader的编译链接
	unsigned int _vertexID = 0;
	unsigned int _fragID = 0;

	char _infoLog[512];
	int _successFlag = 0;

	/*
	* [01] 编译
	*/
	//vertexShader
	_vertexID = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(_vertexID, 1, &_vShaderStr, nullptr);
	glCompileShader(_vertexID);

	glGetShaderiv(_vertexID, GL_COMPILE_STATUS, &_successFlag);
	if (!_successFlag)
	{
		glGetShaderInfoLog(_vertexID, 512, nullptr, _infoLog);
		std::cout << _infoLog;
	}

	//fragmentShader
	_fragID = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(_fragID, 1, &_fShaderStr, nullptr);
	glCompileShader(_fragID);

	glGetShaderiv(_fragID, GL_COMPILE_STATUS, &_successFlag);
	if (!_successFlag)
	{
		glGetShaderInfoLog(_fragID, 512, nullptr, _infoLog);
		std::cout << _infoLog;
	}


	/*
	* [02] 链接
	*/
	m_shaderProgram = glCreateProgram();
	glAttachShader(m_shaderProgram, _vertexID);
	glAttachShader(m_shaderProgram, _fragID);
	glLinkProgram(m_shaderProgram);

	glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &_successFlag);
	if (!_successFlag)
	{
		glGetProgramInfoLog(m_shaderProgram, 512, nullptr, _infoLog);
		std::cout << _infoLog;
	}

	glDeleteShader(_vertexID);
	glDeleteShader(_fragID);
}

void PGLFW::setMatrix(const std::string& _name, glm::mat4 _matrix) const
{
	glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, _name.c_str()), 1, GL_FALSE, glm::value_ptr(_matrix));
}

void PGLFW::rend()
{
	/*
	* 在每个新的渲染迭代开始的时候我们总是希望清屏,否则我们仍能看见上一次迭代的渲染结果(这可能是你想要的效果,但通常这不是)。
	* 我们可以通过调用glClear函数来清空屏幕的颜色缓冲,它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,
	* 可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,所以我们只清空颜色缓冲。
	*/
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);


	//------------------------------------

	//使用m_shaderProgram进行渲染
	glUseProgram(m_shaderProgram);

#if 0
	//使用m_VAO管理的VBO进行绘图
	glBindVertexArray(m_VAO_Triangle);
	glDrawArrays(GL_TRIANGLES, 0, 3);

	glBindVertexArray(m_VAO_Rectangle);
	glDrawArrays(GL_TRIANGLES, 0, 6);

#endif

	glm::mat4 _modelMatrix(1.0f);
	_modelMatrix = glm::rotate(_modelMatrix, glm::radians((float)glfwGetTime() * (0 + 1) * 10), glm::vec3(0.0f, 1.0f, 0.0f));

	setMatrix("_modelMatrix", _modelMatrix);
	setMatrix("_viewMatrix", m_Camera.getMatrix());
	setMatrix("_projMatrix", glm::perspective(glm::radians(45.0f), (float)m_Width / (float)m_Height, 0.1f, 100.0f));

	glBindVertexArray(m_VAO_Cube);
	glDrawArrays(GL_TRIANGLES, 0, 36);

	glUseProgram(0);
	//------------------------------------

}

void PGLFW::run()
{
	while (!glfwWindowShouldClose(m_Window))
	{
		processInput(m_Window);




		//----------------------- 这个中间可以做一些渲染 ---------------------------------------------||||||

	
		rend();

		//---------------------------------------------------------------------------------------------------


		/*
		* 双缓冲(Double Buffer)
		* 应用程序使用单缓冲绘图时可能会存在图像闪烁的问题。 这是因为生成的图像不是一下子被绘制出来的,
		* 而是按照从左到右,由上而下逐像素地绘制而成的。最终图像不是在瞬间显示给用户,而是通过一步一步生成的,
		* 这会导致渲染的结果很不真实。为了规避这些问题,我们应用双缓冲渲染窗口应用程序。前缓冲保存着最终输出的图像,
		* 它会在屏幕上显示;
		* 而所有的的渲染指令都会在后缓冲上绘制。当所有的渲染指令执行完毕后,我们交换(Swap)前缓冲和后缓冲,
		* 这样图像就立即呈显出来,之前提到的不真实感就消除了。
		*/
		glfwSwapBuffers(m_Window);

		//处理一下相关的事件(鼠标键盘等)
		glfwPollEvents();
	}
}


void PGLFW::initRendData()
{
	m_Camera.lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
	m_Camera.setSpeed(0.005f);

	initModle();
}

void PGLFW::initModle()
{
	//------------------------------------------------------------------------------------------------- triangle
	
	//三角形
	float vertices_triangle[] =
	{
		 0.0f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
		-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
		 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
	};

	//VAO是管理数据的,它里面没有具体数据,所以需要创建VBO,向VBO中添加数据
	glGenVertexArrays(1, &m_VAO_Triangle);
	glBindVertexArray(m_VAO_Triangle);

	glGenBuffers(1, &m_VBO_Triangle);
	glBindBuffer(GL_ARRAY_BUFFER, m_VBO_Triangle);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_triangle), vertices_triangle, GL_STATIC_DRAW);

	//告诉OpenGL怎样解析它的数据
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float) * 3));

	//启用锚点
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	//解除绑定
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	//------------------------------------------------------------------------------------------------- rectangle
	//矩形
	float vertices_rectangle[] =
	{
		-0.5f,  0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
		 0.5f,  0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
		-0.5f, -0.5f, 0.0f, 1.0f, 0.2f, 0.5f,

		 0.5f,  0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
		-0.5f, -0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
		 0.5f, -0.5f, 0.0f, 1.0f, 0.2f, 0.5f,
	};

	glGenVertexArrays(1, &m_VAO_Rectangle);
	glBindVertexArray(m_VAO_Rectangle);

	glGenBuffers(1, &m_VBO_Rectangle);
	glBindBuffer(GL_ARRAY_BUFFER, m_VBO_Rectangle);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_rectangle), vertices_rectangle, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float) * 3));

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	//------------------------------------------------------------------------------------------------- cube
	//立方体
	float vertices_cube[] =
	{
	   -0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
		0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
		0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
		0.5f,  0.5f, -0.5f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
	   -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
	   -0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,

	   -0.5f, -0.5f,  0.5f,  1.0f, 0.5f, 0.0f, 0.0f, 0.0f,
		0.5f, -0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
		0.5f,  0.5f,  0.5f,  1.0f, 0.5f, 0.5f, 1.0f, 1.0f,
		0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
	   -0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
	   -0.5f, -0.5f,  0.5f,  1.0f, 0.5f, 0.5f, 0.0f, 0.0f,

	   -0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
	   -0.5f,  0.5f, -0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
	   -0.5f, -0.5f, -0.5f,  0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
	   -0.5f, -0.5f, -0.5f,  1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
	   -0.5f, -0.5f,  0.5f,  1.0f, 0.5f, 0.5f, 0.0f, 0.0f,
	   -0.5f,  0.5f,  0.5f,  1.0f, 0.5f, 0.5f, 1.0f, 0.0f,

		0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
		0.5f,  0.5f, -0.5f,  1.0f, 0.5f, 0.5f, 1.0f, 1.0f,
		0.5f, -0.5f, -0.5f,  1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
		0.5f, -0.5f, -0.5f,  1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
		0.5f, -0.5f,  0.5f,  1.0f, 0.5f, 0.5f, 0.0f, 0.0f,
		0.5f,  0.5f,  0.5f,  1.0f, 0.5f, 0.5f, 1.0f, 0.0f,

	   -0.5f, -0.5f, -0.5f,  0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
		0.5f, -0.5f, -0.5f,  0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
		0.5f, -0.5f,  0.5f,  1.0f, 0.5f, 0.0f, 1.0f, 0.0f,
		0.5f, -0.5f,  0.5f,  0.0f, 0.5f, 0.5f, 1.0f, 0.0f,
	   -0.5f, -0.5f,  0.5f,  0.0f, 0.5f, 0.5f, 0.0f, 0.0f,
	   -0.5f, -0.5f, -0.5f,  0.0f, 0.5f, 0.5f, 0.0f, 1.0f,

	   -0.5f,  0.5f, -0.5f,  0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
		0.5f,  0.5f, -0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
		0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
		0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
	   -0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
	   -0.5f,  0.5f, -0.5f,  0.5f, 1.0f, 0.5f, 0.0f, 1.0f
	};

	glGenVertexArrays(1, &m_VAO_Cube);
	glBindVertexArray(m_VAO_Cube);

	glGenBuffers(1, &m_VBO_Cube);
	glBindBuffer(GL_ARRAY_BUFFER, m_VBO_Cube);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_cube), vertices_cube, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 3));

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);



	//----------------------------------------------------------------------------------------------------------------------------------------
}

入门OpenGL - 旋转的立方体_第1张图片

源码:Hello_OpenGL.zip-图像处理文档类资源-CSDN下载

你可能感兴趣的:(OpenGL_学习记录,音视频,qt,开发语言)