From 892a97c62cbf8dbfa2dc0f4aa438a94758e34d61 Mon Sep 17 00:00:00 2001 From: ZhuohaoHe Date: Mon, 16 Sep 2024 11:29:33 -0400 Subject: [PATCH] update camera system & implement swap buffer and real-time display Signed-off-by: ZhuohaoHe --- src/include/buffer.hpp | 39 ++++++++++++----- src/include/renderer.h | 14 +++---- src/renderer.cpp | 31 +++++++++----- test/system_test/camera.h | 81 +++++++++++++++++++++++++----------- test/system_test/display.cpp | 15 +++---- test/system_test/display.h | 10 ++--- test/system_test/main.cpp | 55 ++++++++++++------------ 7 files changed, 148 insertions(+), 97 deletions(-) diff --git a/src/include/buffer.hpp b/src/include/buffer.hpp index 877cf7a..bf21ad7 100644 --- a/src/include/buffer.hpp +++ b/src/include/buffer.hpp @@ -1,6 +1,7 @@ #ifndef SIMPLERENDER_SRC_INCLUDE_BUFFER_HPP_ #define SIMPLERENDER_SRC_INCLUDE_BUFFER_HPP_ +#include #include #include "math.hpp" @@ -35,29 +36,45 @@ class Buffer { Buffer(size_t width, size_t height) : width_(width), height_(height), - size_(width * height), - framebuffer_(new uint32_t[size_](), std::default_delete()), - matrix_(1.0f) {} + size_(width_ * height_), + framebuffer_1_(new uint32_t[size_](), + std::default_delete()), + framebuffer_2_(new uint32_t[size_](), + std::default_delete()) { + ClearBuffer(framebuffer_1_.get()); + ClearBuffer(framebuffer_2_.get()); + drawBuffer_ = framebuffer_1_.get(); + displayBuffer_ = framebuffer_2_.get(); + } + + void ClearDrawBuffer(Color color) { ClearBuffer(drawBuffer_, color); } - uint32_t* GetFramebuffer() { return framebuffer_.get(); } + void SwapBuffer() { std::swap(drawBuffer_, displayBuffer_); } + + uint32_t* GetDisplayBuffer() { return displayBuffer_; } + uint32_t* GetDrawBuffer() { return drawBuffer_; } uint32_t& operator[](size_t index) { if (index >= size_) { throw std::out_of_range("Index out of range"); } - return framebuffer_.get()[index]; + return drawBuffer_[index]; } - const Matrix4f& GetMatrix() const { return matrix_; } - - void SetMatrix(const Matrix4f& matrix) { matrix_ = matrix; } - private: size_t width_; size_t height_; size_t size_; - std::shared_ptr framebuffer_; - Matrix4f matrix_; + std::unique_ptr framebuffer_1_; + std::unique_ptr framebuffer_2_; + uint32_t* drawBuffer_; + uint32_t* displayBuffer_; + + void ClearBuffer(uint32_t* buffer, Color color) { + std::fill(buffer, buffer + size_, uint32_t(color)); + } + + void ClearBuffer(uint32_t* buffer) { std::fill(buffer, buffer + size_, 0); } }; } // namespace simple_renderer diff --git a/src/include/renderer.h b/src/include/renderer.h index 7f5583e..d4c865d 100755 --- a/src/include/renderer.h +++ b/src/include/renderer.h @@ -33,9 +33,6 @@ namespace simple_renderer { class SimpleRenderer { public: - typedef std::function - DrawPixelFunc; - /** * 构造函数 * @param width @@ -43,8 +40,7 @@ class SimpleRenderer { * @param buffer 要进行绘制的内存区域,大小为 width*height*sizeof(uint32_t) * @param */ - SimpleRenderer(size_t width, size_t height, uint32_t *buffer, - DrawPixelFunc draw_pixel_func); + SimpleRenderer(size_t width, size_t height); /// @name 默认构造/析构函数 /// @{ @@ -57,14 +53,12 @@ class SimpleRenderer { virtual ~SimpleRenderer() = default; /// @} - bool render(const Model &model, const Shader &shader); + bool Render(const Model &model, const Shader &shader, uint32_t *buffer); private: const size_t height_; const size_t width_; - uint32_t *buffer_; std::shared_ptr depth_buffer_; - DrawPixelFunc draw_pixel_func_; LogSystem log_system_; std::shared_ptr shader_; @@ -74,7 +68,9 @@ class SimpleRenderer { * 绘制模型 * @param model 模型 */ - void DrawModel(const Model &model); + void DrawModel(const Model &model, uint32_t *buffer); + + void ClearDepthBuffer(); }; } // namespace simple_renderer diff --git a/src/renderer.cpp b/src/renderer.cpp index c9df35c..b24175b 100755 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -32,29 +32,31 @@ namespace simple_renderer { -SimpleRenderer::SimpleRenderer(size_t width, size_t height, uint32_t *buffer, - DrawPixelFunc draw_pixel_func) +SimpleRenderer::SimpleRenderer(size_t width, size_t height) : height_(height), width_(width), - buffer_(buffer), - draw_pixel_func_(draw_pixel_func), log_system_(LogSystem(kLogFilePath, kLogFileMaxSize, kLogFileMaxCount)) { rasterizer_ = std::make_shared(width, height); // init depth buffer depth_buffer_ = std::shared_ptr(new float[width * height], std::default_delete()); - std::fill(depth_buffer_.get(), depth_buffer_.get() + width * height, - std::numeric_limits::infinity()); } -bool SimpleRenderer::render(const Model &model, const Shader &shader) { +bool SimpleRenderer::Render(const Model &model, const Shader &shader, + uint32_t *buffer) { SPDLOG_INFO("render model: {}", model.GetModelPath()); + ClearDepthBuffer(); shader_ = std::make_shared(shader); - DrawModel(model); + DrawModel(model, buffer); return true; } -void SimpleRenderer::DrawModel(const Model &model) { +void SimpleRenderer::ClearDepthBuffer() { + std::fill(depth_buffer_.get(), depth_buffer_.get() + width_ * height_, + std::numeric_limits::infinity()); +} + +void SimpleRenderer::DrawModel(const Model &model, uint32_t *buffer) { SPDLOG_INFO("draw {}", model.GetModelPath()); std::vector processedVertex; @@ -83,19 +85,26 @@ void SimpleRenderer::DrawModel(const Model &model) { auto v0 = processedVertex[f.GetIndex(0)]; auto v1 = processedVertex[f.GetIndex(1)]; auto v2 = processedVertex[f.GetIndex(2)]; + /* * * Rasterization * * */ auto fragments = rasterizer_->Rasterize(v0, v1, v2); - // material + shader_->SetUniform("material", f.GetMaterial()); + for (const auto &fragment : fragments) { size_t x = fragment.screen_coord[0]; size_t y = fragment.screen_coord[1]; + + if (x >= width_ || y >= height_) { + continue; + } + if (fragment.depth < depth_buffer_[x + y * width_]) { depth_buffer_[x + y * width_] = fragment.depth; /* * * Fragment Shader * * */ auto color = shader_->FragmentShader(fragment); - draw_pixel_func_(x, y, color, buffer_); + buffer[x + y * width_] = static_cast(color); } } } diff --git a/test/system_test/camera.h b/test/system_test/camera.h index d64693d..e5aa89f 100644 --- a/test/system_test/camera.h +++ b/test/system_test/camera.h @@ -25,33 +25,66 @@ namespace simple_renderer { -/** - * camera 抽象 - */ +#pragma once + +#include +#include +#include + class Camera { public: - /// 光照名称 - std::string name_ = "default light name"; - /// 位置 - Vector3f pos_; - /// 方向 - Vector3f dir_; - - /** - * 构造函数 - * @param _name camera 名称 - */ - explicit Camera(const std::string &_name); - - /// @name 默认构造/析构函数 - /// @{ - Camera() = default; - Camera(const Camera &light) = default; - Camera(Camera &&light) = default; - auto operator=(const Camera &light) -> Camera & = default; - auto operator=(Camera &&light) -> Camera & = default; + Camera(Vector3f position) + : position_(position), front_(0.0f, 0.0f, -1.0f), up_(0.0f, 1.0f, 0.0f) {} + + Camera(const Camera& camera) = default; + Camera(Camera&& camera) = default; + auto operator=(const Camera& camera) -> Camera& = default; + auto operator=(Camera&& camera) -> Camera& = default; ~Camera() = default; - /// @} + + // Getters and Setters + void SetPosition(const glm::vec3& pos) { position_ = pos; } + void SetFront(const glm::vec3& frontVec) { + front_ = glm::normalize(frontVec); + } + void SetUp(const glm::vec3& upVec) { up_ = glm::normalize(upVec); } + + glm::vec3 GetPosition() const { return position_; } + glm::vec3 GetFront() const { return front_; } + glm::vec3 GetUp() const { return up_; } + + // Methods to get view and projection matrices + glm::mat4 GetViewMatrix() const { + return glm::lookAt(position_, position_ + front_, up_); + } + + glm::mat4 GetProjectionMatrix(float fov, float aspectRatio, float nearPlane, + float farPlane) const { + return glm::perspective(glm::radians(fov), aspectRatio, nearPlane, + farPlane); + } + + // Additional methods for camera movement (optional) + void MoveForward(float distance) { position_ += front_ * distance; } + + void MoveRight(float distance) { + position_ += glm::normalize(glm::cross(front_, up_)) * distance; + } + + void MoveUp(float distance) { position_ += up_ * distance; } + + void Rotate(float yaw, float pitch) { + glm::vec3 newFront; + newFront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); + newFront.y = sin(glm::radians(pitch)); + newFront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); + front_ = glm::normalize(newFront); + } + + private: + Vector3f position_; + Vector3f front_; + Vector3f up_; }; } // namespace simple_renderer diff --git a/test/system_test/display.cpp b/test/system_test/display.cpp index 777ef41..d2a9b12 100644 --- a/test/system_test/display.cpp +++ b/test/system_test/display.cpp @@ -92,30 +92,31 @@ void Display::loopBegin() { is_exit_ = false; } bool Display::loopShouldClose() { return is_exit_; } -void Display::handleKeyboardEvent(SDL_Event& event) { +void Display::handleKeyboardEvent(SDL_Event& event, + simple_renderer::Camera& camera) { switch (event.key.keysym.sym) { case SDLK_ESCAPE: case SDLK_q: is_exit_ = true; break; case SDLK_UP: - std::cout << "UP" << std::endl; + camera.MoveUp(1.0f); break; case SDLK_DOWN: - std::cout << "DOWN" << std::endl; + camera.MoveUp(-1.0f); break; case SDLK_LEFT: - std::cout << "LEFT" << std::endl; + camera.MoveRight(-1.0f); break; case SDLK_RIGHT: - std::cout << "RIGHT" << std::endl; + camera.MoveRight(1.0f); break; default: break; } } -void Display::handleEvents() { +void Display::handleEvents(simple_renderer::Camera& camera) { SDL_Event event = SDL_Event(); while (SDL_PollEvent(&event) != 0) { switch (event.type) { @@ -123,7 +124,7 @@ void Display::handleEvents() { is_exit_ = true; break; case SDL_KEYDOWN: - handleKeyboardEvent(event); + handleKeyboardEvent(event, camera); break; } } diff --git a/test/system_test/display.h b/test/system_test/display.h index f167540..64160c5 100644 --- a/test/system_test/display.h +++ b/test/system_test/display.h @@ -24,6 +24,7 @@ #include #include "buffer.hpp" +#include "camera.h" /** * 显示抽象 @@ -57,17 +58,12 @@ class Display { */ void fill(const uint32_t *buffer); - /** - * 运行 - */ - void run(); - /** * 显示循环 */ void loopBegin(); - void handleKeyboardEvent(SDL_Event &event); - void handleEvents(); + void handleKeyboardEvent(SDL_Event &event, simple_renderer::Camera &camera); + void handleEvents(simple_renderer::Camera &camera); bool loopShouldClose(); private: diff --git a/test/system_test/main.cpp b/test/system_test/main.cpp index 8d4ed71..f75b29c 100755 --- a/test/system_test/main.cpp +++ b/test/system_test/main.cpp @@ -23,6 +23,7 @@ #include #include "buffer.hpp" +#include "camera.h" #include "display.h" /// @name 默认大小 @@ -31,10 +32,6 @@ static constexpr const size_t kWidth = 800; static constexpr const size_t kHeight = 600; /// @} -static void pixel(size_t x, size_t y, uint32_t color, uint32_t *buffer) { - buffer[x + y * kWidth] = color; -} - /// usage: /// ./bin/system_test ../obj int main(int argc, char **argv) { @@ -43,14 +40,10 @@ int main(int argc, char **argv) { printf("argv[%d]: %s\n", i, argv[i]); } auto obj_path = std::string(argv[1]); - // auto obj_path = std::string( - // "/Users/hezhohao/Programming/GitRepo/SimpleRenderer/obj"); // just for - // debuging simple_renderer::Buffer buffer(kWidth, kHeight); - auto simple_renderer = simple_renderer::SimpleRenderer( - kWidth, kHeight, buffer.GetFramebuffer(), pixel); + auto simple_renderer = simple_renderer::SimpleRenderer(kWidth, kHeight); // obj 路径 std::vector objs; @@ -62,45 +55,51 @@ int main(int argc, char **argv) { models.emplace_back(simple_renderer::Model(obj)); } - auto matrix = simple_renderer::Matrix4f(1.0f); + auto modelMatrix = simple_renderer::Matrix4f(1.0f); simple_renderer::Matrix4f scale_matrix = glm::scale(simple_renderer::Matrix4f(1.0f), - simple_renderer::Vector3f(10.0f, 10.0f, 10.0f)); + simple_renderer::Vector3f(7.0f, 7.0f, 7.0f)); // Translation matrix - simple_renderer::Matrix4f translation_matrix = glm::translate( - simple_renderer::Matrix4f(1.0f), - simple_renderer::Vector3f(kWidth / 2.0f, kHeight / 2.0f, 0.0f)); + simple_renderer::Matrix4f translation_matrix = + glm::translate(simple_renderer::Matrix4f(1.0f), + simple_renderer::Vector3f(30.0f, 30.0f, 0.0f)); simple_renderer::Matrix4f rotation_matrix = glm::rotate(simple_renderer::Matrix4f(1.0f), 90.0f, simple_renderer::Vector3f(1.0f, 0.0f, 0.0f)); // Combined transformation matrix - matrix = translation_matrix * scale_matrix * rotation_matrix; + modelMatrix = scale_matrix * translation_matrix * rotation_matrix; simple_renderer::Shader shader; - shader.SetUniform("modelMatrix", matrix); - shader.SetUniform("viewMatrix", simple_renderer::Matrix4f(1.0f)); - shader.SetUniform("projectionMatrix", simple_renderer::Matrix4f(1.0f)); + shader.SetUniform("modelMatrix", modelMatrix); + simple_renderer::Light light; - light.dir = simple_renderer::Vector3f(1.0f, 1.0f, -1.0f); + light.dir = simple_renderer::Vector3f(1.0f, 5.0f, 1.0f); shader.SetUniform("light", light); - // TODO: add complete camera system - shader.SetUniform("cameraPos", simple_renderer::Vector3f(0.0f, 0.0f, 0.0f)); - - for (auto &model : models) { - simple_renderer.render(model, shader); - } + simple_renderer::Camera camera(simple_renderer::Vector3f(0.0f, 0.0f, 1.0f)); auto display = Display(kWidth, kHeight); - // TODO: support real-time keyboard event display.loopBegin(); + while (!display.loopShouldClose()) { - display.handleEvents(); + display.handleEvents(camera); + + shader.SetUniform("cameraPos", camera.GetPosition()); + shader.SetUniform("viewMatrix", camera.GetViewMatrix()); + shader.SetUniform("projectionMatrix", + camera.GetProjectionMatrix(60.0f, 1.0f, 0.1f, 100.0f)); + + buffer.ClearDrawBuffer(simple_renderer::Color::kBlack); + for (auto &model : models) { + simple_renderer.Render(model, shader, buffer.GetDrawBuffer()); + } + + buffer.SwapBuffer(); - display.fill(buffer.GetFramebuffer()); + display.fill(buffer.GetDisplayBuffer()); } return 0;