|
36 | 36 |
|
37 | 37 | #include "core/config/project_settings.h" |
38 | 38 | #include "core/math/geometry_2d.h" |
| 39 | +#include "editor/editor_settings.h" |
39 | 40 | #include "servers/rendering/rendering_device_binds.h" |
40 | 41 |
|
41 | 42 | //uncomment this if you want to see textures from all the process saved |
@@ -671,6 +672,118 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade |
671 | 672 | return BAKE_OK; |
672 | 673 | } |
673 | 674 |
|
| 675 | +bool LightmapperRD::_load_oidn(const String &p_library_path) { |
| 676 | + if (oidn_lib_path == p_library_path) { |
| 677 | + return oidn_lib_handle != nullptr; |
| 678 | + } |
| 679 | + oidn_lib_path = p_library_path; |
| 680 | + |
| 681 | + String lib_path; |
| 682 | + if (OS::get_singleton()->get_name() == "macOS") { |
| 683 | + lib_path = oidn_lib_path.path_join("libOpenImageDenoise.dylib"); |
| 684 | + } else if (OS::get_singleton()->get_name() == "Windows") { |
| 685 | + lib_path = oidn_lib_path.path_join("OpenImageDenoise.dll"); |
| 686 | + } else { |
| 687 | + lib_path = oidn_lib_path.path_join("libOpenImageDenoise.so"); |
| 688 | + } |
| 689 | + |
| 690 | + _unload_oidn(); |
| 691 | + |
| 692 | + if (OS::get_singleton()->open_dynamic_library(lib_path, oidn_lib_handle, true) != OK) { |
| 693 | + oidn_lib_handle = nullptr; |
| 694 | + ERR_PRINT(vformat("Failed to load %s.", lib_path)); |
| 695 | + return false; |
| 696 | + } |
| 697 | + bool symbols_ok = true; |
| 698 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnNewDevice", (void *&)oidnNewDevice) == OK); |
| 699 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnCommitDevice", (void *&)oidnCommitDevice) == OK); |
| 700 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnNewFilter", (void *&)oidnNewFilter) == OK); |
| 701 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnSetSharedFilterImage", (void *&)oidnSetSharedFilterImage) == OK); |
| 702 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnSetFilterBool", (void *&)oidnSetFilterBool) == OK); |
| 703 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnCommitFilter", (void *&)oidnCommitFilter) == OK); |
| 704 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnExecuteFilter", (void *&)oidnExecuteFilter) == OK); |
| 705 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnGetDeviceError", (void *&)oidnGetDeviceError) == OK); |
| 706 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnReleaseFilter", (void *&)oidnReleaseFilter) == OK); |
| 707 | + symbols_ok = symbols_ok && (OS::get_singleton()->get_dynamic_library_symbol_handle(oidn_lib_handle, "oidnReleaseDevice", (void *&)oidnReleaseDevice) == OK); |
| 708 | + if (!symbols_ok) { |
| 709 | + ERR_PRINT("Failed to load OIDN symbols."); |
| 710 | + _unload_oidn(); |
| 711 | + return false; |
| 712 | + } |
| 713 | + |
| 714 | + oidn_device = oidnNewDevice(OIDN_DEVICE_TYPE_CPU); |
| 715 | + oidnCommitDevice(oidn_device); |
| 716 | + const char *msg = nullptr; |
| 717 | + if (oidnGetDeviceError(oidn_device, &msg) != OIDN_ERROR_NONE) { |
| 718 | + ERR_PRINT("Failed to load OIDN device."); |
| 719 | + _unload_oidn(); |
| 720 | + return false; |
| 721 | + } |
| 722 | + |
| 723 | + return true; |
| 724 | +} |
| 725 | + |
| 726 | +void LightmapperRD::_unload_oidn() { |
| 727 | + if (oidn_lib_handle) { |
| 728 | + if (oidn_device) { |
| 729 | + oidnReleaseDevice(oidn_device); |
| 730 | + oidn_device = nullptr; |
| 731 | + } |
| 732 | + |
| 733 | + OS::get_singleton()->close_dynamic_library(oidn_lib_handle); |
| 734 | + oidn_lib_handle = nullptr; |
| 735 | + } |
| 736 | +} |
| 737 | + |
| 738 | +LightmapperRD::BakeError LightmapperRD::_denoise_oidn(RenderingDevice *p_rd, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh) { |
| 739 | + for (int i = 0; i < p_atlas_slices; i++) { |
| 740 | + Vector<uint8_t> sn = p_rd->texture_get_data(p_source_normal_tex, i); |
| 741 | + Ref<Image> imgn = Image::create_from_data(p_atlas_size.width, p_atlas_size.height, false, Image::FORMAT_RGBAH, sn); |
| 742 | + imgn->convert(Image::FORMAT_RGBF); |
| 743 | + Vector<uint8_t> datan = imgn->get_data(); |
| 744 | + |
| 745 | + for (int j = 0; j < (p_bake_sh ? 4 : 1); j++) { |
| 746 | + int index = i * (p_bake_sh ? 4 : 1) + j; |
| 747 | + |
| 748 | + Vector<uint8_t> sl = p_rd->texture_get_data(p_source_light_tex, index); |
| 749 | + |
| 750 | + Ref<Image> imgl = Image::create_from_data(p_atlas_size.width, p_atlas_size.height, false, Image::FORMAT_RGBAH, sl); |
| 751 | + imgl->convert(Image::FORMAT_RGBF); |
| 752 | + Vector<uint8_t> datal = imgl->get_data(); |
| 753 | + |
| 754 | + void *filter = oidnNewFilter(oidn_device, "RTLightmap"); |
| 755 | + oidnSetSharedFilterImage(filter, "color", (void *)datal.ptrw(), OIDN_FORMAT_FLOAT3, imgl->get_width(), imgl->get_height(), 0, 0, 0); |
| 756 | + oidnSetSharedFilterImage(filter, "normal", (void *)datan.ptrw(), OIDN_FORMAT_FLOAT3, imgn->get_width(), imgn->get_height(), 0, 0, 0); |
| 757 | + oidnSetSharedFilterImage(filter, "output", (void *)datal.ptrw(), OIDN_FORMAT_FLOAT3, imgl->get_width(), imgl->get_height(), 0, 0, 0); |
| 758 | + oidnSetFilterBool(filter, "hdr", true); |
| 759 | + oidnCommitFilter(filter); |
| 760 | + oidnExecuteFilter(filter); |
| 761 | + |
| 762 | + const char *msg = nullptr; |
| 763 | + if (oidnGetDeviceError(oidn_device, &msg) != OIDN_ERROR_NONE) { |
| 764 | + oidnReleaseFilter(filter); |
| 765 | + ERR_FAIL_V_MSG(BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, String(msg)); |
| 766 | + } |
| 767 | + oidnReleaseFilter(filter); |
| 768 | + |
| 769 | + imgl->set_data(imgl->get_width(), imgl->get_height(), false, imgl->get_format(), datal); |
| 770 | + imgl->convert(Image::FORMAT_RGBAH); |
| 771 | + Vector<uint8_t> ds = imgl->get_data(); |
| 772 | + imgl.unref(); // Avoid copy on write. |
| 773 | + { // Restore alpha. |
| 774 | + uint32_t count = sl.size() / 2; |
| 775 | + const uint16_t *src = (const uint16_t *)sl.ptr(); |
| 776 | + uint16_t *dst = (uint16_t *)ds.ptrw(); |
| 777 | + for (uint32_t k = 0; k < count; k += 4) { |
| 778 | + dst[k + 3] = src[k + 3]; |
| 779 | + } |
| 780 | + } |
| 781 | + p_rd->texture_update(p_dest_light_tex, index, ds); |
| 782 | + } |
| 783 | + } |
| 784 | + return BAKE_OK; |
| 785 | +} |
| 786 | + |
674 | 787 | LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function) { |
675 | 788 | RID denoise_params_buffer = p_rd->uniform_buffer_create(sizeof(DenoiseParams)); |
676 | 789 | DenoiseParams denoise_params; |
@@ -1501,8 +1614,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d |
1501 | 1614 | } |
1502 | 1615 |
|
1503 | 1616 | { |
1504 | | - SWAP(light_accum_tex, light_accum_tex2); |
1505 | | - BakeError error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, p_denoiser_strength, atlas_size, atlas_slices, p_bake_sh, p_step_function); |
| 1617 | + String oidn_path = EDITOR_GET("filesystem/tools/oidn/oidn_library_path"); |
| 1618 | + BakeError error; |
| 1619 | + if (!oidn_path.is_empty() && _load_oidn(oidn_path)) { |
| 1620 | + error = _denoise_oidn(rd, light_accum_tex, normal_tex, light_accum_tex, atlas_size, atlas_slices, p_bake_sh); |
| 1621 | + } else { |
| 1622 | + SWAP(light_accum_tex, light_accum_tex2); |
| 1623 | + error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, p_denoiser_strength, atlas_size, atlas_slices, p_bake_sh, p_step_function); |
| 1624 | + } |
1506 | 1625 | if (unlikely(error != BAKE_OK)) { |
1507 | 1626 | return error; |
1508 | 1627 | } |
@@ -1766,3 +1885,7 @@ Vector<Color> LightmapperRD::get_bake_probe_sh(int p_probe) const { |
1766 | 1885 |
|
1767 | 1886 | LightmapperRD::LightmapperRD() { |
1768 | 1887 | } |
| 1888 | + |
| 1889 | +LightmapperRD::~LightmapperRD() { |
| 1890 | + _unload_oidn(); |
| 1891 | +} |
0 commit comments