diff --git a/src/DivaGL/DivaGL.vcxproj b/src/DivaGL/DivaGL.vcxproj
index c38a7e6..0741f14 100644
--- a/src/DivaGL/DivaGL.vcxproj
+++ b/src/DivaGL/DivaGL.vcxproj
@@ -165,6 +165,7 @@ del "$(SolutionDir)bin\$(TargetName).lib"
+
@@ -218,6 +219,7 @@ del "$(SolutionDir)bin\$(TargetName).lib"
+
diff --git a/src/DivaGL/hook.cpp b/src/DivaGL/hook.cpp
index 59abe9f..cdf5799 100644
--- a/src/DivaGL/hook.cpp
+++ b/src/DivaGL/hook.cpp
@@ -11,6 +11,7 @@
#include "auth_3d.hpp"
#include "camera.hpp"
#include "effect.hpp"
+#include "light_param.hpp"
#include "object.hpp"
#include "print.hpp"
#include "resource.h"
@@ -52,6 +53,7 @@ HOOK(int32_t, FASTCALL, data_init, 0x0000000140192FF0) {
camera_patch();
mdl::disp_manager_patch();
effect_patch();
+ light_param_patch();
object_patch();
render_manager_patch();
rob_patch();
diff --git a/src/DivaGL/light_param.cpp b/src/DivaGL/light_param.cpp
new file mode 100644
index 0000000..0a24803
--- /dev/null
+++ b/src/DivaGL/light_param.cpp
@@ -0,0 +1,369 @@
+/*
+ by korenkonder
+ GitHub/GitLab: korenkonder
+*/
+
+#include "light_param.hpp"
+#include "../KKdLib/hash.hpp"
+#include "../KKdLib/str_utils.hpp"
+#include "light_param/light.hpp"
+#include "file_handler.hpp"
+#include "render_context.hpp"
+#include
+
+struct light_param_data_light_data {
+ bool has_type;
+ light_type type;
+ bool has_ambient;
+ vec4 ambient;
+ bool has_diffuse;
+ vec4 diffuse;
+ bool has_specular;
+ vec4 specular;
+ bool has_position;
+ vec3 position;
+ bool has_spot_direction;
+ bool has_spot_exponent;
+ bool has_spot_cutoff;
+ bool has_attenuation;
+ vec3 spot_direction;
+ float_t spot_exponent;
+ float_t spot_cutoff;
+ vec3 attenuation;
+ char has_clip_plane;
+ bool clip_plane[4];
+ bool has_tone_curve;
+ vec3 tone_curve;
+};
+
+static_assert(sizeof(light_param_data_light_data) == 0x8C, "\"light_param_data_light_data\" struct should have a size of 0x8C");
+
+struct light_param_data_light {
+ prj::map> data;
+ bool has_data;
+};
+
+static_assert(sizeof(light_param_data_light) == 0x18, "\"light_param_data_light\" struct should have a size of 0x18");
+
+struct light_param_data_fog_data {
+ bool has_type;
+ fog_type type;
+ bool has_density;
+ float_t density;
+ bool has_linear;
+ float_t linear_start;
+ float_t linear_end;
+ bool has_color;
+ vec4 color;
+};
+
+static_assert(sizeof(light_param_data_fog_data) == 0x30, "\"light_param_data_fog_data\" struct should have a size of 0x30");
+
+struct light_param_data_fog {
+ prj::map data;
+ bool has_data;
+};
+
+static_assert(sizeof(light_param_data_fog) == 0x18, "\"light_param_data_fog\" struct should have a size of 0x18");
+
+struct light_param_data_glow {
+ bool has_exposure;
+ float_t exposure;
+ bool has_gamma;
+ float_t gamma;
+ bool has_saturate_power;
+ int32_t saturate_power;
+ bool has_saturate_coef;
+ float_t saturate_coef;
+ bool has_flare;
+ vec3 flare;
+ bool has_sigma;
+ vec3 sigma;
+ bool has_intensity;
+ vec3 intensity;
+ bool has_auto_exposure;
+ bool auto_exposure;
+ bool has_tone_map_method;
+ int32_t tone_map_method;
+ bool has_fade_color;
+ vec4 fade_color;
+ int32_t fade_color_blend_func;
+ bool has_tone_transform;
+ vec3 tone_transform_start;
+ vec3 tone_transform_end;
+ bool has_data;
+};
+
+static_assert(sizeof(light_param_data_glow) == 0x90, "\"light_param_data_glow\" struct should have a size of 0x90");
+
+struct light_param_data_ibl_diffuse {
+ prj::vector data;
+ GLenum type;
+ int32_t size;
+ int32_t level;
+ GLenum internal_format;
+};
+
+static_assert(sizeof(light_param_data_ibl_diffuse) == 0x28, "\"light_param_data_ibl_diffuse\" struct should have a size of 0x28");
+
+struct light_param_data_ibl_specular_byte_data {
+ prj::vector data;
+ size_t size;
+};
+
+static_assert(sizeof(light_param_data_ibl_specular_byte_data) == 0x20, "\"light_param_data_ibl_specular_byte_data\" struct should have a size of 0x20");
+
+struct light_param_data_ibl_specular_half_data {
+ prj::vector data;
+ size_t size;
+};
+
+static_assert(sizeof(light_param_data_ibl_specular_half_data) == 0x20, "\"light_param_data_ibl_specular_half_data\" struct should have a size of 0x20");
+
+struct light_param_data_ibl_specular {
+ prj::vector uint8_t_data;
+ prj::vector half_t_data;
+};
+
+static_assert(sizeof(light_param_data_ibl_specular) == 0x30, "\"light_param_data_ibl_specular\" struct should have a size of 0x30");
+
+struct light_param_data_ibl {
+ vec4 lit_dir[4];
+ vec4 lit_col[4];
+ mat4 diff_coef[4][3];
+ int32_t widths[6];
+ int32_t heights[6];
+ bool has_data;
+ light_param_data_ibl_diffuse diffuse[2];
+ light_param_data_ibl_specular specular[4];
+};
+
+static_assert(sizeof(light_param_data_ibl) == 0x4C8, "\"light_param_data_ibl\" struct should have a size of 0x4C8");
+
+struct light_param_data_wind_spc {
+ float_t cos;
+ float_t sin;
+};
+
+static_assert(sizeof(light_param_data_wind_spc) == 0x08, "\"light_param_data_wind_spc\" struct should have a size of 0x08");
+
+struct light_param_data_wind {
+ bool has_scale;
+ float_t scale;
+ bool has_cycle;
+ float_t cycle;
+ bool has_rot;
+ vec2 rot;
+ bool has_bias;
+ float_t bias;
+ bool has_spc[16];
+ light_param_data_wind_spc spc[16];
+ bool has_data;
+};
+
+static_assert(sizeof(light_param_data_wind) == 0xB8, "\"light_param_data_wind\" struct should have a size of 0xB8");
+
+struct light_param_data_face_data {
+ float_t offset;
+ float_t scale;
+ vec3 position;
+ vec3 direction;
+};
+
+static_assert(sizeof(light_param_data_face_data) == 0x20, "\"light_param_data_face_data\" struct should have a size of 0x20");
+
+struct __declspec(align(8)) light_param_data_face {
+ light_param_data_face_data data;
+ bool has_data;
+};
+
+static_assert(sizeof(light_param_data_face) == 0x28, "\"light_param_data_face\" struct should have a size of 0x28");
+
+struct light_param_data_storage;
+
+struct light_param_data {
+ prj::string name;
+ prj::string files[6];
+ bool pv;
+ light_param_data_light light;
+ light_param_data_fog fog;
+ light_param_data_glow glow;
+ light_param_data_ibl ibl;
+ light_param_data_wind wind;
+ light_param_data_face face;
+
+ static void set_ibl(const light_param_data_ibl* ibl, const light_param_data_storage* storage);
+ static void set_ibl_diffuse(const light_param_data_ibl_diffuse* diffuse);
+ static void set_ibl_specular(const light_param_data_ibl_specular* specular);
+ static void set_ibl_specular_byte(
+ const light_param_data_ibl_specular_byte_data* data, const int32_t level);
+ static void set_ibl_specular_half(
+ const light_param_data_ibl_specular_half_data* data, const int32_t level);
+};
+
+static_assert(sizeof(light_param_data) == 0x750, "\"light_param_data\" struct should have a size of 0x750");
+
+struct light_param_data_storage {
+ GLuint textures[5];
+ int32_t state;
+ prj::string name;
+ int32_t stage_index;
+ light_param_data default_light_param;
+ prj::map stage;
+ prj::map::iterator current_light_param;
+ prj::map pv_cut;
+ p_file_handler file_handlers[6];
+ p_file_handler farc_file_handler;
+ int32_t pv_id;
+};
+
+static_assert(sizeof(light_param_data_storage) == 0x7F8, "\"light_param_data_storage\" struct should have a size of 0x7F8");
+
+light_param_data_storage* light_param_data_storage_data = (light_param_data_storage*)0x00000001411A06A0;
+
+static uint8_t(FASTCALL* sub_1403EAB10)() = (uint8_t(FASTCALL*)())0x00000001403EAB10;
+
+HOOK(void, FASTCALL, light_param_data__set_ibl, 0x00000001403E7210,
+ const light_param_data_ibl* ibl, const light_param_data_storage* storage) {
+ light_param_data::set_ibl(ibl, storage);
+}
+
+void light_param_patch() {
+ INSTALL_HOOK(light_param_data__set_ibl);
+}
+
+void light_param_data_storage_data_set_ibl() {
+ static const int32_t ibl_texture_index[] = {
+ 9, 10, 11, 12, 13
+ };
+
+ for (int32_t i = 0; i < 5; i++)
+ gl_state_active_bind_texture_cube_map(ibl_texture_index[i],
+ light_param_data_storage_data->textures[i]);
+}
+
+void light_param_data::set_ibl(const light_param_data_ibl* ibl, const light_param_data_storage* storage) {
+ for (int32_t i = 0, j = -1; i < 5; i++, j++) {
+ gl_state_bind_texture_cube_map(storage->textures[i]);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ if (!i) {
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ light_param_data::set_ibl_diffuse(&ibl->diffuse[0]);
+ light_param_data::set_ibl_diffuse(&ibl->diffuse[1]);
+ }
+ else {
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 2);
+ if (sub_1403EAB10()) {
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterfDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, 0.0f);
+ }
+ else {
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteriDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ glTexParameterfDLL(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, -1.5f);
+ }
+ light_param_data::set_ibl_specular(&ibl->specular[j]);
+ }
+ }
+ gl_state_bind_texture_cube_map(0);
+
+ ::light_set* set = &light_set_data[LIGHT_SET_MAIN];
+ set->set_irradiance(ibl->diff_coef[1][0], ibl->diff_coef[1][1], ibl->diff_coef[1][2]);
+
+ float_t len;
+ vec3 pos;
+
+ light_data* l = &set->lights[LIGHT_CHARA];
+ l->get_position(pos);
+ len = vec3::length(pos);
+ if (fabsf(len - 1.0f) < 0.02f)
+ l->set_position(ibl->lit_dir[0]);
+
+ l->set_ibl_color0(ibl->lit_col[0]);
+ l->set_ibl_color1(ibl->lit_col[2]);
+ l->set_ibl_direction(ibl->lit_dir[0]);
+
+ l = &set->lights[LIGHT_STAGE];
+ l->get_position(pos);
+ len = vec3::length(pos);
+ if (fabsf(len - 1.0f) < 0.02f)
+ l->set_position(ibl->lit_dir[1]);
+
+ l->set_ibl_color0(ibl->lit_col[1]);
+ l->set_ibl_direction(ibl->lit_dir[1]);
+}
+
+void light_param_data::set_ibl_diffuse(const light_param_data_ibl_diffuse* diffuse) {
+ if (!diffuse->data.size())
+ return;
+
+ int32_t size = diffuse->size;
+ const int32_t level = diffuse->level;
+ const uint8_t* _data = diffuse->data.data();
+ size_t data_size = diffuse->data.size() / 6;
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 0]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 1]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 2]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 3]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 4]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 5]);
+}
+
+void light_param_data::set_ibl_specular(const light_param_data_ibl_specular* specular) {
+ int32_t level = 0;
+ if (sub_1403EAB10())
+ for (const light_param_data_ibl_specular_half_data& i : specular->half_t_data)
+ light_param_data::set_ibl_specular_half(&i, level++);
+ else
+ for (const light_param_data_ibl_specular_byte_data& i : specular->uint8_t_data)
+ light_param_data::set_ibl_specular_byte(&i, level++);
+}
+
+void light_param_data::set_ibl_specular_byte(
+ const light_param_data_ibl_specular_byte_data* data, const int32_t level) {
+ int32_t size = (int32_t)data->size;
+ const uint8_t* _data = data->data.data();
+ size_t data_size = data->data.size() / 6;
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_RGBA8,
+ size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &_data[data_size * 0]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, GL_RGBA8,
+ size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &_data[data_size * 1]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, GL_RGBA8,
+ size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &_data[data_size * 2]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, GL_RGBA8,
+ size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &_data[data_size * 3]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, GL_RGBA8,
+ size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &_data[data_size * 4]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, GL_RGBA8,
+ size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &_data[data_size * 5]);
+}
+
+void light_param_data::set_ibl_specular_half(
+ const light_param_data_ibl_specular_half_data* data, const int32_t level) {
+ int32_t size = (int32_t)data->size;
+ const half_t* _data = data->data.data();
+ size_t data_size = data->data.size() / 6;
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 0]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 1]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 2]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 3]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 4]);
+ glTexImage2DDLL(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, GL_RGBA16F,
+ size, size, 0, GL_RGBA, GL_HALF_FLOAT, &_data[data_size * 5]);
+}
diff --git a/src/DivaGL/light_param.hpp b/src/DivaGL/light_param.hpp
new file mode 100644
index 0000000..e32bf67
--- /dev/null
+++ b/src/DivaGL/light_param.hpp
@@ -0,0 +1,11 @@
+/*
+ by korenkonder
+ GitHub/GitLab: korenkonder
+*/
+
+#pragma once
+
+#include "types.hpp"
+
+extern void light_param_patch();
+extern void light_param_data_storage_data_set_ibl();
diff --git a/src/DivaGL/render_context.hpp b/src/DivaGL/render_context.hpp
index 45ca254..ba1063d 100644
--- a/src/DivaGL/render_context.hpp
+++ b/src/DivaGL/render_context.hpp
@@ -32,6 +32,8 @@ struct draw_state_stats {
void reset();
};
+static_assert(sizeof(draw_state_stats) == 0x20, "\"draw_state_stats\" struct should have a size of 0x20");
+
struct sss_data {
bool init_data;
bool enable;
@@ -44,6 +46,8 @@ struct sss_data {
void set_texture(int32_t);
};
+static_assert(sizeof(sss_data) == 0xD8, "\"sss_data\" struct should have a size of 0xD8");
+
struct draw_state_struct {
draw_state_stats stats;
draw_state_stats stats_prev;
@@ -72,6 +76,8 @@ struct draw_state_struct {
void set_fog_height(bool value);
};
+static_assert(sizeof(draw_state_struct) == 0x88, "\"draw_state_struct\" struct should have a size of 0x88");
+
struct camera_blur_shader_data {
vec4 g_transform[4];
};
diff --git a/src/DivaGL/render_manager.cpp b/src/DivaGL/render_manager.cpp
index af73c47..939e5ec 100644
--- a/src/DivaGL/render_manager.cpp
+++ b/src/DivaGL/render_manager.cpp
@@ -12,6 +12,7 @@
#include "rob/rob.hpp"
#include "effect.hpp"
#include "gl_state.hpp"
+#include "light_param.hpp"
#include "render.hpp"
#include "render_context.hpp"
#include "render_texture.hpp"
@@ -243,6 +244,8 @@ namespace rndr {
if (!rctx)
return;
+ light_param_data_storage_data_set_ibl();
+
static const vec4 color_clear = 0.0f;
gl_state_bind_framebuffer(0);