Commit b10a8d6d authored by Florian Oetke's avatar Florian Oetke
Browse files

frustum culling and renderer refactoring (implements #27)

parent 267a0b94
......@@ -12,6 +12,7 @@ frag_shader:shadow_model = shader/bin/shadow_model.frag.spv
vert_shader:model = shader/bin/model.vert.spv
frag_shader:model = shader/bin/model.frag.spv
frag_shader:model_emissive = shader/bin/model_emissive.frag.spv
frag_shader:model_alphatest = shader/bin/model_alphatest.frag.spv
vert_shader:ui = shader/bin/ui.vert.spv
frag_shader:ui = shader/bin/ui.frag.spv
......
......@@ -5,6 +5,8 @@
#include "global_uniforms.glsl"
#include "normal_encoding.glsl"
layout(early_fragment_tests) in;
layout(location = 0) in vec3 world_pos;
layout(location = 1) in vec3 view_pos;
layout(location = 2) in vec3 normal;
......@@ -33,9 +35,6 @@ vec3 tangent_space_to_world(vec3 N);
void main() {
vec4 albedo = texture(albedo_sampler, tex_coords);
if(albedo.a < 0.1)
discard;
vec4 mat_data = texture(mat_data_sampler, tex_coords);
vec3 normal = tangent_space_to_world(decode_tangent_normal(mat_data.rg));
......
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#include "global_uniforms.glsl"
#include "normal_encoding.glsl"
layout(location = 0) in vec3 world_pos;
layout(location = 1) in vec3 view_pos;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec2 tex_coords;
layout(location = 0) out vec4 depth_out;
layout(location = 1) out vec4 albedo_mat_id_out;
layout(location = 2) out vec4 mat_data_out;
layout(set=1, binding = 0) uniform sampler2D albedo_sampler;
layout(set=1, binding = 1) uniform sampler2D mat_data_sampler;
layout(push_constant) uniform Per_model_uniforms {
mat4 model;
vec4 light_color;
vec4 options;
} model_uniforms;
const float PI = 3.14159265359;
vec3 decode_tangent_normal(vec2 tn);
vec3 tangent_space_to_world(vec3 N);
void main() {
vec4 albedo = texture(albedo_sampler, tex_coords);
if(albedo.a < 0.1)
discard;
vec4 mat_data = texture(mat_data_sampler, tex_coords);
vec3 normal = tangent_space_to_world(decode_tangent_normal(mat_data.rg));
float roughness = mat_data.b;
float metallic = mat_data.a;
roughness = mix(0.01, 0.99, roughness*roughness);
depth_out = vec4(-view_pos.z / global_uniforms.proj_planes.y, 0,0,1);
albedo_mat_id_out = vec4(albedo.rgb, 0.0);
mat_data_out = vec4(encode_normal(normal), roughness, metallic);
float disect = model_uniforms.options.x;
if(disect>0 && world_pos.z>=disect)
discard;
}
vec3 decode_tangent_normal(vec2 tn) {
if(dot(tn,tn)<0.00001)
return vec3(0,0,1);
vec3 N = vec3(tn*2-1, 0);
N.z = sqrt(1 - dot(N.xy, N.xy));
return N;
}
vec3 tangent_space_to_world(vec3 N) {
vec3 VN = normalize(normal);
// calculate tangent
vec3 p_dx = dFdx(view_pos);
vec3 p_dy = dFdy(view_pos);
vec2 tc_dx = dFdx(tex_coords);
vec2 tc_dy = dFdy(tex_coords);
vec3 p_dy_N = cross(p_dy, VN);
vec3 p_dx_N = cross(VN, p_dx);
vec3 T = p_dy_N * tc_dx.x + p_dx_N * tc_dy.x;
vec3 B = p_dy_N * tc_dx.y + p_dx_N * tc_dy.y;
float inv_max = inversesqrt(max(dot(T,T), dot(B,B)));
mat3 TBN = mat3(T*inv_max, B*inv_max, VN);
return normalize(TBN * N);
}
......@@ -5,6 +5,8 @@
#include "global_uniforms.glsl"
#include "normal_encoding.glsl"
layout(early_fragment_tests) in;
layout(location = 0) in vec3 world_pos;
layout(location = 1) in vec3 view_pos;
layout(location = 2) in vec3 normal;
......@@ -28,9 +30,6 @@ layout(push_constant) uniform Per_model_uniforms {
void main() {
vec4 albedo = texture(albedo_sampler, tex_coords);
if(albedo.a < 0.1)
discard;
depth_out = vec4(-view_pos.z / global_uniforms.proj_planes.y, 0,0,1);
albedo_mat_id = vec4(albedo.rgb, 1.0);
mat_data = vec4(encode_normal(normalize(normal)), 0.0, 0.0);
......
......@@ -24,8 +24,11 @@ add_subdirectory(sf2)
if(MIRRAGE_BUILD_MESH_CONVERTER)
add_subdirectory(assimp)
set_property(TARGET assimp PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/assimp/include" "${CMAKE_CURRENT_BINARY_DIR}/assimp/include")
find_package(assimp 4.1)
if(NOT assimp_FOUND)
add_subdirectory(assimp)
set_property(TARGET assimp PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/assimp/include" "${CMAKE_CURRENT_BINARY_DIR}/assimp/include")
endif()
add_subdirectory(stb_image)
endif()
......@@ -4,6 +4,7 @@
#include <mirrage/renderer/pass/blit_pass.hpp>
#include <mirrage/renderer/pass/bloom_pass.hpp>
#include <mirrage/renderer/pass/deferred_pass.hpp>
#include <mirrage/renderer/pass/frustum_culling_pass.hpp>
#include <mirrage/renderer/pass/gen_mipmap_pass.hpp>
#include <mirrage/renderer/pass/gi_pass.hpp>
#include <mirrage/renderer/pass/gui_pass.hpp>
......@@ -25,10 +26,10 @@ namespace mirrage {
char** env)
: Engine(org, title, version_major, version_minor, debug, false, argc, argv, env)
, _renderer_factory(std::make_unique<renderer::Deferred_renderer_factory>(
graphics_context(),
*this,
window(),
assets(),
util::make_vector(renderer::make_pass_factory<renderer::Shadowmapping_pass_factory>(),
util::make_vector(renderer::make_pass_factory<renderer::Frustum_culling_pass_factory>(),
renderer::make_pass_factory<renderer::Shadowmapping_pass_factory>(),
renderer::make_pass_factory<renderer::Deferred_pass_factory>(),
renderer::make_pass_factory<renderer::Gen_mipmap_pass_factory>(),
renderer::make_pass_factory<renderer::Ssao_pass_factory>(),
......
......@@ -11,7 +11,7 @@ namespace mirrage {
Meta_system::Meta_system(Game_engine& engine)
: _entities(engine.assets(), this)
, _renderer(engine.renderer_factory().create_renderer(_entities, *this))
, _renderer(engine.renderer_factory().create_renderer(_entities))
, _model_loading(std::make_unique<renderer::Loading_system>(_entities, engine.assets()))
, _nims(std::make_unique<systems::Nim_system>(_entities))
{
......
......@@ -64,10 +64,7 @@ namespace mirrage {
: Screen(engine)
, _mailbox(engine.bus())
, _meta_system(static_cast<Game_engine&>(engine))
, _gui(engine.window().viewport(),
engine.assets(),
engine.input(),
_meta_system.renderer().find_pass<gui::Gui_renderer>())
, _gui(engine.gui())
, _performance_log(util::nothing)
, _window_width(engine.window().width())
, _window_height(engine.window().height())
......@@ -320,8 +317,6 @@ namespace mirrage {
void Test_screen::_draw()
{
_gui.start_frame();
if(_show_ui) {
_draw_settings_window();
_draw_histogram_window();
......
......@@ -40,7 +40,7 @@ namespace mirrage {
Meta_system _meta_system;
gui::Gui _gui;
gui::Gui& _gui;
ecs::Entity_facet _camera;
ecs::Entity_facet _sun;
......
......@@ -11,6 +11,7 @@
#include <assimp/scene.h> // Output data structure
#include <assimp/Importer.hpp> // C++ importer interface
#include <glm/gtx/norm.hpp>
#include <gsl/gsl>
#include <fstream>
......@@ -70,6 +71,35 @@ namespace mirrage {
out.write(reinterpret_cast<const char*>(value.data()), value.size() * sizeof(T));
}
struct Bounding_sphere_calculator {
bool first_point = true;
glm::vec3 min_vertex_pos;
glm::vec3 max_vertex_pos;
glm::vec3 center;
float radius_2 = 0.0f;
void add_point(glm::vec3 p)
{
if(first_point) {
first_point = false;
min_vertex_pos = p;
max_vertex_pos = p;
return;
}
min_vertex_pos.x = std::min(min_vertex_pos.x, p.x);
min_vertex_pos.y = std::min(min_vertex_pos.y, p.y);
min_vertex_pos.z = std::min(min_vertex_pos.z, p.z);
max_vertex_pos.x = std::max(max_vertex_pos.x, p.x);
max_vertex_pos.y = std::max(max_vertex_pos.y, p.y);
max_vertex_pos.z = std::max(max_vertex_pos.z, p.z);
}
void start_process() { center = min_vertex_pos + (max_vertex_pos - min_vertex_pos) / 2.f; }
void process_point(glm::vec3 p) { radius_2 = std::max(radius_2, glm::distance2(p, center)); }
};
} // namespace
......@@ -124,6 +154,8 @@ namespace mirrage {
vertex_count += mesh->mNumVertices;
}
auto rigged = false; // TODO
// load meshes
auto indices = std::vector<std::uint32_t>();
auto vertices = std::vector<renderer::Model_vertex>();
......@@ -167,9 +199,30 @@ namespace mirrage {
"Unable to open output file \"" << model_out_filename << "\"!");
auto header = renderer::Model_file_header();
header.vertex_count = gsl::narrow<std::uint32_t>(vertices.size() * sizeof(renderer::Model_vertex));
header.index_count = gsl::narrow<std::uint32_t>(indices.size() * sizeof(std::uint32_t));
header.vertex_size = gsl::narrow<std::uint32_t>(vertices.size() * sizeof(renderer::Model_vertex));
header.index_size = gsl::narrow<std::uint32_t>(indices.size() * sizeof(std::uint32_t));
header.submesh_count = gsl::narrow<std::uint32_t>(sub_meshes.size());
header.flags = rigged ? 1 : 0;
// calculate bounding sphere
auto bounding_sphere = Bounding_sphere_calculator{};
for(auto& v : vertices) {
bounding_sphere.add_point(v.position);
}
bounding_sphere.start_process();
for(auto& v : vertices) {
bounding_sphere.process_point(v.position);
}
header.bounding_sphere_radius = std::sqrt(bounding_sphere.radius_2);
header.bounding_sphere_offset_x = bounding_sphere.center.x;
header.bounding_sphere_offset_y = bounding_sphere.center.y;
header.bounding_sphere_offset_z = bounding_sphere.center.z;
LOG(plog::debug) << "Bounds: " << header.bounding_sphere_radius << " at "
<< header.bounding_sphere_offset_x << "/" << header.bounding_sphere_offset_y << "/"
<< header.bounding_sphere_offset_z;
// write header
write(model_out_file, header);
......@@ -179,6 +232,28 @@ namespace mirrage {
write(model_out_file, sub_mesh.index_offset);
write(model_out_file, sub_mesh.index_count);
// calculate bounding sphere
auto bounding_sphere = Bounding_sphere_calculator{};
for(auto i = 0u; i < sub_mesh.index_count; i++) {
auto idx = indices.at(i + sub_mesh.index_offset);
bounding_sphere.add_point(vertices.at(idx).position);
}
bounding_sphere.start_process();
for(auto i = 0u; i < sub_mesh.index_count; i++) {
auto idx = indices.at(i + sub_mesh.index_offset);
bounding_sphere.process_point(vertices.at(idx).position);
}
write(model_out_file, std::sqrt(bounding_sphere.radius_2));
write(model_out_file, bounding_sphere.center.x);
write(model_out_file, bounding_sphere.center.y);
write(model_out_file, bounding_sphere.center.z);
LOG(plog::debug) << "Sub-Bounds: " << std::sqrt(bounding_sphere.radius_2) << " at "
<< bounding_sphere.center.x << "/" << bounding_sphere.center.y << "/"
<< bounding_sphere.center.z;
auto material_id_length = gsl::narrow<std::uint32_t>(sub_mesh.material_id.size());
write(model_out_file, material_id_length);
model_out_file.write(sub_mesh.material_id.data(), material_id_length);
......
......@@ -74,6 +74,7 @@ namespace mirrage {
auto& screens() noexcept { return _screens; }
auto& translator() noexcept { return *_translator; }
auto& net() noexcept { return *_net_manager; }
auto& gui() noexcept { return *_gui; }
protected:
virtual void _on_pre_frame(util::Time) {}
......@@ -96,6 +97,7 @@ namespace mirrage {
std::unique_ptr<input::Input_manager> _input_manager;
std::unique_ptr<Engine_event_filter> _event_filter;
std::unique_ptr<net::Net_manager> _net_manager;
std::unique_ptr<gui::Gui> _gui;
double _current_time = 0;
double _last_time = 0;
......
......@@ -3,6 +3,7 @@
#include <mirrage/asset/asset_manager.hpp>
#include <mirrage/graphic/context.hpp>
#include <mirrage/graphic/window.hpp>
#include <mirrage/gui/gui.hpp>
#include <mirrage/input/input_manager.hpp>
#include <mirrage/net/net_manager.hpp>
#include <mirrage/translations.hpp>
......@@ -116,6 +117,8 @@ namespace mirrage {
_graphics_main_window.process([&](auto& window) {
_input_manager->viewport({0, 0, window.width(), window.height()});
_input_manager->window(window.window_handle());
_gui = std::make_unique<gui::Gui>(window.viewport(), *_asset_manager, *_input_manager);
});
if(headless) {
......@@ -199,6 +202,9 @@ namespace mirrage {
_on_pre_frame(delta_time_smoothed * second);
if(_gui)
_gui->start_frame();
_screens.on_frame(delta_time_smoothed * second);
_on_post_frame(delta_time_smoothed * second);
......
......@@ -24,6 +24,7 @@ namespace mirrage::ecs::components {
void rotate_local(float yaw, float pitch);
auto to_mat4() const noexcept -> glm::mat4;
auto to_mat3() const noexcept -> glm::mat3;
glm::vec3 position{0, 0, 0};
glm::quat orientation{1, 0, 0, 0};
......
......@@ -46,7 +46,7 @@ namespace mirrage::ecs {
// user interface; thread-safe
auto emplace() noexcept -> Entity_facet;
auto emplace(const std::string& blueprint) -> Entity_facet;
auto emplace(const std::string& blueprint) -> Entity_facet; // TODO/FIXME: currently NOT thread-safe
auto get(Entity_handle entity) -> util::maybe<Entity_facet>;
auto get_handle(Entity_id id) const -> Entity_handle { return _handles.get(id); }
auto validate(Entity_handle entity) -> bool { return _handles.valid(entity); }
......
......@@ -38,4 +38,13 @@ namespace mirrage::ecs::components {
model[3] = glm::vec4(position, 1.f);
return model;
}
auto Transform_comp::to_mat3() const noexcept -> glm::mat3
{
// clang-format off
return glm::toMat3(orientation) * glm::mat3(
scale.x, 0, 0,
0, scale.y, 0,
0, 0, scale.z);
// clang-format on
}
} // namespace mirrage::ecs::components
......@@ -58,7 +58,8 @@ namespace mirrage::gui {
class Gui_renderer {
public:
virtual ~Gui_renderer() = default;
Gui_renderer(Gui& gui);
virtual ~Gui_renderer();
void draw_gui();
......@@ -81,7 +82,7 @@ namespace mirrage::gui {
virtual void finalize_draw() = 0;
private:
Gui* _gui = nullptr;
Gui* _gui;
};
// TODO: gamepad input: https://gist.github.com/vurtun/519801825b4ccfad6767
......@@ -90,17 +91,13 @@ namespace mirrage::gui {
// https://github.com/vurtun/nuklear/blob/master/example/skinning.c
class Gui {
public:
Gui(glm::vec4 viewport,
asset::Asset_manager& assets,
input::Input_manager& input,
util::tracking_ptr<Gui_renderer> renderer);
Gui(glm::vec4 viewport, asset::Asset_manager& assets, input::Input_manager& input);
~Gui();
void draw();
void start_frame();
auto ctx() -> nk_context*;
auto renderer() noexcept -> auto& { return _renderer; }
void viewport(glm::vec4 new_viewport);
......@@ -108,16 +105,19 @@ namespace mirrage::gui {
auto centered_left(int width, int height) -> struct nk_rect;
auto centered_right(int width, int height) -> struct nk_rect;
auto ready() const noexcept { return bool(_impl); }
private:
friend class Gui_renderer;
struct PImpl;
glm::vec4 _viewport;
asset::Asset_manager& _assets;
input::Input_manager& _input;
util::tracking_ptr<Gui_renderer> _renderer;
Gui_renderer* _last_renderer;
std::unique_ptr<PImpl> _impl;
glm::vec4 _viewport;
asset::Asset_manager& _assets;
input::Input_manager& _input;
Gui_renderer* _renderer = nullptr;
Gui_renderer* _last_renderer = nullptr;
std::unique_ptr<PImpl> _impl;
void _init();
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment