Updated lightmap baker to dynamically calculate lightmap sizes based on surface area.

This commit is contained in:
Nathan Warden 2019-06-22 10:27:09 -05:00
parent 05a0a68c72
commit 09737ef6a7
4 changed files with 91 additions and 10 deletions

View File

@ -221,6 +221,15 @@ Vector3 BakedLightmap::get_extents() const {
return extents;
}
void BakedLightmap::set_bake_default_texels_per_unit(const float &p_bake_texels_per_unit) {
bake_default_texels_per_unit = p_bake_texels_per_unit;
update_gizmo();
}
float BakedLightmap::get_bake_default_texels_per_unit() const {
return bake_default_texels_per_unit;
}
void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plot_meshes, List<PlotLight> &plot_lights) {
MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
@ -236,7 +245,7 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plo
}
}
if (all_have_uv2 && mesh->get_lightmap_size_hint() != Size2()) {
if (all_have_uv2) {
//READY TO BAKE! size hint could be computed if not found, actually..
AABB aabb = mesh->get_aabb();
@ -463,7 +472,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
btd.text = RTR("Lighting Meshes: ") + mesh_name + " (" + itos(pmc) + "/" + itos(mesh_list.size()) + ")";
btd.pass = step;
btd.last_step = 0;
err = baker.make_lightmap(E->get().local_xform, E->get().mesh, lm, _bake_time, &btd);
err = baker.make_lightmap(E->get().local_xform, E->get().mesh, bake_default_texels_per_unit, lm, _bake_time, &btd);
if (err != OK) {
bake_end_function();
if (err == ERR_SKIP)
@ -473,7 +482,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
step += 100;
} else {
err = baker.make_lightmap(E->get().local_xform, E->get().mesh, lm);
err = baker.make_lightmap(E->get().local_xform, E->get().mesh, bake_default_texels_per_unit, lm);
}
if (err == OK) {
@ -790,6 +799,9 @@ void BakedLightmap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BakedLightmap::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &BakedLightmap::get_extents);
ClassDB::bind_method(D_METHOD("set_bake_default_texels_per_unit", "texels"), &BakedLightmap::set_bake_default_texels_per_unit);
ClassDB::bind_method(D_METHOD("get_bake_default_texels_per_unit"), &BakedLightmap::get_bake_default_texels_per_unit);
ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &BakedLightmap::set_propagation);
ClassDB::bind_method(D_METHOD("get_propagation"), &BakedLightmap::get_propagation);
@ -814,6 +826,7 @@ void BakedLightmap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_energy", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_hdr"), "set_hdr", "is_hdr");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bake_extents"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_default_texels_per_unit"), "set_bake_default_texels_per_unit", "get_bake_default_texels_per_unit");
ADD_GROUP("Capture", "capture_");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "capture_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_capture_cell_size", "get_capture_cell_size");
ADD_GROUP("Data", "");
@ -836,6 +849,7 @@ void BakedLightmap::_bind_methods() {
BakedLightmap::BakedLightmap() {
extents = Vector3(10, 10, 10);
bake_default_texels_per_unit = 20;
bake_cell_size = 0.25;
capture_cell_size = 0.5;

View File

@ -119,6 +119,7 @@ private:
float bake_cell_size;
float capture_cell_size;
Vector3 extents;
float bake_default_texels_per_unit;
float propagation;
float energy;
BakeQuality bake_quality;
@ -178,6 +179,9 @@ public:
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
void set_bake_default_texels_per_unit(const float &p_extents);
float get_bake_default_texels_per_unit() const;
void set_propagation(float p_propagation);
float get_propagation() const;

View File

@ -1794,19 +1794,82 @@ void VoxelLightBaker::_lightmap_bake_point(uint32_t p_x, LightMap *p_line) {
}
}
Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float), void *p_bake_time_ud) {
Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, float default_texels_per_unit, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float), void *p_bake_time_ud) {
//transfer light information to a lightmap
Ref<Mesh> mesh = p_mesh;
int width = mesh->get_lightmap_size_hint().x;
int height = mesh->get_lightmap_size_hint().y;
//step 1 - create lightmap
int width;
int height;
Vector<LightMap> lightmap;
lightmap.resize(width * height);
Transform xform = to_cell_space * p_xform;
if (mesh->get_lightmap_size_hint() == Size2()) {
double area = 0;
double uv_area = 0;
for (int i = 0; i < mesh->get_surface_count(); i++) {
Array arrays = mesh->surface_get_arrays(i);
PoolVector<Vector3> vertices = arrays[Mesh::ARRAY_VERTEX];
PoolVector<Vector2> uv2 = arrays[Mesh::ARRAY_TEX_UV2];
PoolVector<int> indices = arrays[Mesh::ARRAY_INDEX];
ERR_FAIL_COND_V(vertices.size() == 0, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(uv2.size() == 0, ERR_INVALID_PARAMETER);
int vc = vertices.size();
PoolVector<Vector3>::Read vr = vertices.read();
PoolVector<Vector2>::Read u2r = uv2.read();
PoolVector<int>::Read ir;
int ic = 0;
if (indices.size()) {
ic = indices.size();
ir = indices.read();
}
int faces = ic ? ic / 3 : vc / 3;
for (int j = 0; j < faces; j++) {
Vector3 vertex[3];
Vector2 uv[3];
for (int k = 0; k < 3; k++) {
int idx = ic ? ir[j * 3 + k] : j * 3 + k;
vertex[k] = xform.xform(vr[idx]);
uv[k] = u2r[idx];
}
Vector3 p1 = vertex[0];
Vector3 p2 = vertex[1];
Vector3 p3 = vertex[2];
double a = p1.distance_to(p2);
double b = p2.distance_to(p3);
double c = p3.distance_to(p1);
double halfPerimeter = (a + b + c) / 2.0;
area += sqrt(halfPerimeter * (halfPerimeter - a) * (halfPerimeter - b) * (halfPerimeter - c));
Vector2 uv_p1 = uv[0];
Vector2 uv_p2 = uv[1];
Vector2 uv_p3 = uv[2];
double uv_a = uv_p1.distance_to(uv_p2);
double uv_b = uv_p2.distance_to(uv_p3);
double uv_c = uv_p3.distance_to(uv_p1);
double uv_halfPerimeter = (uv_a + uv_b + uv_c) / 2.0;
uv_area += sqrt(uv_halfPerimeter * (uv_halfPerimeter - uv_a) * (uv_halfPerimeter - uv_b) * (uv_halfPerimeter - uv_c));
}
}
if (uv_area < 0.0001f) {
uv_area = 1.0;
}
int pixels = (ceil((1.0 / sqrt(uv_area)) * sqrt(area * default_texels_per_unit)));
width = height = CLAMP(pixels, 2, 4096);
} else {
width = mesh->get_lightmap_size_hint().x;
height = mesh->get_lightmap_size_hint().y;
}
lightmap.resize(width * height);
//step 2 plot faces to lightmap
for (int i = 0; i < mesh->get_surface_count(); i++) {

View File

@ -177,7 +177,7 @@ public:
PoolVector<float> light;
};
Error make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float) = NULL, void *p_bake_time_ud = NULL);
Error make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, float default_texels_per_unit, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float) = NULL, void *p_bake_time_ud = NULL);
PoolVector<int> create_gi_probe_data();
Ref<MultiMesh> create_debug_multimesh(DebugMode p_mode = DEBUG_ALBEDO);