IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> [C++] [OpenGL] 基于GLFW+GLAD的OpenGL简单程序 -> 正文阅读

[C++知识库][C++] [OpenGL] 基于GLFW+GLAD的OpenGL简单程序

代码

test.cpp

#include "SimpleGL/glad.c"
#include <GLFW/glfw3.h>
#include <iostream>

#include "SimpleGL/Program.hpp"
#include "SimpleGL/Camera.hpp"
#include "SimpleGL/Buffer.hpp"
#include "SimpleGL/Error.hpp"
#include "SimpleGL/Sprite.hpp"

using namespace glm;
using namespace SimpleGL;
using namespace std;

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);

bool isFirst;
vec2 lastPos;
float deltaTime;
float lastTime;
Camera camera;

int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	GLFWmonitor* monitor = glfwGetPrimaryMonitor();
	const GLFWvidmode* videomode = glfwGetVideoMode(monitor);
	int width = videomode->width;
	int height = videomode->height;
	GLFWwindow* window = glfwCreateWindow(width, height, "LearnOpenGL", monitor, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	lastTime = glfwGetTime();
	isFirst = true;

	glEnable(GL_DEPTH_TEST);

	camera.m_projection.loadPerspective(120.0f, 1.0f, 0.1f, 100.0f);

	Sprite triangle = Sprite(vec3(0, 0, -1));

	Program program;
	VertexBufferObject vbo1;
	VertexBufferObject vbo2;
	VertexArrayObject vao;
	ElementBufferObject ebo;

	bool success = program.loadProgramFromFile("shader/usual.vert", "shader/usual.frag");
	string error = program.getError();
	cout << (success ? "program no error" : error) << endl;

	GLfloat ver[] =
	{
		0.0f, 0.5f, 0.0f,// 1.0, 0.0, 0.0,
		-0.5f, -0.5f, 0.0f,// 0.0, 1.0, 0.0,
		0.5f, -0.5f, 0.0f,// 0.0, 0.0, 1.0

		-100.0f, 0.0f, 0.0f,
		100.0f, 0.0f, 0.0f,
		0.0f, -100.0f, 0.0f,
		0.0f, 100.0f, 0.0f,
		0.0f, 0.0f, -100.0f,
		0.0f, 0.0f, 100.0f
	};

	GLfloat col[] =
	{
		1.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 1.0f,

		1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f,
		0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 1.0f,
		0.0f, 0.0f, 1.0f
	};

	GLuint ind[] =
	{
		0, 1, 2,
	};

	vao.bindVertexArray();
	GLuint v1 = vbo1.getBufferID();
	GLuint v2 = vbo2.getBufferID();
	GLuint v3 = ebo.getBufferID();
	GLenum type = GL_ARRAY_BUFFER;
	glBindBuffer(type, v1);
	glBufferData(type, sizeof(ver), ver, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	glBindBuffer(type, v2);
	glBufferData(type, sizeof(col), col, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(1);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, v3);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ind), ind, GL_STATIC_DRAW);
	vao.bindVertexArray0();
	vbo1.bindBuffer0();
	ebo.bindBuffer0();
	vbo1.deleteBuffer();
	vbo2.deleteBuffer();
	ebo.deleteBuffer();

	while (!glfwWindowShouldClose(window))
	{
		processInput(window);

		float nowTime = glfwGetTime();
		deltaTime = nowTime - lastTime;
		lastTime = nowTime;

		glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		program.useProgram();
		program.setUniform("u_projection", camera.m_projection.matrix);
		program.setUniform("u_view", camera.m_view.matrix);
		vao.bindVertexArray();
		//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, NULL);

		program.setUniform("u_model", triangle.matrix);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		program.setUniform("u_model", glm::mat4(1.0f));
		glDrawArrays(GL_LINES, 3, 6);

		vao.bindVertexArray0();
		triangle.rotate(vec3(0, 1, 0));

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	program.deleteProgram();
	vao.deleteVertexArray();

	glfwTerminate();
	return 0;
}

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

	else if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		camera.processMove(Camera::Direction::FORWARD, deltaTime);
	else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		camera.processMove(Camera::Direction::BACKWARD, deltaTime);
	else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		camera.processMove(Camera::Direction::LEFT, deltaTime);
	else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		camera.processMove(Camera::Direction::RIGHT, deltaTime);
	else if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
		camera.processMove(Camera::Direction::UP, deltaTime);
	else if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
		camera.processMove(Camera::Direction::DOWN, deltaTime);
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
	camera.m_projection.loadPerspective(120.0f, float(width) / float(height), 0.1f, 100.0f);
}

void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	vec2 nowPos = vec2(xpos, ypos);
	if (isFirst)
	{
		lastPos = nowPos;
		isFirst = false;
	}

	vec2 delta = nowPos - lastPos;
	lastPos = nowPos;
	camera.processRotate(-delta.x, delta.y);
}

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	camera.processZoom(yoffset);
}

Sprite.hpp

#ifndef __SIMPLEGL_SPRITE_HPP__
#define __SIMPLEGL_SPRITE_HPP__
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

namespace SimpleGL
{
	class Sprite
	{
		public:
			glm::vec3 m_position;
			glm::vec3 m_rotate;
			glm::vec3 m_scale;
			glm::mat4 matrix;

		public:
			Sprite(glm::vec3 position = glm::vec3(0.0f), glm::vec3 rotate = glm::vec3(0.0f), glm::vec3 scale = glm::vec3(1.0f)) : m_position(position), m_rotate(rotate), m_scale(scale), matrix(glm::mat4(1.0f))
			{
				generateMatrix();
			}

		public:
			Sprite& setPosition(glm::vec3 position)
			{
				m_position = position;
				generateMatrix();
				return *this;
			}
			Sprite& setRotate(glm::vec3 angle)
			{
				m_rotate = angle;
				generateMatrix();
				return *this;
			}
			Sprite& setScale(glm::vec3 size)
			{
				m_scale = size;
				generateMatrix();
				return *this;
			}

			Sprite& translate(glm::vec3 distance)
			{
				m_position += distance;
				generateMatrix();
				return *this;
			}
			Sprite& rotate(glm::vec3 angle)
			{
				m_rotate += angle;
				generateMatrix();
				return *this;
			}
			Sprite& scale(glm::vec3 size)
			{
				m_scale += size;
				generateMatrix();
				return *this;
			}

			glm::mat4 generateMatrix()
			{
				matrix = glm::mat4(1.0f);
				matrix = glm::translate(matrix, m_position);
				matrix = glm::rotate(matrix, glm::radians(m_rotate.x), glm::vec3(1.0f, 0.0f, 0.0f));
				matrix = glm::rotate(matrix, glm::radians(m_rotate.y), glm::vec3(0.0f, 1.0f, 0.0f));
				matrix = glm::rotate(matrix, glm::radians(m_rotate.z), glm::vec3(0.0f, 0.0f, 1.0f));
				matrix = glm::scale(matrix, m_scale);
				return matrix;
			}
	};
}

#endif

Program.hpp

#ifndef __SIMPLEGL_SHADER_HPP__
#define __SIMPLEGL_SHADER_HPP__
#include <iostream>
#include <sstream>
#include <fstream>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Error.hpp" 

#include "glad.c"

namespace SimpleGL
{
	class Program
	{
		private:
			GLuint m_programID;
			std::stringstream m_error;

		public:
			static std::string check(GLuint ID, GLenum type)
			{
				GLint success;
				std::string result = std::string();

				if (type != GL_PROGRAM)
				{
					glGetShaderiv(ID, GL_COMPILE_STATUS, &success);
					if (!success)
					{
						GLchar* infoLog = NULL;
						GLint length;
						glGetShaderiv(ID, GL_INFO_LOG_LENGTH, &length);
						infoLog = new char[length];
						glGetShaderInfoLog(ID, length, NULL, infoLog);
						result = std::string("Shader Error:\n") + std::string(infoLog);
						delete[] infoLog;
					}
				}
				else
				{
					glGetProgramiv(ID, GL_LINK_STATUS, &success);
					if (!success)
					{
						GLchar* infoLog = NULL;
						GLint length;
						glGetProgramiv(ID, GL_INFO_LOG_LENGTH, &length);
												infoLog = new char[length];
						glGetProgramInfoLog(ID, length, NULL, infoLog);
						result = std::string("Program Error:\n") + std::string(infoLog);
						delete[] infoLog;
					}
				}

				return result;
			}
			static GLuint createShader(std::string source, GLenum type, std::stringstream* error_output = nullptr)
			{
				const GLchar* s = source.data();
				GLuint shader = glCreateShader(type);
				glShaderSource(shader, 1, &s, NULL);
				glCompileShader(shader);
				std::string error = check(shader, type);

				if (error_output != nullptr)
				{
					if (error.length() > 0)
					{
						*error_output << error << std::endl;
					}
				}

				if (error.length() > 0)
				{
					glDeleteShader(shader);
					return 0;
				}
				return shader;
			}
			static GLuint createProgram(std::string vSource, std::string fSource, std::string gSource, std::stringstream* error_output = nullptr)
			{
				GLuint vShader = createShader(vSource, GL_VERTEX_SHADER, error_output);
				GLuint fShader = createShader(fSource, GL_FRAGMENT_SHADER, error_output);
				GLuint gShader = 0;
				if (gSource.length() > 0)
				{
					gShader = createShader(gSource, GL_GEOMETRY_SHADER, error_output);
				}

				GLuint program = glCreateProgram();
				glAttachShader(program, vShader);
				glAttachShader(program, fShader);
				if (gShader != 0)
				{
					glAttachShader(program, gShader);
				}
				glLinkProgram(program);
				std::string error = check(program, GL_PROGRAM);

				glDeleteShader(vShader);
				glDeleteShader(fShader);
				if (gShader != 0)
				{
					glDeleteShader(gShader);
				}

				if (error_output != nullptr)
				{
					if (error.length() > 0)
					{
						*error_output << error << std::endl;
					}
				}

				if (error.length() > 0)
				{
					glDeleteProgram(program);
					return 0;
				}

				return program;
			}
			static std::string loadStringFromStream(std::istream& is)
			{
				std::stringstream result;
				std::string temp;
				while (getline(is, temp))
				{
					result << temp << std::endl;
				}
				return result.str();
			}

		public:
			Program()
			{
				m_programID = 0;
			}
			Program(std::string vSource, std::string fSource, std::string gSource = "")
			{
				m_programID = createProgram(vSource, fSource, gSource, &m_error);
			}

			bool loadProgram(std::string vSource, std::string fSource, std::string gSource = "")
			{
				GLuint id = createProgram(vSource, fSource, gSource, &m_error);
				if (id == 0)
				{
					return false;
				}

				m_programID = id;
				return true;
			}
			bool loadProgramFromStream(std::istream& vStream, std::istream& fStream)
			{
				std::string vSource = loadStringFromStream(vStream);
				std::string fSource = loadStringFromStream(fStream);
				return loadProgram(vSource, fSource);
			}
			bool loadProgramFromStream(std::istream& vStream, std::istream& fStream, std::istream& gStream)
			{
				std::string vSource = loadStringFromStream(vStream);
				std::string fSource = loadStringFromStream(fStream);
				std::string gSource = loadStringFromStream(gStream);
				return loadProgram(vSource, fSource, gSource);
			}
			bool loadProgramFromFile(std::string vPath, std::string fPath)
			{
				std::ifstream vStream;
				std::ifstream fStream;
				bool result;

				try
				{
					vStream.open(vPath);
					fStream.open(fPath);

					if (!vStream.is_open())
					{
						return false;
					}
					if (!fStream.is_open())
					{
						return false;
					}

					result = loadProgramFromStream(vStream, fStream);

					vStream.close();
					fStream.close();

				}
				catch (std::ifstream::failure& e)
				{
					result = false;
					m_error << "File Error:\n" << e.what() << std::endl;
				}

				return result;
			}
			bool loadProgramFromFile(std::string vPath, std::string fPath, std::string gPath)
			{
				std::ifstream vStream;
				std::ifstream fStream;
				std::ifstream gStream;
				bool result;

				try
				{
					vStream.open(vPath);
					fStream.open(fPath);
					gStream.open(gPath);

					if (!vStream.is_open())
					{
						return false;
					}
					if (!fStream.is_open())
					{
						return false;
					}
					if (!gStream.is_open())
					{
						return false;
					}

					result = loadProgramFromStream(vStream, fStream, gStream);

					vStream.close();
					fStream.close();
					gStream.close();

				}
				catch (std::ifstream::failure& e)
				{
					result = false;
					m_error << "File Error:\n" << e.what() << std::endl;
				}

				return result;
			}

			bool compile()
			{
				clearError();
				glLinkProgram(m_programID);
				std::string error = check(m_programID, GL_PROGRAM);
				if (error.length() > 0)
				{
					m_error << error << std::endl;
					return false;
				}
				return true;
			}

			Program& deleteProgram()
			{
				if (m_programID != 0)
				{
					glDeleteProgram(m_programID);
				}
				return *this;
			}

			Program& setProgramID(GLuint ID)
			{
				m_programID = ID;
				return *this;
			}
			GLuint getProgramID()
			{
				return m_programID;
			}

			Program& useProgram()
			{
				if (m_programID != 0)
				{
					glUseProgram(m_programID);
				}
				return *this;
			}

			std::string getError()
			{
				return m_error.str();
			}
			Program& clearError()
			{
				m_error.str("");
				return *this;
			}

		public:
			GLuint getUniformLocation(std::string name)
			{
				if (m_programID != 0)
				{
					return glGetUniformLocation(m_programID, name.data());
				}
				return -1;
			}

			Program& setUniform(std::string name, glm::mat4 matrix, GLenum transpose = GL_FALSE)
			{
				if (m_programID != 0)
				{
					GLuint location = getUniformLocation(name);
					glUniformMatrix4fv(location, 1, transpose, glm::value_ptr(matrix));
				}
				return *this;
			}
	};

	//It just means existence,no idea to program it.
	//GL_COMPUTE_SHADER
	class ComputeProgram
	{
		private:
			GLuint m_programID;

		public:
			static std::string check(GLuint program)
			{
				return std::string();
			}
			static GLuint create(std::string cSource)
			{
				return 0;
			}

		public:
			ComputeProgram() {}
	};
}

#endif

Buffer.hpp

#ifndef __SIMPLEGL_BUFFER_HPP__
#define __SIMPLEGL_BUFFER_HPP__
#include "glad.c"

namespace SimpleGL
{
	class BufferObject
	{
		private:
			GLuint m_bufferObjectID;
			GLenum m_type;

		public:
			static void bindBuffer0(GLenum type)
			{
				glBindBuffer(type, 0);
			}

		public:
			BufferObject(GLenum type)
			{
				m_type = type;
				genBuffer();
				bindBuffer();
				bindBuffer0();
			}

			~BufferObject()
			{
				deleteBuffer();
			}

		public:
			BufferObject& setBufferID(GLuint id)
			{
				m_bufferObjectID = id;
				return *this;
			}

			GLuint getBufferID()
			{
				return m_bufferObjectID;
			}

			const GLuint getBufferType()
			{
				return m_type;
			}

		public:
			bool genBuffer()
			{
				deleteBuffer();
				glGenBuffers(1, &m_bufferObjectID);
				return (m_bufferObjectID != 0);
			}

			BufferObject& bindBuffer()
			{
				if (m_bufferObjectID != 0)
				{
					glBindBuffer(m_type, m_bufferObjectID);
				}
				return *this;
			}
			BufferObject& bindBuffer0()
			{
				bindBuffer0(m_type);
				return *this;
			}

			BufferObject& deleteBuffer()
			{
				if (m_bufferObjectID != 0)
				{
					glDeleteBuffers(1, &m_bufferObjectID);
					m_bufferObjectID = 0;
				}
				return *this;
			}
	};

	class VertexBufferObject : public BufferObject
	{
		public:
			VertexBufferObject() : BufferObject(GL_ARRAY_BUFFER) {}
	};

	class ElementBufferObject : public BufferObject
	{
		public:
			ElementBufferObject() : BufferObject(GL_ELEMENT_ARRAY_BUFFER) {}
	};

	class VertexArrayObject
	{
		private:
			GLuint m_VertexArrayObjectID;

		public:
			static void bindVertexArray0()
			{
				glBindVertexArray(0);
			}

		public:
			VertexArrayObject()
			{
				genVertexArray();
				bindVertexArray();
				bindVertexArray0();
			}
			~VertexArrayObject()
			{
				deleteVertexArray();
			}

		public:
			VertexArrayObject& setVertexArrayObjectID(GLuint id)
			{
				m_VertexArrayObjectID = id;
				return *this;
			}
			GLuint getVertexArrayObjectID()
			{
				return m_VertexArrayObjectID;
			}

		public:
			bool genVertexArray()
			{
				deleteVertexArray();
				glGenVertexArrays(1, &m_VertexArrayObjectID);
				return (m_VertexArrayObjectID != 0);
			}

			VertexArrayObject& bindVertexArray()
			{
				if (m_VertexArrayObjectID != 0)
				{
					glBindVertexArray(m_VertexArrayObjectID);
				}
				return *this;
			}

			VertexArrayObject& deleteVertexArray()
			{
				if (m_VertexArrayObjectID != 0)
				{
					glDeleteVertexArrays(1, &m_VertexArrayObjectID);
					m_VertexArrayObjectID = 0;
				}
				return *this;
			}
	};
}

#endif

Error.hpp

#ifndef __SIMPLEGL_ERROR_HPP__
#define __SIMPLEGL_ERROR_HPP__
#include "glad.c"
#include <sstream>

namespace SimpleGL
{
	class Error
	{
		public:
			static std::string parse(GLenum error)
			{
				std::string result;
				switch (error)
				{
					case GL_NO_ERROR:
						result = "GL_NO_ERROR";
						break;
					case GL_INVALID_ENUM:
						result = "GL_INVALID_ENUM";
						break;
					case GL_INVALID_VALUE:
						result = "GL_INVALID_VALUE";
						break;
					case GL_INVALID_OPERATION:
						result = "GL_INVALID_OPERATION";
						break;
					case GL_STACK_OVERFLOW:
						result = "GL_STACK_OVERFLOW";
						break;
					case GL_STACK_UNDERFLOW:
						result = "GL_STACK_UNDERFLOW";
						break;
					case GL_OUT_OF_MEMORY:
						result = "GL_OUT_OF_MEMORY";
						break;
					case GL_INVALID_FRAMEBUFFER_OPERATION:
						result = "GL_INVALID_FRAMEBUFFER_OPERATION";
						break;
					default:
						result = "Unknow";
						break;
				}
				return result;
			}

			//https://learnopengl.com/In-Practice/Debugging
			static std::string describe(GLenum error)
			{
				std::string result;
				switch (error)
				{
					case GL_NO_ERROR:
						result = "No user error reported since the last call to glGetError.";
						break;
					case GL_INVALID_ENUM:
						result = "Set when an enumeration parameter is not legal.";
						break;
					case GL_INVALID_VALUE:
						result = "Set when a value parameter is not legal.";
						break;
					case GL_INVALID_OPERATION:
						result = "Set when the state for a command is not legal for its given parameters.";
						break;
					case GL_STACK_OVERFLOW:
						result = "Set when a stack pushing operation causes a stack overflow.";
						break;
					case GL_STACK_UNDERFLOW:
						result = "Set when a stack popping operation occurs while the stack is at its lowest point.";
						break;
					case GL_OUT_OF_MEMORY:
						result = "Set when a memory allocation operation cannot allocate (enough) memory.";
						break;
					case GL_INVALID_FRAMEBUFFER_OPERATION:
						result = "Set when reading or writing to a framebuffer that is not complete.";
						break;
					default:
						result = "Unknown enumeration.";
						break;
				}
				return result;
			}

		public:
			GLenum error;
			std::string value;
			std::string description;

		public:
			Error()
			{
				error = glGetError();
				value = parse(error);
				description = describe(error);
			}

			Error& operator()()
			{
				error = glGetError();
				value = parse(error);
				description = describe(error);
				return *this;
			}

			std::string toString()
			{
				std::stringstream sstr;
				sstr << "Error Number:" << error << std::endl
				     << "Error String:" << value << std::endl
				     << "Error Description:" << description << std::endl;
				return sstr.str();
			}
	};
}

#endif

Camera.hpp

#ifndef __SIMPLEGL_CAMERA_HPP__
#define __SIMPLEGL_CAMERA_HPP__
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

namespace SimpleGL
{
	class Camera
	{
		public:
			enum Direction
			{
				FORWARD,
				BACKWARD,
				LEFT,
				RIGHT,
				UP,
				DOWN
			};

			class View
			{
				public:
					glm::vec3 position;
					glm::vec3 front;
					glm::vec3 center;
					glm::vec3 up;
					glm::vec3 right;
					float yaw;
					float pitch;
					glm::mat4 matrix;

				public:
					View(glm::vec3 po = glm::vec3(0.0f), float y = 0, float pi = 0, glm::vec3 u = glm::vec3(0.0f, 1.0f, 0.0f))
					{
						position = po;
						yaw = y;
						pitch = pi;
						up = u;

						update();
					}

				public:
					View& update()
					{
						if (pitch > 89.9f)
							pitch =  89.9f;
						if (pitch < -89.9f)
							pitch = -89.9f;
						float h = glm::cos(glm::radians(pitch));
						float x = glm::cos(glm::radians(yaw)) * h;
						float y = glm::sin(glm::radians(pitch));
						float z = glm::sin(glm::radians(yaw)) * h;
						front = glm::normalize(glm::vec3(x, y, z));
						center = position + front;
						right = glm::normalize(glm::cross(front, up));
						return *this;
					}

					glm::mat4 generateMatrix()
					{
						matrix = glm::lookAt(position, center, up);
						return matrix;
					}
			};

			class Projection
			{
				public:
					float fovy;
					float aspect;
					float near_plane;
					float far_plane;
					glm::mat4 matrix;

				public:
					Projection() : fovy(120.0f), aspect(1.0f), near_plane(0.1f), far_plane(100.0f), matrix(glm::mat4(1.0f)) {}
					Projection(float n, float f) : near_plane(n), far_plane(f), matrix(glm::mat4(1.0f)) {}

					glm::mat4 loadPerspective(float f, float a, float ne, float fa)
					{
						fovy = f;
						aspect = a;
						near_plane = ne;
						far_plane = fa;
						return loadPerspective();
					}
					glm::mat4 loadPerspective()
					{
						matrix = glm::perspective(fovy, aspect, near_plane, far_plane);
						return matrix;
					};
			};



		public:
			View m_view;
			Projection m_projection;
			float m_sensitivity;
			float m_movement_speed;

		public:
			Camera(View view = View(), Projection projection = Projection()) : m_view(view), m_projection(projection), m_sensitivity(0.05f), m_movement_speed(1) {}

			Camera& processMove(Direction direction, float deltaTime)
			{
				float distance = m_movement_speed * deltaTime;
				if (direction == Direction::FORWARD)
					m_view.position += m_view.front * distance;
				else if (direction == Direction::BACKWARD)
					m_view.position += (-m_view.front) * distance;
				else if (direction == Direction::LEFT)
					m_view.position += (-m_view.right) * distance;
				else if (direction == Direction::RIGHT)
					m_view.position += m_view.right * distance;
				else if (direction == Direction::UP)
					m_view.position += m_view.up * distance;
				else if (direction == Direction::DOWN)
					m_view.position += (-m_view.up) * distance;
				m_view.update();
				m_view.generateMatrix();
				return *this;
			}
			Camera& processRotate(float dx, float dy)
			{
				m_view.yaw += dx * m_sensitivity;
				m_view.pitch += dy * m_sensitivity;
				m_view.update();
				m_view.generateMatrix();
				return *this;
			}
			Camera& processZoom(float offset)
			{
				m_projection.fovy += offset;
				if (m_projection.fovy < 1.0f)
					m_projection.fovy = 1.0f;
				else if (m_projection.fovy > 179.9f)
					m_projection.fovy = 179.9f;
				m_projection.loadPerspective();
				return *this;
			}
	};
}

#endif

运行结果

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:09:20  更:2022-04-27 11:10:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 23:36:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码