Files
korenkonder_ReDIVA/src/KKdLib/light_param/ibl.cpp
T
2023-09-16 16:52:33 +03:00

450 lines
14 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "ibl.hpp"
#include "../io/file_stream.hpp"
#include "../io/memory_stream.hpp"
#include "../io/path.hpp"
#include "../str_utils.hpp"
static void light_param_ibl_read_inner(light_param_ibl* ibl, stream& s);
static const char* light_param_ibl_read_line(char* buf, int32_t size, const char* src);
static void light_param_ibl_specular_generate_mipmaps(light_param_ibl_specular* specular);
static void light_param_ibl_specular_generate_mipmap(float_t* src, float_t* dst, size_t size);
light_param_ibl::light_param_ibl() : ready(), lit_col(), lit_dir(), diff_coef() {
}
light_param_ibl::~light_param_ibl() {
}
void light_param_ibl::read(const char* path) {
char* path_ibl = str_utils_add(path, ".ibl");
if (path_check_file_exists(path_ibl)) {
file_stream s;
s.open(path_ibl, "rb");
if (s.check_not_null())
light_param_ibl_read_inner(this, s);
}
free_def(path_ibl);
}
void light_param_ibl::read(const wchar_t* path) {
wchar_t* path_ibl = str_utils_add(path, L".ibl");
if (path_check_file_exists(path_ibl)) {
file_stream s;
s.open(path_ibl, L"rb");
if (s.check_not_null())
light_param_ibl_read_inner(this, s);
}
free_def(path_ibl);
}
void light_param_ibl::read(const void* data, size_t size) {
memory_stream s;
s.open(data, size);
light_param_ibl_read_inner(this, s);
}
bool light_param_ibl::load_file(void* data, const char* path, const char* file, uint32_t hash) {
size_t file_len = utf8_length(file);
const char* t = strrchr(file, '.');
if (t)
file_len = t - file;
std::string s;
s.assign(path);
s.append(file, file_len);
light_param_ibl* ibl = (light_param_ibl*)data;
ibl->read(s.c_str());
return ibl->ready;
}
light_param_ibl_diffuse::light_param_ibl_diffuse() : data(), size() {
}
light_param_ibl_diffuse::~light_param_ibl_diffuse() {
}
light_param_ibl_specular::light_param_ibl_specular() : data(), max_level(), size() {
}
light_param_ibl_specular::~light_param_ibl_specular() {
}
static void light_param_ibl_read_inner(light_param_ibl* ibl, stream& s) {
char* data = force_malloc<char>(s.length + 1);
s.read(data, s.length);
data[s.length] = 0;
char buf[0x200];
const char* d = light_param_ibl_read_line(buf, sizeof(buf), data);
if (str_utils_compare(buf, "VF5_IBL"))
return;
int32_t widths[6] = { 0 };
int32_t heights[6] = { 0 };
while (d) {
do
d = light_param_ibl_read_line(buf, sizeof(buf), d);
while (buf[0] == '#');
if (!str_utils_compare(buf, "VERSION"))
d = light_param_ibl_read_line(buf, sizeof(buf), d);
else if (!str_utils_compare(buf, "LIT_DIR")) {
d = light_param_ibl_read_line(buf, sizeof(buf), d);
int32_t index;
if (sscanf_s(buf, "%d", &index) != 1)
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
vec4 dir;
if (sscanf_s(buf, "%f %f %f", &dir.x, &dir.y, &dir.z) != 3)
goto End;
dir.w = 0.0f;
ibl->lit_dir[index] = dir;
}
else if (!str_utils_compare(buf, "LIT_COL")) {
d = light_param_ibl_read_line(buf, sizeof(buf), d);
int32_t index;
if (sscanf_s(buf, "%d", &index) != 1)
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
vec4 col;
if (sscanf_s(buf, "%f %f %f", &col.x, &col.y, &col.z) != 3)
goto End;
col.w = 0.0f;
ibl->lit_col[index] = col;
}
else if (!str_utils_compare(buf, "DIFF_COEF")) {
d = light_param_ibl_read_line(buf, sizeof(buf), d);
int32_t index;
if (sscanf_s(buf, "%d", &index) != 1)
goto End;
for (int32_t i = 0; i < 3; i++) {
d = light_param_ibl_read_line(buf, sizeof(buf), d);
mat4& mat = ibl->diff_coef[index][i];
if (sscanf_s(buf, "%f %f %f %f", &mat.row0.x, &mat.row1.x, &mat.row2.x, &mat.row3.x) != 4)
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
if (sscanf_s(buf, "%f %f %f %f", &mat.row0.y, &mat.row1.y, &mat.row2.y, &mat.row3.y) != 4)
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
if (sscanf_s(buf, "%f %f %f %f", &mat.row0.z, &mat.row1.z, &mat.row2.z, &mat.row3.z) != 4)
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
if (sscanf_s(buf, "%f %f %f %f", &mat.row0.w, &mat.row1.w, &mat.row2.w, &mat.row3.w) != 4)
goto End;
}
}
else if (!str_utils_compare(buf, "LIGHT_MAP")) {
d = light_param_ibl_read_line(buf, sizeof(buf), d);
int32_t index;
if (sscanf_s(buf, "%d", &index) != 1)
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
if (str_utils_compare(buf, "RGBA16F_CUBE"))
goto End;
d = light_param_ibl_read_line(buf, sizeof(buf), d);
int32_t w;
int32_t h;
if (sscanf_s(buf, "%d %d", &w, &h) != 2)
goto End;
widths[index] = w;
heights[index] = h;
}
else if (!str_utils_compare(buf, "BINARY")) {
half_t* dh = (half_t*)d;
for (int32_t i = 0, j = -2; i < 6; i++, j++) {
size_t size = widths[i];
size = 4 * (size * size);
if (i < 2) {
light_param_ibl_diffuse* diffuse = &ibl->diffuse[i];
diffuse->data = std::vector<half_t>(size * 6);
diffuse->size = widths[i];
for (int32_t k = 0; k < 6; k++, dh += size)
memcpy(&diffuse->data[size * k], dh, sizeof(half_t) * size);
}
else {
const int32_t max_level = 2;
light_param_ibl_specular* specular = &ibl->specular[j];
specular->data = std::vector<std::vector<half_t>>(max_level + 1ULL);
specular->max_level = max_level;
specular->size = widths[i];
size_t img_size = widths[i];
for (int32_t i = 0; i <= max_level; i++, img_size /= 2)
specular->data[i] = std::vector<half_t>(4 * (img_size * img_size) * 6);
std::vector<half_t>& specular_data = specular->data[0];
for (int32_t k = 0; k < 6; k++, dh += size)
memcpy(&specular_data[size * k], dh, sizeof(half_t) * size);
light_param_ibl_specular_generate_mipmaps(specular);
}
}
break;
}
else
goto End;
}
free_def(data);
ibl->ready = true;
return;
End:
free_def(data);
}
static const char* light_param_ibl_read_line(char* buf, int32_t size, const char* src) {
char* b = buf;
if (!src || !*src)
return 0;
for (int32_t i = 0; i < size - 1; i++, b++) {
char c = *b = *src++;
if (!c) {
b++;
break;
}
else if (c == '\n') {
*b++ = 0;
break;
}
else if (c == '\r' && *src == '\n') {
*b++ = 0;
src++;
break;
}
}
if (!str_utils_compare(buf, "EOF"))
return 0;
return src;
}
static void light_param_ibl_specular_generate_mipmaps(light_param_ibl_specular* specular) {
size_t size = specular->size;
int32_t max_level = specular->max_level;
float_t* data_f32[2];
data_f32[0] = force_malloc<float_t>(4 * (size * size) * 6);
data_f32[1] = force_malloc<float_t>(4 * ((size / 2) * (size / 2)) * 6);
for (int32_t i = 0; i < max_level; i++, size /= 2) {
size_t data_size = 4 * (size * size) * 6;
size_t data_size_2 = 4 * ((size / 2) * (size / 2)) * 6;
if (!i) {
std::vector<half_t>& data = specular->data[i];
float_t* temp = data_f32[0];
for (size_t j = 0; j < data_size; j++)
temp[j] = half_to_float(data[j]);
}
light_param_ibl_specular_generate_mipmap(data_f32[0], data_f32[1], (int32_t)size);
float_t* temp = data_f32[0];
data_f32[0] = data_f32[1];
data_f32[1] = temp;
std::vector<half_t>& data = specular->data[i + 1ULL];
temp = data_f32[0];
for (size_t j = 0; j < data_size_2; j++)
data[j] = float_to_half(temp[j]);
}
free_def(data_f32[0]);
free_def(data_f32[1]);
}
static void light_param_ibl_specular_generate_mipmap(float_t* src, float_t* dst, size_t size) {
const float_t kernel[] = {
0.025f, 0.050f, 0.050f, 0.025f,
0.050f, 0.125f, 0.125f, 0.050f,
0.050f, 0.125f, 0.125f, 0.050f,
0.025f, 0.050f, 0.050f, 0.025f,
};
size_t v2;
size_t v5;
size_t v6;
size_t v7;
size_t v8;
size_t v9;
size_t v10;
size_t v11;
size_t v12;
size_t v13;
size_t v14;
size_t v15;
size_t v16;
size_t v17;
float_t v18;
size_t v19;
float_t v20;
float_t v21;
size_t v22;
float_t v23;
float_t* v24;
size_t v25;
float_t* v26;
float_t* v27;
size_t v28;
float_t v29;
float_t v30;
float_t v31;
float_t* v32;
float_t* v33;
size_t v34;
float_t v35;
size_t v36;
size_t v37;
size_t v38;
size_t v39;
size_t v40;
size_t v41;
size_t v43;
size_t v44;
v2 = size;
v5 = size / 2;
v6 = 0;
v7 = 0;
v44 = 0;
v40 = v5;
v43 = 4 * v5 * v5;
v8 = v43;
v9 = 6;
v10 = 4 * v2 * v2;
v37 = 6;
do {
v11 = 0;
if (v5) {
v12 = v5 - 1;
v39 = v5 - 1;
do {
v13 = 0;
v14 = 4;
if (!v11)
v13 = 1;
if (v11 == v12)
v14 = 3;
v15 = 0;
v41 = v13;
v16 = v5 * v11;
v38 = v5 * v11;
do {
v17 = 0;
v18 = 0.0;
if (!v15)
v17 = 1;
v19 = 4;
if (v15 == v12)
v19 = 3;
v20 = 0.0;
v21 = 0.0;
v22 = v13;
v23 = 0.0;
if (v13 < v14) {
v24 = (float_t*)&kernel[4 * v13 + 1 + v17];
do {
v25 = v17;
if (v17 < v19) {
if ((v19 - v17) >= 4) {
v26 = v24;
v27 = &src[8 * v15 + 6 + 4 * v17 + 4 * v2 * (v22 + 2 * v11 - 1) + v7];
v28 = ((v19 - v17 - 4) >> 2) + 1;
v25 = v17 + 4 * v28;
do {
v29 = *(v26 - 1);
v30 = *v26;
v27 += 16;
v26 += 4;
v31 = *(v26 - 2);
v18 += v29 + v30 + *(v26 - 3) + v31;
v21 += v29 * *(v27 - 25) + v30 * *(v27 - 21) + *(v26 - 3) * *(v27 - 17) + v31 * *(v27 - 13);
v23 += v29 * *(v27 - 26) + v30 * *(v27 - 22) + *(v26 - 3) * *(v27 - 18) + v31 * *(v27 - 14);
v20 += v29 * *(v27 - 24) + v30 * *(v27 - 20) + *(v26 - 3) * *(v27 - 16) + v31 * *(v27 - 12);
--v28;
} while (v28);
}
if (v25 < v19) {
v32 = (float_t*)&kernel[4 * v22 + v25];
v33 = &src[8 * v15 - 2 + 4 * v25 + 4 * v2 * (v22 + 2 * v11 - 1) + v7];
v34 = v19 - v25;
do {
v35 = *v32;
v33 += 4;
++v32;
v18 = v18 + v35;
v23 += v35 * *(v33 - 6);
v21 += v35 * *(v33 - 5);
v20 += v35 * *(v33 - 4);
--v34;
} while (v34);
}
}
++v22;
v24 += 4;
} while (v22 < v14);
v16 = v38;
v12 = v39;
v6 = v44;
}
v36 = v6 + 4 * (v16 + v15++);
v18 = 1.0f / v18;
dst[v36] = v18 * v23;
dst[v36 + 1] = v18 * v21;
dst[v36 + 2] = v18 * v20;
dst[v36 + 3] = 1.0f;
v5 = v40;
v13 = v41;
} while (v15 < v40);
++v11;
} while (v11 < v40);
v9 = v37;
v8 = v43;
v10 = 4 * v2 * v2;
}
v6 += v8;
v7 += v10;
v37 = --v9;
v44 = v6;
} while (v9);
}