From e85d5888513644c40bc6bf3b5276ab5ff241a2ff Mon Sep 17 00:00:00 2001 From: milek7 Date: Tue, 12 Mar 2019 00:53:34 +0100 Subject: [PATCH] multi viewports (temporaily disable VAO) --- Globals.cpp | 11 ++ Globals.h | 9 ++ application.cpp | 28 ++++- application.h | 4 +- gl/bindable.h | 4 +- gl/buffer.cpp | 2 +- gl/buffer.h | 2 +- gl/vao.cpp | 62 +++++++-- gl/vao.h | 30 ++++- openglgeometrybank.cpp | 9 +- precipitation.cpp | 8 +- renderer.cpp | 280 +++++++++++++++++++++++------------------ renderer.h | 28 +++-- skydome.cpp | 10 +- 14 files changed, 314 insertions(+), 173 deletions(-) diff --git a/Globals.cpp b/Globals.cpp index 9cb7eaf3..067606c2 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -833,6 +833,17 @@ global_settings::ConfigParse(cParser &Parser) { Parser >> network_client->first; Parser >> network_client->second; } + else if (token == "extraviewport") + { + Parser.getTokens(3 + 16, false); + + extraviewport_config conf; + Parser >> conf.monitor >> conf.width >> conf.height; + for (size_t i = 0; i < 16; i++) + Parser >> conf.transform[i / 4][i % 4]; + + extra_viewports.push_back(conf); + } } while ((token != "") && (token != "endconfig")); //(!Parser->EndOfFile) // na koniec trochę zależności if (!bLoadTraction) // wczytywanie drutów i słupów diff --git a/Globals.h b/Globals.h index 53f490ab..55c2f28e 100644 --- a/Globals.h +++ b/Globals.h @@ -202,6 +202,15 @@ struct global_settings { bool gfx_shadergamma = false; bool gfx_usegles = false; + struct extraviewport_config { + std::string monitor; + int width; + int height; + glm::mat4 transform; + }; + + std::vector extra_viewports; + std::vector> network_servers; std::optional> network_client; diff --git a/application.cpp b/application.cpp index 9298af12..03f64019 100644 --- a/application.cpp +++ b/application.cpp @@ -470,7 +470,7 @@ void eu07_application::on_focus_change(bool focus) { } GLFWwindow * -eu07_application::window( int const Windowindex ) { +eu07_application::window( int const Windowindex, bool visible, int width, int height, GLFWmonitor *monitor ) { if( Windowindex >= 0 ) { return ( @@ -479,14 +479,36 @@ eu07_application::window( int const Windowindex ) { nullptr ); } // for index -1 create a new child window - glfwWindowHint( GLFW_VISIBLE, GL_FALSE ); - auto *childwindow = glfwCreateWindow( 1, 1, "eu07helper", nullptr, m_windows.front() ); + + glfwWindowHint( GLFW_VISIBLE, visible ); + + auto *childwindow = glfwCreateWindow( width, height, "eu07helper", monitor, m_windows.front() ); if( childwindow != nullptr ) { m_windows.emplace_back( childwindow ); } return childwindow; } +GLFWmonitor* eu07_application::find_monitor(const std::string &str) { + int monitor_count; + GLFWmonitor **monitors = glfwGetMonitors(&monitor_count); + + for (size_t i = 0; i < monitor_count; i++) { + std::string name(glfwGetMonitorName(monitors[i])); + std::replace(std::begin(name), std::end(name), ' ', '_'); + + int x, y; + glfwGetMonitorPos(monitors[i], &x, &y); + + std::string desc = name + ":" + std::to_string(x) + "," + std::to_string(y); + + if (desc == str) + return monitors[i]; + } + + return nullptr; +} + // private: void diff --git a/application.h b/application.h index 06416382..a0c743b1 100644 --- a/application.h +++ b/application.h @@ -78,7 +78,9 @@ public: on_focus_change(bool focus); // gives access to specified window, creates a new window if index == -1 GLFWwindow * - window( int const Windowindex = 0 ); + window(int const Windowindex = 0 , bool visible = false, int width = 1, int height = 1, GLFWmonitor *monitor = nullptr); + GLFWmonitor * + find_monitor(const std::string &str); // generate network sync verification number double generate_sync(); diff --git a/gl/bindable.h b/gl/bindable.h index 30e1cf8c..b845dadb 100644 --- a/gl/bindable.h +++ b/gl/bindable.h @@ -6,7 +6,7 @@ namespace gl class bindable { protected: - static bindable* active; + thread_local static bindable* active; public: void bind() @@ -23,5 +23,5 @@ namespace gl } }; - template bindable* bindable::active; + template thread_local bindable* bindable::active; } diff --git a/gl/buffer.cpp b/gl/buffer.cpp index b8be8d50..512176ab 100644 --- a/gl/buffer.cpp +++ b/gl/buffer.cpp @@ -79,4 +79,4 @@ void gl::buffer::download(targets target, void *data, int offset, int size) } } -GLuint gl::buffer::binding_points[13]; +thread_local GLuint gl::buffer::binding_points[13]; diff --git a/gl/buffer.h b/gl/buffer.h index 602d8e28..13f73699 100644 --- a/gl/buffer.h +++ b/gl/buffer.h @@ -7,7 +7,7 @@ namespace gl { class buffer : public object { - static GLuint binding_points[13]; + thread_local static GLuint binding_points[13]; public: enum targets diff --git a/gl/vao.cpp b/gl/vao.cpp index a07ec47b..88a2149c 100644 --- a/gl/vao.cpp +++ b/gl/vao.cpp @@ -1,24 +1,72 @@ #include "stdafx.h" #include "vao.h" +/* gl::vao::vao() { - glGenVertexArrays(1, *this); + glGenVertexArrays(1, *this); } gl::vao::~vao() { - glDeleteVertexArrays(1, *this); + glDeleteVertexArrays(1, *this); } -void gl::vao::setup_attrib(int attrib, int size, int type, int stride, int offset) +void gl::vao::setup_attrib(gl::buffer &buffer, int attrib, int size, int type, int stride, int offset) { - bind(); - glVertexAttribPointer(attrib, size, type, GL_FALSE, stride, reinterpret_cast(offset)); - glEnableVertexAttribArray(attrib); + bind(); + buffer.bind(gl::buffer::ARRAY_BUFFER); + glVertexAttribPointer(attrib, size, type, GL_FALSE, stride, reinterpret_cast(offset)); + glEnableVertexAttribArray(attrib); + +} + +void gl::vao::setup_ebo(buffer &ebo) +{ + bind(); + ebo.bind(gl::buffer::ELEMENT_ARRAY_BUFFER); } void gl::vao::bind(GLuint i) { - glBindVertexArray(i); + glBindVertexArray(i); +} +*/ + +void gl::vao::setup_attrib(gl::buffer &buffer, int attrib, int size, int type, int stride, int offset) +{ + params.push_back({buffer, attrib, size, type, stride, offset}); + active = nullptr; +} + +void gl::vao::setup_ebo(buffer &e) +{ + ebo = &e; + active = nullptr; +} + +void gl::vao::bind() +{ + if (active == this) + return; + active = this; + + for (attrib_params ¶m : params) { + param.buffer.bind(gl::buffer::ARRAY_BUFFER); + glVertexAttribPointer(param.attrib, param.size, param.type, GL_FALSE, param.stride, reinterpret_cast(param.offset)); + glEnableVertexAttribArray(param.attrib); + } + + for (size_t i = params.size(); i < 4; i++) + glDisableVertexAttribArray(i); + + if (ebo) + ebo->bind(gl::buffer::ELEMENT_ARRAY_BUFFER); + else + gl::buffer::unbind(gl::buffer::ELEMENT_ARRAY_BUFFER); +} + +void gl::vao::unbind() +{ + active = nullptr; } diff --git a/gl/vao.h b/gl/vao.h index fd9a60b3..16ea06a8 100644 --- a/gl/vao.h +++ b/gl/vao.h @@ -2,18 +2,36 @@ #include "object.h" #include "bindable.h" +#include "buffer.h" namespace gl { - class vao : public object, public bindable + class vao : public bindable { + struct attrib_params { + // TBD: should be shared_ptr? (when buffer is destroyed by owner VAO could still potentially exist) + gl::buffer &buffer; + + int attrib; + int size; + int type; + int stride; + int offset; + }; + buffer *ebo = nullptr; + + std::vector params; + public: - vao(); - ~vao(); + //vao(); + //~vao(); - void setup_attrib(int attrib, int size, int type, int stride, int offset); + void setup_attrib(buffer &buffer, int attrib, int size, int type, int stride, int offset); + void setup_ebo(buffer &ebo); - using bindable::bind; - static void bind(GLuint i); + //using bindable::bind; + void bind(); + static void unbind(); + //static void bind(GLuint i); }; } diff --git a/openglgeometrybank.cpp b/openglgeometrybank.cpp index 54582bbb..bc0c20ef 100644 --- a/openglgeometrybank.cpp +++ b/openglgeometrybank.cpp @@ -280,13 +280,12 @@ void opengl_vbogeometrybank::setup_buffer() if (!m_vao) { m_vao.emplace(); - m_buffer->bind(gl::buffer::ARRAY_BUFFER); - m_vao->setup_attrib(0, 3, GL_FLOAT, sizeof(basic_vertex), 0 * sizeof(GL_FLOAT)); + m_vao->setup_attrib(*m_buffer, 0, 3, GL_FLOAT, sizeof(basic_vertex), 0 * sizeof(GL_FLOAT)); // NOTE: normal and color streams share the data - m_vao->setup_attrib(1, 3, GL_FLOAT, sizeof(basic_vertex), 3 * sizeof(GL_FLOAT)); - m_vao->setup_attrib(2, 2, GL_FLOAT, sizeof(basic_vertex), 6 * sizeof(GL_FLOAT)); - m_vao->setup_attrib(3, 4, GL_FLOAT, sizeof(basic_vertex), 8 * sizeof(GL_FLOAT)); + m_vao->setup_attrib(*m_buffer, 1, 3, GL_FLOAT, sizeof(basic_vertex), 3 * sizeof(GL_FLOAT)); + m_vao->setup_attrib(*m_buffer, 2, 2, GL_FLOAT, sizeof(basic_vertex), 6 * sizeof(GL_FLOAT)); + m_vao->setup_attrib(*m_buffer, 3, 4, GL_FLOAT, sizeof(basic_vertex), 8 * sizeof(GL_FLOAT)); m_buffer->unbind(gl::buffer::ARRAY_BUFFER); m_vao->unbind(); diff --git a/precipitation.cpp b/precipitation.cpp index 19eb0695..d119e768 100644 --- a/precipitation.cpp +++ b/precipitation.cpp @@ -186,20 +186,18 @@ basic_precipitation::render() { m_vertexbuffer->allocate(gl::buffer::ARRAY_BUFFER, m_vertices.size() * sizeof( glm::vec3 ), GL_STATIC_DRAW); m_vertexbuffer->upload(gl::buffer::ARRAY_BUFFER, m_vertices.data(), 0, m_vertices.size() * sizeof( glm::vec3 )); - m_vertexbuffer->bind(gl::buffer::ARRAY_BUFFER); - m_vao->setup_attrib(0, 3, GL_FLOAT, sizeof(glm::vec3), 0); + m_vao->setup_attrib(*m_vertexbuffer, 0, 3, GL_FLOAT, sizeof(glm::vec3), 0); m_uvbuffer.emplace(); m_uvbuffer->allocate(gl::buffer::ARRAY_BUFFER, m_uvs.size() * sizeof( glm::vec2 ), GL_STATIC_DRAW); m_uvbuffer->upload(gl::buffer::ARRAY_BUFFER, m_uvs.data(), 0, m_uvs.size() * sizeof( glm::vec2 )); - m_uvbuffer->bind(gl::buffer::ARRAY_BUFFER); - m_vao->setup_attrib(1, 2, GL_FLOAT, sizeof(glm::vec2), 0); + m_vao->setup_attrib(*m_uvbuffer, 1, 2, GL_FLOAT, sizeof(glm::vec2), 0); m_indexbuffer.emplace(); m_indexbuffer->allocate(gl::buffer::ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof( unsigned short ), GL_STATIC_DRAW); m_indexbuffer->upload(gl::buffer::ELEMENT_ARRAY_BUFFER, m_indices.data(), 0, m_indices.size() * sizeof( unsigned short )); - m_indexbuffer->bind(gl::buffer::ELEMENT_ARRAY_BUFFER); + m_vao->setup_ebo(*m_indexbuffer); m_vao->unbind(); // NOTE: vertex and index source data is superfluous past this point, but, eh diff --git a/renderer.cpp b/renderer.cpp index 8d6c7ff0..0dda7c04 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -64,13 +64,6 @@ bool opengl_camera::visible(TDynamicObject const *Dynamic) const void opengl_camera::draw(glm::vec3 const &Offset) const { // m7t port to core gl - /* - ::glBegin( GL_LINES ); - for( auto const pointindex : frustumshapepoinstorder ) { - ::glVertex3fv( glm::value_ptr( glm::vec3{ m_frustumpoints[ pointindex ] } - Offset ) ); - } - ::glEnd(); - */ } bool opengl_renderer::Init(GLFWwindow *Window) @@ -82,33 +75,6 @@ bool opengl_renderer::Init(GLFWwindow *Window) m_window = Window; - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - glClearColor(51.0f / 255.0f, 102.0f / 255.0f, 85.0f / 255.0f, 1.0f); // initial background Color - - glFrontFace(GL_CCW); - glEnable(GL_CULL_FACE); - - glEnable(GL_DEPTH_TEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - - if (!Global.gfx_usegles) - glClearDepth(0.0f); - else - glClearDepthf(0.0f); - - glDepthFunc(GL_GEQUAL); - - if (GLAD_GL_ARB_clip_control) - glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); - else if (GLAD_GL_EXT_clip_control) - glClipControlEXT(GL_LOWER_LEFT_EXT, GL_ZERO_TO_ONE_EXT); - - if (!Global.gfx_usegles) - glEnable(GL_PROGRAM_POINT_SIZE); - gl::glsl_common_setup(); if (true == Global.ScaleSpecularValues) @@ -127,7 +93,6 @@ bool opengl_renderer::Init(GLFWwindow *Window) // create dynamic light pool for (int idx = 0; idx < Global.DynamicLightCount; ++idx) { - opengl_light light; light.id = 1 + idx; @@ -199,23 +164,71 @@ bool opengl_renderer::Init(GLFWwindow *Window) viewport_config &default_viewport = *m_viewports.front().get(); default_viewport.width = Global.gfx_framebuffer_width; default_viewport.height = Global.gfx_framebuffer_height; + default_viewport.main = true; + default_viewport.window = m_window; - /* - default_viewport.camera_transform = glm::rotate(glm::mat4(), 0.5f, glm::vec3(1.0f, 0.0f, 0.f)); - - m_viewports.push_back(std::make_unique()); - viewport_config &vp2 = *m_viewports.back().get(); - vp2.width = Global.gfx_framebuffer_width; - vp2.height = Global.gfx_framebuffer_height; - - vp2.camera_transform = glm::rotate(glm::mat4(), -0.5f, glm::vec3(1.0f, 0.0f, 0.f)); - */ + for (const global_settings::extraviewport_config &conf : Global.extra_viewports) { + m_viewports.push_back(std::make_unique()); + viewport_config &vp = *m_viewports.back().get(); + vp.width = conf.width; + vp.height = conf.height; + vp.window = Application.window(-1, true, vp.width, vp.height, Application.find_monitor(conf.monitor)); + vp.camera_transform = conf.transform; + std::cout << "ZXZ " << glm::to_string(vp.camera_transform) << std::endl; + } for (auto &viewport : m_viewports) { if (!init_viewport(*viewport.get())) return false; } + glfwMakeContextCurrent(m_window); + + if (Global.gfx_shadowmap_enabled) + { + m_shadow_fb = std::make_unique(); + m_shadow_tex = std::make_unique(); + m_shadow_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize); + m_shadow_fb->attach(*m_shadow_tex, GL_DEPTH_ATTACHMENT); + + if (!m_shadow_fb->is_complete()) + return false; + + WriteLog("shadows enabled"); + + m_cabshadows_fb = std::make_unique(); + m_cabshadows_tex = std::make_unique(); + m_cabshadows_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize); + m_cabshadows_fb->attach(*m_cabshadows_tex, GL_DEPTH_ATTACHMENT); + + if (!m_cabshadows_fb->is_complete()) + return false; + + WriteLog("cabshadows enabled"); + } + + if (Global.gfx_envmap_enabled) + { + m_env_rb = std::make_unique(); + m_env_rb->alloc(Global.gfx_format_depth, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE); + m_env_tex = std::make_unique(); + m_env_tex->alloc(Global.gfx_format_color, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE, GL_RGB, GL_FLOAT); + + m_env_fb = std::make_unique(); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + for (int i = 0; i < 6; i++) + { + m_env_fb->attach(*m_empty_cubemap, i, GL_COLOR_ATTACHMENT0); + m_env_fb->clear(GL_COLOR_BUFFER_BIT); + } + + m_env_fb->detach(GL_COLOR_ATTACHMENT0); + m_env_fb->attach(*m_env_rb, GL_DEPTH_ATTACHMENT); + + WriteLog("envmap enabled"); + } + m_pick_tex = std::make_unique(); m_pick_tex->alloc_rendertarget(GL_RGB8, GL_RGB, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE); m_pick_rb = std::make_unique(); @@ -290,8 +303,49 @@ bool opengl_renderer::Init(GLFWwindow *Window) bool opengl_renderer::init_viewport(viewport_config &vp) { + glfwMakeContextCurrent(vp.window); + + WriteLog("init viewport: " + std::to_string(vp.width) + ", " + std::to_string(vp.height)); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + glClearColor(51.0f / 255.0f, 102.0f / 255.0f, 85.0f / 255.0f, 1.0f); // initial background Color + + glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + + glEnable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!Global.gfx_usegles) + glClearDepth(0.0f); + else + glClearDepthf(0.0f); + + glDepthFunc(GL_GEQUAL); + + if (GLAD_GL_ARB_clip_control) + glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); + else if (GLAD_GL_EXT_clip_control) + glClipControlEXT(GL_LOWER_LEFT_EXT, GL_ZERO_TO_ONE_EXT); + + if (!Global.gfx_usegles) + glEnable(GL_PROGRAM_POINT_SIZE); + + { + GLuint v; + glGenVertexArrays(1, &v); + glBindVertexArray(v); + } + int samples = 1 << Global.iMultisampling; + model_ubo->bind_uniform(); + scene_ubo->bind_uniform(); + light_ubo->bind_uniform(); + if (!Global.gfx_skippipeline) { vp.msaa_rbc = std::make_unique(); @@ -339,49 +393,6 @@ bool opengl_renderer::init_viewport(viewport_config &vp) return false; } - if (Global.gfx_shadowmap_enabled) - { - vp.shadow_fb = std::make_unique(); - vp.shadow_tex = std::make_unique(); - vp.shadow_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize); - vp.shadow_fb->attach(*vp.shadow_tex, GL_DEPTH_ATTACHMENT); - - if (!vp.shadow_fb->is_complete()) - return false; - - vp.cabshadows_fb = std::make_unique(); - vp.cabshadows_tex = std::make_unique(); - vp.cabshadows_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize); - vp.cabshadows_fb->attach(*vp.cabshadows_tex, GL_DEPTH_ATTACHMENT); - - if (!vp.cabshadows_fb->is_complete()) - return false; - - WriteLog("shadows enabled"); - } - - if (Global.gfx_envmap_enabled) - { - vp.env_rb = std::make_unique(); - vp.env_rb->alloc(Global.gfx_format_depth, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE); - vp.env_tex = std::make_unique(); - vp.env_tex->alloc(Global.gfx_format_color, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE, GL_RGB, GL_FLOAT); - - vp.env_fb = std::make_unique(); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - for (int i = 0; i < 6; i++) - { - vp.env_fb->attach(*m_empty_cubemap, i, GL_COLOR_ATTACHMENT0); - vp.env_fb->clear(GL_COLOR_BUFFER_BIT); - } - - vp.env_fb->detach(GL_COLOR_ATTACHMENT0); - vp.env_fb->attach(*vp.env_rb, GL_DEPTH_ATTACHMENT); - - WriteLog("envmap enabled"); - } - return true; } @@ -432,7 +443,9 @@ bool opengl_renderer::Render() for (auto &viewport : m_viewports) { Render_pass(*viewport.get(), rendermode::color); } - //Render_pass(*m_viewports.front().get(), rendermode::color); + + glfwMakeContextCurrent(m_window); + m_current_viewport = &(*m_viewports.front()); m_drawcount = m_cellqueue.size(); m_debugtimestext.clear(); @@ -466,7 +479,12 @@ bool opengl_renderer::Render() void opengl_renderer::SwapBuffers() { Timer::subsystem.gfx_swap.start(); - glfwSwapBuffers(m_window); + + for (auto &viewport : m_viewports) { + if (viewport->window) + glfwSwapBuffers(viewport->window); + } + // swapbuffers() could unbind current buffers so we prepare for it on our end gfx::opengl_vbogeometrybank::reset(); Timer::subsystem.gfx_swap.stop(); @@ -505,8 +523,15 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) { glDebug("rendermode::color"); + glDebug("context switch"); + glfwMakeContextCurrent(vp.window); + m_current_viewport = &vp; + if (!simulation::is_ready) { + if (!vp.main) + break; + gl::framebuffer::unbind(); glClearColor(0.0f, 0.5f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -532,7 +557,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) setup_shadow_map(nullptr, m_renderpass); setup_env_map(nullptr); - if (Global.gfx_shadowmap_enabled) + if (Global.gfx_shadowmap_enabled && vp.main) { glDebug("render shadowmap start"); Timer::subsystem.gfx_shadows.start(); @@ -546,12 +571,12 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glDebug("render shadowmap end"); } - if (Global.gfx_envmap_enabled) + if (Global.gfx_envmap_enabled && vp.main) { // potentially update environmental cube map if (Render_reflections(vp)) setup_pass(vp, m_renderpass, Mode); // restore color pass settings - setup_env_map(vp.env_tex.get()); + setup_env_map(m_env_tex.get()); } glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -566,7 +591,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) else vp.msaa_fb->setup_drawing(1); - glViewport(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height); + glViewport(0, 0, vp.width, vp.height); vp.msaa_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -575,7 +600,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) if (!Global.gfx_usegles && !Global.gfx_shadergamma) glEnable(GL_FRAMEBUFFER_SRGB); glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, Global.iWindowWidth, Global.iWindowHeight); + glViewport(0, 0, vp.width, vp.height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } @@ -610,7 +635,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) { glDebug("render cab opaque"); if (Global.gfx_shadowmap_enabled) - setup_shadow_map(vp.cabshadows_tex.get(), m_cabshadowpass); + setup_shadow_map(m_cabshadows_tex.get(), m_cabshadowpass); auto const *vehicle = simulation::Train->Dynamic(); Render_cab(vehicle, vehicle->InteriorLightLevel, false); @@ -621,7 +646,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) model_ubs.future = future; if (Global.gfx_shadowmap_enabled) - setup_shadow_map(vp.shadow_tex.get(), m_shadowpass); + setup_shadow_map(m_shadow_tex.get(), m_shadowpass); Render(simulation::Region); @@ -639,7 +664,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glDebug("render translucent cab"); model_ubs.future = glm::mat4(); if (Global.gfx_shadowmap_enabled) - setup_shadow_map(vp.cabshadows_tex.get(), m_cabshadowpass); + setup_shadow_map(m_cabshadows_tex.get(), m_cabshadowpass); // cache shadow colour in case we need to account for cab light auto const *vehicle{simulation::Train->Dynamic()}; if (Global.Overcast > 1.0f) @@ -665,8 +690,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) if (Global.gfx_postfx_motionblur_enabled) { vp.main_fb->clear(GL_COLOR_BUFFER_BIT); - vp.msaa_fb->blit_to(vp.main_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0); - vp.msaa_fb->blit_to(vp.main_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT1); + vp.msaa_fb->blit_to(vp.main_fb.get(), vp.width, vp.height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0); + vp.msaa_fb->blit_to(vp.main_fb.get(), vp.width, vp.height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT1); model_ubs.param[0].x = m_framerate / (1.0 / Global.gfx_postfx_motionblur_shutter); model_ubo->update(model_ubs); @@ -675,12 +700,12 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) else { vp.main2_fb->clear(GL_COLOR_BUFFER_BIT); - vp.msaa_fb->blit_to(vp.main2_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0); + vp.msaa_fb->blit_to(vp.main2_fb.get(), vp.width, vp.height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0); } if (!Global.gfx_usegles && !Global.gfx_shadergamma) glEnable(GL_FRAMEBUFFER_SRGB); - glViewport(0, 0, Global.iWindowWidth, Global.iWindowHeight); + glViewport(0, 0, vp.width, vp.height); m_pfx_tonemapping->apply(*vp.main2_tex, nullptr); opengl_texture::reset_unit_cache(); } @@ -691,8 +716,10 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glDebug("uilayer render"); Timer::subsystem.gfx_gui.start(); - draw_debug_ui(); - Application.render_ui(); + if (vp.main) { + draw_debug_ui(); + Application.render_ui(); + } Timer::subsystem.gfx_gui.stop(); @@ -716,8 +743,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glEnable(GL_DEPTH_TEST); glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize); - vp.shadow_fb->bind(); - vp.shadow_fb->clear(GL_DEPTH_BUFFER_BIT); + m_shadow_fb->bind(); + m_shadow_fb->clear(GL_DEPTH_BUFFER_BIT); setup_matrices(); setup_drawing(false); @@ -734,7 +761,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glDisable(GL_POLYGON_OFFSET_FILL); - vp.shadow_fb->unbind(); + m_shadow_fb->unbind(); glDebug("rendermodeshadows ::end"); @@ -751,8 +778,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glEnable(GL_DEPTH_TEST); glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize); - vp.cabshadows_fb->bind(); - vp.cabshadows_fb->clear(GL_DEPTH_BUFFER_BIT); + m_cabshadows_fb->bind(); + m_cabshadows_fb->clear(GL_DEPTH_BUFFER_BIT); setup_matrices(); setup_drawing(false); @@ -766,7 +793,7 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) glDisable(GL_POLYGON_OFFSET_FILL); - vp.cabshadows_fb->unbind(); + m_cabshadows_fb->unbind(); glDebug("rendermode::cabshadows end"); @@ -783,8 +810,8 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) // NOTE: buffer attachment and viewport setup in this mode is handled by the wrapper method glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - vp.env_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - vp.env_fb->bind(); + m_env_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_env_fb->bind(); setup_env_map(m_empty_cubemap.get()); @@ -800,13 +827,13 @@ void opengl_renderer::Render_pass(viewport_config &vp, rendermode const Mode) // opaque parts... setup_drawing(false); - setup_shadow_map(vp.shadow_tex.get(), m_shadowpass); + setup_shadow_map(m_shadow_tex.get(), m_shadowpass); scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION); scene_ubo->update(scene_ubs); Render(simulation::Region); - vp.env_fb->unbind(); + m_env_fb->unbind(); glDebug("rendermode::reflections end"); @@ -891,12 +918,12 @@ bool opengl_renderer::Render_reflections(viewport_config &vp) glViewport(0, 0, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE); for (m_environmentcubetextureface = 0; m_environmentcubetextureface < 6; ++m_environmentcubetextureface) { - vp.env_fb->attach(*vp.env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0); - if (vp.env_fb->is_complete()) + m_env_fb->attach(*m_env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0); + if (m_env_fb->is_complete()) Render_pass(vp, rendermode::reflections); } - vp.env_tex->generate_mipmaps(); - vp.env_fb->detach(GL_COLOR_ATTACHMENT0); + m_env_tex->generate_mipmaps(); + m_env_fb->detach(GL_COLOR_ATTACHMENT0); return true; } @@ -1720,7 +1747,7 @@ void opengl_renderer::Render(scene::basic_region *Region) Render(std::begin(m_sectionqueue), std::end(m_sectionqueue)); // draw queue is filled while rendering sections - if (EditorModeFlag) + if (EditorModeFlag && m_current_viewport->main) { // when editor mode is active calculate world position of the cursor // at this stage the z-buffer is filled with only ground geometry @@ -3430,6 +3457,11 @@ void opengl_renderer::Render_Alpha(TSubModel *Submodel) // utility methods void opengl_renderer::Update_Pick_Control() { + // context-switch workaround + gl::buffer::unbind(gl::buffer::PIXEL_PACK_BUFFER); + gl::buffer::unbind(gl::buffer::PIXEL_UNPACK_BUFFER); + gl::buffer::unbind(gl::buffer::ARRAY_BUFFER); + if (!m_picking_pbo->is_busy()) { unsigned char pickreadout[4]; @@ -3548,11 +3580,11 @@ glm::dvec3 opengl_renderer::get_mouse_depth() } else { - gl::framebuffer::blit(m_current_viewport->msaa_fb.get(), m_depth_pointer_fb.get(), bufferpos.x, bufferpos.y, 1, 1, GL_DEPTH_BUFFER_BIT, 0); + gl::framebuffer::blit(m_viewports.front()->msaa_fb.get(), m_depth_pointer_fb.get(), bufferpos.x, bufferpos.y, 1, 1, GL_DEPTH_BUFFER_BIT, 0); m_depth_pointer_fb->bind(); m_depth_pointer_pbo->request_read(0, 0, 1, 1, 4, GL_DEPTH_COMPONENT, GL_FLOAT); - m_current_viewport->msaa_fb->bind(); + m_viewports.front()->msaa_fb->bind(); } } else @@ -3577,7 +3609,7 @@ glm::dvec3 opengl_renderer::get_mouse_depth() } else { - gl::framebuffer::blit(m_current_viewport->msaa_fb.get(), m_depth_pointer_fb.get(), 0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_DEPTH_BUFFER_BIT, 0); + gl::framebuffer::blit(m_viewports.front()->msaa_fb.get(), m_depth_pointer_fb.get(), 0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_DEPTH_BUFFER_BIT, 0); m_empty_vao->bind(); m_depth_pointer_tex->bind(0); @@ -3587,7 +3619,7 @@ glm::dvec3 opengl_renderer::get_mouse_depth() m_depth_pointer_pbo->request_read(bufferpos.x, bufferpos.y, 1, 1, 16, GL_RGBA_INTEGER, GL_UNSIGNED_INT); m_depth_pointer_shader->unbind(); m_empty_vao->unbind(); - m_current_viewport->msaa_fb->bind(); + m_viewports.front()->msaa_fb->bind(); } } @@ -3893,7 +3925,7 @@ bool opengl_renderer::Init_caps() if (Global.gfx_framebuffer_height == -1) Global.gfx_framebuffer_height = Global.iWindowHeight; - WriteLog("rendering at " + std::to_string(Global.gfx_framebuffer_width) + "x" + std::to_string(Global.gfx_framebuffer_height)); + WriteLog("main window size: " + std::to_string(Global.gfx_framebuffer_width) + "x" + std::to_string(Global.gfx_framebuffer_height)); return true; } diff --git a/renderer.h b/renderer.h index 74027361..32847f4c 100644 --- a/renderer.h +++ b/renderer.h @@ -239,6 +239,9 @@ class opengl_renderer int width; int height; + bool main = false; + GLFWwindow *window = nullptr; + glm::mat4 camera_transform; std::unique_ptr msaa_fb; @@ -252,18 +255,10 @@ class opengl_renderer std::unique_ptr main2_fb; std::unique_ptr main2_tex; - - std::unique_ptr shadow_fb; - std::unique_ptr shadow_tex; - - std::unique_ptr cabshadows_fb; - std::unique_ptr cabshadows_tex; - - std::unique_ptr env_fb; - std::unique_ptr env_rb; - std::unique_ptr env_tex; }; + viewport_config *m_current_viewport = nullptr; + typedef std::vector opengllight_array; // methods @@ -315,7 +310,7 @@ class opengl_renderer void draw_debug_ui(); // members - GLFWwindow *m_window{nullptr}; + GLFWwindow *m_window{nullptr}; // main window gfx::geometrybank_manager m_geometry; material_manager m_materials; texture_manager m_textures; @@ -355,7 +350,6 @@ class opengl_renderer float m_fogrange = 2000.0f; renderpass_config m_renderpass; // parameters for current render pass - viewport_config *m_current_viewport; // active viewport section_sequence m_sectionqueue; // list of sections in current render pass cell_sequence m_cellqueue; renderpass_config m_colorpass; // parametrs of most recent color pass @@ -415,6 +409,16 @@ class opengl_renderer std::unique_ptr m_empty_cubemap; + std::unique_ptr m_cabshadows_fb; + std::unique_ptr m_cabshadows_tex; + + std::unique_ptr m_env_fb; + std::unique_ptr m_env_rb; + std::unique_ptr m_env_tex; + + std::unique_ptr m_shadow_fb; + std::unique_ptr m_shadow_tex; + std::unique_ptr m_picking_pbo; std::unique_ptr m_picking_node_pbo; diff --git a/skydome.cpp b/skydome.cpp index fc7c47f3..d6da2def 100644 --- a/skydome.cpp +++ b/skydome.cpp @@ -132,22 +132,20 @@ void CSkyDome::Render() { m_vertexbuffer->allocate(gl::buffer::ARRAY_BUFFER, m_vertices.size() * sizeof( glm::vec3 ), GL_STATIC_DRAW); m_vertexbuffer->upload(gl::buffer::ARRAY_BUFFER, m_vertices.data(), 0, m_vertices.size() * sizeof( glm::vec3 )); - m_vertexbuffer->bind(gl::buffer::ARRAY_BUFFER); - m_vao->setup_attrib(0, 3, GL_FLOAT, sizeof(glm::vec3), 0); + m_vao->setup_attrib(*m_vertexbuffer, 0, 3, GL_FLOAT, sizeof(glm::vec3), 0); m_coloursbuffer.emplace(); m_coloursbuffer->allocate(gl::buffer::ARRAY_BUFFER, m_colours.size() * sizeof( glm::vec3 ), GL_STATIC_DRAW); m_coloursbuffer->upload(gl::buffer::ARRAY_BUFFER, m_colours.data(), 0, m_colours.size() * sizeof( glm::vec3 )); - m_coloursbuffer->bind(gl::buffer::ARRAY_BUFFER); - m_vao->setup_attrib(1, 3, GL_FLOAT, sizeof(glm::vec3), 0); + m_vao->setup_attrib(*m_coloursbuffer, 1, 3, GL_FLOAT, sizeof(glm::vec3), 0); m_indexbuffer.emplace(); m_indexbuffer->allocate(gl::buffer::ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof( unsigned short ), GL_STATIC_DRAW); m_indexbuffer->upload(gl::buffer::ELEMENT_ARRAY_BUFFER, m_indices.data(), 0, m_indices.size() * sizeof( unsigned short )); - m_indexbuffer->bind(gl::buffer::ELEMENT_ARRAY_BUFFER); + m_vao->setup_ebo(*m_indexbuffer); - m_vao->unbind(); + m_vao->unbind(); } m_shader->bind();