mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-21 00:32:39 +02:00
204 lines
11 KiB
C++
204 lines
11 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 <array>
|
|
#include <cstdint>
|
|
|
|
#include "rendering/geometrybank.h"
|
|
#include "interfaces/IMaterial.h"
|
|
#include "interfaces/ITexture.h"
|
|
#include "utilities/Globals.h"
|
|
|
|
struct lighting_data;
|
|
|
|
namespace gl
|
|
{
|
|
class program;
|
|
}
|
|
|
|
namespace gfx
|
|
{
|
|
// material painted over the heightmap terrain, and the size (metres) its textures are repeated at; 0: the size given by the material, or 8 m
|
|
struct terrain_layer
|
|
{
|
|
material_handle material{null_handle};
|
|
float size{0.f};
|
|
float rotation{0.f}; // degrees the textures are turned by
|
|
};
|
|
|
|
// kind of grass grown over the heightmap terrain (heightmap::grass_def), colours in linear rgb
|
|
struct grass_kind
|
|
{
|
|
glm::vec3 base{0.f}; // at the root of the blades
|
|
glm::vec3 tip{0.f};
|
|
float height{0.3f}; // metres
|
|
float variation{0.4f}; // share of the height the blades differ by, either way
|
|
float width{0.012f}; // metres, at the root
|
|
float density{60.f}; // blades per square metre where painted fully
|
|
float bend{0.3f}; // share of the height the tips lean over by
|
|
glm::vec3 dry{0.f}; // the tips dried out, in autumn and winter
|
|
float seasonal{1.f}; // how much the kind follows the seasons, 0..1
|
|
};
|
|
|
|
// a chunk of the heightmap terrain the grass grows on, see gfx_renderer::Terrain_Grass()
|
|
struct grass_chunk
|
|
{
|
|
std::uint64_t id{0}; // the same for the same chunk, as long as it's in memory
|
|
std::uint64_t version{0}; // changes with every change of what the grass is made of
|
|
glm::dvec2 corner{0.0}; // x, z
|
|
float size{0.f}; // metres along a side
|
|
float low{0.f}, high{0.f}; // the lowest and the highest point
|
|
int cells{0}; // quads of the grid along a side
|
|
float const *heights{nullptr}; // (cells + 1)^2, rows of growing z
|
|
int samples{0}; // grass samples along a side less one
|
|
std::uint8_t const *density{nullptr}; // (samples + 1)^2 per kind, planar
|
|
std::array<int, 4> kinds{-1, -1, -1, -1}; // indices of the kinds of the samples, -1 unused
|
|
int holes{0}; // hole samples along a side less one, 0: none
|
|
std::uint8_t const *hole_mask{nullptr}; // (holes + 1)^2, 255: cut
|
|
};
|
|
} // namespace gfx
|
|
|
|
class gfx_renderer {
|
|
|
|
public:
|
|
// types
|
|
// constructors
|
|
// destructor
|
|
virtual ~gfx_renderer() {}
|
|
// methods
|
|
virtual auto Init( GLFWwindow *Window ) -> bool = 0;
|
|
virtual bool AddViewport(const global_settings::extraviewport_config &conf) = 0;
|
|
virtual void Shutdown() = 0;
|
|
// main draw call. returns false on error
|
|
virtual auto Render() -> bool = 0;
|
|
virtual void SwapBuffers() = 0;
|
|
virtual auto Framerate() -> float = 0;
|
|
// 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
|
|
virtual auto Create_Bank() -> gfx::geometrybank_handle = 0;
|
|
// creates a new indexed geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
|
virtual auto Insert(gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) -> gfx::geometry_handle = 0;
|
|
// creates a new geometry chunk of specified type from supplied data, in specified bank. returns: handle to the chunk or NULL
|
|
virtual auto Insert(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometrybank_handle const &Geometry, int const Type) -> gfx::geometry_handle = 0;
|
|
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
|
virtual auto Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) -> bool = 0;
|
|
// replaces the index and the vertex data of specified indexed chunk with the supplied data of the same counts.
|
|
// returns: false if it wasn't replaced (the counts differ, or the backend can't)
|
|
virtual auto Replace_Indexed( gfx::index_array &Indices, gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry ) -> bool { return false; }
|
|
// adds supplied vertex data at the end of specified chunk
|
|
virtual auto Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) -> bool = 0;
|
|
// provides direct access to index data of specfied chunk
|
|
virtual auto Indices( gfx::geometry_handle const &Geometry ) const->gfx::index_array const & = 0;
|
|
// provides direct access to vertex data of specfied chunk
|
|
virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0;
|
|
// provides direct access to vertex user data of specfied chunk
|
|
virtual auto UserData( gfx::geometry_handle const &Geometry ) const ->gfx::userdata_array const & = 0;
|
|
// kind of geometry of specified chunk, -1 when the renderer doesn't tell
|
|
virtual auto Primitive( gfx::geometry_handle const &Geometry ) const -> int { return -1; }
|
|
// material methods
|
|
virtual auto Fetch_Material( std::string const &Filename, bool const Loadnow = true ) -> material_handle = 0;
|
|
virtual void Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) = 0;
|
|
virtual auto Material( material_handle const Material ) const -> IMaterial const * = 0;
|
|
// the same material with its highlights damped, for faces which aren't polished like the surfaces they are cut from. backends which can't make one give back the material itself
|
|
virtual auto Matte_Material( material_handle const Material ) -> material_handle { return Material; }
|
|
virtual auto Tinted_Material( material_handle const Material, glm::vec3 const &Colour ) -> material_handle { return Material; }
|
|
// heightmap terrain: material of a chunk blending the materials of up to 8 layers by their weights.
|
|
// Weights: (Samples + 1)^2 values per layer, planar, rows of growing z, the weights of a sample adding up to 255; null with a single layer.
|
|
// Placement: corner of the chunk (x, z) in the texture coordinates of its mesh, and the size of the chunk.
|
|
// Reuse: a material made by this call before, to be filled anew, or null_handle.
|
|
// Holes: (HoleSamples + 1)^2 values (255: the ground is cut there), rows like the weights; null without holes. the cells
|
|
// cut out entirely are left out of the geometry, the material cuts the rest of the openings.
|
|
// returns: the material. backends which can't blend give back the material of the layer covering the most
|
|
virtual auto Terrain_Material( material_handle const Reuse, std::vector<gfx::terrain_layer> const &Layers, int const Samples, std::uint8_t const *Weights, glm::vec3 const &Placement,
|
|
int const HoleSamples = 0, std::uint8_t const *Holes = nullptr ) -> material_handle;
|
|
// gives back a material made by Terrain_Material, once its chunk is gone
|
|
virtual void Terrain_Release( material_handle const Material ) {}
|
|
// heightmap terrain: the grass to draw, the kinds of the grass palette and the chunks near the camera which have grass.
|
|
// the data of the chunks is read during the call only; a chunk the renderer has with the same id and version isn't read
|
|
// again. chunks left out are dropped. backends which can't draw grass ignore it
|
|
virtual void Terrain_Grass( std::vector<gfx::grass_kind> const &Kinds, std::vector<gfx::grass_chunk> const &Chunks ) {}
|
|
// shader methods
|
|
virtual auto Fetch_Shader( std::string const &name ) -> std::shared_ptr<gl::program> = 0;
|
|
// texture methods
|
|
virtual auto Fetch_Texture( std::string const &Filename, bool const Loadnow = true, GLint format_hint = GL_SRGB_ALPHA ) -> texture_handle = 0;
|
|
virtual void Bind_Texture( texture_handle const Texture ) = 0;
|
|
virtual void Bind_Texture( std::size_t const Unit, texture_handle const Texture ) = 0;
|
|
virtual auto Texture( texture_handle const Texture ) -> ITexture & = 0;
|
|
virtual auto Texture( texture_handle const Texture ) const -> ITexture const & = 0;
|
|
// utility methods
|
|
virtual void Pick_Control_Callback( std::function<void( TSubModel const *, const glm::vec2 )> Callback ) = 0;
|
|
virtual void Pick_Node_Callback( std::function<void( scene::basic_node * )> Callback ) = 0;
|
|
virtual auto Pick_Control() const -> TSubModel const * = 0;
|
|
virtual auto Pick_Node() const -> scene::basic_node const * = 0;
|
|
|
|
virtual auto Mouse_Position() const -> glm::dvec3 = 0;
|
|
virtual auto Mouse_Hit() const -> bool { return true; }
|
|
// editor helpers: matrices/position of the most recent color pass camera.
|
|
// the view matrix is camera-relative (rotation only, camera at origin), matching the
|
|
// camera-relative rendering used by the engine; build object matrices relative to Camera_Position().
|
|
// default implementations return identity so backends without a usable camera still compile.
|
|
virtual auto Camera_View_Matrix() const -> glm::mat4 { return glm::mat4( 1.f ); }
|
|
virtual auto Camera_Projection_Matrix() const -> glm::mat4 { return glm::mat4( 1.f ); }
|
|
virtual auto Camera_Position() const -> glm::dvec3 { return glm::dvec3( 0.0 ); }
|
|
// maintenance methods
|
|
virtual void Update( double const Deltatime ) = 0;
|
|
virtual void Update_Pick_Control() = 0;
|
|
virtual void Update_Pick_Node() = 0;
|
|
virtual auto Update_Mouse_Position() -> glm::dvec3 = 0;
|
|
virtual bool Debug_Ui_State(std::optional<bool>) = 0;
|
|
// debug methods
|
|
virtual auto info_times() const -> std::string const & = 0;
|
|
virtual auto info_stats() const -> std::string const & = 0;
|
|
// imgui renderer
|
|
virtual class imgui_renderer *GetImguiRenderer() = 0;
|
|
virtual void MakeScreenshot() = 0;
|
|
// draws the model of a scenery instance on its own into a square image of Size pixels on white background, the model
|
|
// seen in perspective from the front, side and above and filling the image less Margin pixels at each edge.
|
|
// Image receives rgb rows, top row first. returns false if the backend can't make previews or there's nothing to draw
|
|
virtual auto Render_Preview( TAnimModel *Instance, int const Size, int const Margin, bool const Shadows, std::vector<std::uint8_t> &Image ) -> bool { return false; }
|
|
};
|
|
|
|
class gfx_renderer_factory
|
|
{
|
|
public:
|
|
using create_method = std::unique_ptr<gfx_renderer>(*)();
|
|
|
|
bool register_backend(const std::string &backend, create_method func);
|
|
std::unique_ptr<gfx_renderer> create(const std::string &name);
|
|
|
|
static gfx_renderer_factory* get_instance();
|
|
|
|
private:
|
|
std::unordered_map<std::string, create_method> backends;
|
|
static gfx_renderer_factory *instance;
|
|
};
|
|
|
|
class imgui_renderer
|
|
{
|
|
public:
|
|
virtual bool Init() = 0;
|
|
virtual void Shutdown() = 0;
|
|
virtual void BeginFrame() = 0;
|
|
virtual void Render() = 0;
|
|
// images of the user interface itself (e.g. the previews of the node bank), apart from the textures of the scene: rgba, rows
|
|
// from the top, in srgb. returns: id for ImGui::Image, 0 if the renderer can't make them
|
|
virtual std::uint64_t Create_Image(std::uint8_t const *Rgba, int const Width, int const Height)
|
|
{
|
|
return 0;
|
|
}
|
|
virtual void Release_Image(std::uint64_t const Image) {}
|
|
};
|
|
|
|
extern std::unique_ptr<gfx_renderer> GfxRenderer;
|
|
|
|
//---------------------------------------------------------------------------
|