Skip to content

Commit e2046c6

Browse files
committed
Initial commit for baking reflections
1 parent 20ce5b1 commit e2046c6

7 files changed

+445
-0
lines changed

src/probe.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <godot_cpp/core/class_db.hpp>
2+
3+
#include "probe.hpp"
4+
#include "server.hpp"
5+
6+
#include "phonon.h"
7+
8+
using namespace godot;
9+
10+
void SteamAudioProbe::_bind_methods() {
11+
ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SteamAudioProbe::set_radius);
12+
ClassDB::bind_method(D_METHOD("get_radius"), &SteamAudioProbe::get_radius);
13+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius"), "set_radius", "get_radius");
14+
}
15+
16+
SteamAudioProbe::SteamAudioProbe() {
17+
radius = 1.0f;
18+
mesh = memnew(MeshInstance3D);
19+
sphere.instantiate();
20+
mesh->set_name("mesh");
21+
mesh->set_mesh(sphere);
22+
sphere->set_radius(radius);
23+
add_child(mesh);
24+
}
25+
26+
SteamAudioProbe::~SteamAudioProbe() {
27+
}
28+
29+
void SteamAudioProbe::set_radius(float p_radius) {
30+
radius = p_radius;
31+
sphere->set_radius(radius);
32+
}
33+
34+
float SteamAudioProbe::get_radius() const {
35+
return radius;
36+
}

src/probe.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef GODOT_STEAM_AUDIO_PROBE_HPP
2+
#define GODOT_STEAM_AUDIO_PROBE_HPP
3+
4+
#include "godot_cpp/classes/node3d.hpp"
5+
#include "godot_cpp/classes/mesh_instance3d.hpp"
6+
#include "godot_cpp/classes/sphere_shape3d.hpp"
7+
8+
#include "phonon.h"
9+
10+
using namespace godot;
11+
12+
class SteamAudioProbe : public Node3D {
13+
GDCLASS(SteamAudioProbe, Node3D)
14+
15+
private:
16+
MeshInstance3D *mesh;
17+
Ref<SphereShape3D> sphere;
18+
float radius;
19+
20+
protected:
21+
static void _bind_methods();
22+
23+
public:
24+
SteamAudioProbe();
25+
~SteamAudioProbe();
26+
27+
void set_radius(float p_radius);
28+
float get_radius() const;
29+
};
30+
31+
#endif // GODOT_STEAM_AUDIO_PROBE_HPP

src/reflection_baked_data.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include "reflection_baked_data.hpp"
2+
#include <godot_cpp/core/class_db.hpp>
3+
#include <godot_cpp/variant/utility_functions.hpp>
4+
5+
using namespace godot;
6+
7+
void SteamAudioBakedReflectionData::_bind_methods() {
8+
ClassDB::bind_method(D_METHOD("set_serialized_data", "data"), &SteamAudioBakedReflectionData::set_serialized_data);
9+
ClassDB::bind_method(D_METHOD("get_serialized_data"), &SteamAudioBakedReflectionData::get_serialized_data);
10+
11+
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "serialized_data"), "set_serialized_data", "get_serialized_data");
12+
}
13+
14+
SteamAudioBakedReflectionData::SteamAudioBakedReflectionData() {
15+
}
16+
17+
SteamAudioBakedReflectionData::~SteamAudioBakedReflectionData() {
18+
}
19+
20+
void SteamAudioBakedReflectionData::set_serialized_data(const PackedByteArray& p_data) {
21+
serialized_data = p_data;
22+
}
23+
24+
PackedByteArray SteamAudioBakedReflectionData::get_serialized_data() const {
25+
return serialized_data;
26+
}

src/reflection_baked_data.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef GODOT_STEAM_AUDIO_REFLECTION_BAKED_DATA_HPP
2+
#define GODOT_STEAM_AUDIO_REFLECTION_BAKED_DATA_HPP
3+
4+
#include <godot_cpp/classes/resource.hpp>
5+
#include <phonon.h>
6+
7+
namespace godot {
8+
9+
class SteamAudioBakedReflectionData : public Resource {
10+
GDCLASS(SteamAudioBakedReflectionData, Resource)
11+
12+
private:
13+
PackedByteArray serialized_data;
14+
15+
protected:
16+
static void _bind_methods();
17+
18+
public:
19+
SteamAudioBakedReflectionData();
20+
~SteamAudioBakedReflectionData();
21+
22+
void set_serialized_data(const PackedByteArray& p_data);
23+
PackedByteArray get_serialized_data() const;
24+
};
25+
26+
}
27+
28+
#endif // GODOT_STEAM_AUDIO_BAKED_REFLECTION_BAKED_DATA_HPP

src/reflection_baker.cpp

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
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

Comments
 (0)