xcal
基于 C++23 的现代图形渲染引擎
载入中...
搜索中...
未找到
opengl_render.cc
浏览该文件的文档.
2//
3#include <xcal/public.h>
4
5#include <cstddef>
6#include <cstdio>
7#include <memory>
16#include <xcmath/utils/show.hpp>
17
18//
19#ifdef GL_BACKEND_GLBINDING
20# include <glbinding-aux/ContextInfo.h>
21# include <glbinding/gl/functions.h>
22# include <glbinding/glbinding.h>
23#endif
24
25//
26#include <GLFW/glfw3.h>
27
28#undef OUT // undefine OUT macro to avoid conflict with xcal::OUT
29#define ROLE OpenGL
30#define LABEL OpenGLRender
32
33void framebuffer_size_callback(GLFWwindow* window, int w, int h) {
35 glfwGetWindowUserPointer(window))
36 ->framebuffer_size_callback(window, w, h);
37}
38
40#ifdef GL_BACKEND_GLBINDING
41 glbinding::initialize(glfwGetProcAddress, false);
42#elif defined(GL_BACKEND_GLAD)
43 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
44 throw std::runtime_error("Failed to initialize GLAD");
45 }
46#else
47# error "No OpenGL backend defined"
48#endif
49}
50
52 : xcal::render::Render(scene),
53 ui_render_(nullptr),
54 default_camera_(std::make_unique<xcal::camera::PerspectiveCamera>(
55 45.0, 16 / 9.0, 0.1, 1000.0)),
56 current_camera_(default_camera_.get()) {
57 _I("OpenGLRender created: " _SELF);
58 setup_glfw();
59 setup_gl();
60 ui_render_ = std::make_unique<ui::ListUi>(
61 std::make_unique<ui::ImGuiGlfw3OpenGL3Backend>(window_), this);
62 ui_render_->init();
63 setup_scene();
64}
66 ui_render_->deinit();
67 objects_.clear();
68
69 if (window_) {
70 glfwDestroyWindow(window_);
71 window_ = nullptr;
72 }
73 glfwTerminate();
74 _I("OpenGLRender destroyed: " _SELF);
75};
76void xcal::render::opengl::OpenGLRender::show(int width, int height) {
77 if (!window_) {
78 _E("GLFW window is not created");
79 return;
80 }
81 glfwSetWindowSize(window_, width, height);
82 glfwMakeContextCurrent(window_);
83 for (auto& obj : objects_) {
84 obj.second->create();
85 }
86 ::framebuffer_size_callback(window_, width, height);
87 _I("show loop started");
88 while (!glfwWindowShouldClose(window_)) {
89 glfwPollEvents();
90 ui_render_->render_();
91
92 _gl glClear(_gl GL_COLOR_BUFFER_BIT | _gl GL_DEPTH_BUFFER_BIT);
93 render_frame();
94 ui_render_->before_swap_buffers();
95 glfwSwapBuffers(window_);
96 }
97 _I("show loop ended");
98 _I("destroying objects");
99 for (auto& obj : objects_) obj.second->destroy();
100 _I("objects destroyed ");
101}
103 if (playing_timeline_ && !playing_timeline_->finished()) {
104 if (auto n = std::chrono::high_resolution_clock::now();
105 n - last_time_point_ >
106 std::chrono::milliseconds(
107 size_t(1000 / playing_timeline_->frame_rate()))) {
108 playing_timeline_->next();
109 last_time_point_ = n;
110 }
111 }
112 if (current_camera_) {
113 if (current_camera_->should_update()) {
114 for (auto& obj : objects_) {
115 _D("updating object: " << obj.first
116 << " with camera: " << current_camera_);
117 _D("pvurcurrent_camera_atrix: "
118 << current_camera_->pv_matrix());
119 obj.second->update_projection_view(
120 current_camera_->pv_matrix());
121 }
122 }
123 }
124 for (const auto& obj : objects_) {
125 auto& obj_ptr = obj.second;
126 if (obj_ptr) {
127 obj_ptr->render();
128 }
129 }
130};
132 Render::set_scene(scene);
133 setup_scene();
134};
135void xcal::render::opengl::OpenGLRender::setup_scene() {
136 _I("setup_scene" << scene());
137 objects_.clear();
138 if (!scene()) {
139 _W("scene is null");
140 return;
141 }
142 _D("Number of mobjects in scene: " << scene()->mobjects().size());
143 for (auto& obj : scene()->mobjects()) {
144 _D("Processing mobject: " << obj.get());
145 auto obj_ptr = object::create(obj.get());
146 if (!obj_ptr) {
147 _E("Failed to create object for " << obj.get());
148 continue;
149 }
150 objects_.insert({obj.get(), std::move(obj_ptr)});
151 }
152 ui_render_->flush();
153};
155 int w,
156 int h) {
157 // aspect_ = w / static_cast<float>(h);
158 if (default_camera_->type() == camera::CameraType::Perspective) {
159 auto* cam = static_cast<xcal::camera::PerspectiveCamera*>(
160 default_camera_.get());
161 cam->set_aspect((float_t)w / static_cast<float>(h));
162 }
163
164 // _D("framebuffer_size_callback: " << w << "x" << h);
165 // 计算保持宽高比的视口尺寸
166 float target_aspect =
167 (current_camera_->type() == camera::CameraType::Perspective)
168 ? ((const camera::PerspectiveCamera*)current_camera_)
169 ->aspect()
170 .value()
171 : (float_t)w / static_cast<float>(h);
172 int viewport_width = w;
173 int viewport_height = h;
174 int viewport_x = 0;
175 int viewport_y = 0;
176
177 // 计算实际宽高比
178 float actual_aspect = static_cast<float>(w) / static_cast<float>(h);
179
180 if (actual_aspect > target_aspect) {
181 // 窗口太宽,上下加黑边
182 viewport_width = static_cast<int>((float_t)h * target_aspect);
183 viewport_height = h;
184 viewport_x = (w - viewport_width) / 2;
185 viewport_y = 0;
186 } else {
187 // 窗口太高,左右加黑边
188 viewport_width = w;
189 viewport_height = static_cast<int>((float_t)w / target_aspect);
190 viewport_x = 0;
191 viewport_y = (h - viewport_height) / 2;
192 }
193
194 // 设置视口
195 _gl glViewport(viewport_x, viewport_y, viewport_width, viewport_height);
196 _gl glClearColor(current_camera_->background_color().r(),
197 current_camera_->background_color().g(),
198 current_camera_->background_color().b(),
199 current_camera_->background_color().a());
200
201 // _D("Viewport set to: " << viewport_x << ", " << viewport_y << ", "
202 // << viewport_width << ", " << viewport_height);
203}
205 _gl GLint width, height;
206 glfwGetFramebufferSize(window_, &width, &height);
207 std::vector<char> pixels(width * height * 4); // RGBA
208 _gl glReadPixels(0, 0, width, height, _gl GL_RGBA, _gl GL_UNSIGNED_BYTE,
209 pixels.data());
210 std::cerr << "Read: " << width << "x" << height << " pixels\n";
211 return pixels;
212}
213void xcal::render::opengl::OpenGLRender::setup_glfw() {
214 glfwInit();
215 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
216 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
217 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
218 window_ = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr);
219 if (window_ == nullptr) {
220 glfwTerminate();
221 _D("Failed to create GLFW window");
222 throw std::runtime_error("Failed to create GLFW window");
223 }
224 glfwMakeContextCurrent(window_);
225 if (!enable_window_dark_titlebar(window_)) {
226 _D("Failed to enable dark titlebar");
227 }
228 glfwSetWindowUserPointer(window_, this);
229};
230void xcal::render::opengl::OpenGLRender::setup_gl() {
232 _gl glEnable(_gl GL_DEPTH_TEST);
233 _gl glDepthFunc(_gl GL_LESS);
234 _gl glEnable(_gl GL_BLEND);
235 _gl glBlendFunc(_gl GL_SRC_ALPHA, _gl GL_ONE_MINUS_SRC_ALPHA);
236 glfwSetFramebufferSizeCallback(window_, ::framebuffer_size_callback);
237};
239 animation::Timeline* timeline) {
240 if (playing_timeline_ && !playing_timeline_->finished()) return false;
241 _I("play_timeline: " << timeline);
242 playing_timeline_ = std::make_unique<animation::TimelineDriver>(timeline);
243 playing_timeline_->ready_to_play();
244 return true;
245}
抽象相机基类
PerspectiveCamera * set_aspect(float aspect)
设置宽高比
void framebuffer_size_callback(GLFWwindow *window, int w, int h)
std::vector< char > read_pixels_char() const
void show(int width=800, int height=600)
bool_t play_timeline(animation::Timeline *timeline)
void set_scene(Scene *scene) override
@ Perspective
透视相机
xcal::render::opengl::object::object_ptr create(T *mobject)
bool bool_t
Definition public.h:28
float float_t
Definition public.h:27
void init_glbackend()
Definition opengl.cc:52
void framebuffer_size_callback(GLFWwindow *window, int w, int h)
Definition opengl.cc:17
void init_glbackend()
void framebuffer_size_callback(GLFWwindow *window, int w, int h)
透视相机类
struct GLFWwindow GLFWwindow
Definition typedef.hpp:6