|
| 1 | +#include "reflection_baker.hpp" |
| 2 | +#include "server.hpp" |
| 3 | + |
| 4 | +#include <godot_cpp/core/class_db.hpp> |
| 5 | +#include <godot_cpp/variant/utility_functions.hpp> |
| 6 | + |
| 7 | +#include "steam_audio.hpp" |
| 8 | + |
| 9 | +using namespace godot; |
| 10 | + |
| 11 | +void SteamAudioReflectionBaker::_bind_methods() { |
| 12 | + // Bind methods |
| 13 | + ClassDB::bind_method(D_METHOD("set_baked_data", "data"), &SteamAudioReflectionBaker::set_baked_data); |
| 14 | + ClassDB::bind_method(D_METHOD("get_baked_data"), &SteamAudioReflectionBaker::get_baked_data); |
| 15 | + ClassDB::bind_method(D_METHOD("start_bake"), &SteamAudioReflectionBaker::start_bake); |
| 16 | + ClassDB::bind_method(D_METHOD("get_is_baking"), &SteamAudioReflectionBaker::get_is_baking); |
| 17 | + ClassDB::bind_method(D_METHOD("get_bake_progress"), &SteamAudioReflectionBaker::get_bake_progress); |
| 18 | + ClassDB::bind_method(D_METHOD("set_num_rays", "num_rays"), &SteamAudioReflectionBaker::set_num_rays); |
| 19 | + ClassDB::bind_method(D_METHOD("get_num_rays"), &SteamAudioReflectionBaker::get_num_rays); |
| 20 | + ClassDB::bind_method(D_METHOD("set_num_bounces", "num_bounces"), &SteamAudioReflectionBaker::set_num_bounces); |
| 21 | + ClassDB::bind_method(D_METHOD("get_num_bounces"), &SteamAudioReflectionBaker::get_num_bounces); |
| 22 | + ClassDB::bind_method(D_METHOD("set_duration", "duration"), &SteamAudioReflectionBaker::set_duration); |
| 23 | + ClassDB::bind_method(D_METHOD("get_duration"), &SteamAudioReflectionBaker::get_duration); |
| 24 | + ClassDB::bind_method(D_METHOD("set_num_diffuse_samples", "num_diffuse_samples"), &SteamAudioReflectionBaker::set_num_diffuse_samples); |
| 25 | + ClassDB::bind_method(D_METHOD("get_num_diffuse_samples"), &SteamAudioReflectionBaker::get_num_diffuse_samples); |
| 26 | + ClassDB::bind_method(D_METHOD("set_irradiance_min_distance", "irradiance_min_distance"), &SteamAudioReflectionBaker::set_irradiance_min_distance); |
| 27 | + ClassDB::bind_method(D_METHOD("get_irradiance_min_distance"), &SteamAudioReflectionBaker::get_irradiance_min_distance); |
| 28 | + ClassDB::bind_method(D_METHOD("set_bake_parametric", "bake_parametric"), &SteamAudioReflectionBaker::set_bake_parametric); |
| 29 | + ClassDB::bind_method(D_METHOD("get_bake_parametric"), &SteamAudioReflectionBaker::get_bake_parametric); |
| 30 | + ClassDB::bind_method(D_METHOD("set_bake_convolution", "bake_convolution"), &SteamAudioReflectionBaker::set_bake_convolution); |
| 31 | + ClassDB::bind_method(D_METHOD("get_bake_convolution"), &SteamAudioReflectionBaker::get_bake_convolution); |
| 32 | + ClassDB::bind_method(D_METHOD("set_center", "center"), &SteamAudioReflectionBaker::set_center); |
| 33 | + ClassDB::bind_method(D_METHOD("get_center"), &SteamAudioReflectionBaker::get_center); |
| 34 | + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SteamAudioReflectionBaker::set_radius); |
| 35 | + ClassDB::bind_method(D_METHOD("get_radius"), &SteamAudioReflectionBaker::get_radius); |
| 36 | + ClassDB::bind_method(D_METHOD("set_probe_spacing", "probe_spacing"), &SteamAudioReflectionBaker::set_probe_spacing); |
| 37 | + ClassDB::bind_method(D_METHOD("get_probe_spacing"), &SteamAudioReflectionBaker::get_probe_spacing); |
| 38 | + ClassDB::bind_method(D_METHOD("set_probe_height", "probe_height"), &SteamAudioReflectionBaker::set_probe_height); |
| 39 | + ClassDB::bind_method(D_METHOD("get_probe_height"), &SteamAudioReflectionBaker::get_probe_height); |
| 40 | + ClassDB::bind_method(D_METHOD("set_probe_generation_extents", "probe_generation_extents"), &SteamAudioReflectionBaker::set_probe_generation_extents); |
| 41 | + ClassDB::bind_method(D_METHOD("get_probe_generation_extents"), &SteamAudioReflectionBaker::get_probe_generation_extents); |
| 42 | + |
| 43 | + // Add properties |
| 44 | + ADD_GROUP("Reflection Bake", ""); |
| 45 | + ADD_PROPERTY(PropertyInfo(Variant::INT, "num_rays"), "set_num_rays", "get_num_rays"); |
| 46 | + ADD_PROPERTY(PropertyInfo(Variant::INT, "num_bounces"), "set_num_bounces", "get_num_bounces"); |
| 47 | + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "duration"), "set_duration", "get_duration"); |
| 48 | + ADD_PROPERTY(PropertyInfo(Variant::INT, "num_diffuse_samples"), "set_num_diffuse_samples", "get_num_diffuse_samples"); |
| 49 | + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "irradiance_min_distance"), "set_irradiance_min_distance", "get_irradiance_min_distance"); |
| 50 | + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_parametric"), "set_bake_parametric", "get_bake_parametric"); |
| 51 | + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_convolution"), "set_bake_convolution", "get_bake_convolution"); |
| 52 | + |
| 53 | + ADD_GROUP("Scene", ""); |
| 54 | + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center"), "set_center", "get_center"); |
| 55 | + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius"), "set_radius", "get_radius"); |
| 56 | + |
| 57 | + ADD_GROUP("Probes", ""); |
| 58 | + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "probe_spacing"), "set_probe_spacing", "get_probe_spacing"); |
| 59 | + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "probe_height"), "set_probe_height", "get_probe_height"); |
| 60 | + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "probe_generation_extents"), "set_probe_generation_extents", "get_probe_generation_extents"); |
| 61 | + |
| 62 | + ADD_GROUP("Bake Data", ""); |
| 63 | + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "baked_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedReflectionData"), "set_baked_data", "get_baked_data"); |
| 64 | +} |
| 65 | + |
| 66 | +SteamAudioReflectionBaker::SteamAudioReflectionBaker() { |
| 67 | + probe_batch = nullptr; |
| 68 | + is_baking = false; |
| 69 | + bake_progress = 0.0f; |
| 70 | + |
| 71 | + // Initialize properties from ReflectionBakeConfig |
| 72 | + num_rays = 32768; |
| 73 | + num_bounces = 64; |
| 74 | + duration = 2.0f; |
| 75 | + num_diffuse_samples = 1024; |
| 76 | + irradiance_min_distance = 1.0f; |
| 77 | + bake_parametric = true; |
| 78 | + bake_convolution = true; |
| 79 | +} |
| 80 | + |
| 81 | +SteamAudioReflectionBaker::~SteamAudioReflectionBaker() { |
| 82 | + if (probe_batch) { |
| 83 | + iplProbeBatchRelease(&probe_batch); |
| 84 | + } |
| 85 | +} |
| 86 | + |
| 87 | +void SteamAudioReflectionBaker::generate_probes() { |
| 88 | + float x = probe_generation_extents.x; |
| 89 | + float y = probe_generation_extents.y; |
| 90 | + float z = probe_generation_extents.z; |
| 91 | + IPLMatrix4x4 box_transform = IPLMatrix4x4{ { |
| 92 | + {x, 0.0f, 0.0f, 0.0f}, |
| 93 | + {0.0f, y, 0.0f, 0.0f}, |
| 94 | + {0.0f, 0.0f, z, 0.0f}, |
| 95 | + {0.0f, 0.0f, 0.0f, 1.0f} |
| 96 | + } }; |
| 97 | + |
| 98 | + IPLProbeGenerationParams probe_params{}; |
| 99 | + probe_params.type = IPL_PROBEGENERATIONTYPE_UNIFORMFLOOR; |
| 100 | + probe_params.spacing = probe_spacing; |
| 101 | + probe_params.height = probe_height; |
| 102 | + probe_params.transform = box_transform; |
| 103 | + |
| 104 | + IPLContext context = SteamAudioServer::get_singleton()->get_global_state(false)->ctx; |
| 105 | + IPLScene scene = SteamAudioServer::get_singleton()->get_global_state(false)->scene; |
| 106 | + |
| 107 | + IPLProbeArray probe_array = nullptr; |
| 108 | + iplProbeArrayCreate(context, &probe_array); |
| 109 | + iplProbeArrayGenerateProbes(probe_array, scene, &probe_params); |
| 110 | + |
| 111 | + iplProbeBatchCreate(context, &probe_batch); |
| 112 | + iplProbeBatchAddProbeArray(probe_batch, probe_array); |
| 113 | + |
| 114 | + TypedArray<Node> probes = find_children("*", "SteamAudioProbe", true, false); |
| 115 | + for (int i = 0; i < probes.size(); i++) { |
| 116 | + SteamAudioProbe *p = Object::cast_to<SteamAudioProbe>(probes[i]); |
| 117 | + IPLSphere sphere{ipl_vec3_from(p->get_global_position()), p->get_radius()}; |
| 118 | + iplProbeBatchAddProbe(probe_batch, sphere); |
| 119 | + } |
| 120 | + |
| 121 | + iplProbeBatchCommit(probe_batch); |
| 122 | +} |
| 123 | + |
| 124 | +void SteamAudioReflectionBaker::set_baked_data(const Ref<SteamAudioBakedReflectionData>& p_data) { |
| 125 | +} |
| 126 | + |
| 127 | +Ref<SteamAudioBakedReflectionData> SteamAudioReflectionBaker::get_baked_data() const { |
| 128 | + return nullptr; |
| 129 | +} |
| 130 | + |
| 131 | +IPLReflectionsBakeParams SteamAudioReflectionBaker::get_bake_params() const { |
| 132 | + IPLBakedDataIdentifier identifier{}; |
| 133 | + identifier.type = IPL_BAKEDDATATYPE_REFLECTIONS; |
| 134 | + identifier.variation = IPL_BAKEDDATAVARIATION_DYNAMIC; |
| 135 | + identifier.endpointInfluence.center = ipl_vec3_from(center); // world-space position of the source |
| 136 | + identifier.endpointInfluence.radius = radius; // only bake reflections for probes within 100m of the source |
| 137 | + |
| 138 | + |
| 139 | + IPLReflectionsBakeParams params{}; |
| 140 | + params.scene = SteamAudioServer::get_singleton()->get_global_state(false)->scene; |
| 141 | + params.probeBatch; // filled out by bake manager |
| 142 | + |
| 143 | + params.sceneType = IPL_SCENETYPE_DEFAULT; |
| 144 | + params.identifier = identifier; |
| 145 | + params.savedDuration = 2.0f; |
| 146 | + params.order = 2; |
| 147 | + params.numThreads = 8; |
| 148 | + |
| 149 | + params.numRays = num_rays; |
| 150 | + params.numBounces = num_bounces; |
| 151 | + params.numDiffuseSamples = num_diffuse_samples; |
| 152 | + params.irradianceMinDistance = irradiance_min_distance; |
| 153 | + if (bake_parametric) { |
| 154 | + params.bakeFlags = static_cast<IPLReflectionsBakeFlags>( |
| 155 | + static_cast<int>(params.bakeFlags) | IPL_REFLECTIONSBAKEFLAGS_BAKEPARAMETRIC |
| 156 | + ); |
| 157 | + } |
| 158 | + if (bake_convolution) { |
| 159 | + params.bakeFlags = static_cast<IPLReflectionsBakeFlags>( |
| 160 | + static_cast<int>(params.bakeFlags) | IPL_REFLECTIONSBAKEFLAGS_BAKECONVOLUTION |
| 161 | + ); |
| 162 | + } |
| 163 | + return params; |
| 164 | +} |
| 165 | + |
| 166 | +void SteamAudioReflectionBaker::start_bake() { |
| 167 | + if (is_baking) { |
| 168 | + return; |
| 169 | + } |
| 170 | + |
| 171 | + is_baking = true; |
| 172 | + |
| 173 | + generate_probes(); |
| 174 | + IPLReflectionsBakeParams params = get_bake_params(); |
| 175 | + iplReflectionsBakerBake(context, &bakeParams, nullptr, nullptr); |
| 176 | + |
| 177 | + is_baking = false; |
| 178 | +} |
| 179 | + |
| 180 | +void SteamAudioReflectionBaker::bake_progress_callback(float progress, void* user_data) { |
| 181 | + SteamAudioReflectionBaker* manager = static_cast<SteamAudioReflectionBaker*>(user_data); |
| 182 | + manager->bake_progress = progress; |
| 183 | + |
| 184 | + // Print progress every 10% |
| 185 | + static int last_percentage = -1; |
| 186 | + int current_percentage = static_cast<int>(progress * 100); |
| 187 | + if (current_percentage / 10 != last_percentage / 10) { |
| 188 | + last_percentage = current_percentage; |
| 189 | + UtilityFunctions::print("[Steam Audio] Baking reflections: ", String::num_int64(current_percentage), "%"); |
| 190 | + } |
| 191 | +} |
| 192 | + |
| 193 | +bool SteamAudioReflectionBaker::get_is_baking() const {return is_baking;} |
| 194 | +float SteamAudioReflectionBaker::get_bake_progress() const {return bake_progress;} |
| 195 | +void SteamAudioReflectionBaker::set_num_rays(int p_num_rays) { num_rays = p_num_rays; } |
| 196 | +int SteamAudioReflectionBaker::get_num_rays() const { return num_rays; } |
| 197 | +void SteamAudioReflectionBaker::set_num_bounces(int p_num_bounces) { num_bounces = p_num_bounces; } |
| 198 | +int SteamAudioReflectionBaker::get_num_bounces() const { return num_bounces; } |
| 199 | +void SteamAudioReflectionBaker::set_duration(float p_duration) { duration = p_duration; } |
| 200 | +float SteamAudioReflectionBaker::get_duration() const { return duration; } |
| 201 | +void SteamAudioReflectionBaker::set_num_diffuse_samples(int p_num_diffuse_samples) { num_diffuse_samples = p_num_diffuse_samples; } |
| 202 | +int SteamAudioReflectionBaker::get_num_diffuse_samples() const { return num_diffuse_samples; } |
| 203 | +void SteamAudioReflectionBaker::set_irradiance_min_distance(float p_irradiance_min_distance) { irradiance_min_distance = p_irradiance_min_distance; } |
| 204 | +float SteamAudioReflectionBaker::get_irradiance_min_distance() const { return irradiance_min_distance; } |
| 205 | +void SteamAudioReflectionBaker::set_bake_parametric(bool p_bake_parametric) { bake_parametric = p_bake_parametric; } |
| 206 | +bool SteamAudioReflectionBaker::get_bake_parametric() const { return bake_parametric; } |
| 207 | +void SteamAudioReflectionBaker::set_bake_convolution(bool p_bake_convolution) { bake_convolution = p_bake_convolution; } |
| 208 | +bool SteamAudioReflectionBaker::get_bake_convolution() const { return bake_convolution; } |
| 209 | +void SteamAudioReflectionBaker::set_center(Vector3 p_center) { center = p_center; } |
| 210 | +Vector3 SteamAudioReflectionBaker::get_center() const { return center; } |
| 211 | +void SteamAudioReflectionBaker::set_radius(float p_radius) { radius = p_radius; } |
| 212 | +float SteamAudioReflectionBaker::get_radius() const { return radius; } |
| 213 | +void SteamAudioReflectionBaker::set_probe_spacing(float p_probe_spacing) { probe_spacing = p_probe_spacing; } |
| 214 | +float SteamAudioReflectionBaker::get_probe_spacing() const { return probe_spacing; } |
| 215 | +void SteamAudioReflectionBaker::set_probe_height(float p_probe_height) { probe_height = p_probe_height; } |
| 216 | +float SteamAudioReflectionBaker::get_probe_height() const { return probe_height; } |
| 217 | +void SteamAudioReflectionBaker::set_probe_generation_extents(Vector3 p_probe_generation_extents) { probe_generation_extents = p_probe_generation_extents; } |
| 218 | +Vector3 SteamAudioReflectionBaker::get_probe_generation_extents() const { return probe_generation_extents; } |
0 commit comments