19#ifdef GL_BACKEND_GLBINDING
20# include <glbinding-aux/ContextInfo.h>
21# include <glbinding/gl/functions.h>
22# include <glbinding/glbinding.h>
26#include <GLFW/glfw3.h>
30#define LABEL OpenGLRender
35 glfwGetWindowUserPointer(window))
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");
47# error "No OpenGL backend defined"
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);
60 ui_render_ = std::make_unique<ui::ListUi>(
61 std::make_unique<ui::ImGuiGlfw3OpenGL3Backend>(window_),
this);
70 glfwDestroyWindow(window_);
74 _I(
"OpenGLRender destroyed: " _SELF);
78 _E(
"GLFW window is not created");
81 glfwSetWindowSize(window_, width, height);
82 glfwMakeContextCurrent(window_);
83 for (
auto& obj : objects_) {
87 _I(
"show loop started");
88 while (!glfwWindowShouldClose(window_)) {
90 ui_render_->render_();
92 _gl glClear(_gl GL_COLOR_BUFFER_BIT | _gl GL_DEPTH_BUFFER_BIT);
94 ui_render_->before_swap_buffers();
95 glfwSwapBuffers(window_);
97 _I(
"show loop ended");
98 _I(
"destroying objects");
99 for (
auto& obj : objects_) obj.second->destroy();
100 _I(
"objects destroyed ");
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;
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());
124 for (
const auto& obj : objects_) {
125 auto& obj_ptr = obj.second;
135void xcal::render::opengl::OpenGLRender::setup_scene() {
136 _I(
"setup_scene" << scene());
142 _D(
"Number of mobjects in scene: " << scene()->mobjects().size());
143 for (
auto& obj : scene()->mobjects()) {
144 _D(
"Processing mobject: " << obj.get());
147 _E(
"Failed to create object for " << obj.get());
150 objects_.insert({obj.get(), std::move(obj_ptr)});
160 default_camera_.get());
166 float target_aspect =
171 : (
float_t)w /
static_cast<float>(h);
172 int viewport_width = w;
173 int viewport_height = h;
178 float actual_aspect =
static_cast<float>(w) /
static_cast<float>(h);
180 if (actual_aspect > target_aspect) {
182 viewport_width =
static_cast<int>((
float_t)h * target_aspect);
184 viewport_x = (w - viewport_width) / 2;
189 viewport_height =
static_cast<int>((
float_t)w / target_aspect);
191 viewport_y = (h - viewport_height) / 2;
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());
205 _gl GLint width, height;
206 glfwGetFramebufferSize(window_, &width, &height);
207 std::vector<char> pixels(width * height * 4);
208 _gl glReadPixels(0, 0, width, height, _gl GL_RGBA, _gl GL_UNSIGNED_BYTE,
210 std::cerr <<
"Read: " << width <<
"x" << height <<
" pixels\n";
213void xcal::render::opengl::OpenGLRender::setup_glfw() {
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) {
221 _D(
"Failed to create GLFW window");
222 throw std::runtime_error(
"Failed to create GLFW window");
224 glfwMakeContextCurrent(window_);
225 if (!enable_window_dark_titlebar(window_)) {
226 _D(
"Failed to enable dark titlebar");
228 glfwSetWindowUserPointer(window_,
this);
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);
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();
PerspectiveCamera * set_aspect(float aspect)
设置宽高比
virtual void set_scene(Scene *scene)
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)
OpenGLRender(Scene *scene)
bool_t play_timeline(animation::Timeline *timeline)
void set_scene(Scene *scene) override
xcal::render::opengl::object::object_ptr create(T *mobject)
void framebuffer_size_callback(GLFWwindow *window, int w, int h)
void framebuffer_size_callback(GLFWwindow *window, int w, int h)
struct GLFWwindow GLFWwindow