17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 09:49:19 +02:00
Files
maszyna/betterRenderer/renderer/include/nvrenderer/nvrenderer.h
maj00r c15e200e37 Merge the track layout editor into cpp20-modules, ported to modules
The editor branch was written against headers and the PCH, both of which this
branch has done away with, so its own files were ported rather than merged: the
five headers it added are now interface units and their .cpp files module
implementation units.

- editor/{puwg1992,polandmap,turnouts,orthophoto} become eu07.editor.* modules,
  application/planpanel becomes eu07.application.planpanel. The plan tool keeps
  to its own module rather than joining the eu07.simcore partitions: it stands on
  the editor's libraries and eu07.application.uilayer, not on the simulation core,
  so :editoruilayer can export import it without a cycle.
- glm arrives by import eu07.glm, never by include, as the rest of the tree does.
  maj0sted is header-only and glm-free, so its headers stay includes in the global
  module fragment - every unit that names those types includes them itself, since
  a global fragment is not visible across units.
- the one textual conflict was :editoruilayer's include block against this
  branch's imports; resolved this branch's way plus the planpanel import.

Builds with clang 22 (-DWITH_BETTER_RENDERER=OFF) and starts into the editor on
empty ground with -editor alone.
2026-09-13 12:36:21 +02:00

799 lines
28 KiB
C++

#pragma once
#ifdef _WIN32
#include <windows.h> // before any import: its guard must be set here
#endif
//STL includes required by EU07 includes
#include <array>
#include <condition_variable>
#include <cstddef>
#include <cstdint>
#include <deque>
#include <functional>
#include <future>
#include <memory>
#include <mutex>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <variant>
#include <vector>
#include <math.h>
// OpenGL includes required by EU07 includes
#include <glad/glad.h> // for GLuint, GLint
#include <GLFW/glfw3.h> // for GLFWwindow
#include "utilities/Globals_macros.h"
// Div. includes required by EU07 includes
#include <nvrhi/nvrhi.h>
#include <yaml-cpp/yaml.h>
#include <entt/container/dense_map.hpp>
// EU07 includes. This header is consumed by translation units that include
// nothing else, so everything it names has to be imported here rather than
// relied on to arrive from the including file.
#include "nvrenderer_enums.h"
#include "quadtree.h"
#include "resource_registry.h"
#include <chrono>
#include <limits>
#include <ostream>
#include <sstream>
#include <type_traits>
import eu07.utilities.classes;
import eu07.utilities.globals;
import eu07.simcore;
import eu07.rendering.geometrybank;
import eu07.global_include.interfaces.imaterial;
import eu07.global_include.interfaces.itexture;
import eu07.gl.shader;
import eu07.rendering.renderer;
import eu07.environment.sky;
import eu07.glm;
namespace Rt {
struct IRtModel;
}
template <typename Renderer>
struct MaRendererConstants {
static constexpr size_t NumMaterialPasses() noexcept {
return static_cast<size_t>(Renderer::RenderPassType::Num);
}
static constexpr size_t NumDrawTypes() noexcept {
return static_cast<size_t>(Renderer::DrawType::Num);
}
static constexpr size_t NumShadowPipelines() noexcept {
return NumDrawTypes() << 1;
}
static constexpr size_t NumMaterialPipelines() noexcept {
return NumDrawTypes() * NumMaterialPasses();
}
static constexpr size_t GetPipelineIndex(
typename Renderer::RenderPassType pass_type,
typename Renderer::DrawType draw_type) {
return static_cast<size_t>(draw_type) * NumMaterialPasses() +
static_cast<size_t>(pass_type);
}
static constexpr size_t GetDefaultShadowPipelineIndex(
typename Renderer::DrawType type, const bool masked) {
return static_cast<size_t>(type) << 1 | !!masked & 1;
}
};
class NvRenderer : public gfx_renderer, public MaResourceRegistry {
public:
enum class Api { D3D11, D3D12, Vulkan };
using RenderPassType = RendererEnums::RenderPassType;
using DrawType = RendererEnums::DrawType;
public:
using Constants = MaRendererConstants<NvRenderer>;
// SZ renderer interface implementation
virtual ~NvRenderer() override {}
virtual bool Init(GLFWwindow *Window) override;
virtual bool AddViewport(
const global_settings::extraviewport_config &conf) override;
virtual void Shutdown() override;
virtual bool Render() override;
virtual void SwapBuffers() override;
virtual float Framerate() override;
virtual gfx::geometrybank_handle Create_Bank() override;
virtual 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;
virtual gfx::geometry_handle Insert(gfx::vertex_array &Vertices,
gfx::userdata_array &Userdata,
gfx::geometrybank_handle const &Geometry,
int const Type) override;
virtual bool Replace(gfx::vertex_array &Vertices,
gfx::userdata_array &Userdata,
gfx::geometry_handle const &Geometry, int const Type,
std::size_t const Offset = 0) override;
virtual bool Append(gfx::vertex_array &Vertices,
gfx::userdata_array &Userdata,
gfx::geometry_handle const &Geometry,
int const Type) override;
virtual gfx::index_array const &Indices(
gfx::geometry_handle const &Geometry) const override;
virtual gfx::vertex_array const &Vertices(
gfx::geometry_handle const &Geometry) const override;
const gfx::userdata_array &UserData(
const gfx::geometry_handle &Geometry) const override;
virtual material_handle Fetch_Material(std::string const &Filename,
bool const Loadnow = true) override;
virtual void Bind_Material(material_handle const Material,
TSubModel const *sm = nullptr,
lighting_data const *lighting = nullptr) override;
virtual IMaterial const *Material(
material_handle const Material) const override;
virtual std::shared_ptr<gl::program> Fetch_Shader(
std::string const &name) override;
virtual texture_handle Fetch_Texture(
std::string const &Filename, bool const Loadnow = true,
GLint format_hint = GL_SRGB_ALPHA) override;
virtual void Bind_Texture(texture_handle const Texture) override;
virtual void Bind_Texture(std::size_t const Unit,
texture_handle const Texture) override;
virtual ITexture &Texture(texture_handle const Texture) override;
virtual ITexture const &Texture(texture_handle const Texture) const override;
virtual void Pick_Control_Callback(
std::function<void(TSubModel const *, const glm::vec2)> Callback)
override;
virtual void Pick_Node_Callback(
std::function<void(scene::basic_node *)> Callback) override;
virtual TSubModel const *Pick_Control() const override;
virtual scene::basic_node const *Pick_Node() const override;
virtual glm::dvec3 Mouse_Position() const override;
// matrices of the most recent colour pass, for overlays drawn on top of the rendered world
virtual glm::mat4 Camera_View_Matrix() const override {
return static_cast<glm::mat4>(m_camera_view);
}
virtual glm::mat4 Camera_Projection_Matrix() const override {
return static_cast<glm::mat4>(m_camera_projection);
}
virtual glm::dvec3 Camera_Position() const override {
return m_camera_position;
}
virtual void Update(double const Deltatime) override;
virtual void Update_Pick_Control() override;
virtual void Update_Pick_Node() override;
virtual glm::dvec3 Update_Mouse_Position() override;
virtual bool Debug_Ui_State(std::optional<bool>) override;
virtual std::string const &info_times() const override;
virtual std::string const &info_stats() const override;
virtual imgui_renderer *GetImguiRenderer() override;
virtual void MakeScreenshot() override;
NvRenderer(Api api) : m_api(api), MaResourceRegistry(nullptr) {}
static bool d3d11_renderer_register;
static bool d3d12_renderer_register;
static bool vk_renderer_register;
static bool renderer_register;
struct IFrustumTester {
virtual bool IntersectSphere(const glm::dvec3 &origin,
double radius) const = 0;
virtual bool IntersectBox(const glm::dvec3 &origin,
const glm::dvec3 &extent) const = 0;
virtual bool IntersectBox(const glm::dmat4x3 &transform,
const glm::dvec3 &origin,
const glm::dvec3 &extent) const = 0;
};
class NvRendererBackend *GetBackend() const { return m_backend.get(); }
// private:
friend class NvRendererBackend;
friend class NvRendererMessageCallback;
friend class NvImguiRenderer;
friend class NvTextureManager;
friend struct NvGbuffer;
friend struct NvSsao;
friend struct FullScreenPass;
friend struct NvTAA;
friend struct NvFSR;
friend struct MaEnvironment;
friend struct MaShadowMap;
Api m_api;
std::shared_ptr<class NvRendererBackend> m_backend;
std::shared_ptr<class NvRendererMessageCallback> m_message_callback;
std::shared_ptr<class NvImguiRenderer> m_imgui_renderer;
std::shared_ptr<struct NvGbuffer> m_gbuffer;
std::shared_ptr<struct NvGbuffer> m_gbuffer_cube;
std::shared_ptr<struct NvGbuffer> m_gbuffer_shadow;
std::shared_ptr<struct GbufferLighting> m_gbuffer_lighting;
std::shared_ptr<struct GbufferBlitPass> m_gbuffer_blit;
std::shared_ptr<struct NvSsao> m_ssao;
std::shared_ptr<struct MotionCache> m_motion_cache;
std::shared_ptr<struct InstanceBank> m_instance_cache;
std::shared_ptr<struct NvTAA> m_taa;
std::shared_ptr<struct TonemapPass> m_tonemap;
std::shared_ptr<struct NvFSR> m_fsr;
std::shared_ptr<struct MaEnvironment> m_environment;
std::shared_ptr<struct MaShadowMap> m_shadow_map;
std::shared_ptr<struct MaContactShadows> m_contact_shadows;
std::shared_ptr<struct Bloom> m_bloom;
std::shared_ptr<struct Sky> m_sky;
std::shared_ptr<struct MaAutoExposure> m_auto_exposure;
std::shared_ptr<struct WindshieldRain> m_windshield_rain;
std::unordered_map<TModel3d const *, std::shared_ptr<Rt::IRtModel>> rt_models;
std::shared_ptr<Rt::IRtModel> GetRtModel(TModel3d const *);
std::shared_ptr<struct MaConfig> m_config;
struct MaConfig *GetConfig() const { return m_config.get(); }
static struct MaConfig *Config();
struct GeometryBounds {
glm::dvec3 m_origin;
glm::dvec3 m_extent;
};
GeometryBounds GetGeometryBounds(gfx::geometry_handle const &handle) const;
size_t GetCurrentFrame() const;
void DebugUi();
glm::dmat4 m_previous_view_proj;
glm::dmat4 m_previous_view;
bool m_debug_ui_active;
nvrhi::CommandListHandle m_command_list;
nvrhi::EventQueryHandle m_upload_event_query;
std::mutex m_mtx_context_lock;
glm::dvec3 m_previous_env_position;
uint64_t m_previous_env_frame;
glm::dvec3 m_mouse_ro;
glm::dvec3 m_mouse_rd;
// colour pass camera, kept so overlays can place world points on screen. the view matrix is
// camera-relative (rotation only), matching the camera-relative rendering used throughout
glm::dmat4 m_camera_view{1.};
glm::dmat4 m_camera_projection{1.};
glm::dvec3 m_camera_position{0.};
TSubModel const *m_picked_submodel = nullptr;
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 {
RenderPassType m_type;
double m_draw_range;
uint64_t m_frame_index;
bool m_draw_shapes = true;
bool m_draw_lines = true;
bool m_draw_tanimobj = true;
bool m_draw_dynamic = true;
bool m_draw_track = true;
bool m_draw_instances = true;
bool m_sort_batches = true;
bool m_sort_transparents = true;
nvrhi::CommandListHandle m_command_list_draw;
nvrhi::CommandListHandle m_command_list_preparation;
nvrhi::FramebufferHandle m_framebuffer;
nvrhi::ViewportState m_viewport_state;
glm::dmat4 m_projection;
glm::dvec3 m_origin;
glm::dmat3 m_transform;
glm::dmat3 m_history_transform;
double ScreenRadius(const glm::dvec3 &origin, double radius) const {
glm::dvec4 ndc =
m_projection *
glm::dvec4(0., radius, -glm::length(origin - m_origin), 1.);
return glm::abs(ndc.y / ndc.w);
}
double ScreenRadius(double sqr_distance, double radius) const {
glm::dvec4 ndc =
m_projection * glm::dvec4(0., radius, -glm::sqrt(sqr_distance), 1.);
return glm::abs(ndc.y / ndc.w);
}
bool NeedsHistory() const { return m_type == RenderPassType::Deferred; }
bool SphereVisible(const glm::dvec3 &origin, double radius) const {
return !m_frustum_tester ||
m_frustum_tester->IntersectSphere(origin - m_origin, radius);
}
bool BoxVisible(const glm::dvec3 &origin, const glm::dvec3 &extent) const {
return !m_frustum_tester ||
m_frustum_tester->IntersectBox(origin - m_origin, extent);
}
bool BoxVisible(glm::dmat4x3 transform, const glm::dvec3 &origin,
const glm::dvec3 &extent) const {
transform[3] -= m_origin;
return !m_frustum_tester ||
m_frustum_tester->IntersectBox(transform, origin, extent);
}
bool Visible(scene::bounding_area const &area) const {
return SphereVisible(area.center, area.radius);
}
bool Visible(TDynamicObject *dynamic) const {
return SphereVisible(dynamic->GetPosition(), dynamic->radius() * 1.25);
}
const IFrustumTester *m_frustum_tester;
};
struct GeometryChunk {
std::vector<gfx::basic_vertex> m_vertices;
std::vector<gfx::basic_index> m_indices;
size_t m_vertex_offset;
size_t m_index_offset;
size_t m_vertex_count;
size_t m_index_count;
bool m_indexed;
bool m_is_uptodate = false;
uint64_t m_last_frame_requested = static_cast<uint64_t>(-1);
uint64_t m_last_frame_updated = static_cast<uint64_t>(-1);
uint64_t m_last_frame_uploaded = static_cast<uint64_t>(-1);
nvrhi::BufferHandle m_index_buffer;
nvrhi::BufferHandle m_vertex_buffer;
nvrhi::EventQueryHandle m_chunk_ready_handle;
std::future<void> m_chunk_upload;
glm::vec3 m_origin;
glm::vec3 m_extent;
glm::dvec3 m_last_position_requested;
std::function<bool(gfx::vertex_array &, int)> m_replace_impl;
void UpdateBounds();
};
struct GeometryBank {
nvrhi::BufferHandle m_index_buffer;
nvrhi::BufferHandle m_vertex_buffer;
size_t m_vertex_count;
size_t m_index_count;
std::vector<GeometryChunk> m_chunks;
bool m_is_uptodate = false;
nvrhi::EventQueryHandle m_uploaded_query;
uint64_t m_last_frame_requested = static_cast<uint64_t>(-1);
};
std::vector<GeometryBank> m_geometry_banks;
nvrhi::BufferHandle m_culling_view_data;
struct GeometryBatch {
struct CullingViewData {
glm::vec4 m_frustum_planes[6];
glm::mat4 m_projection;
};
struct CullingPushConstants {
glm::vec3 m_origin;
float m_instance_radius;
float m_min_radius;
float m_max_radius;
uint32_t m_num_instances;
};
struct CullingCommandBuffer {
uint32_t m_index_count_per_instance;
uint32_t m_instance_count;
uint32_t m_start_index_location;
int32_t m_base_vertex_location;
uint32_t m_start_instance_location;
};
gfx::geometry_handle m_geometry;
material_handle m_material;
std::vector<glm::dmat4> m_transforms;
glm::vec3 m_diffuse;
glm::dvec3 m_origin;
glm::dvec3 m_extent;
glm::dvec3 m_instance_origin;
nvrhi::BufferHandle m_static_instance_buffer;
nvrhi::BufferHandle m_instance_buffer;
nvrhi::BufferHandle m_static_command_buffer;
nvrhi::BufferHandle m_command_buffer;
nvrhi::BindingSetHandle m_culling_binding_set;
double m_sqr_distance_max;
double m_sqr_distance_min;
double m_instance_radius;
std::string m_name;
};
std::vector<GeometryBatch> m_geometry_batches;
QuadTree m_batch_quadtree;
struct TrackBatch {
std::string m_name;
glm::dvec3 m_origin;
glm::dvec3 m_extent;
glm::dvec3 m_geometry_origin;
glm::vec3 m_diffuse;
std::vector<nvrhi::DrawArguments> m_draw_commands;
gfx::geometry_handle m_geometry;
material_handle m_material;
nvrhi::BufferHandle m_command_buffer;
struct BufferRegion {
size_t m_start_vertex;
size_t m_vertex_count;
size_t m_start_index;
size_t m_index_count;
};
std::vector<BufferRegion> m_regions;
std::vector<bool> m_regions_need_update;
};
bool TrackBatchPartialUpdate(size_t batch_index, size_t track_index,
gfx::vertex_array &vertices);
std::vector<TrackBatch> m_track_batches;
QuadTree m_track_quadtree;
struct Shape {
std::string m_name;
glm::dvec3 m_origin;
glm::dvec3 m_extent;
glm::dvec3 m_geometry_origin;
gfx::geometry_handle m_geometry;
bool m_draw_in_opaque;
bool m_draw_in_transparent;
material_handle m_material;
glm::vec3 m_diffuse;
};
std::vector<Shape> m_shapes;
QuadTree m_shape_quadtree;
struct Line {
std::string m_name;
glm::dvec3 m_origin;
glm::dvec3 m_extent;
glm::dvec3 m_geometry_origin;
gfx::geometry_handle m_geometry;
float m_line_width;
glm::vec3 m_color;
float m_metalness;
float m_roughness;
};
std::vector<Line> m_lines;
QuadTree m_line_quadtree;
struct Renderable {
struct RenderableItem {
bool m_render_in_forward = false;
glm::dmat4x3 m_transform;
glm::dmat4x3 m_history_transform;
gfx::geometry_handle m_geometry;
material_handle m_material;
double m_sqr_distance_max;
double m_sqr_distance_min;
float m_opacity;
float m_selfillum;
glm::vec3 m_diffuse;
std::string_view m_name = "";
};
struct SpotLight {
glm::vec3 m_color;
glm::dvec3 m_origin;
glm::vec3 m_direction;
float m_radius;
float m_cos_inner_cone;
float m_cos_outer_cone;
};
std::vector<RenderableItem> m_items;
std::vector<SpotLight> m_spotlights;
bool m_render_in_deferred = false;
bool m_render_in_forward = false;
void Reset() {
m_items.clear();
m_spotlights.clear();
m_render_in_deferred = false;
m_render_in_forward = false;
}
};
struct AnimObj {
std::string m_name;
glm::dvec3 m_origin;
glm::dvec3 m_extent;
bool m_render_in_deferred;
bool m_render_in_forward;
bool m_animatable;
bool m_was_once_animated = false;
double m_sqr_distance_max;
double m_sqr_distance_min;
double m_distance;
TAnimModel *m_model;
Renderable m_renderable;
};
std::vector<AnimObj> m_animateds;
QuadTree m_animated_quadtree;
struct DynObj {
TDynamicObject *m_dynamic;
glm::dvec3 m_location;
double m_radius;
double m_distance;
Renderable m_renderable;
Renderable m_renderable_kabina;
};
uint32_t m_dynamic_with_kabina;
std::vector<DynObj> m_dynamics;
std::vector<uint32_t> m_renderable_dynamics;
std::vector<Renderable::SpotLight> m_renderable_spotlights;
struct Cell {
scene::basic_cell *m_cell;
glm::dvec3 m_origin;
glm::dvec3 m_extent;
};
std::vector<Cell> m_cells;
QuadTree m_cell_quadtree;
void GatherSpotLights(const RenderPass &pass);
void UpdateGeometry(gfx::geometry_handle handle, const RenderPass &pass,
bool *p_is_uploading = nullptr);
section_sequence m_sectionqueue;
cell_sequence m_cellqueue;
struct MaterialCache;
struct MaterialTemplate : public MaResourceRegistry {
struct TextureBinding {
std::string m_name;
std::string m_sampler_name;
int m_hint;
bool disable_anisotropy = false;
bool disable_filter = false;
bool disable_mip_bias = false;
texture_handle m_default_texture;
};
bool m_enable_refraction = false;
nvrhi::static_vector<TextureBinding, 8> m_texture_bindings;
std::array<nvrhi::GraphicsPipelineHandle, Constants::NumMaterialPipelines()>
m_pipelines;
std::array<MaResourceMappingSet, Constants::NumMaterialPipelines()>
m_resource_mappings;
std::string m_name;
std::string m_masked_shadow_texture;
nvrhi::BindingLayoutHandle m_binding_layout;
virtual bool CreateBindingSet(size_t pipeline_index, MaterialCache &cache);
[[nodiscard]] nvrhi::IGraphicsPipeline *GetPipeline(
RenderPassType pass_type, DrawType draw_type, bool alpha_masked) const;
virtual void Init(const YAML::Node &conf);
MaterialTemplate(const std::string &name, NvRenderer *renderer)
: m_name(name), MaResourceRegistry(renderer), m_renderer(renderer) {}
NvRenderer *m_renderer;
};
struct MaterialCache : public IMaterial, public MaResourceRegistry {
explicit MaterialCache(MaterialTemplate *my_template)
: MaResourceRegistry(my_template), m_template(my_template) {}
void Init() { InitResourceRegistry(); }
std::array<uint64_t, Constants::NumMaterialPipelines()>
m_last_texture_updates{};
std::string m_name;
std::array<nvrhi::IGraphicsPipeline *, Constants::NumMaterialPipelines()>
m_pipelines;
std::array<nvrhi::BindingSetHandle, Constants::NumMaterialPipelines()>
m_binding_sets;
std::array<texture_handle, 8> m_texture_handles;
nvrhi::BindingSetHandle m_binding_set;
nvrhi::BindingSetHandle m_binding_set_cubemap;
nvrhi::BindingSetHandle m_binding_set_shadow;
glm::dvec3 m_last_position_requested;
MaterialTemplate *m_template;
bool m_masked_shadow;
int m_shadow_rank;
uint64_t m_last_frame_requested = 0;
std::optional<float> m_opacity;
glm::dvec2 m_size;
[[nodiscard]] bool ShouldRenderInPass(const RenderPass &pass) const;
void finalize(bool Loadnow) override {}
bool update() override { return false; }
[[nodiscard]] float get_or_guess_opacity() const override {
if (m_opacity.has_value()) return *m_opacity;
if (m_masked_shadow)
return 0.0f;
else
return 0.5f;
}
bool is_translucent() const override { return m_masked_shadow; }
glm::vec2 GetSize() const override { return m_size; }
std::string GetName() const override { return m_name; }
std::optional<float> GetSelfillum() const override { return std::nullopt; }
texture_handle GetTexture(int slot) const override { return m_texture_handles[slot]; };
int GetShadowRank() const override { return m_shadow_rank; }
};
std::unordered_map<std::string, material_handle> m_material_map;
std::vector<MaterialCache> m_material_cache;
bool m_scene_initialized = false;
bool m_envir_can_filter = false;
std::array<nvrhi::InputLayoutHandle, static_cast<size_t>(DrawType::Num)>
m_input_layouts;
nvrhi::InputLayoutHandle GetInputLayout(DrawType draw_type);
struct DrawConstants {
glm::mat4 m_jittered_projection;
glm::mat4 m_projection;
glm::mat4 m_projection_history;
};
struct CubeDrawConstants {
glm::mat4 m_face_projection;
};
struct PushConstantsDraw {
glm::mat3x4 m_modelview;
glm::mat3x4 m_modelview_history;
glm::vec3 m_diffuse;
float m_alpha_threshold;
float m_alpha_mult;
float m_selfillum;
};
typedef PushConstantsDraw PushConstantsCubemap;
struct PushConstantsLine {
glm::mat3x4 m_modelview;
glm::mat3x4 m_modelview_history;
glm::vec3 m_color;
float m_line_weight;
float m_metalness;
float m_roughness;
};
struct PushConstantsShadow {
glm::mat4 m_modelviewprojection;
float m_alpha_threshold;
};
bool InitMaterials();
std::unordered_map<std::string_view, std::shared_ptr<MaterialTemplate>>
m_material_templates;
nvrhi::FramebufferHandle m_framebuffer_forward;
nvrhi::BindingLayoutHandle m_binding_layout_drawconstants;
nvrhi::BindingLayoutHandle m_binding_layout_cubedrawconstants;
nvrhi::BindingLayoutHandle m_binding_layout_shadowdrawconstants;
nvrhi::BindingLayoutHandle m_binding_layout_forward;
nvrhi::BindingSetHandle m_binding_set_drawconstants;
nvrhi::BindingSetHandle m_binding_set_cubedrawconstants;
nvrhi::BindingSetHandle m_binding_set_shadowdrawconstants;
nvrhi::BindingSetHandle m_binding_set_line;
std::array<nvrhi::BindingSetHandle, 2> m_binding_set_forward;
nvrhi::BufferHandle m_cubedrawconstant_buffer;
nvrhi::BufferHandle m_drawconstant_buffer;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()> m_vertex_shader;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()> m_vertex_shader_prepass;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()>
m_vertex_shader_cubemap;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()>
m_vertex_shader_shadow;
nvrhi::BindingLayoutHandle m_binding_layout_shadow_masked;
nvrhi::BindingLayoutHandle m_binding_layout_prepass;
nvrhi::ShaderHandle m_pixel_shader_shadow_masked;
nvrhi::ShaderHandle m_pixel_shader_prepass_masked;
std::array<nvrhi::InputLayoutHandle, Constants::NumDrawTypes()>
m_input_layout;
std::array<nvrhi::GraphicsPipelineHandle, Constants::NumShadowPipelines()>
m_pso_shadow;
std::array<nvrhi::GraphicsPipelineHandle, Constants::NumShadowPipelines()>
m_pso_prepass;
nvrhi::GraphicsPipelineHandle m_pso_line;
std::condition_variable m_cv_next_frame;
glm::mat4 m_previous_projection;
struct DrawCallStat {
void Reset() {
m_drawcalls = 0;
m_triangles = 0;
}
int m_drawcalls = 0;
int m_triangles = 0;
void Draw(nvrhi::DrawArguments const &args) {
++m_drawcalls;
m_triangles += args.vertexCount * args.instanceCount / 3;
}
};
DrawCallStat m_drawcalls_shape{};
DrawCallStat m_drawcalls_line{};
DrawCallStat m_drawcalls_tanimobj{};
DrawCallStat m_drawcalls_dynamic{};
DrawCallStat m_drawcalls_track{};
DrawCallStat m_drawcalls_instances{};
DrawCallStat *m_drawcall_counter = nullptr;
bool m_draw_shapes = true;
bool m_draw_lines = true;
bool m_draw_tanimobj = true;
bool m_draw_dynamic = true;
bool m_draw_track = true;
bool m_draw_instances = true;
bool m_sort_batches = true;
bool m_sort_transparents = true;
bool m_pause_animations = false;
std::unordered_set<const void *> m_batched_instances;
static const void *CombinePointers(const void *a, const void *b) {
union {
struct {
uint32_t a;
uint32_t b;
};
const void *c;
} val{};
val.a = static_cast<uint32_t>(reinterpret_cast<uint64_t>(a));
val.b = static_cast<uint32_t>(reinterpret_cast<uint64_t>(b));
return val.c;
}
static double SqrDistToScreenSize(double sqr_dist, double radius) {
double dist = glm::sqrt(sqr_dist);
glm::dmat4 std_projection =
glm::perspectiveRH_ZO(glm::radians(45.), 1., .1, 2e5);
glm::dvec4 ndc = std_projection * glm::dvec4(0., radius, -dist, 1.);
return glm::abs(ndc.y / ndc.w);
};
void UpdateDrawData(const RenderPass &pass, const glm::dmat4 &transform,
const glm::dmat4 &history_transform,
float opacity_threshold, float opacity_mult,
float selfillum, const glm::vec3& diffuse);
void UpdateDrawDataLine(const RenderPass &pass, const glm::dmat4 &transform,
const glm::dmat4 &history_transform,
const Line &line);
void BindConstants(const RenderPass &pass, nvrhi::GraphicsState &gfx_state);
bool BindMaterial(material_handle handle, DrawType draw_type,
const RenderPass &pass, nvrhi::GraphicsState &gfx_state,
float &alpha_threshold, bool *out_is_refractive = nullptr);
bool BindLineMaterial(DrawType draw_type, const RenderPass &pass,
nvrhi::GraphicsState &gfx_state);
bool BindGeometry(gfx::geometry_handle handle, const RenderPass &pass,
nvrhi::GraphicsState &gfx_state, nvrhi::DrawArguments &args,
bool &indexed);
void GatherModelsForBatching();
void GatherTracksForBatching();
void GatherShapesForBatching();
void GatherAnimatedsForBatching();
void GatherCellsForAnimation();
void GatherDynamics();
void RenderBatches(const RenderPass &pass);
void RenderTracks(const RenderPass &pass);
void RenderShapes(const RenderPass &pass);
void RenderLines(const RenderPass &pass);
void RenderAnimateds(const RenderPass &pass);
void RenderKabina(const RenderPass &pass);
void Render(const Renderable &renderable, const RenderPass &pass,
const glm::dvec3 &history_origin, const double distance);
void Animate(const glm::dvec3 &origin, double radius, uint64_t frame);
void Render(TAnimModel *Instance, const RenderPass &pass);
bool Render(TDynamicObject *Dynamic, const RenderPass &pass);
bool Render(TModel3d *Model, material_data const *Material,
float const Squaredistance, const RenderPass &pass);
void Render(TSubModel *Submodel, const RenderPass &pass);
bool Render_cab(TDynamicObject const *Dynamic, const RenderPass &pass);
void Animate(AnimObj &instance, const glm::dvec3 &origin, uint64_t frame);
void Animate(DynObj &instance, const glm::dvec3 &origin, uint64_t frame);
void Animate(Renderable &renderable, TModel3d *Model,
const material_data *material, double distance,
const glm::dvec3 &position, const glm::vec3 &angle,
uint64_t frame);
void Animate(Renderable &renderable, TModel3d *Model,
const material_data *material, double distance,
const glm::dmat4 &transform, uint64_t frame);
void Animate(Renderable &renderable, TSubModel *Submodel,
const material_data *material, double distance,
const glm::dmat4 &transform, uint64_t frame);
#if LIBMANUL_WITH_D3D12
bool InitForD3D12(GLFWwindow *Window);
#endif
#if LIBMANUL_WITH_VULKAN
bool InitForVulkan(GLFWwindow *Window);
#endif
};