mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 13:19:20 +02:00
Today's work on the binary scene format plan (binary-scene-format-plan.md), from the first measurement to a terrain that bakes itself on first run and streams from a thread. The step-by-step history is kept on backup/scene-streaming-format-presquash-0916. Measuring first. -loadprofile times a scenery load by stage and by node kind and reports node counts and resident memory. On l204 terrain is 95% of the bytes and 99.8% of the nodes; on quarkmce2007 vehicles, not models, dominate what is left. The terrain turned out to be a heightfield in all but name, a ribbon covering 12% of its bounding box. The heightfield. scene/heightfieldformat.h is the .ehf layout: Morton-ordered tiles of 128 samples with one shared edge sample, a point-sampled mip chain, zstd per tile, a nodata sentinel, a material palette with a measured tiling per material, and a stamp of the rules that decided what counted as terrain. scene/heightfieldreader.h reads it for the tool, the renderer and the loader alike, and scene/terraincooker.h writes it, shared by the terraincook tool and the engine so a first-run bake is the file the tool would have made. The cooker rasterises every triangle where it is drawn (through scene::place_in_world, the placement the region applies too), keeps an upper surface laid within half a metre over another and the lower of two further apart, and then asks each triangle whether the heightfield shows it: laid, reaching a sample, keeping nearly all it claimed, and with the ground around it drawn at every level out to 2 km. Baking on first run. simulation/terrainbake bakes <scenario>.ehf the first time a scenery is opened, choosing the grid step from the first 200,000 vertices, and on later loads leaves out the triangles its node table says the heightfield shows. Everything else - trees, grass tufts, gantries, bridge decks - is drawn as written, so a bad bake can at worst draw something twice, and the heightfield sits 2 cm under the triangles so the original wins there. Nodes are keyed by file, line, include parameters and placement; an edited file changes its keys and those nodes are drawn again. A bake under older rules, or without its table, is thrown away and redone. A launcher copy named $scenario shares the scenario's files. -nobaketerrain shows the triangles as written. A scenery can still name hand-cooked fields, several at different steps. Drawing and streaming. rendering/terrainclipmap draws resident tiles at the mip level their distance earns, deriving the grid from gl_VertexID and texturing in world space with the scenery's own materials. rendering/terraintileloader reads and decodes tiles on a thread of its own; the renderer rescans what is in range only after moving a quarter of a tile, asks for what is missing nearest first, uploads at most 32 tiles a frame, drops arrivals the camera has moved past, and keeps drawing a tile at the level it has until the right one arrives. The terrain has its own range, terrainrange in the ini and a slider in the debug panel, 20 km by default and independent of basedrawrange; the far plane of an ordinary view is pushed out to it. The debug panel shows the range, tiles in view, on the gpu, wanted and queued, and how many sit at each level. Events. The event queue moved out of the events into a binary heap with a deterministic tie-break, and an event is handed its activator instead of storing it, so basic_event is a definition and nothing else. The logic container. scene/logicformat.h and scene/logiccontainer write a scenery's events, their targets and sibling chains as flat, deterministic arrays with a schema hash that refuses a mismatched build. simulation/logiccook cooks it from the loaded state whenever it is missing, stale or unreadable, reads it straight back to check it, and resolves each target to a position in the registry its event kind searches. -cooklogic forces a cook, -verifylogic only checks. Nothing reads it at load yet. Prefabs. scene/prefab describes a signal by the aspects it can show - lights, speeds, animation channels, a sound - instead of pasting an .inc per variant, and expands an instance to ordinary scenery text. Tried on a light signal and a shape signal. Screenshots without a person present: -shot x,y,z[,yaw[,pitch]], -shotsettle, -shotstay.
568 lines
22 KiB
C++
568 lines
22 KiB
C++
module;
|
|
#include <chrono>
|
|
#include <deque>
|
|
#include <limits>
|
|
#include <mutex>
|
|
#include <sstream>
|
|
#include <type_traits>
|
|
#include <ostream>
|
|
#include "glad/glad.h"
|
|
#include <GLFW/glfw3.h>
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include "utilities/Globals_macros.h"
|
|
|
|
export module eu07.rendering.opengl33renderer;
|
|
import eu07.gl.vao;
|
|
import eu07.utilities.color;
|
|
import eu07.glm;
|
|
import eu07.global_include.interfaces.imaterial;
|
|
import eu07.global_include.interfaces.itexture;
|
|
import eu07.model.material;
|
|
import eu07.model.texture;
|
|
import eu07.rendering.geometrybank;
|
|
import eu07.utilities.classes;
|
|
import eu07.vehicle.camera;
|
|
import eu07.utilities.globals;
|
|
import eu07.rendering.renderer;
|
|
import eu07.rendering.openglcamera;
|
|
import eu07.rendering.opengl33light;
|
|
import eu07.rendering.opengl33particles;
|
|
import eu07.rendering.opengl33skydome;
|
|
import eu07.rendering.terrainclipmap;
|
|
import eu07.rendering.terrainstatus;
|
|
import eu07.rendering.opengl33precipitation;
|
|
import eu07.simulation.simulationenvironment;
|
|
import eu07.simcore;
|
|
import eu07.rendering.lightarray;
|
|
import eu07.vr.vr_interface;
|
|
import eu07.gl.ubo;
|
|
import eu07.gl.framebuffer;
|
|
import eu07.gl.renderbuffer;
|
|
import eu07.gl.postfx;
|
|
import eu07.gl.shader;
|
|
import eu07.rendering.terrainclipmap;
|
|
import eu07.gl.cubemap;
|
|
import eu07.gl.glsl_common;
|
|
import eu07.gl.pbo;
|
|
import eu07.gl.query;
|
|
|
|
export {
|
|
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
|
|
|
|
// bare-bones render controller, in lack of anything better yet
|
|
class opengl33_renderer : public gfx_renderer {
|
|
public:
|
|
// constructors
|
|
opengl33_renderer() = default;
|
|
// destructor
|
|
~opengl33_renderer() {}
|
|
// methods
|
|
bool
|
|
Init( GLFWwindow *Window ) override;
|
|
void
|
|
Shutdown() override;
|
|
bool
|
|
AddViewport(const global_settings::extraviewport_config &conf) override;
|
|
// main draw call. returns false on error
|
|
bool
|
|
Render() override;
|
|
void
|
|
SwapBuffers() override;
|
|
inline
|
|
float
|
|
Framerate() override { return m_framerate; }
|
|
// geometry methods
|
|
// NOTE: hands-on geometry management is exposed as a temporary measure; ultimately all visualization data should be generated/handled automatically by the renderer itself
|
|
// creates a new geometry bank. returns: handle to the bank or NULL
|
|
gfx::geometrybank_handle
|
|
Create_Bank() override;
|
|
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
|
gfx::geometry_handle Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override;
|
|
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
|
gfx::geometry_handle Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) override;
|
|
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
|
bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override;
|
|
// adds supplied vertex data at the end of specified chunk
|
|
bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override;
|
|
// provides direct access to index data of specfied chunk
|
|
gfx::index_array const &
|
|
Indices( gfx::geometry_handle const &Geometry ) const override;
|
|
// provides direct access to vertex data of specfied chunk
|
|
gfx::vertex_array const &
|
|
Vertices( gfx::geometry_handle const &Geometry ) const override;
|
|
// provides direct access to vertex data of specfied chunk
|
|
gfx::userdata_array const &
|
|
UserData( gfx::geometry_handle const &Geometry ) const override;
|
|
// material methods
|
|
material_handle
|
|
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override;
|
|
void
|
|
Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) override;
|
|
IMaterial const *
|
|
Material( material_handle const Material ) const override;
|
|
// shader methods
|
|
auto Fetch_Shader( std::string const &name ) -> std::shared_ptr<gl::program> override;
|
|
// texture methods
|
|
texture_handle
|
|
Fetch_Texture( std::string const &Filename, bool const Loadnow = true, GLint format_hint = GL_SRGB_ALPHA ) override;
|
|
void
|
|
Bind_Texture( texture_handle const Texture ) override;
|
|
void
|
|
Bind_Texture( std::size_t const Unit, texture_handle const Texture ) override;
|
|
ITexture &
|
|
Texture( texture_handle const Texture ) override;
|
|
ITexture const &
|
|
Texture( texture_handle const Texture ) const override;
|
|
// utility methods
|
|
void
|
|
Pick_Control_Callback( std::function<void( TSubModel const *, const glm::vec2 )> Callback ) override;
|
|
void
|
|
Pick_Node_Callback( std::function<void( scene::basic_node * )> Callback ) override;
|
|
TSubModel const *
|
|
Pick_Control() const override { return m_pickcontrolitem; }
|
|
scene::basic_node const *
|
|
Pick_Node() const override { return m_picksceneryitem; }
|
|
glm::dvec3
|
|
Mouse_Position() const override { return m_worldmousecoordinates; }
|
|
glm::mat4
|
|
Camera_View_Matrix() const override { return glm::mat4( glm::mat3( m_colorpass.pass_camera.modelview() ) ); }
|
|
glm::mat4
|
|
Camera_Projection_Matrix() const override { return m_colorpass.pass_camera.projection(); }
|
|
glm::dvec3
|
|
Camera_Position() const override { return m_colorpass.pass_camera.position(); }
|
|
// maintenance methods
|
|
void
|
|
Update( double const Deltatime ) override;
|
|
bool
|
|
Debug_Ui_State(std::optional<bool>) override;
|
|
void
|
|
Update_Pick_Control() override;
|
|
void
|
|
Update_Pick_Node() override;
|
|
glm::dvec3
|
|
Update_Mouse_Position() override;
|
|
// debug methods
|
|
std::string const &
|
|
info_times() const override;
|
|
std::string const &
|
|
info_stats() const override;
|
|
void MakeScreenshot() override;
|
|
|
|
|
|
|
|
opengl_material & Material( material_handle const Material );
|
|
opengl_material const & Material( TSubModel const * Submodel ) const;
|
|
// draws supplied geometry handles
|
|
void Draw_Geometry(std::vector<gfx::geometrybank_handle>::iterator begin, std::vector<gfx::geometrybank_handle>::iterator end);
|
|
void Draw_Geometry(const gfx::geometrybank_handle &handle);
|
|
// material methods
|
|
void Bind_Material_Shadow(material_handle const Material);
|
|
void Update_AnimModel(TAnimModel *model);
|
|
|
|
// members
|
|
GLenum static const sunlight{0};
|
|
|
|
static std::unique_ptr<gfx_renderer> create_func();
|
|
|
|
private:
|
|
// types
|
|
enum class rendermode
|
|
{
|
|
none,
|
|
color,
|
|
shadows,
|
|
reflections,
|
|
pickcontrols,
|
|
pickscenery
|
|
};
|
|
|
|
struct debug_stats
|
|
{
|
|
int dynamics{0};
|
|
int models{0};
|
|
int submodels{0};
|
|
int paths{0};
|
|
int traction{0};
|
|
int shapes{0};
|
|
int lines{0};
|
|
int particles{0};
|
|
int drawcalls{0};
|
|
int instanced_drawcalls{0}; // drawcalls issued via instanced render path (one per TModel3d batch)
|
|
int instances{0}; // total instances drawn via instanced render path
|
|
int triangles{0};
|
|
|
|
debug_stats& operator+=( const debug_stats& Right ) {
|
|
dynamics += Right.dynamics;
|
|
models += Right.models;
|
|
submodels += Right.submodels;
|
|
paths += Right.paths;
|
|
traction += Right.traction;
|
|
shapes += Right.shapes;
|
|
lines += Right.lines;
|
|
particles += Right.particles;
|
|
drawcalls += Right.drawcalls;
|
|
instanced_drawcalls += Right.instanced_drawcalls;
|
|
instances += Right.instances;
|
|
return *this; }
|
|
};
|
|
|
|
using section_sequence = std::vector<scene::basic_section *>;
|
|
using distancecell_pair = std::pair<double, scene::basic_cell *>;
|
|
using cell_sequence = std::vector<distancecell_pair>;
|
|
|
|
struct renderpass_config
|
|
{
|
|
opengl_camera pass_camera;
|
|
opengl_camera viewport_camera;
|
|
rendermode draw_mode{rendermode::none};
|
|
float draw_range{0.0f};
|
|
debug_stats draw_stats;
|
|
};
|
|
|
|
struct viewport_config {
|
|
int width;
|
|
int height;
|
|
|
|
float draw_range;
|
|
|
|
bool main = false;
|
|
|
|
GLFWwindow *window = nullptr; // ogl window context
|
|
bool real_window = true; // whether we need to blit onto GLFWwindow surface
|
|
bool custom_backbuffer = false; // whether we want to render to our offscreen LDR backbuffer (pipeline required)
|
|
bool shadow = false; // include this viewport area in shadowmap
|
|
|
|
enum vp_type {
|
|
normal,
|
|
custom,
|
|
vr_left,
|
|
vr_right
|
|
} proj_type;
|
|
viewport_proj_config projection;
|
|
|
|
// main msaa render target for pipeline mode
|
|
std::unique_ptr<gl::framebuffer> msaa_fb;
|
|
std::unique_ptr<gl::renderbuffer> msaa_rbc;
|
|
std::unique_ptr<gl::renderbuffer> msaa_rbv;
|
|
std::unique_ptr<gl::renderbuffer> msaa_rbd;
|
|
|
|
// msaa resolve buffer (when using motion blur)
|
|
std::unique_ptr<gl::framebuffer> main_fb;
|
|
std::unique_ptr<opengl_texture> main_texv;
|
|
std::unique_ptr<opengl_texture> main_texd;
|
|
std::unique_ptr<opengl_texture> main_tex;
|
|
|
|
// final HDR buffer (also serving as msaa resolve buffer when not using motion blur)
|
|
std::unique_ptr<gl::framebuffer> main2_fb;
|
|
std::unique_ptr<opengl_texture> main2_tex;
|
|
|
|
// ssao
|
|
std::unique_ptr<opengl_texture> ssao_tex;
|
|
std::unique_ptr<opengl_texture> ssao_blur_tex;
|
|
std::unique_ptr<gl::framebuffer> ssao_fb;
|
|
std::unique_ptr<gl::framebuffer> ssao_blur_fb;
|
|
|
|
// LDR backbuffer for offscreen rendering
|
|
std::unique_ptr<gl::framebuffer> backbuffer_fb;
|
|
std::unique_ptr<opengl_texture> backbuffer_tex;
|
|
|
|
bool initialized = false;
|
|
};
|
|
|
|
viewport_config *m_current_viewport = nullptr;
|
|
|
|
typedef std::vector<opengl33_light> opengllight_array;
|
|
|
|
// methods
|
|
std::unique_ptr<gl::program> make_shader(std::string v, std::string f);
|
|
bool Init_caps();
|
|
void setup_pass(viewport_config &Viewport, renderpass_config &Config, rendermode const Mode, float const Znear = 0.f, float const Zfar = 1.f, bool const Ignoredebug = false);
|
|
void setup_matrices();
|
|
void setup_drawing(bool const Alpha = false);
|
|
void setup_shadow_unbind_map();
|
|
void setup_shadow_bind_map();
|
|
void setup_shadow_color( glm::vec4 const &Shadowcolor );
|
|
void setup_env_map(gl::cubemap *tex);
|
|
void setup_environment_light(TEnvironmentType const Environment = e_flat);
|
|
void setup_sunlight_intensity( float const Factor = 1.f);
|
|
// runs jobs needed to generate graphics for specified render pass
|
|
void Render_pass(viewport_config &vp, rendermode const Mode);
|
|
// draws the cooked terrain heightfield, if one is open
|
|
void Render_terrain();
|
|
// creates dynamic environment cubemap
|
|
bool Render_reflections(viewport_config &vp);
|
|
bool Render(world_environment *Environment);
|
|
void Render(scene::basic_region *Region);
|
|
void Render(section_sequence::iterator First, section_sequence::iterator Last);
|
|
void Render(cell_sequence::iterator First, cell_sequence::iterator Last);
|
|
void Render(scene::shape_node const &Shape, bool const Ignorerange);
|
|
void Render(TAnimModel *Instance);
|
|
// batched render path for many TAnimModel instances that share the same TModel3d.
|
|
// Caller guarantees every instance has m_instanceable == true (no per-instance lights,
|
|
// no submodel animation, no replacable skins). Each call counts as one
|
|
// instanced_drawcall in draw_stats and contributes Instances.size() to the
|
|
// instances counter. Instances are still individually frustum/distance culled.
|
|
void Render_Instanced( TModel3d *Model, std::vector<TAnimModel *> const &Instances );
|
|
bool Render(TDynamicObject *Dynamic);
|
|
bool Render(TModel3d *Model, material_data const *Material, float const Squaredistance, glm::dvec3 const &Position, glm::vec3 const &Angle);
|
|
bool Render(TModel3d *Model, material_data const *Material, float const Squaredistance);
|
|
void Render(TSubModel *Submodel);
|
|
void Render(TTrack *Track);
|
|
void Render(scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last);
|
|
// renders the per-track sleeper instances (TTrack::m_sleeper_local_transforms) via GPU instancing.
|
|
// caller must already have the camera-relative world-space transform set on the matrix stack.
|
|
// no-op if the track has no sleepermodel, Global.SleeperDistance is 0, or the camera is beyond
|
|
// Global.SleeperDistance from the track origin.
|
|
void Render_Sleepers( TTrack *Track );
|
|
bool Render_cab(TDynamicObject const *Dynamic, float const Lightlevel, bool const Alpha = false);
|
|
bool Render_interior( bool const Alpha = false );
|
|
bool Render_lowpoly( TDynamicObject *Dynamic, float const Squaredistance, bool const Setup, bool const Alpha = false );
|
|
bool Render_coupler_adapter( TDynamicObject *Dynamic, float const Squaredistance, int const End, bool const Alpha = false );
|
|
void Render(TMemCell *Memcell);
|
|
void Render_particles();
|
|
void Render_precipitation();
|
|
void Render_vr_models();
|
|
void Render_Alpha(scene::basic_region *Region);
|
|
void Render_Alpha(cell_sequence::reverse_iterator First, cell_sequence::reverse_iterator Last);
|
|
void Render_Alpha(TAnimModel *Instance);
|
|
void Render_Alpha(TTraction *Traction);
|
|
void Render_Alpha(scene::lines_node const &Lines);
|
|
bool Render_Alpha(TDynamicObject *Dynamic);
|
|
bool Render_Alpha(TModel3d *Model, material_data const *Material, float const Squaredistance, glm::dvec3 const &Position, glm::vec3 const &Angle);
|
|
bool Render_Alpha(TModel3d *Model, material_data const *Material, float const Squaredistance);
|
|
void Render_Alpha(TSubModel *Submodel);
|
|
void Update_Lights(light_array &Lights);
|
|
glm::vec3 pick_color(std::size_t const Index);
|
|
std::size_t pick_index(glm::ivec3 const &Color);
|
|
|
|
bool init_viewport(viewport_config &vp);
|
|
|
|
void draw(const gfx::geometry_handle &handle);
|
|
void draw(std::vector<gfx::geometrybank_handle>::iterator begin, std::vector<gfx::geometrybank_handle>::iterator end);
|
|
|
|
void draw_debug_ui();
|
|
|
|
// members
|
|
GLFWwindow *m_window{nullptr}; // main window
|
|
gfx::geometrybank_manager m_geometry;
|
|
material_manager m_materials;
|
|
texture_manager m_textures;
|
|
opengl33_light m_sunlight;
|
|
opengllight_array m_lights;
|
|
/*
|
|
float m_sunandviewangle; // cached dot product of sunlight and camera vectors
|
|
*/
|
|
gfx::geometry_handle m_billboardgeometry{0, 0};
|
|
texture_handle m_glaretexture{-1};
|
|
texture_handle m_suntexture{-1};
|
|
texture_handle m_moontexture{-1};
|
|
texture_handle m_smoketexture{-1};
|
|
texture_handle m_headlightstexture{-1};
|
|
|
|
// main shadowmap resources
|
|
int m_shadowbuffersize{2048};
|
|
glm::mat4 m_shadowtexturematrix; // conversion from camera-centric world space to light-centric clip space
|
|
|
|
int m_environmentcubetextureface{0}; // helper, currently processed cube map face
|
|
double m_environmentupdatetime{0}; // time of the most recent environment map update
|
|
glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update
|
|
opengl33_skydome m_skydomerenderer;
|
|
// cooked terrain heightfields, ordered finest first. a scenery carries a coarse
|
|
// regional model and a fine corridor per line, and they overlap
|
|
std::vector<std::unique_ptr<terrain_clipmap>> m_terrain;
|
|
bool m_terrainattempted { false };
|
|
opengl33_precipitation m_precipitationrenderer;
|
|
opengl33_particles m_particlerenderer; // particle visualization subsystem
|
|
|
|
unsigned int m_framestamp; // id of currently rendered gfx frame
|
|
float m_framerate;
|
|
double m_updateaccumulator{0.0};
|
|
std::string m_debugtimestext;
|
|
std::string m_pickdebuginfo;
|
|
//debug_stats m_debugstats;
|
|
std::string m_debugstatstext;
|
|
struct simulation_state {
|
|
std::string weather;
|
|
std::string season;
|
|
} m_simulationstate;
|
|
|
|
glm::vec4 m_baseambient{0.0f, 0.0f, 0.0f, 1.0f};
|
|
glm::vec4 m_shadowcolor{colors::shadow};
|
|
// TEnvironmentType m_environment { e_flat };
|
|
float m_specularopaquescalefactor{1.f};
|
|
float m_speculartranslucentscalefactor{1.f};
|
|
|
|
float m_fogrange = 2000.0f;
|
|
|
|
renderpass_config m_renderpass; // parameters for current render pass
|
|
section_sequence m_sectionqueue; // list of sections in current render pass
|
|
cell_sequence m_cellqueue;
|
|
// frame-level accumulation of per-cell opaque instance buckets. Each visited
|
|
// cell's buckets are merged here keyed by (TModel3d*, skins), so that
|
|
// Render_Instanced() runs once per unique model across the whole pass instead
|
|
// of once per cell -- collapsing many tiny instanced draws into a few large
|
|
// batches. Reused every pass; cleared at the top of Render(scene::basic_region*).
|
|
scene::basic_cell::instance_bucket_map m_frame_instance_buckets;
|
|
renderpass_config m_colorpass; // parametrs of most recent color pass
|
|
std::array<renderpass_config, 3> m_shadowpass; // parametrs of most recent shadowmap pass for each of csm stages
|
|
std::vector<TSubModel const *> m_pickcontrolsitems;
|
|
std::vector<TSubModel const *> m_picksurfaceitems;
|
|
TSubModel const *m_pickcontrolitem{nullptr};
|
|
std::vector<scene::basic_node *> m_picksceneryitems;
|
|
scene::basic_node *m_picksceneryitem{nullptr};
|
|
glm::vec3 m_worldmousecoordinates { 0.f };
|
|
#ifdef EU07_USE_DEBUG_CAMERA
|
|
renderpass_config m_worldcamera; // debug item
|
|
#endif
|
|
|
|
std::optional<gl::query> m_timequery;
|
|
GLuint64 m_gllasttime = 0;
|
|
|
|
double m_precipitationrotation;
|
|
|
|
glm::mat4 perspective_projection_raw(float fovy, float aspect, float znear, float zfar);
|
|
glm::mat4 perspective_projection(const viewport_proj_config &c, float n, float f, glm::mat4 &frustum);
|
|
glm::mat4 ortho_projection(float left, float right, float bottom, float top, float z_near, float z_far);
|
|
glm::mat4 ortho_frustumtest_projection(float left, float right, float bottom, float top, float z_near, float z_far);
|
|
|
|
std::vector<std::function<void(TSubModel const *, glm::vec2)>> m_control_pick_requests;
|
|
std::vector<std::function<void(scene::basic_node *)>> m_node_pick_requests;
|
|
|
|
std::unique_ptr<gl::shader> m_vertex_shader;
|
|
|
|
std::unique_ptr<gl::ubo> scene_ubo;
|
|
std::unique_ptr<gl::ubo> model_ubo;
|
|
std::unique_ptr<gl::ubo> light_ubo;
|
|
// per-instance modelview UBO for GPU-instanced draws.
|
|
// Slot 0 is initialized once to identity and never overwritten by non-instanced
|
|
// rendering, so existing draws (where gl_InstanceID==0) compute identity*modelview
|
|
// in the vertex shader and behave exactly as before. Render_Instanced uploads
|
|
// per-instance camera-space root matrices to slots 0..N-1, calls glDrawElementsInstanced*,
|
|
// then restores slot 0 to identity for subsequent non-instanced draws.
|
|
std::unique_ptr<gl::ubo> instance_ubo;
|
|
// when > 0, the renderer is inside a Render_Instanced() call. The draw(handle)
|
|
// method routes to glDrawElementsInstanced* with this many instances rather
|
|
// than a single regular draw. The vertex shader reads per-instance modelview
|
|
// from instance_ubo[gl_InstanceID]. Reset to 0 by Render_Instanced() on exit.
|
|
std::size_t m_current_instance_count { 0 };
|
|
// persistent scratch buffer for Render_Instanced(): holds the per-instance
|
|
// camera-space root modelview matrices for the batch currently being built.
|
|
// Kept as a member rather than a function-local so its heap allocation is
|
|
// reused across calls -- clear() retains capacity, so once it has grown to
|
|
// the largest batch seen, steady-state frames perform no allocation here.
|
|
std::vector<glm::mat4> m_instance_modelviews;
|
|
gl::scene_ubs scene_ubs;
|
|
gl::model_ubs model_ubs;
|
|
gl::light_ubs light_ubs;
|
|
|
|
std::unordered_map<std::string, std::shared_ptr<gl::program>> m_shaders;
|
|
|
|
std::unique_ptr<gl::program> m_line_shader;
|
|
std::unique_ptr<gl::program> m_freespot_shader;
|
|
std::unique_ptr<gl::program> m_billboard_shader;
|
|
std::unique_ptr<gl::program> m_celestial_shader;
|
|
std::unique_ptr<gl::program> m_hiddenarea_shader;
|
|
std::unique_ptr<gl::program> m_copy_shader;
|
|
|
|
std::unique_ptr<gl::vao> m_empty_vao;
|
|
|
|
std::vector<std::unique_ptr<viewport_config>> m_viewports;
|
|
|
|
std::unique_ptr<gl::postfx> m_pfx_motionblur;
|
|
std::unique_ptr<gl::postfx> m_pfx_tonemapping;
|
|
std::unique_ptr<gl::postfx> m_pfx_chromaticaberration;
|
|
|
|
// postfx ssao
|
|
std::unique_ptr<gl::postfx> m_pfx_ssao;
|
|
std::unique_ptr<gl::postfx> m_pfx_ssao_blur;
|
|
std::unique_ptr<gl::postfx> m_pfx_ssao_apply;
|
|
std::unique_ptr<opengl_texture> m_ssao_noise_tex;
|
|
glm::vec3 m_ssao_kernel[32];
|
|
|
|
std::unique_ptr<gl::program> m_shadow_shader;
|
|
std::unique_ptr<gl::program> m_alpha_shadow_shader;
|
|
|
|
std::unique_ptr<gl::framebuffer> m_pick_fb;
|
|
std::unique_ptr<opengl_texture> m_pick_tex;
|
|
std::unique_ptr<gl::renderbuffer> m_pick_rb;
|
|
std::unique_ptr<gl::program> m_pick_surface_shader;
|
|
std::unique_ptr<gl::program> m_pick_shader;
|
|
|
|
std::unique_ptr<gl::cubemap> m_empty_cubemap;
|
|
|
|
std::unique_ptr<gl::framebuffer> m_env_fb;
|
|
std::unique_ptr<gl::renderbuffer> m_env_rb;
|
|
std::unique_ptr<gl::cubemap> m_env_tex;
|
|
|
|
std::unique_ptr<gl::framebuffer> m_shadow_fb;
|
|
std::unique_ptr<opengl_texture> m_shadow_tex;
|
|
|
|
std::unique_ptr<gl::pbo> m_picking_pbo;
|
|
std::unique_ptr<gl::pbo> m_picking_node_pbo;
|
|
|
|
std::unique_ptr<gl::pbo> m_depth_pointer_pbo;
|
|
std::unique_ptr<gl::framebuffer> m_depth_pointer_fb;
|
|
std::unique_ptr<gl::framebuffer> m_depth_pointer_fb2;
|
|
std::unique_ptr<gl::renderbuffer> m_depth_pointer_rb;
|
|
std::unique_ptr<opengl_texture> m_depth_pointer_tex;
|
|
std::unique_ptr<gl::program> m_depth_pointer_shader;
|
|
|
|
material_handle m_invalid_material;
|
|
|
|
bool m_blendingenabled;
|
|
|
|
bool m_widelines_supported;
|
|
|
|
struct headlight_config_s
|
|
{
|
|
float in_cutoff = 1.005f;
|
|
float out_cutoff = 0.993f;
|
|
|
|
float falloff_linear = 0.15f;
|
|
float falloff_quadratic = 0.15f;
|
|
|
|
float intensity = 1.0f;
|
|
float ambient = 0.0f;
|
|
};
|
|
|
|
headlight_config_s headlight_config;
|
|
|
|
std::unique_ptr<vr_interface> vr;
|
|
bool debug_ui_active = false;
|
|
|
|
static bool renderer_register;
|
|
|
|
class opengl33_imgui_renderer : public imgui_renderer
|
|
{
|
|
virtual bool Init() override;
|
|
virtual void Shutdown() override;
|
|
virtual void BeginFrame() override;
|
|
virtual void Render() override;
|
|
} m_imgui_renderer;
|
|
|
|
virtual imgui_renderer* GetImguiRenderer() override {
|
|
return &m_imgui_renderer;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
} // export
|