#include #include #include #include #include #include #include #include #include #include #include //#include //#include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace entt::literals; const char* argv0; static void setup_textures(MM::Engine& engine) { auto& rm_t = MM::ResourceManager::ref(); auto [w, h] = engine.getService().getWindowSize(); // we dont have a gbuffer in this example { // gbuffer // depth #ifdef MM_OPENGL_3_GLES rm_t.reload( "depth", GL_DEPTH_COMPONENT24, // d16 is the onlyone for gles 2 (TODO: test for 3) w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); #else rm_t.reload( "depth", GL_DEPTH_COMPONENT32F, // TODO: stencil? w, h, GL_DEPTH_COMPONENT, GL_FLOAT ); #endif #if 0 // albedo rm_t.reload( "albedo", #ifdef MM_OPENGL_3_GLES GL_RGB565, #else GL_RGBA8, // waste of A #endif w, h, GL_RGB, GL_UNSIGNED_BYTE ); #endif #if 0 // normal rm_t.reload( "normal", // prolly fine, but need to remapp to -1,1 #ifdef MM_OPENGL_3_GLES GL_RGB565, #else GL_RGBA8, // waste of A #endif w, h, GL_RGB, GL_UNSIGNED_BYTE ); #endif } const float render_scale = 1.f; // hdr color gles3 / webgl2 rm_t.reload( "hdr_color", GL_RGBA16F, w * render_scale, h * render_scale, GL_RGBA, GL_HALF_FLOAT ); { // filter rm_t.get("hdr_color"_hs)->bind(0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } static void setup_fbos(MM::Engine& engine) { auto& rs = engine.getService(); auto& rm_t = MM::ResourceManager::ref(); const float render_scale = 1.f; #if 0 rs.targets["clear_opaque"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("albedo"_hs), GL_COLOR_ATTACHMENT0) .attachTexture(rm_t.get("opaque_depth"_hs), GL_DEPTH_ATTACHMENT) .setResize(true) .finish(); assert(rs.targets["clear_opaque"]); rs.targets["clear_opaque_normal"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("normal"_hs), GL_COLOR_ATTACHMENT0) .setResize(true) .finish(); assert(rs.targets["clear_opaque"]); rs.targets["opaque"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("albedo"_hs), GL_COLOR_ATTACHMENT0) .attachTexture(rm_t.get("normal"_hs), GL_COLOR_ATTACHMENT1) .attachTexture(rm_t.get("opaque_depth"_hs), GL_DEPTH_ATTACHMENT) .setResize(true) .finish(); assert(rs.targets["opaque"]); rs.targets["tmp_read"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("normal"_hs), GL_COLOR_ATTACHMENT0) .setResize(false) .finish(); assert(rs.targets["tmp_read"]); rs.targets["depth_read"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("opaque_depth"_hs), GL_DEPTH_ATTACHMENT) .setResize(false) .finish(); assert(rs.targets["depth_read"]); rs.targets["deferred_shading"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("hdr_color"_hs), GL_COLOR_ATTACHMENT0) .setResize(true) .finish(); assert(rs.targets["deferred_shading"]); #endif rs.targets["game_view"] = MM::OpenGL::FBOBuilder::start() .attachTexture(rm_t.get("hdr_color"_hs), GL_COLOR_ATTACHMENT0) .attachTexture(rm_t.get("depth"_hs), GL_DEPTH_ATTACHMENT) .setResizeFactors(render_scale, render_scale) .setResize(true) .finish(); assert(rs.targets["game_view"]); } TEST(hdr_bloom_pipeline, it) { MM::Engine engine; auto& sdl_ss = engine.addService(); ASSERT_TRUE(engine.enableService()); sdl_ss.createGLWindow("hdr_bloom_pipeline_example", 1280, 720); engine.addService(); ASSERT_TRUE(engine.enableService()); bool provide_ret = engine.provide(); ASSERT_TRUE(provide_ret); auto& scene = engine.tryService()->getScene(); engine.addService(argv0, "hdr_bloom_pipeline_example"); ASSERT_TRUE(engine.enableService()); auto& rs = engine.addService(); ASSERT_TRUE(engine.enableService()); { // setup rendering // TODO: split vertically setup_textures(engine); setup_fbos(engine); // clear auto& clear_opaque = rs.addRenderTask(engine); clear_opaque.target_fbo = "game_view"; // clears all color attachments clear_opaque.r = 0.f; clear_opaque.g = 0.f; clear_opaque.b = 0.f; clear_opaque.a = 1.f; clear_opaque.mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; { // render, whatever MM::OpenGL::RenderTasks::SimpleRect& bsrr_rend = rs.addRenderTask(engine); bsrr_rend.target_fbo = "game_view"; } // rn does rt too MM::OpenGL::setup_bloom(engine); // not part of setup_bloom auto& comp = rs.addRenderTask(engine); comp.color_tex = "hdr_color"; comp.bloom_tex = "blur_tmp1"; comp.target_fbo = "display"; } scene.on_construct().connect<&entt::registry::emplace_or_replace>(); scene.on_construct().connect<&entt::registry::emplace_or_replace>(); scene.on_construct().connect<&entt::registry::emplace_or_replace>(); scene.on_construct().connect<&entt::registry::emplace_or_replace>(); scene.on_update().connect<&entt::registry::emplace_or_replace>(); scene.on_update().connect<&entt::registry::emplace_or_replace>(); scene.on_update().connect<&entt::registry::emplace_or_replace>(); scene.on_update().connect<&entt::registry::emplace_or_replace>(); scene.on_update().connect<&entt::registry::emplace_or_replace>(); // in this example only rotation is touched // setup v system auto& org = scene.set(); org.emplace("simple_rotational_velocity_patching"); org.emplace("position3d_from_2d"); org.emplace("transform3d_translate"); org.emplace("transform3d_rotate2d"); org.emplace("transform3d_scale2d"); org.emplace("transform_clear_dirty"); // HACK: instead you would switch to this scene engine.getService().updateOrganizerVertices(scene); MM::Random::SRNG rng{42}; for (int i = 0; i < 5; i++) { auto e = scene.create(); auto& p = scene.emplace(e); p.pos.x = 0.f; p.pos.y = 25.f - i * 10.f; auto& s = scene.emplace(e); s.scale = {50.f, i*0.2f + 0.1f}; auto& col = scene.emplace(e); col.color = {3.f, 3.f, 3.f, 1.f}; } for (int i = 0; i < 10; i++) { auto e = scene.create(); auto& p = scene.emplace(e); p.pos.x = i * 9.f - 40; // zoffset is created by event auto& s = scene.emplace(e); s.scale = {5,5}; scene.emplace(e); auto& v = scene.emplace(e); v.rot_vel = i * 0.3f; auto& col = scene.emplace(e); col.color = {rng.zeroToOne()*2.f, rng.zeroToOne()*2.f, rng.zeroToOne()*2.f, 1.f}; } engine.run(); } int main(int argc, char** argv) { argv0 = argv[0]; ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }