mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 15:39:20 +02:00
* Text displays: accept characters above 127, in windows-1250 or utf-8 A text display (sub-model of type "text") looks up the sub-model of each character in a 256 entry table, and indexed it with a plain char. With char being signed, any character above 127 gave a negative index: reading the text went outside the table, and so did filling the table if a character sub-model had such a name. In effect the displays could only show ASCII, and a text with national characters could crash. The lookup is now keyed by unicode code point. Both the displayed text and the names of the character sub-models are decoded as utf-8 if they are valid utf-8, and as windows-1250 otherwise, so legacy (ansi) sceneries and models work next to utf-8 ones, and the two can be mixed. A short ansi text can be valid utf-8 by accident (two upper case accented letters in a row will do); when both readings are possible the one which finds more of its characters in the model is used. The rest is unchanged: the first character of the text still isn't displayed, the characters are still drawn in the translucent pass only. A missing text pointer no longer gets dereferenced. * Text displays: prepare the characters once for each text The sequence of character sub-models was cached for the last text only, so displays of several instances drawn in turn decoded their texts again on every draw. It is now kept for each text the display shows; the texts of the instances don't change, so a draw costs a single lookup. Also the comments added in the renderers are now in English. * Text displays: move the text decoding to utilities utf8_to_utf32() and win1250_to_utf32(), with the windows-1250 table, now sit next to win1250_to_utf8(). The existing function maps only the Polish letters and passes other bytes above 127 through, so it can't serve the displays. * Text displays: address the SonarCloud findings std::array instead of the C-style arrays, the utf-8 sequence length worked out in a function of its own instead of nested conditional operators, std::byte for the bit operations, std::ranges::count_if and contains(). The character loop of the renderers moved to Render_Alpha_text(), which takes the nesting back to the limit, and the static pasText is accessed through the class.
397 lines
15 KiB
C++
397 lines
15 KiB
C++
/*
|
|
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/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "rendering/renderer.h"
|
|
#include "rendering/opengllight.h"
|
|
#include "rendering/openglcamera.h"
|
|
#include "rendering/openglparticles.h"
|
|
#include "rendering/openglskydome.h"
|
|
#include "rendering/openglprecipitation.h"
|
|
#include "rendering/lightarray.h"
|
|
#include "scene/scene.h"
|
|
#include "simulation/simulationenvironment.h"
|
|
#include "world/MemCell.h"
|
|
|
|
#define EU07_USE_PICKING_FRAMEBUFFER
|
|
//#define EU07_USE_DEBUG_SHADOWMAP
|
|
//#define EU07_USE_DEBUG_CABSHADOWMAP
|
|
//#define EU07_USE_DEBUG_CAMERA
|
|
//#define EU07_USE_DEBUG_SOUNDEMITTERS
|
|
//#define EU07_DISABLECABREFLECTIONS
|
|
|
|
// bare-bones render controller, in lack of anything better yet
|
|
class opengl_renderer : public gfx_renderer {
|
|
|
|
public:
|
|
// types
|
|
// constructors
|
|
opengl_renderer() = default;
|
|
// destructor
|
|
~opengl_renderer() { }
|
|
// methods
|
|
bool
|
|
Init( GLFWwindow *Window ) override;
|
|
// main draw call. returns false on error
|
|
bool
|
|
Render() override;
|
|
void
|
|
SwapBuffers() override;
|
|
inline
|
|
float
|
|
Framerate() override { return m_framerate; }
|
|
|
|
bool AddViewport(const global_settings::extraviewport_config &conf) override { return false; }
|
|
bool Debug_Ui_State(std::optional<bool>) override { return false; }
|
|
void Shutdown() override {}
|
|
|
|
// 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.camera.modelview() ) ); }
|
|
glm::mat4
|
|
Camera_Projection_Matrix() const override { return m_colorpass.camera.projection(); }
|
|
glm::dvec3
|
|
Camera_Position() const override { return m_colorpass.camera.position(); }
|
|
// maintenance methods
|
|
void
|
|
Update( double const Deltatime ) 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 const & Material( TSubModel const * Submodel ) const;
|
|
|
|
// members
|
|
GLenum static const sunlight { GL_LIGHT0 };
|
|
|
|
static std::unique_ptr<gfx_renderer> create_func();
|
|
|
|
private:
|
|
// types
|
|
enum class rendermode {
|
|
none,
|
|
color,
|
|
shadows,
|
|
cabshadows,
|
|
reflections,
|
|
pickcontrols,
|
|
pickscenery
|
|
};
|
|
|
|
enum textureunit {
|
|
helper = 0,
|
|
shadows,
|
|
normals,
|
|
diffuse
|
|
};
|
|
|
|
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 };
|
|
};
|
|
|
|
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 camera;
|
|
rendermode draw_mode { rendermode::none };
|
|
float draw_range { 0.0f };
|
|
debug_stats draw_stats;
|
|
};
|
|
|
|
struct units_state {
|
|
|
|
bool diffuse { false };
|
|
bool shadows { false };
|
|
bool reflections { false };
|
|
};
|
|
|
|
typedef std::vector<opengl_light> opengllight_array;
|
|
|
|
// methods
|
|
void
|
|
Disable_Lights();
|
|
void
|
|
setup_pass( 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_units( bool const Diffuse, bool const Shadows, bool const Reflections );
|
|
void
|
|
setup_shadow_map( GLuint const Texture, glm::mat4 const &Transformation );
|
|
void
|
|
setup_shadow_color( glm::vec4 const &Shadowcolor );
|
|
void
|
|
setup_environment_light( TEnvironmentType const Environment = e_flat );
|
|
void
|
|
switch_units( bool const Diffuse, bool const Shadows, bool const Reflections );
|
|
// helper, texture manager method; activates specified texture unit
|
|
void
|
|
select_unit( GLint const Textureunit );
|
|
// runs jobs needed to generate graphics for specified render pass
|
|
void
|
|
Render_pass( rendermode const Mode );
|
|
// creates dynamic environment cubemap
|
|
bool
|
|
Render_reflections();
|
|
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 );
|
|
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 );
|
|
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_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 );
|
|
// characters of a text display
|
|
void
|
|
Render_Alpha_text( TSubModel *Submodel );
|
|
void
|
|
Update_Lights( light_array &Lights );
|
|
bool
|
|
Init_caps();
|
|
glm::vec3
|
|
pick_color( std::size_t const Index );
|
|
std::size_t
|
|
pick_index( glm::ivec3 const &Color );
|
|
|
|
// members
|
|
GLFWwindow *m_window { nullptr };
|
|
gfx::geometrybank_manager m_geometry;
|
|
material_manager m_materials;
|
|
texture_manager m_textures;
|
|
opengl_light m_sunlight;
|
|
opengllight_array m_lights;
|
|
opengl_skydome m_skydomerenderer;
|
|
opengl_precipitation m_precipitationrenderer;
|
|
opengl_particles m_particlerenderer; // particle visualization subsystem
|
|
/*
|
|
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_reflectiontexture { -1 };
|
|
texture_handle m_smoketexture { -1 };
|
|
material_handle m_invalid_material;
|
|
// TODO: refactor framebuffer stuff into an object
|
|
bool m_framebuffersupport { false };
|
|
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
|
GLuint m_pickframebuffer { 0 };
|
|
GLuint m_picktexture { 0 };
|
|
GLuint m_pickdepthbuffer { 0 };
|
|
#endif
|
|
// main shadowmap resources
|
|
int m_shadowbuffersize { 2048 };
|
|
GLuint m_shadowframebuffer { 0 };
|
|
GLuint m_shadowtexture { 0 };
|
|
#ifdef EU07_USE_DEBUG_SHADOWMAP
|
|
GLuint m_shadowdebugtexture{ 0 };
|
|
#endif
|
|
#ifdef EU07_USE_DEBUG_CABSHADOWMAP
|
|
GLuint m_cabshadowdebugtexture{ 0 };
|
|
#endif
|
|
glm::mat4 m_shadowtexturematrix; // conversion from camera-centric world space to light-centric clip space
|
|
// cab shadowmap resources
|
|
GLuint m_cabshadowframebuffer { 0 };
|
|
GLuint m_cabshadowtexture { 0 };
|
|
glm::mat4 m_cabshadowtexturematrix; // conversion from cab-centric world space to light-centric clip space
|
|
// environment map resources
|
|
GLuint m_environmentframebuffer { 0 };
|
|
GLuint m_environmentcubetexture { 0 };
|
|
GLuint m_environmentdepthbuffer { 0 };
|
|
bool m_environmentcubetexturesupport { false }; // indicates whether we can use the dynamic environment cube map
|
|
int m_environmentcubetextureface { 0 }; // helper, currently processed cube map face
|
|
double m_environmentupdatetime { 0.0 }; // time of the most recent environment map update
|
|
glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update
|
|
|
|
int m_helpertextureunit { 0 };
|
|
int m_shadowtextureunit { 1 };
|
|
int m_normaltextureunit { 2 };
|
|
int m_diffusetextureunit{ 3 };
|
|
units_state m_unitstate;
|
|
|
|
unsigned int m_framestamp; // id of currently rendered gfx frame
|
|
float m_framerate;
|
|
double m_updateaccumulator { 0.0 };
|
|
// double m_pickupdateaccumulator { 0.0 };
|
|
std::string m_debugtimestext;
|
|
std::string m_pickdebuginfo;
|
|
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 };
|
|
float m_fogrange { 2000.f };
|
|
// TEnvironmentType m_environment { e_flat };
|
|
float m_specularopaquescalefactor { 1.f };
|
|
float m_speculartranslucentscalefactor { 1.f };
|
|
bool m_renderspecular{ false }; // controls whether to include specular component in the calculations
|
|
|
|
renderpass_config m_renderpass; // parameters for current render pass
|
|
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
|
|
renderpass_config m_shadowpass; // parametrs of most recent shadowmap pass
|
|
renderpass_config m_cabshadowpass; // parameters of most recent cab shadowmap pass
|
|
std::vector<TSubModel *> m_pickcontrolsitems;
|
|
TSubModel *m_pickcontrolitem { nullptr };
|
|
std::vector<scene::basic_node *> m_picksceneryitems;
|
|
scene::basic_node *m_picksceneryitem { nullptr };
|
|
glm::vec3 m_worldmousecoordinates { 0.f };
|
|
std::vector<std::function<void( TSubModel const *, const glm::vec2 )>> m_control_pick_requests;
|
|
std::vector<std::function<void( scene::basic_node * )>> m_node_pick_requests;
|
|
#ifdef EU07_USE_DEBUG_CAMERA
|
|
renderpass_config m_worldcamera; // debug item
|
|
#endif
|
|
bool m_isATI;
|
|
|
|
static bool renderer_register;
|
|
|
|
class opengl_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;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|