虽然是基于我的代码写的,但是部分还是能用的
SimpleGL.hpp这是最重要的头文件,所有代码都包括了它
#ifndef __SIMPLEGL_MAIN_HPP__ #define __SIMPLEGL_MAIN_HPP__ #if defined(USE_GLEW) #include#else #include #endif namespace SimpleGL { bool initGL() { #if defined(__glad_h_) if(!gladLoadGL()) return false; #elif defined(__glew_h__) if(glewInit() != GLEW_OK) return false; #endif return true; } } #include "Program.hpp" #include "Camera.hpp" #include "Error.hpp" #include "Sprite.hpp" #include "Texture.hpp" #include "Model.hpp" #include "GLFWUtils.hpp" #endif
介绍一下这句代码
如果定义了“USE_GLEW”,就会导入GLEW,否则就导入GLAD
用glad.c是因为直接用glad.h就显示未定义资源(就很奇怪)
#if defined(USE_GLEW) #includeCamera#else #include #endif
Camera类被我重写了
#ifndef __SIMPLEGL_CAMERA_HPP__ #define __SIMPLEGL_CAMERA_HPP__ #includeGLFWUtils#include #include #include namespace SimpleGL { class LookAt { public: const float PITCH_MAX = 89.9f; enum PitchDirection { POSITIVE_Y, ZERO, NEGATIVE_Y }; enum YawDirection { POSITIVE_X, POSITIVE_Z, NEGATIVE_X, NEGATIVE_Z }; enum MovementDirection { FORWARD, BACKWARD, LEFT, RIGHT, UP, DOWN }; enum MovementSpeed { VERY_SLOW, SLOW, NORMAL, FAST, VERY_FAST, CUSTOM }; private: glm::vec3 m_position; glm::vec3 m_front; glm::vec3 m_up; glm::vec3 m_right; float m_yaw; float m_pitch; glm::mat4 m_view_matrix; MovementSpeed m_movement_speed; float m_speed; float m_sensitivity; public: LookAt(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 front = glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)) { m_position = position; m_front = front; m_up = up; calcAngle(); update(); m_movement_speed = MovementSpeed::NORMAL; m_speed = 1.0f; m_view_matrix = glm::mat4(1.0f); m_sensitivity = 0.05f; } LookAt(glm::vec3 position, float yaw, float pitch, glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)) { m_position = position; m_yaw = yaw; m_pitch = pitch; m_up = up; update(); m_movement_speed = MovementSpeed::NORMAL; m_speed = 1.0f; m_view_matrix = glm::mat4(1.0f); m_sensitivity = 0.05f; } public: LookAt& operator=(const LookAt& lookAt) { m_position = lookAt.m_position; m_front = lookAt.m_front; m_up = lookAt.m_up; m_right = lookAt.m_right; m_yaw = lookAt.m_yaw; m_pitch = lookAt.m_pitch; m_view_matrix = lookAt.m_view_matrix; m_movement_speed = lookAt.m_movement_speed; m_speed = lookAt.m_speed; m_sensitivity = lookAt.m_sensitivity; return *this; } public: LookAt& calcAngle() { m_front = glm::normalize(m_front); m_yaw = glm::degrees(glm::atan(m_front.z, m_front.x)); m_pitch = glm::degrees(glm::asin(m_front.y)); return *this; } LookAt& update() { if (m_pitch > PITCH_MAX) m_pitch = PITCH_MAX; if (m_pitch < -PITCH_MAX) m_pitch = -PITCH_MAX; float h = glm::cos(glm::radians(m_pitch)); float x = glm::cos(glm::radians(m_yaw)) * h; float y = glm::sin(glm::radians(m_pitch)); float z = glm::sin(glm::radians(m_yaw)) * h; m_front = glm::normalize(glm::vec3(x, y, z)); m_right = glm::normalize(glm::cross(m_front, m_up)); m_view_matrix = glm::lookAt(m_position, m_position + m_front, m_up); return *this; } public: LookAt& setYawDirection(YawDirection direction) { if (direction == YawDirection::POSITIVE_X) m_yaw = 0.0f; else if (direction == YawDirection::POSITIVE_Z) m_yaw = 90.0f; else if (direction == YawDirection::NEGATIVE_X) m_yaw = 180.0f; else if (direction == YawDirection::NEGATIVE_Z) m_yaw = 270.0f; update(); return *this; } LookAt& setYaw(float yaw) { m_yaw = yaw; update(); return *this; } LookAt& yaw(float degree) { m_yaw += degree; update(); return *this; } float getYaw() { return m_yaw; } LookAt& setPitchDirection(PitchDirection direction) { if (direction == PitchDirection::POSITIVE_Y) m_pitch = PITCH_MAX; else if (direction == PitchDirection::ZERO) m_pitch = 0.0f; else if (direction == PitchDirection::NEGATIVE_Y) m_pitch = -PITCH_MAX; update(); return *this; } LookAt& setPitch(float pitch) { m_pitch = pitch; update(); return *this; } LookAt& pitch(float degree) { m_pitch += degree; update(); return *this; } float getPitch() { return m_pitch; } LookAt& setPosition(glm::vec3 position) { m_position = position; update(); return *this; } LookAt& move(glm::vec3 distance, float deltaTime = 1.0f) { m_position += distance * deltaTime; update(); return *this; } glm::vec3 getPosition() { return m_position; } LookAt& setFront(glm::vec3 front) { m_front = front; calcAngle(); update(); return *this; } glm::vec3 getFront() { return m_front; } LookAt& setUp(glm::vec3 up) { m_up = up; update(); return *this; } glm::vec3 getUp() { return m_up; } LookAt& setMovementSpeed(MovementSpeed movement_speed, float speed = 1.0f) { m_movement_speed = movement_speed; if (m_movement_speed == MovementSpeed::VERY_SLOW) m_speed = 0.2f; else if (m_movement_speed == MovementSpeed::SLOW) m_speed = 0.5f; else if (m_movement_speed == MovementSpeed::NORMAL) m_speed = 1.0f; else if (m_movement_speed == MovementSpeed::FAST) m_speed = 2.0f; else if (m_movement_speed == MovementSpeed::VERY_FAST) m_speed = 5.0f; else if (m_movement_speed == MovementSpeed::CUSTOM) m_speed = speed; return *this; } float getMovementSpeed() { return m_speed; } LookAt& move(MovementDirection direction, float deltaTime = 1.0f) { if (direction == MovementDirection::FORWARD) m_position += m_front * m_speed * deltaTime; else if (direction == MovementDirection::BACKWARD) m_position += (-m_front) * m_speed * deltaTime; else if (direction == MovementDirection::LEFT) m_position += (-m_right) * m_speed * deltaTime; else if (direction == MovementDirection::RIGHT) m_position += m_right * m_speed * deltaTime; else if (direction == MovementDirection::UP) m_position += m_up * m_speed * deltaTime; else if (direction == MovementDirection::DOWN) m_position += (-m_up) * m_speed * deltaTime; update(); return *this; } inline float clocksToSeconds(clock_t clocks) { return float(clocks) / float(CLOCKS_PER_SEC); } LookAt& rotate(float deltaX, float deltaY) { m_yaw += deltaX * m_sensitivity; m_pitch += deltaY * m_sensitivity; update(); return *this; } LookAt& setRotateSpeed(float sensitivity) { m_sensitivity = sensitivity; return *this; } float getSensitivity() { return m_sensitivity; } LookAt& setViewMatrix(glm::mat4 matrix) { m_view_matrix = matrix; return *this; } glm::mat4 getViewMatrix() { return m_view_matrix; } }; class Projection { public: const float FOVY_MIN = 0.1f; const float FOVY_MAX = 179.9f; enum ProjectionType { ORTHO, FRUSTUM, PERSPECTIVE }; private: ProjectionType m_projection_type; float m_fovy; float m_aspect; float m_left; float m_right; float m_bottom; float m_top; float m_near; float m_far; glm::mat4 m_projection_matrix; public: Projection(float near_plane = 0.1f, float far_plane = 100.0f) { m_near = near_plane; m_far = far_plane; m_projection_type = Projection::PERSPECTIVE; m_projection_matrix = glm::mat4(1.0f); } Projection(float fovy, float aspect, float near_plane = 0.1f, float far_plane = 100.0f) { m_fovy = fovy; m_aspect = aspect; m_near = near_plane; m_far = far_plane; m_projection_type = Projection::PERSPECTIVE; m_projection_matrix = glm::mat4(1.0f); } Projection(float l, float r, float b, float t, float n = 0.1f, float f = 100.0f) { m_left = l; m_right = r; m_bottom = b; m_top = t; m_near = n; m_far = f; m_projection_type = Projection::PERSPECTIVE; m_projection_matrix = glm::mat4(1.0f); } public: Projection& operator=(const Projection& projection) { m_projection_type = projection.m_projection_type; m_fovy = projection.m_fovy; m_aspect = projection.m_aspect; m_left = projection.m_left; m_right = projection.m_right; m_bottom = projection.m_bottom; m_top = projection.m_top; m_near = projection.m_near; m_far = projection.m_far; m_projection_matrix = projection.m_projection_matrix; return *this; } public: Projection& setProjectionType(ProjectionType type) { m_projection_type = type; return *this; } ProjectionType getProjectionType() { return m_projection_type; } Projection& setFovy(float fovy) { m_fovy = fovy; update(); return *this; } Projection& zoom(float degree) { m_fovy += degree; update(); return *this; } float getFovy() { return m_fovy; } Projection& setAspect(float aspect) { m_aspect = aspect; update(); return *this; } float getAspect() { return m_aspect; } Projection& set(float l, float r, float b, float t, float n = 0.1f, float f = 100.0f) { m_left = l; m_right = r; m_bottom = b; m_top = t; m_near = n; m_far = f; update(); return *this; } Projection& set(float fovy, float aspect, float near_plane = 0.1f, float far_plane = 100.0f) { m_fovy = fovy; m_aspect = aspect; m_near = near_plane; m_far = far_plane; update(); return *this; } Projection& update() { if (m_fovy < FOVY_MIN) m_fovy = FOVY_MIN; else if (m_fovy > FOVY_MAX) m_fovy = FOVY_MAX; if (m_projection_type == ProjectionType::ORTHO) m_projection_matrix = glm::ortho(m_left, m_right, m_bottom, m_top, m_near, m_far); else if (m_projection_type == ProjectionType::FRUSTUM) m_projection_matrix = glm::frustum(m_left, m_right, m_bottom, m_top, m_near, m_far); else if (m_projection_type == ProjectionType::PERSPECTIVE) m_projection_matrix = glm::perspective(m_fovy, m_aspect, m_near, m_far); return *this; } Projection& setProjectionMatrix(glm::mat4 matrix) { m_projection_matrix = matrix; return *this; } glm::mat4 getProjectionMatrix() { return m_projection_matrix; } }; class Camera : public LookAt, public Projection { public: Camera() : LookAt(), Projection() {} Camera(glm::vec3 position, glm::vec3 front, glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)) : LookAt(position, front, up), Projection() {} Camera(glm::vec3 position, float yaw, float pitch, glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)) : LookAt(position, yaw, pitch, up), Projection() {} }; } #endif
最后才是今天的主角
#ifndef __SIMPLEGL_GLFWUTILS_HPP__ #define __SIMPLEGL_GLFWUTILS_HPP__ #include "SimpleGL.hpp" #include简单的示例#include namespace SimpleGL { class GLFWUtils { public: static void processInput(GLFWwindow* window, Camera& camera, float deltaTime) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.move(SimpleGL::Camera::MovementDirection::FORWARD, deltaTime); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.move(SimpleGL::Camera::MovementDirection::BACKWARD, deltaTime); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.move(SimpleGL::Camera::MovementDirection::LEFT, deltaTime); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.move(SimpleGL::Camera::MovementDirection::RIGHT, deltaTime); if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) camera.move(SimpleGL::Camera::MovementDirection::UP, deltaTime); if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) camera.move(SimpleGL::Camera::MovementDirection::DOWN, deltaTime); if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_PRESS) { float speed = camera.getMovementSpeed(); speed -= 0.01f; speed = std::max(speed, 0.1f); camera.setMovementSpeed(SimpleGL::Camera::MovementSpeed::CUSTOM, speed); } else if (glfwGetKey(window, GLFW_KEY_F2) == GLFW_PRESS) { float speed = camera.getMovementSpeed(); speed += 0.01f; speed = std::min(speed, 5.0f); camera.setMovementSpeed(SimpleGL::Camera::MovementSpeed::CUSTOM, speed); } } static void processCursor(Camera& camera, glm::vec2& lastPos, glm::vec2 currentPos, bool& isFirst) { if (isFirst) { lastPos = currentPos; isFirst = false; } glm::vec2 delta = currentPos - lastPos; lastPos = currentPos; camera.rotate(-delta.x, delta.y); } static void processResize(Camera& camera, int width, int height) { camera.setAspect(float(width) / float(height)); glViewport(0, 0, width, height); } static void processScroll(Camera& camera, float offset) { camera.zoom(offset); } template static T* getUserData(GLFWwindow* window) { return (T*)glfwGetWindowUserPointer(window); } static GLFWwindow* initWindow_FullScreen(std::string title, int major = 3, int minor = 3) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* videomode = glfwGetVideoMode(monitor); GLFWwindow* window = glfwCreateWindow(videomode->width, videomode->height, title.data(), monitor, NULL); glfwMakeContextCurrent(window); return window; } static void disableCursor(GLFWwindow* window) { if (window != nullptr) glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); } static void calcDeltaTime(float& lastTime, float& deltaTime) { float currentTime = glfwGetTime(); deltaTime = currentTime - lastTime; lastTime = currentTime; } template static T* newUserData(GLFWwindow* window) { T* data = new T; glfwSetWindowUserPointer(window, data); return data; } }; } #endif
最最最后是一个简单的示例
//#define USE_GLFW #include "SimpleGL/SimpleGL.hpp" #include运行结果#include class RenderableSprite : public SimpleGL::Sprite { public: GLuint VAO; GLuint count; GLenum mode; public: RenderableSprite() { VAO = 0; count = 0; mode = GL_TRIANGLES; } ~RenderableSprite() { glDeleteVertexArrays(1, &VAO); } public: RenderableSprite& render(SimpleGL::Program& program) { program.setUniform("u_model", getModelMatrix()); glBindVertexArray(VAO); glDrawArrays(mode, 0, count); glBindVertexArray(0); return *this; } }; struct Data { SimpleGL::Camera camera; SimpleGL::Program program; GLuint FBO; GLuint texture; RenderableSprite axis; RenderableSprite model; bool isFirst; glm::vec2 lastPos; float lastTime; float deltaTime; }; void processInput(GLFWwindow* window); void cursor_pos(GLFWwindow* window, double x, double y); void framebuffer_size(GLFWwindow* window, int width, int height); void scroll(GLFWwindow* window,double x,double y); int main() { glfwInit(); GLFWwindow* window = SimpleGL::GLFWUtils::initWindow_FullScreen("OpenGL 3.3"); glfwSetCursorPosCallback(window, cursor_pos); glfwSetFramebufferSizeCallback(window, framebuffer_size); glfwSetScrollCallback(window,scroll); SimpleGL::GLFWUtils::disableCursor(window); if (!SimpleGL::initGL()) { std::cout << "Failed to init GL." << std::endl; return -1; } glEnable(GL_DEPTH_TEST); Data* data = SimpleGL::GLFWUtils::newUserData(window); data->isFirst = true; data->lastTime = glfwGetTime(); data->camera.setPosition(glm::vec3(1, 1, 1)); data->camera.setFront(glm::vec3(-1, -1, -1)); data->camera.set(60, 1); bool success = data->program.loadProgramFromFile("shader/vertex.vert", "shader/lighting.frag"); if (!success) { std::cout << "Failed to load program." << std::endl; std::cout << data->program.getError() << std::endl; return -1; } GLfloat axis_ver[] = { -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 axis_col[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GLuint axis_vao; GLuint axis_vbo[2]; glGenVertexArrays(1, &axis_vao); glGenBuffers(2, axis_vbo); glBindVertexArray(axis_vao); glBindBuffer(GL_ARRAY_BUFFER, axis_vbo[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(axis_ver), axis_ver, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); glBindBuffer(GL_ARRAY_BUFFER, axis_vbo[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(axis_col), axis_col, GL_STATIC_DRAW); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(2, axis_vbo); RenderableSprite axis; axis.VAO = axis_vao; axis.count = sizeof(axis_ver) / sizeof(float) / 3; axis.mode = GL_LINES; data->axis = axis; while (!glfwWindowShouldClose(window)) { SimpleGL::GLFWUtils::calcDeltaTime(data->lastTime,data->deltaTime); processInput(window); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); data->program.useProgram(); data->program.setUniform("u_projection", data->camera.getProjectionMatrix()); data->program.setUniform("u_view", data->camera.getViewMatrix()); data->program.setUniform("u_cameraposition", data->camera.getPosition()); data->program.setUniform("u_enableUniformColor", false); data->program.setUniform("u_enableTexture", false); data->program.setUniform("u_enableLighting", false); data->axis.render(data->program); glfwSwapBuffers(window); glfwPollEvents(); } delete data; glfwTerminate(); return 0; } void processInput(GLFWwindow* window) { Data* data = SimpleGL::GLFWUtils::getUserData(window); SimpleGL::GLFWUtils::processInput(window,data->camera,data->deltaTime); } void cursor_pos(GLFWwindow* window, double x, double y) { Data* data = SimpleGL::GLFWUtils::getUserData(window); glm::vec2 currentPos = glm::vec2(x, y); SimpleGL::GLFWUtils::processCursor(data->camera,data->lastPos,currentPos,data->isFirst); } void framebuffer_size(GLFWwindow* window, int width, int height) { Data* data = SimpleGL::GLFWUtils::getUserData(window); SimpleGL::GLFWUtils::processResize(data->camera,width,height); } void scroll(GLFWwindow* window,double x,double y) { Data* data = SimpleGL::GLFWUtils::getUserData(window); SimpleGL::GLFWUtils::processScroll(data->camera,y); }
结果就算了,就一坐标轴


![[C++] [OpenGL] GLFW工具类 [C++] [OpenGL] GLFW工具类](http://www.mshxw.com/aiimages/31/849644.png)
