首頁 > 軟體

C++ OpenGL實現旋轉立方體的繪製

2022-07-28 14:02:40

1、Z-緩衝

//開啟深度測試
glEnable(GL_DEPTH_TEST);

2、GLM庫函數

3、PVM矩陣

4、PVM矩陣的使用

我們需要引入GLM函數庫的標頭檔案:

#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>

設定vew矩陣的相關引數:

//相機引數
glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);     //攝像機位置
glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);       //攝像機方向
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);           //攝像機上向量

設定project矩陣視野fov:

float fov = 45.0f;

// Transform座標變換矩陣
		glm::mat4 model(1);//model矩陣,區域性座標變換至世界座標
		model = glm::translate(model, glm::vec3(0.0,0.0,0.0));
		model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
		model = glm::scale(model, glm::vec3(1.0f,1.0f,1.0f));

glm::mat4 view(1);//view矩陣,世界座標變換至觀察座標系
		view = glm::lookAt(camera_position, camera_position + camera_front, camera_up);

glm::mat4 projection(1);//projection矩陣,投影矩陣
		projection = glm::perspective(glm::radians(fov), (float)screen_width / screen_height, 0.1f, 100.0f);

int model_location = glGetUniformLocation(shader.ID, "model"); //獲取著色器內某個引數的位置
		

glUniformMatrix4fv(model_location, 1, GL_FALSE, glm::value_ptr(model));//寫入引數值

gl_Position=projection*view*model*vec4(aPos,1.0);

5、工程檔案結構

shader.h

#ifndef __SHADER_H__
#define __SHADER_H__
 
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "string"
 
class Shader
{
public:
	unsigned int ID;
 
	Shader(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path);
	~Shader();
 
	void Use();
	void SetBool(const std::string &name, bool value) const;
	void SetInt(const std::string &name, int value) const;
	void SetFloat(const std::string &name, float value) const;
	void SetVec2(const std::string &name, const glm::vec2 &value) const;
	void SetVec2(const std::string &name, float x, float y) const;
	void SetVec3(const std::string &name, const glm::vec3 &value) const;
	void SetVec3(const std::string &name, float x, float y, float z) const;
	void SetVec4(const std::string &name, const glm::vec4 &value) const;
	void SetVec4(const std::string &name, float x, float y, float z, float w) const;
	void SetMat2(const std::string &name, const glm::mat2 &value) const;
	void SetMat3(const std::string &name, const glm::mat3 &value) const;
	void SetMat4(const std::string &name, const glm::mat4 &value) const;
 
private:
	int GetShaderFromFile(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path,
		std::string *vertex_shader_code, std::string *fragment_shader_code);
	int LinkShader(const char* vertex_shader_code, const char* fragment_shader_code);
	int GetUniform(const std::string &name) const;
	void CheckCompileErrors(GLuint shader, std::string type);
};
 
#endif // !__SHADER_H__
#ifndef __SHADER_H__
#define __SHADER_H__
 
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "string"
 
class Shader
{
public:
	unsigned int ID;
 
	Shader(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path);
	~Shader();
 
	void Use();
	void SetBool(const std::string &name, bool value) const;
	void SetInt(const std::string &name, int value) const;
	void SetFloat(const std::string &name, float value) const;
	void SetVec2(const std::string &name, const glm::vec2 &value) const;
	void SetVec2(const std::string &name, float x, float y) const;
	void SetVec3(const std::string &name, const glm::vec3 &value) const;
	void SetVec3(const std::string &name, float x, float y, float z) const;
	void SetVec4(const std::string &name, const glm::vec4 &value) const;
	void SetVec4(const std::string &name, float x, float y, float z, float w) const;
	void SetMat2(const std::string &name, const glm::mat2 &value) const;
	void SetMat3(const std::string &name, const glm::mat3 &value) const;
	void SetMat4(const std::string &name, const glm::mat4 &value) const;
 
private:
	int GetShaderFromFile(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path,
		std::string *vertex_shader_code, std::string *fragment_shader_code);
	int LinkShader(const char* vertex_shader_code, const char* fragment_shader_code);
	int GetUniform(const std::string &name) const;
	void CheckCompileErrors(GLuint shader, std::string type);
};
 
#endif // !__SHADER_H__
#ifndef __SHADER_H__
#define __SHADER_H__
 
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "string"
 
class Shader
{
public:
	unsigned int ID;
 
	Shader(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path);
	~Shader();
 
	void Use();
	void SetBool(const std::string &name, bool value) const;
	void SetInt(const std::string &name, int value) const;
	void SetFloat(const std::string &name, float value) const;
	void SetVec2(const std::string &name, const glm::vec2 &value) const;
	void SetVec2(const std::string &name, float x, float y) const;
	void SetVec3(const std::string &name, const glm::vec3 &value) const;
	void SetVec3(const std::string &name, float x, float y, float z) const;
	void SetVec4(const std::string &name, const glm::vec4 &value) const;
	void SetVec4(const std::string &name, float x, float y, float z, float w) const;
	void SetMat2(const std::string &name, const glm::mat2 &value) const;
	void SetMat3(const std::string &name, const glm::mat3 &value) const;
	void SetMat4(const std::string &name, const glm::mat4 &value) const;
 
private:
	int GetShaderFromFile(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path,
		std::string *vertex_shader_code, std::string *fragment_shader_code);
	int LinkShader(const char* vertex_shader_code, const char* fragment_shader_code);
	int GetUniform(const std::string &name) const;
	void CheckCompileErrors(GLuint shader, std::string type);
};
 
#endif // !__SHADER_H__

shader.cpp

#include "Shader.h"
#include "fstream"
#include "sstream"
#include "iostream"
 
Shader::Shader(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path)
{
	std::string vertex_shader_code;
	std::string fragment_shader_code;
	if (GetShaderFromFile(vertex_shader_path, fragment_shader_path, &vertex_shader_code, &fragment_shader_code))
	{
		return;
	}
	if (LinkShader(vertex_shader_code.c_str(), fragment_shader_code.c_str()))
	{
		return;
	}
}
 
Shader::~Shader()
{
 
}
 
void Shader::Use()
{
	glUseProgram(ID);
}
 
void Shader::SetBool(const std::string &name, bool value) const
{
	SetInt(name, (int)value);
}
 
void Shader::SetInt(const std::string &name, int value) const
{
	glUniform1i(GetUniform(name), value);
}
 
void Shader::SetFloat(const std::string &name, float value) const
{
	glUniform1f(GetUniform(name), value);
}
 
void Shader::SetVec2(const std::string &name, float x, float y) const
{
	glUniform2f(GetUniform(name), x, y);
}
 
void Shader::SetVec2(const std::string &name, const glm::vec2 &value) const
{
	SetVec2(name, value.x, value.y);
}
 
void Shader::SetVec3(const std::string &name, float x, float y, float z) const
{
	glUniform3f(GetUniform(name), x, y, z);
}
 
void Shader::SetVec3(const std::string &name, const glm::vec3 &value) const
{
	SetVec3(name, value.x, value.y, value.z);
}
 
void Shader::SetVec4(const std::string &name, float x, float y, float z, float w) const
{
	glUniform4f(GetUniform(name), x, y, z, w);
}
 
void Shader::SetVec4(const std::string &name, const glm::vec4 &value) const
{
	SetVec4(name, value.x, value.y, value.z, value.w);
}
 
void Shader::SetMat2(const std::string &name, const glm::mat2 &value) const
{
	glUniformMatrix2fv(GetUniform(name), 1, GL_FALSE, &value[0][0]);
}
 
void Shader::SetMat3(const std::string &name, const glm::mat3 &value) const
{
	glUniformMatrix3fv(GetUniform(name), 1, GL_FALSE, &value[0][0]);
}
 
void Shader::SetMat4(const std::string &name, const glm::mat4 &value) const
{
	glUniformMatrix4fv(GetUniform(name), 1, GL_FALSE, &value[0][0]);
}
 
int Shader::GetShaderFromFile(const GLchar* vertex_shader_path, const GLchar* fragment_shader_path, std::string *vertex_shader_code, std::string *fragment_shader_code)
{
	std::ifstream vertex_shader_file;
	std::ifstream fragment_shader_file;
	vertex_shader_file.exceptions(std::ifstream::badbit | std::ifstream::failbit);
	fragment_shader_file.exceptions(std::ifstream::badbit | std::ifstream::failbit);
	try
	{
		vertex_shader_file.open(vertex_shader_path);
		fragment_shader_file.open(fragment_shader_path);
		std::stringstream vertex_shader_stream, fragment_shader_stream;
		vertex_shader_stream << vertex_shader_file.rdbuf();
		fragment_shader_stream << fragment_shader_file.rdbuf();
		vertex_shader_file.close();
		fragment_shader_file.close();
		*vertex_shader_code = vertex_shader_stream.str();
		*fragment_shader_code = fragment_shader_stream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::cout << "Load Shader File Error!" << std::endl;
		return -1;
	}
	return 0;
}
 
int Shader::LinkShader(const char* vertex_shader_code, const char* fragment_shader_code)
{
	int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertex_shader, 1, &vertex_shader_code, NULL);
	glCompileShader(vertex_shader);
	CheckCompileErrors(vertex_shader, "VERTEX");
 
	int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragment_shader, 1, &fragment_shader_code, NULL);
	glCompileShader(fragment_shader);
	CheckCompileErrors(fragment_shader, "FRAGMENT");
 
	this->ID = glCreateProgram();
	glAttachShader(ID, vertex_shader);
	glAttachShader(ID, fragment_shader);
	glLinkProgram(ID);
	CheckCompileErrors(ID, "PROGRAM");
 
	glDeleteShader(vertex_shader);
	glDeleteShader(fragment_shader);
	return 0;
}
 
int Shader::GetUniform(const std::string &name) const
{
	int position = glGetUniformLocation(ID, name.c_str());
	if (position == -1)
	{
		std::cout << "uniform " << name << " set failed!" << std::endl;
	}
	return position;
}
 
void Shader::CheckCompileErrors(GLuint shader, std::string type)
{
	GLint success;
	GLchar infoLog[512];
	if (type == "PROGRAM")
	{
		glGetProgramiv(shader, GL_LINK_STATUS, &success);
		if (!success)
		{
			glGetProgramInfoLog(shader, 512, NULL, infoLog);
			std::cout << "ERROR::PROGRAM_LINKING_ERROR!n" << infoLog << std::endl;
		}
	}
	else
	{
		glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
		if (!success)
		{
			glGetShaderInfoLog(shader, 512, NULL, infoLog);
			std::cout << "ERROR::SHADER::" << type << "::COMPILATION_FAILEDn" << infoLog << std::endl;
		}
	}
}

main.cpp 

//總體流程
//1. 初始化並建立視窗
//2. 載入立方體頂點VAOVBO以及著色器並開啟深度測試
//3. 進入主迴圈清除緩衝
//4. 使用立方體著色器,構造並傳入pvm矩陣,繪製
//5. 迴圈結束,釋放VAOVBO
 
#include <iostream>
#include "glad/glad.h"
#include "GLFW/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
 
#include "shader.h"
 
const float vertices[] = {                  //立方體陣列
	-0.5f, -0.5f, -0.5f, 1.0f,0.0f,0.0f,
	0.5f, -0.5f, -0.5f,  1.0f,0.0f,0.0f,
	0.5f,  0.5f, -0.5f,  1.0f,0.0f,0.0f,
	0.5f,  0.5f, -0.5f,  1.0f,0.0f,0.0f,
	-0.5f,  0.5f, -0.5f,  1.0f,0.0f,0.0f,
	-0.5f, -0.5f, -0.5f,  1.0f,0.0f,0.0f,
 
	-0.5f, -0.5f,  0.5f,  0.0f,1.0f,0.0f,
	0.5f, -0.5f,  0.5f,  0.0f,1.0f,0.0f,
	0.5f,  0.5f,  0.5f,  0.0f,1.0f,0.0f,
	0.5f,  0.5f,  0.5f,  0.0f,1.0f,0.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,1.0f,0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,1.0f,0.0f,
 
	-0.5f,  0.5f,  0.5f,  0.0f,0.0f,1.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,0.0f,1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,0.0f,1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,0.0f,1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,0.0f,1.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,0.0f,1.0f,
 
	0.5f,  0.5f,  0.5f,  0.5f,0.0f,0.0f,
	0.5f,  0.5f, -0.5f,  0.5f,0.0f,0.0f,
	0.5f, -0.5f, -0.5f,  0.5f,0.0f,0.0f,
	0.5f, -0.5f, -0.5f,  0.5f,0.0f,0.0f,
	0.5f, -0.5f,  0.5f,  0.5f,0.0f,0.0f,
	0.5f,  0.5f,  0.5f,  0.5f,0.0f,0.0f,
 
	-0.5f, -0.5f, -0.5f,  0.0f,0.5f,0.0f,
	0.5f, -0.5f, -0.5f,  0.0f,0.5f,0.0f,
	0.5f, -0.5f,  0.5f,  0.0f,0.5f,0.0f,
	0.5f, -0.5f,  0.5f,  0.0f,0.5f,0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,0.5f,0.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,0.5f,0.0f,
 
	-0.5f,  0.5f, -0.5f,  0.0f,0.0f,0.5f,
	0.5f,  0.5f, -0.5f,  0.0f,0.0f,0.5f,
	0.5f,  0.5f,  0.5f,  0.0f,0.0f,0.5f,
	0.5f,  0.5f,  0.5f,  0.0f,0.0f,0.5f,
	-0.5f,  0.5f,  0.5f,  0.0f,0.0f,0.5f,
	-0.5f,  0.5f, -0.5f,  0.0f,0.0f,0.5f
};
 
float screen_width = 1280.0f;          //視窗寬度
float screen_height = 720.0f;          //視窗高度
//相機引數
glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f);     //攝像機位置
glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);       //攝像機方向
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);           //攝像機上向量
//視野
float fov = 45.0f;
 
int main() {
	// 初始化GLFW
	glfwInit();                                                     // 初始化GLFW
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);                  // OpenGL版本為3.3,主次版本號均設為3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 使用核心模式(無需向後相容性)
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // 如果使用的是Mac OS X系統,需加上這行
	glfwWindowHint(GLFW_RESIZABLE, FALSE);						    // 不可改變視窗大小
 
																	// 建立視窗(寬、高、視窗名稱)
	auto window = glfwCreateWindow(screen_width, screen_height, "Cube", nullptr, nullptr);
	if (window == nullptr) {                                        // 如果視窗建立失敗,輸出Failed to Create OpenGL Context
		std::cout << "Failed to Create OpenGL Context" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);                                 // 將視窗的上下文設定為當前執行緒的主上下文
 
																	// 初始化GLAD,載入OpenGL函數指標地址的函數
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}
 
	// 指定當前視口尺寸(前兩個引數為左下角位置,後兩個引數是渲染視窗寬、高)
	glViewport(0, 0, screen_width, screen_height);
 
 
	Shader shader("res/shader/task-cube.vs", "res/shader/task-cube.fs");//載入著色器
 
	// 生成並繫結VAO和VBO
	GLuint vertex_array_object; // == VAO
	glGenVertexArrays(1, &vertex_array_object);
	glBindVertexArray(vertex_array_object);
 
	GLuint vertex_buffer_object; // == VBO
	glGenBuffers(1, &vertex_buffer_object);
	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
	// 將頂點資料繫結至當前預設的緩衝中
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
 
	// 設定頂點屬性指標
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
 
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(1);
 
 
	glEnable(GL_DEPTH_TEST);
	// Render loop主迴圈
	while (!glfwWindowShouldClose(window)) {
		//進入主迴圈,清理顏色緩衝深度緩衝
		glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清理顏色緩衝和深度緩衝
 
		shader.Use();
 
		// Transform座標變換矩陣
		glm::mat4 model(1);//model矩陣,區域性座標變換至世界座標
		model = glm::translate(model, glm::vec3(0.0,0.0,0.0));
		model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
		model = glm::scale(model, glm::vec3(1.0f,1.0f,1.0f));
		glm::mat4 view(1);//view矩陣,世界座標變換至觀察座標系
		view = glm::lookAt(camera_position, camera_position + camera_front, camera_up);
		glm::mat4 projection(1);//projection矩陣,投影矩陣
		projection = glm::perspective(glm::radians(fov), (float)screen_width / screen_height, 0.1f, 100.0f);
 
		
		// 向著色器中傳入引數
		int model_location = glGetUniformLocation(shader.ID, "model"); //獲取著色器內某個引數的位置
		glUniformMatrix4fv(model_location, 1, GL_FALSE, glm::value_ptr(model));//寫入引數值
		int view_location = glGetUniformLocation(shader.ID, "view");
		glUniformMatrix4fv(view_location, 1, GL_FALSE, glm::value_ptr(view));
		int projection_location = glGetUniformLocation(shader.ID, "projection");
		glUniformMatrix4fv(projection_location, 1, GL_FALSE, glm::value_ptr(projection));
		//繪製
		glBindVertexArray(vertex_array_object);
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);
		
		
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	//釋放VAOVBO
	glDeleteVertexArrays(1, &vertex_array_object);
	glDeleteBuffers(1, &vertex_buffer_object);
 
	// 清理所有的資源並正確退出程式
	glfwTerminate();
	return 0;
}

輸出結果:

到此這篇關於C++ OpenGL實現旋轉立方體的繪製的文章就介紹到這了,更多相關C++ OpenGL旋轉立方體內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com