diff --git a/src/app/main.cpp b/src/app/main.cpp index 7138f7cd8..6c809fbcb 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -475,7 +475,7 @@ public: m_engine->update(*m_universe); m_pipeline->render(); auto* renderer = m_engine->getPluginManager().getPlugin("renderer"); - static_cast(renderer)->frame(false); + static_cast(renderer)->frame(); m_engine->getFileSystem().updateAsyncTransactions(); if (frame_time < 1 / 60.0f) { diff --git a/src/engine/job_system.cpp b/src/engine/job_system.cpp index 77ec1d6f5..85fa0675e 100644 --- a/src/engine/job_system.cpp +++ b/src/engine/job_system.cpp @@ -65,8 +65,8 @@ struct System MT::Event m_work_signal; Array m_workers; Array m_job_queue; - FiberDecl m_fiber_pool[256]; - int m_free_fibers_indices[256]; + FiberDecl m_fiber_pool[512]; + int m_free_fibers_indices[512]; int m_num_free_fibers; Array m_sleeping_fibers; IAllocator& m_allocator; diff --git a/src/engine/no_resources.cpp b/src/engine/no_resources.cpp deleted file mode 100644 index c894fdb52..000000000 --- a/src/engine/no_resources.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "stb/mf_resource.h" -const mf_resource* mf_resources = nullptr; -int mf_resources_count = 0; diff --git a/src/renderer/editor/plugins.cpp b/src/renderer/editor/plugins.cpp index e1f9a9c95..d06227d51 100644 --- a/src/renderer/editor/plugins.cpp +++ b/src/renderer/editor/plugins.cpp @@ -1515,12 +1515,13 @@ struct EnvironmentProbePlugin final : public PropertyGrid::IPlugin void generateCubemap(ComponentUID cmp) { - // TODO - /*static const int TEXTURE_SIZE = 1024; + ASSERT(cmp.isValid()); + const EntityRef entity = (EntityRef)cmp.entity; + + static const int TEXTURE_SIZE = 1024; Universe* universe = m_app.getWorldEditor().getUniverse(); - if (universe->getName()[0] == '\0') - { + if (universe->getName()[0] == '\0') { g_log_error.log("Editor") << "Universe must be saved before environment probe can be generated."; return; } @@ -1532,46 +1533,40 @@ struct EnvironmentProbePlugin final : public PropertyGrid::IPlugin Vec3 probe_position = universe->getPosition((EntityRef)cmp.entity); auto* scene = static_cast(universe->getScene(CAMERA_TYPE)); - EntityRef camera_entity = scene->getCameraInSlot("probe"); - if (!camera_entity.isValid()) - { - g_log_error.log("Renderer") << "No camera in slot 'probe'."; - return; - } - - scene->setCameraFOV(camera_entity, Math::degreesToRadians(90)); + Viewport viewport; + viewport.is_ortho = false; + viewport.fov = Math::degreesToRadians(90.f); + viewport.near = 0.1f; + viewport.far = 10000.f; + viewport.w = TEXTURE_SIZE; + viewport.h = TEXTURE_SIZE; m_pipeline->setScene(scene); - // TODO - //m_pipeline->resize(TEXTURE_SIZE, TEXTURE_SIZE); + m_pipeline->setViewport(viewport); Renderer* renderer = static_cast(plugin_manager.getPlugin("renderer")); - Vec3 dirs[] = {{-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}}; Vec3 ups[] = {{0, 1, 0}, {0, 1, 0}, {0, 0, 1}, {0, 0, -1}, {0, 1, 0}, {0, 1, 0}}; Vec3 ups_opengl[] = { { 0, -1, 0 },{ 0, -1, 0 },{ 0, 0, 1 },{ 0, 0, -1 },{ 0, -1, 0 },{ 0, -1, 0 } }; Array data(allocator); data.resize(6 * TEXTURE_SIZE * TEXTURE_SIZE * 4); - ffr::TextureHandle texture = ffr::allocTextureHandle(); - ffr::createTexture(texture, TEXTURE_SIZE, TEXTURE_SIZE, ffr::TextureFormat::RGBA8, 0, nullptr); - renderer->frame(false); // submit - renderer->frame(false); // wait for gpu - for (int i = 0; i < 6; ++i) - { - Matrix mtx = Matrix::IDENTITY; - mtx.setTranslation(probe_position); + renderer->startCapture(); + for (int i = 0; i < 6; ++i) { const bool ndc_bottom_left = ffr::isOriginBottomLeft(); Vec3 side = crossProduct(ndc_bottom_left ? ups_opengl[i] : ups[i], dirs[i]); + Matrix mtx = Matrix::IDENTITY; mtx.setZVector(dirs[i]); mtx.setYVector(ndc_bottom_left ? ups_opengl[i] : ups[i]); mtx.setXVector(side); - universe->setMatrix(camera_entity, mtx); + viewport.pos = probe_position; + viewport.rot = mtx.getRotation(); + m_pipeline->setViewport(viewport); m_pipeline->render(); const ffr::TextureHandle res = m_pipeline->getOutput(); - ffr::getTextureImage(res, TEXTURE_SIZE * TEXTURE_SIZE * 4, &data[i * TEXTURE_SIZE * TEXTURE_SIZE * 4]); + renderer->getTextureImage(res, TEXTURE_SIZE * TEXTURE_SIZE * 4, &data[i * TEXTURE_SIZE * TEXTURE_SIZE * 4]); if (ndc_bottom_left) continue; @@ -1585,6 +1580,10 @@ struct EnvironmentProbePlugin final : public PropertyGrid::IPlugin flipX(tmp, TEXTURE_SIZE); } } + renderer->stopCapture(); + renderer->frame(); + renderer->frame(); + cmft::Image image; cmft::Image irradiance; @@ -1612,29 +1611,38 @@ struct EnvironmentProbePlugin final : public PropertyGrid::IPlugin cmft::imageFromRgba32f(image, cmft::TextureFormat::RGBA8); cmft::imageFromRgba32f(irradiance, cmft::TextureFormat::RGBA8); - - int irradiance_size = 32; int radiance_size = 128; int reflection_size = TEXTURE_SIZE; - if (scene->isEnvironmentProbeCustomSize(cmp.entity)) - { - irradiance_size = scene->getEnvironmentProbeIrradianceSize(cmp.entity); - radiance_size = scene->getEnvironmentProbeRadianceSize(cmp.entity); - reflection_size = scene->getEnvironmentProbeReflectionSize(cmp.entity); + if (scene->isEnvironmentProbeCustomSize(entity)) { + irradiance_size = scene->getEnvironmentProbeIrradianceSize(entity); + radiance_size = scene->getEnvironmentProbeRadianceSize(entity); + reflection_size = scene->getEnvironmentProbeReflectionSize(entity); } + for (int i = 3; i < data.size(); i += 4) data[i] = 0xff; saveCubemap(cmp, (u8*)irradiance.m_data, irradiance_size, "_irradiance"); saveCubemap(cmp, (u8*)image.m_data, radiance_size, "_radiance"); - if (scene->isEnvironmentProbeReflectionEnabled(cmp.entity)) - { + if (scene->isEnvironmentProbeReflectionEnabled(entity)) { + auto& fs = m_app.getWorldEditor().getEngine().getFileSystem(); + for(int i = 0; i < 6; ++i) { + const char* pp[] = { + "test0.tga", + "test1.tga", + "test2.tga", + "test3.tga", + "test4.tga", + "test5.tga", + }; + auto* f = fs.open(fs.getDefaultDevice(), Path(pp[i]), FS::Mode::CREATE_AND_WRITE); + Lumix::Texture::saveTGA(f, TEXTURE_SIZE, TEXTURE_SIZE, 4, data.begin() + 4 * TEXTURE_SIZE * TEXTURE_SIZE * i, Path(pp[i]), m_app.getWorldEditor().getAllocator()); + fs.close(*f); + } saveCubemap(cmp, &data[0], reflection_size, ""); } - ffr::destroy(texture); - - scene->reloadEnvironmentProbe(cmp.entity);*/ + scene->reloadEnvironmentProbe(entity); } @@ -2878,7 +2886,7 @@ struct EditorUIRenderPlugin final : public StudioApp::GUIPlugin cmd->plugin = this; renderer->push(cmd); - renderer->frame(false); + renderer->frame(); } diff --git a/src/renderer/ffr/ffr.cpp b/src/renderer/ffr/ffr.cpp index 80b5fea2f..085b84c9f 100644 --- a/src/renderer/ffr/ffr.cpp +++ b/src/renderer/ffr/ffr.cpp @@ -893,6 +893,16 @@ void applyUniformMatrix4x3f(int location, const float* value) glUniformMatrix4x3fv(location, 1, false, value); } +void applyUniform1i(int location, int value) +{ + glUniform1i(location, value); +} + +void applyUniform4f(int location, const float* value) +{ + glUniform4fv(location, 1, value); +} + void applyUniformMatrix3x4f(int location, const float* value) { glUniformMatrix3x4fv(location, 1, false, value); @@ -933,6 +943,9 @@ void useProgram(ProgramHandle handle) case UniformType::INT: glUniform1i(pu.loc, *(int*)u.data); break; + case UniformType::IVEC2: + glUniform2iv(pu.loc, u.count, (int*)u.data); + break; default: ASSERT(false); break; } } @@ -1160,6 +1173,22 @@ void update(BufferHandle buffer, const void* data, size_t offset, size_t size) } +void startCapture() +{ + if (g_ffr.rdoc_api) { + g_ffr.rdoc_api->StartFrameCapture(nullptr, nullptr); + } +} + + +void stopCapture() +{ + if (g_ffr.rdoc_api) { + g_ffr.rdoc_api->EndFrameCapture(nullptr, nullptr); + } +} + + void swapBuffers() { checkThread(); @@ -1553,6 +1582,7 @@ static uint getSize(UniformType type) { case UniformType::INT: return sizeof(int); case UniformType::FLOAT: return sizeof(float); + case UniformType::IVEC2: return sizeof(int) * 2; case UniformType::VEC2: return sizeof(float) * 2; case UniformType::VEC3: return sizeof(float) * 3; case UniformType::VEC4: return sizeof(float) * 4; @@ -1700,6 +1730,7 @@ ProgramHandle createProgram(const char** srcs, const ShaderType* types, int num, case GL_FLOAT_MAT4: ffr_type = UniformType::MAT4; break; case GL_FLOAT_MAT4x3: ffr_type = UniformType::MAT4X3; break; case GL_FLOAT_MAT3x4: ffr_type = UniformType::MAT3X4; break; + case GL_INT_VEC2: ffr_type = UniformType::IVEC2; break; default: ASSERT(false); ffr_type = UniformType::VEC4; break; } diff --git a/src/renderer/ffr/ffr.h b/src/renderer/ffr/ffr.h index 309597e23..60bee5d35 100644 --- a/src/renderer/ffr/ffr.h +++ b/src/renderer/ffr/ffr.h @@ -103,6 +103,7 @@ enum class UniformType : uint { VEC2, VEC3, VEC4, + IVEC2, MAT4, MAT4X3, MAT3X4 @@ -151,6 +152,8 @@ bool isHomogenousDepth(); bool isOriginBottomLeft(); void checkThread(); void shutdown(); +void startCapture(); +void stopCapture(); void clear(uint flags, const float* color, float depth); @@ -210,6 +213,8 @@ void setUniformMatrix3x4f(UniformHandle uniform, const float* value); void setUniformMatrix4f(UniformHandle uniform, const float* value); void setUniformMatrix4x3f(UniformHandle uniform, const float* value); int getUniformLocation(ProgramHandle program_handle, UniformHandle uniform); +void applyUniform1i(int location, int value); +void applyUniform4f(int location, const float* value); void applyUniformMatrix3x4f(int location, const float* value); void applyUniformMatrix4f(int location, const float* value); void applyUniformMatrix4fv(int location, uint count, const float* value); diff --git a/src/renderer/ffr/gl_ext.h b/src/renderer/ffr/gl_ext.h index fb9e10750..9c6f401e3 100644 --- a/src/renderer/ffr/gl_ext.h +++ b/src/renderer/ffr/gl_ext.h @@ -85,6 +85,7 @@ FFR_GL_IMPORT(PFNGLTEXTUREPARAMETERIPROC, glTextureParameteri); FFR_GL_IMPORT(PFNGLTEXTURESTORAGE2DPROC, glTextureStorage2D); FFR_GL_IMPORT(PFNGLTEXTURESTORAGE3DPROC, glTextureStorage3D); FFR_GL_IMPORT(PFNGLUNIFORM1IPROC, glUniform1i); +FFR_GL_IMPORT(PFNGLUNIFORM2IVPROC, glUniform2iv); FFR_GL_IMPORT(PFNGLUNIFORM1FVPROC, glUniform1fv); FFR_GL_IMPORT(PFNGLUNIFORM2FVPROC, glUniform2fv); FFR_GL_IMPORT(PFNGLUNIFORM3FVPROC, glUniform3fv); diff --git a/src/renderer/pipeline.cpp b/src/renderer/pipeline.cpp index 3077867d9..8ccaec6b7 100644 --- a/src/renderer/pipeline.cpp +++ b/src/renderer/pipeline.cpp @@ -75,6 +75,7 @@ struct PipelineImpl final : Pipeline m_draw2d.PushClipRectFullScreen(); m_draw2d.PushTextureID(font_atlas.TexID); + m_position_radius_uniform = ffr::allocUniform("u_pos_radius", ffr::UniformType::VEC4, 1); m_terrain_params_uniform = ffr::allocUniform("u_terrain_params", ffr::UniformType::VEC4, 1); m_rel_camera_pos_uniform = ffr::allocUniform("u_rel_camera_pos", ffr::UniformType::VEC4, 1); m_terrain_scale_uniform = ffr::allocUniform("u_terrain_scale", ffr::UniformType::VEC4, 1); @@ -87,6 +88,37 @@ struct PipelineImpl final : Pipeline m_radiance_map_uniform = ffr::allocUniform("u_radiancemap", ffr::UniformType::INT, 1); m_material_params_uniform = ffr::allocUniform("u_material_params", ffr::UniformType::VEC4, 1); m_material_color_uniform = ffr::allocUniform("u_material_color", ffr::UniformType::VEC4, 1); + + float cube_verts[] = { + -1, -1, -1, + 1, -1, -1, + 1, -1, 1, + -1, -1, 1, + -1, 1, -1, + 1, 1, -1, + 1, 1, 1, + -1, 1, 1 + }; + const Renderer::MemRef vb_mem = m_renderer.copy(cube_verts, sizeof(cube_verts)); + m_cube_vb = m_renderer.createBuffer(vb_mem); + + u16 cube_indices[] = { + 0, 1, 2, + 0, 2, 3, + 4, 6, 5, + 4, 7, 6, + 0, 4, 5, + 0, 5, 1, + 2, 6, 7, + 2, 7, 3, + 0, 3, 7, + 0, 7, 4, + 1, 2, 6, + 1, 6, 5 + }; + + const Renderer::MemRef ib_mem = m_renderer.copy(cube_indices, sizeof(cube_indices)); + m_cube_ib = m_renderer.createBuffer(ib_mem); } @@ -350,6 +382,8 @@ struct PipelineImpl final : Pipeline state.camera_inv_view_projection = state.camera_view_projection; state.camera_inv_view_projection.inverse(); state.time = m_timer->getTimeSinceStart(); + state.framebuffer_size.x = m_viewport.w; + state.framebuffer_size.y = m_viewport.h; const EntityPtr global_light = m_scene->getActiveGlobalLight(); if(global_light.isValid()) { @@ -516,7 +550,6 @@ struct PipelineImpl final : Pipeline vertex_decl.addAttribute(2, ffr::AttributeType::FLOAT, false, false); vertex_decl.addAttribute(4, ffr::AttributeType::U8, true, false); - ffr::BufferHandle vb = ffr::allocBufferHandle(); ffr::BufferHandle ib = ffr::allocBufferHandle(); ffr::createBuffer(vb, vtx_buffer_mem.size, vtx_buffer_mem.data); @@ -835,6 +868,168 @@ struct PipelineImpl final : Pipeline return cp; } + + static int bindTextures(lua_State* L) + { + struct Cmd : Renderer::RenderCommandBase { + void setup() override {} + void execute() override + { + for(int i = 0; i < m_textures_count; ++i) { + ffr::bindTexture(m_offset + i, m_textures[i].handle); + ffr::setUniform1i(m_textures[i].uniform, i + m_offset); + } + } + + struct { + ffr::TextureHandle handle; + ffr::UniformHandle uniform; + } m_textures[16]; + int m_offset = 0; + int m_textures_count = 0; + }; + + const int pipeline_idx = lua_upvalueindex(1); + if (lua_type(L, pipeline_idx) != LUA_TLIGHTUSERDATA) { + LuaWrapper::argError(L, pipeline_idx); + } + PipelineImpl* pipeline = LuaWrapper::toType(L, pipeline_idx); + LuaWrapper::checkTableArg(L, 1); + + const int offset = lua_gettop(L) > 1 ? LuaWrapper::checkArg(L, 2) : 0; + + Cmd* cmd = LUMIX_NEW(pipeline->m_renderer.getAllocator(), Cmd); + cmd->m_offset = offset; + lua_pushnil(L); + while (lua_next(L, 1) != 0) { + if(lua_type(L, -1) != LUA_TNUMBER) { + LUMIX_DELETE(pipeline->m_renderer.getAllocator(), cmd); + return luaL_error(L, "%s", "Incorrect texture arguments of bindTextures"); + } + + if(lua_type(L, -2) != LUA_TSTRING) { + LUMIX_DELETE(pipeline->m_renderer.getAllocator(), cmd); + return luaL_error(L, "%s", "Incorrect texture arguments of bindTextures"); + } + + if (cmd->m_textures_count > lengthOf(cmd->m_textures)) { + LUMIX_DELETE(pipeline->m_renderer.getAllocator(), cmd); + return luaL_error(L, "%s", "Too many texture in bindTextures call"); + } + + const char* uniform_name = lua_tostring(L, -2); + cmd->m_textures[cmd->m_textures_count].uniform = ffr::allocUniform(uniform_name, ffr::UniformType::INT, 1); + + const int rb_idx = (int)lua_tointeger(L, -1); + cmd->m_textures[cmd->m_textures_count].handle = pipeline->m_renderbuffers[rb_idx].handle; + ++cmd->m_textures_count; + + lua_pop(L, 1); + } + + pipeline->m_renderer.push(cmd); + + return 0; + }; + + + static int renderEnvProbeVolumes(lua_State* L) + { + const int pipeline_idx = lua_upvalueindex(1); + if (lua_type(L, pipeline_idx) != LUA_TLIGHTUSERDATA) { + LuaWrapper::argError(L, pipeline_idx); + } + PipelineImpl* pipeline = LuaWrapper::toType(L, pipeline_idx); + const int shader_id = LuaWrapper::checkArg(L, 1); + const Shader* shader = [&] { + for (const ShaderRef& s : pipeline->m_shaders) { + if(s.id == shader_id) { + return s.res; + } + } + return (Shader*)nullptr; + }(); + if (!shader) { + return luaL_error(L, "Unknown shader id %d in renderEnvProbeVolumes.", shader_id); + } + const CameraParams cp = checkCameraParams(L, 2); + + struct Cmd : public Renderer::RenderCommandBase + { + struct Probe + { + Vec3 pos; + ffr::TextureHandle texture; + }; + + Cmd(IAllocator& allocator) : m_probes(allocator) {} + + void setup() override + { + m_pipeline->getScene()->getEnvironmentProbes(m_probes); + } + + + void execute() override + { + PROFILE_FUNCTION(); + if(m_probes.empty()) return; + + ffr::pushDebugGroup("environment"); + const Shader::Program& prog = Shader::getProgram(m_shader, 0); + if(!prog.handle.isValid()) return; + + const int pos_radius_uniform_loc = ffr::getUniformLocation(prog.handle, m_pos_radius_uniform); + + ffr::VertexDecl decl; + decl.addAttribute(3, ffr::AttributeType::FLOAT, false, false); + + ffr::setVertexBuffer(&decl, m_vb, 0, nullptr); + ffr::setIndexBuffer(m_ib); + ffr::useProgram(prog.handle); + ffr::setState(0); + const int irradiance_map_loc = ffr::getUniformLocation(prog.handle, m_irradiance_map_uniform); + const int radiance_map_loc = ffr::getUniformLocation(prog.handle, m_radiance_map_uniform); + const Vec3 cam_pos = m_camera_params.pos; + for (const EnvProbeInfo& probe : m_probes) { + const Vec4 pos_radius(probe.position - cam_pos, probe.radius); + ffr::bindTexture(0, probe.radiance); + ffr::applyUniform1i(irradiance_map_loc, 0); + ffr::bindTexture(1, probe.radiance); + ffr::applyUniform1i(radiance_map_loc, 1); + ffr::applyUniform4f(pos_radius_uniform_loc, &pos_radius.x); + ffr::drawTriangles(36); + } + ffr::popDebugGroup(); + } + + ffr::BufferHandle m_ib; + ffr::BufferHandle m_vb; + ffr::UniformHandle m_pos_radius_uniform; + ffr::UniformHandle m_irradiance_map_uniform; + ffr::UniformHandle m_radiance_map_uniform; + CameraParams m_camera_params; + PipelineImpl* m_pipeline; + Array m_probes; + Shader::RenderData* m_shader; + }; + + if(shader->isReady()) { + IAllocator& allocator = pipeline->m_renderer.getAllocator(); + Cmd* cmd = LUMIX_NEW(allocator, Cmd)(allocator); + cmd->m_pipeline = pipeline; + cmd->m_shader = shader->m_render_data; + cmd->m_ib = pipeline->m_cube_ib; + cmd->m_vb = pipeline->m_cube_vb; + cmd->m_camera_params = cp; + cmd->m_irradiance_map_uniform = pipeline->m_irradiance_map_uniform; + cmd->m_radiance_map_uniform = pipeline->m_radiance_map_uniform; + cmd->m_pos_radius_uniform = pipeline->m_position_radius_uniform; + pipeline->m_renderer.push(cmd); + } + return 0; + } + static int renderMeshes(lua_State* L) { @@ -2090,9 +2285,11 @@ struct PipelineImpl final : Pipeline registerConst("STENCIL_KEEP", (uint)ffr::StencilOps::KEEP); registerConst("STENCIL_REPLACE", (uint)ffr::StencilOps::REPLACE); + registerCFunction("bindTextures", PipelineImpl::bindTextures); registerCFunction("drawArray", PipelineImpl::drawArray); registerCFunction("getCameraParams", PipelineImpl::getCameraParams); registerCFunction("getShadowCameraParams", PipelineImpl::getShadowCameraParams); + registerCFunction("renderEnvProbeVolumes", PipelineImpl::renderEnvProbeVolumes); registerCFunction("renderMeshes", PipelineImpl::renderMeshes); registerCFunction("renderParticles", PipelineImpl::renderParticles); registerCFunction("renderTerrains", PipelineImpl::renderTerrains); @@ -2151,6 +2348,7 @@ struct PipelineImpl final : Pipeline Array m_shaders; Timer* m_timer; + ffr::UniformHandle m_position_radius_uniform; ffr::UniformHandle m_terrain_params_uniform; ffr::UniformHandle m_rel_camera_pos_uniform; ffr::UniformHandle m_terrain_scale_uniform; @@ -2163,6 +2361,8 @@ struct PipelineImpl final : Pipeline ffr::UniformHandle m_radiance_map_uniform; ffr::UniformHandle m_material_params_uniform; ffr::UniformHandle m_material_color_uniform; + ffr::BufferHandle m_cube_vb; + ffr::BufferHandle m_cube_ib; }; diff --git a/src/renderer/render_scene.cpp b/src/renderer/render_scene.cpp index 5f6a2906e..34c697025 100644 --- a/src/renderer/render_scene.cpp +++ b/src/renderer/render_scene.cpp @@ -117,6 +117,7 @@ struct EnvironmentProbe Texture* texture; Texture* irradiance; Texture* radiance; + float radius; u64 guid; FlagSet flags; u16 radiance_size = 128; @@ -1093,6 +1094,7 @@ public: EnvironmentProbe& probe = m_environment_probes[entity]; serializer.write("guid", probe.guid); serializer.write("flags", probe.flags.base); + serializer.write("radius", probe.radius); serializer.write("radiance_size", probe.radiance_size); serializer.write("irradiance_size", probe.irradiance_size); serializer.write("reflection_size", probe.reflection_size); @@ -1109,6 +1111,7 @@ public: EnvironmentProbe& probe = m_environment_probes.insert(entity); serializer.read(&probe.guid); serializer.read(&probe.flags.base); + serializer.read(&probe.radius); serializer.read(&probe.radiance_size); serializer.read(&probe.irradiance_size); serializer.read(&probe.reflection_size); @@ -1319,6 +1322,7 @@ public: EntityRef entity = m_environment_probes.getKey(i); serializer.write(entity); const EnvironmentProbe& probe = m_environment_probes.at(i); + serializer.write(probe.radius); serializer.write(probe.guid); serializer.write(probe.flags.base); serializer.write(probe.radiance_size); @@ -3417,32 +3421,31 @@ bgfx::TextureHandle& handle = pipeline->getRenderbuffer(framebuffer_name, render void reloadEnvironmentProbe(EntityRef entity) override { - // TODO - ASSERT(false); - /* auto& probe = m_environment_probes[entity]; - auto* texture_manager = m_engine.getResourceManager().get(Texture::TYPE); - if (probe.texture) texture_manager->unload(*probe.texture); + ResourceManagerHub& rm = m_engine.getResourceManager(); + if (probe.texture) probe.texture->getResourceManager().unload(*probe.texture); probe.texture = nullptr; StaticString path; - if (probe.flags.isSet(EnvironmentProbe::REFLECTION)) - { + if (probe.flags.isSet(EnvironmentProbe::REFLECTION)) { path << "universes/" << m_universe.getName() << "/probes/" << probe.guid << ".dds"; - probe.texture = static_cast(texture_manager->load(Path(path))); - probe.texture->setFlag(BGFX_TEXTURE_SRGB, true); + probe.texture = rm.load(Path(path)); + // TODO + //probe.texture->setFlag(BGFX_TEXTURE_SRGB, true); } path = "universes/"; path << m_universe.getName() << "/probes/" << probe.guid << "_irradiance.dds"; - probe.irradiance = static_cast(texture_manager->load(Path(path))); - probe.irradiance->setFlag(BGFX_TEXTURE_SRGB, true); - probe.irradiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true); - probe.irradiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true); + if(probe.irradiance) probe.irradiance->getResourceManager().unload(*probe.irradiance); + probe.irradiance = rm.load(Path(path)); + //probe.irradiance->setFlag(BGFX_TEXTURE_SRGB, true); + //probe.irradiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true); + //probe.irradiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true); path = "universes/"; path << m_universe.getName() << "/probes/" << probe.guid << "_radiance.dds"; - probe.radiance = static_cast(texture_manager->load(Path(path))); - probe.radiance->setFlag(BGFX_TEXTURE_SRGB, true); - probe.radiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true); - probe.radiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);*/ + if (probe.radiance) probe.irradiance->getResourceManager().unload(*probe.radiance); + probe.radiance = rm.load(Path(path)); + //probe.radiance->setFlag(BGFX_TEXTURE_SRGB, true); + //probe.radiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true); + //probe.radiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true); } @@ -3465,38 +3468,67 @@ bgfx::TextureHandle& handle = pipeline->getRenderbuffer(framebuffer_name, render return nearest; } + + void getEnvironmentProbes(Array& probes) override + { + PROFILE_FUNCTION(); + probes.resize(m_environment_probes.size()); + for (int i = 0; i < m_environment_probes.size(); ++i) { + const EnvironmentProbe& probe = m_environment_probes.at(i); + const EntityRef entity = m_environment_probes.getKey(i); + EnvProbeInfo& out = probes[i]; + out.radius = probe.radius; + out.position = m_universe.getPosition(entity); + out.radiance = probe.radiance && probe.radiance->isReady() ? probe.radiance->handle : ffr::INVALID_TEXTURE; + out.irradiance = probe.irradiance && probe.irradiance->isReady() ? probe.irradiance->handle : ffr::INVALID_TEXTURE; + out.reflection = probe.texture && probe.texture->isReady() ? probe.texture->handle : ffr::INVALID_TEXTURE; + } + } - int getEnvironmentProbeIrradianceSize(EntityRef entity) + + int getEnvironmentProbeIrradianceSize(EntityRef entity) override { return m_environment_probes[entity].irradiance_size; } - void setEnvironmentProbeIrradianceSize(EntityRef entity, int size) + void setEnvironmentProbeIrradianceSize(EntityRef entity, int size) override { m_environment_probes[entity].irradiance_size = size; } - int getEnvironmentProbeRadianceSize(EntityRef entity) + float getEnvironmentProbeRadius(EntityRef entity) override + { + return m_environment_probes[entity].radius; + } + + + void setEnvironmentProbeRadius(EntityRef entity, float radius) override + { + m_environment_probes[entity].radius = radius; + } + + + int getEnvironmentProbeRadianceSize(EntityRef entity) override { return m_environment_probes[entity].radiance_size; } - void setEnvironmentProbeRadianceSize(EntityRef entity, int size) + void setEnvironmentProbeRadianceSize(EntityRef entity, int size) override { m_environment_probes[entity].radiance_size = size; } - int getEnvironmentProbeReflectionSize(EntityRef entity) + int getEnvironmentProbeReflectionSize(EntityRef entity) override { return m_environment_probes[entity].reflection_size; } - void setEnvironmentProbeReflectionSize(EntityRef entity, int size) + void setEnvironmentProbeReflectionSize(EntityRef entity, int size) override { m_environment_probes[entity].reflection_size = size; } @@ -3916,6 +3948,7 @@ bgfx::TextureHandle& handle = pipeline->getRenderbuffer(framebuffer_name, render probe.irradiance->setFlag(Texture::Flags::SRGB, true); probe.radiance = rm.load(Path("models/common/default_probe.dds")); probe.radiance->setFlag(Texture::Flags::SRGB, true); + probe.radius = 1; probe.guid = Math::randGUID(); m_universe.onComponentCreated(entity, ENVIRONMENT_PROBE_TYPE, this); diff --git a/src/renderer/render_scene.h b/src/renderer/render_scene.h index 9f33bb8ab..bdf489292 100644 --- a/src/renderer/render_scene.h +++ b/src/renderer/render_scene.h @@ -5,6 +5,7 @@ #include "engine/flag_set.h" #include "engine/matrix.h" #include "engine/iplugin.h" +#include "ffr/ffr.h" struct lua_State; @@ -102,6 +103,16 @@ struct GrassInfo }; +struct EnvProbeInfo +{ + Vec3 position; + float radius; + ffr::TextureHandle reflection; + ffr::TextureHandle radiance; + ffr::TextureHandle irradiance; +}; + + struct DebugTriangle { Vec3 p0; @@ -355,6 +366,7 @@ public: virtual float getPointLightSpecularIntensity(EntityRef entity) = 0; virtual void setPointLightSpecularIntensity(EntityRef entity, float color) = 0; + virtual void getEnvironmentProbes(Array& probes) = 0; virtual int getEnvironmentProbeIrradianceSize(EntityRef entity) = 0; virtual void setEnvironmentProbeIrradianceSize(EntityRef entity, int size) = 0; virtual int getEnvironmentProbeRadianceSize(EntityRef entity) = 0; @@ -371,6 +383,8 @@ public: virtual void reloadEnvironmentProbe(EntityRef entity) = 0; virtual EntityPtr getNearestEnvironmentProbe(const Vec3& pos) const = 0; virtual u64 getEnvironmentProbeGUID(EntityRef entity) const = 0; + virtual float getEnvironmentProbeRadius(EntityRef entity) = 0; + virtual void setEnvironmentProbeRadius(EntityRef entity, float radius) = 0; virtual void setTextMeshText(EntityRef entity, const char* text) = 0; virtual const char* getTextMeshText(EntityRef entity) = 0; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 6910d4a97..3b05de63e 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -281,6 +281,7 @@ static void registerProperties(IAllocator& allocator) BoneProperty() ), component("environment_probe", + property("Radius", LUMIX_PROP(RenderScene, EnvironmentProbeRadius)), property("Enabled reflection", LUMIX_PROP_FULL(RenderScene, isEnvironmentProbeReflectionEnabled, enableEnvironmentProbeReflection)), property("Override global size", LUMIX_PROP_FULL(RenderScene, isEnvironmentProbeCustomSize, enableEnvironmentProbeCustomSize)), property("Radiance size", LUMIX_PROP(RenderScene, EnvironmentProbeRadianceSize)), @@ -506,6 +507,29 @@ struct RendererImpl final : public Renderer } + void getTextureImage(ffr::TextureHandle texture, int size, void* data) override + { + struct Cmd : RenderCommandBase { + void setup() override {} + void execute() override { + ffr::pushDebugGroup("get image data"); + ffr::getTextureImage(handle, size, buf); + ffr::popDebugGroup(); + } + + ffr::TextureHandle handle; + uint size; + void* buf; + }; + + Cmd* cmd = LUMIX_NEW(m_render_task.m_allocator, Cmd); + cmd->handle = texture; + cmd->size = size; + cmd->buf = data; + push(cmd); + } + + ffr::TextureHandle loadTexture(const MemRef& memory, u32 flags, ffr::TextureInfo* info) override { ASSERT(memory.size > 0); @@ -840,6 +864,34 @@ struct RendererImpl final : public Renderer } + void startCapture() override + { + struct Cmd : RenderCommandBase { + void setup() override {} + void execute() override { + PROFILE_FUNCTION(); + ffr::startCapture(); + } + }; + Cmd* cmd = LUMIX_NEW(m_allocator, Cmd); + push(cmd); + } + + + void stopCapture() override + { + struct Cmd : RenderCommandBase { + void setup() override {} + void execute() override { + PROFILE_FUNCTION(); + ffr::stopCapture(); + } + }; + Cmd* cmd = LUMIX_NEW(m_allocator, Cmd); + push(cmd); + } + + void pushSwapCommand() { struct SwapCmd : RenderCommandBase { @@ -852,6 +904,7 @@ struct RendererImpl final : public Renderer renderer->m_render_task.m_transient_buffer_offset = 0; } RendererImpl* renderer; + bool capture; }; SwapCmd* swap_cmd = LUMIX_NEW(m_allocator, SwapCmd); swap_cmd->renderer = this; @@ -859,7 +912,7 @@ struct RendererImpl final : public Renderer } - void frame(bool capture) override + void frame() override { PROFILE_FUNCTION(); pushSwapCommand(); diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 870ee555c..3acc58b6e 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -80,7 +80,9 @@ class LUMIX_RENDERER_API Renderer : public IPlugin enum { MAX_SHADER_DEFINES = 32 }; public: virtual ~Renderer() {} - virtual void frame(bool capture) = 0; + virtual void startCapture() = 0; + virtual void stopCapture() = 0; + virtual void frame() = 0; virtual void resize(int width, int height) = 0; virtual void makeScreenshot(const Path& filename) = 0; virtual u8 getShaderDefineIdx(const char* define) = 0; @@ -112,6 +114,7 @@ class LUMIX_RENDERER_API Renderer : public IPlugin virtual ffr::TextureHandle createTexture(uint w, uint h, ffr::TextureFormat format, u32 flags, const MemRef& memory) = 0; virtual ffr::TextureHandle loadTexture(const MemRef& memory, u32 flags, ffr::TextureInfo* info) = 0; + virtual void getTextureImage(ffr::TextureHandle texture, int size, void* data) = 0; virtual void destroy(ffr::TextureHandle tex) = 0; virtual void push(RenderCommandBase* cmd) = 0; diff --git a/src/renderer/shader.cpp b/src/renderer/shader.cpp index 5603949b4..5e153ecd4 100644 --- a/src/renderer/shader.cpp +++ b/src/renderer/shader.cpp @@ -63,6 +63,7 @@ const Shader::Program& Shader::getProgram(RenderData* rd, u32 defines) " float u_light_intensity;\n" " float u_light_indirect_intensity;\n" " float u_time;\n" + " ivec2 u_framebuffer_size;\n" "};\n" "uniform samplerCube u_irradiancemap;\n" "uniform samplerCube u_radiancemap;\n" @@ -94,7 +95,7 @@ const Shader::Program& Shader::getProgram(RenderData* rd, u32 defines) for(int& i : program.attribute_by_semantics) i = -1; // TODO shader path - last argument - program.handle = ffr::createProgram(codes, types, rd->sources.size(), prefixes, 2 + defines_count, "TODO"); + program.handle = ffr::createProgram(codes, types, rd->sources.size(), prefixes, 2 + defines_count, rd->path.c_str()); program.use_semantics = false; if (program.handle.isValid()) { ffr::uniformBlockBinding(program.handle, "GlobalState", 0); @@ -397,6 +398,7 @@ bool Shader::load(FS::IFile& file) IAllocator& allocator = m_renderer.getAllocator(); m_render_data = LUMIX_NEW(allocator, RenderData)(m_renderer, allocator); + m_render_data->path = getPath(); lua_pushlightuserdata(L, this); lua_setfield(L, LUA_GLOBALSINDEX, "this"); diff --git a/src/renderer/shader.h b/src/renderer/shader.h index ca90994b5..e0250c006 100644 --- a/src/renderer/shader.h +++ b/src/renderer/shader.h @@ -101,6 +101,7 @@ public: Array sources; Array include; Array attributes; + Path path; }* m_render_data; public: