370 lines
11 KiB
C++
370 lines
11 KiB
C++
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
*/
|
|
|
|
#include "shadow.hpp"
|
|
#include "../AFTModsShared/light_param/light.hpp"
|
|
#include "render_context.hpp"
|
|
#include "render_manager.hpp"
|
|
#include <Helpers.h>
|
|
|
|
#define MIN_SHADOW_RANGE (1.2f)
|
|
#define SHADOW_RANGE_SEPARATE (MIN_SHADOW_RANGE * 2.0f)
|
|
|
|
Shadow*& shadow_ptr = *(Shadow**)0x000000014CC587B8;
|
|
|
|
void(FASTCALL* sub_1405E8A20)(Shadow* shad, int32_t index, const vec3& pos)
|
|
= (void(FASTCALL*)(Shadow* shad, int32_t index, const vec3 & pos))0x00000001405E8A20;
|
|
void(FASTCALL* shadow_ptr_free)() = (void(FASTCALL*)())0x00000001405E8610;
|
|
void(FASTCALL* shadow_ptr_init)() = (void(FASTCALL*)())0x00000001405E8890;
|
|
|
|
static void sub_1405E60E0(Shadow* shad);
|
|
static void sub_1405E63D0(Shadow* shad);
|
|
static void sub_1405E6840(Shadow* shad);
|
|
static void sub_1405E6910(Shadow* shad);
|
|
static void sub_1405E6B70(Shadow* shad);
|
|
|
|
void Shadow::ctrl() {
|
|
for (int32_t i = 0; i < 2; i++)
|
|
shadow_enable[i] = false;
|
|
|
|
if (render_manager.shadow) {
|
|
view_mat[0] = camera_data.view;
|
|
view_mat[1] = camera_data.inv_view;
|
|
|
|
light_data& light_chara = light_set_data[LIGHT_SET_MAIN].lights[LIGHT_CHARA];
|
|
|
|
vec3 position;
|
|
light_chara.get_position(position);
|
|
float_t length = vec3::length(position);
|
|
if (length < 0.000001f)
|
|
direction = { 0.0f, 1.0f, 0.0f };
|
|
else
|
|
direction = -position * (1.0f / length);
|
|
|
|
for (int32_t i = 0; i < 2; i++)
|
|
if (disp_manager->get_obj_count((mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_CHARA + i)))
|
|
shadow_enable[i] = true;
|
|
}
|
|
|
|
sub_1405E6840(this);
|
|
}
|
|
|
|
void Shadow::free() {
|
|
for (RenderTexture& i : render_textures)
|
|
i.Free();
|
|
|
|
reset();
|
|
}
|
|
|
|
float_t Shadow::get_shadow_range() {
|
|
return shadow_range * shadow_range_factor;
|
|
}
|
|
|
|
int32_t Shadow::init() {
|
|
struct shadow_texture_init_params {
|
|
GLenum target;
|
|
int32_t width;
|
|
int32_t height;
|
|
int32_t max_level;
|
|
GLenum color_format;
|
|
GLenum depth_format;
|
|
};
|
|
|
|
shadow_texture_init_params* init_param = (shadow_texture_init_params*)0x140A81E00;
|
|
for (int32_t i = 0; i < 7; i++, init_param++)
|
|
if (render_textures[i].Init(init_param->width, init_param->height,
|
|
init_param->max_level, init_param->color_format, init_param->depth_format) < 0)
|
|
return -1;
|
|
|
|
for (int32_t i = 0; i < 3; i++) {
|
|
gl_rend_state.bind_texture_2d(render_textures[i].GetColorTex());
|
|
glTexParameteriDLL(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
|
glTexParameteriDLL(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
|
static const vec4 border_color = 1.0f;
|
|
glTexParameterfvDLL(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color);
|
|
}
|
|
gl_rend_state.bind_texture_2d(0);
|
|
gl_get_error_print();
|
|
return 0;
|
|
}
|
|
|
|
void Shadow::reset() {
|
|
shadow_range = 1.2f;
|
|
shadow_range_factor = 1.0f;
|
|
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
view_point[i] = 1.0f;
|
|
field_1C0[i] = 0.0f;
|
|
field_1C8[i] = 0.0f;
|
|
index[i] = i;
|
|
}
|
|
|
|
for (RenderTexture*& i : curr_render_textures)
|
|
i = 0;
|
|
|
|
view_mat[0] = mat4_identity;
|
|
view_mat[1] = mat4_identity;
|
|
blur_filter = BLUR_FILTER_9;
|
|
near_blur = 1;
|
|
field_2BC = 2;
|
|
far_blur = 1;
|
|
distance = 4.0f;
|
|
field_2C4 = 0.4f;
|
|
z_near = 0.1f;
|
|
z_far = 20.0f;
|
|
field_2D0 = 1.4f;
|
|
field_2D4 = 10000.0f;
|
|
field_2D8 = 80.0f;
|
|
field_2DC = 2.0f;
|
|
field_2E0 = 0.05f;
|
|
shadow_ambient = 0.4f;
|
|
num_shadow = 0;
|
|
direction = vec3(0.0f, -1.0f, -1.0f) * (1.0f / sqrtf(2.0f));
|
|
show_texture = false;
|
|
self_shadow = true;
|
|
separate = false;
|
|
z_half_range = (z_far - z_near) * 0.5f;
|
|
}
|
|
|
|
Shadow* shadow_ptr_get() {
|
|
return shadow_ptr;
|
|
}
|
|
|
|
HOOK(void, FASTCALL, shadow_ctrl, 0x0000000140502390) {
|
|
shadow_ptr_get()->ctrl();
|
|
}
|
|
|
|
HOOK(void, FASTCALL, Shadow__free, 0x00000001405E8350, Shadow* This) {
|
|
This->free();
|
|
}
|
|
|
|
void shadow_patch() {
|
|
INSTALL_HOOK(shadow_ctrl);
|
|
INSTALL_HOOK(Shadow__free);
|
|
}
|
|
|
|
static void sub_1405E60E0(Shadow* shad) {
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
shad->position[i] = 0.0f;
|
|
shad->field_1C8[i] = 0.0f;
|
|
|
|
if (!shad->shadow_enable[i] || !shad->positions[i].size())
|
|
continue;
|
|
|
|
vec3 position = 0.0f;
|
|
for (vec3& j : shad->positions[i])
|
|
position += j;
|
|
|
|
float_t v14 = (float_t)(int64_t)shad->positions[i].size();
|
|
if (v14 < 0.0f)
|
|
v14 += (float_t)UINT64_MAX;
|
|
position *= 1.0f / v14;
|
|
|
|
float_t v15 = 0.0f;
|
|
for (vec3& j : shad->positions[i]) {
|
|
vec3 v22 = position - j;
|
|
vec3 v23 = vec3::dot(v22, shad->direction);
|
|
float_t v24 = vec3::distance(shad->direction * v23, v22);
|
|
v15 = max_def(v15, max_def(v24 - 0.25f, 0.0f));
|
|
}
|
|
shad->position[i] = position;
|
|
shad->field_1C8[i] = v15;
|
|
}
|
|
|
|
for (prj::vector<vec3>& i : shad->positions)
|
|
i.clear();
|
|
}
|
|
|
|
static void sub_1405E63D0(Shadow* shad) {
|
|
if (shad->num_shadow <= 0)
|
|
return;
|
|
|
|
vec3 view_point = 0.0f;
|
|
vec3 interest = 0.0f;
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
if (!shad->shadow_enable[i])
|
|
continue;
|
|
|
|
const vec3 v11 = shad->position[i] - shad->direction * shad->z_half_range;
|
|
const float_t v9 = vec3::distance(shad->view_point[i], v11);
|
|
const float_t v12 = vec3::distance(shad->interest[i], shad->position[i]);
|
|
if (v9 > 0.1f || v12 > 0.1f) {
|
|
shad->view_point[i] = v11;
|
|
shad->interest[i] = shad->position[i];
|
|
}
|
|
|
|
view_point += shad->view_point[i];
|
|
interest += shad->interest[i];
|
|
}
|
|
|
|
shad->view_point_shared = view_point * (1.0f / (float_t)shad->num_shadow);
|
|
shad->interest_shared = interest * (1.0f / (float_t)shad->num_shadow);
|
|
}
|
|
|
|
static void sub_1405E6840(Shadow* shad) {
|
|
int32_t count = 0;
|
|
shad->num_shadow = 0;
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
if (shad->shadow_enable[i] && shad->positions[i].size()) {
|
|
++shad->num_shadow;
|
|
count += (int32_t)shad->positions->size();
|
|
}
|
|
else
|
|
shad->shadow_enable[i] = false;
|
|
}
|
|
|
|
if (count < 3) {
|
|
sub_1405E60E0(shad);
|
|
sub_1405E63D0(shad);
|
|
sub_1405E6910(shad);
|
|
}
|
|
else
|
|
sub_1405E6B70(shad);
|
|
}
|
|
|
|
static void sub_1405E6910(Shadow* shad) {
|
|
const float_t v2 = max_def(shad->field_1C8[0], shad->field_1C8[1]);
|
|
shad->separate = false;
|
|
shad->shadow_range = v2 + MIN_SHADOW_RANGE;
|
|
shad->index[0] = 0;
|
|
shad->index[1] = 1;
|
|
|
|
if (shad->num_shadow < 2)
|
|
return;
|
|
|
|
const vec3 v12 = shad->position[0] - shad->interest_shared;
|
|
const vec3 v14 = shad->position[1] - shad->interest_shared;
|
|
float_t v16 = vec3::distance((shad->direction * vec3::dot(v12, shad->direction)), v12);
|
|
v16 = max_def(v16 - 0.25f, 0.0f);
|
|
|
|
if (v2 + MIN_SHADOW_RANGE + v16 > v2 + SHADOW_RANGE_SEPARATE) {
|
|
shad->shadow_range = v2 + SHADOW_RANGE_SEPARATE;
|
|
shad->separate = true;
|
|
}
|
|
else
|
|
shad->shadow_range = v2 + MIN_SHADOW_RANGE + v16;
|
|
|
|
if (vec3::dot(v12, shad->direction) < vec3::dot(v14, shad->direction)) {
|
|
shad->index[0] = 1;
|
|
shad->index[1] = 0;
|
|
}
|
|
}
|
|
|
|
static void sub_1405E6B70(Shadow* shad) {
|
|
vec3 v3;
|
|
vec3 v86;
|
|
if (shad->direction.y * shad->direction.y < 0.99f) {
|
|
v86 = vec3::cross(shad->direction, vec3(0.0f, 1.0f, 0.0f));
|
|
v3 = vec3::cross(v86, shad->direction);
|
|
v86 = vec3::normalize(v86);
|
|
v3 = vec3::normalize(v3);
|
|
}
|
|
else {
|
|
v3 = { 0.0f, 0.0f, 1.0f };
|
|
v86 = { 1.0f, 0.0f, 0.0f };
|
|
}
|
|
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
shad->position[i] = 0.0f;
|
|
shad->field_1C8[i] = 0.0f;
|
|
|
|
if (!shad->shadow_enable[i] || !shad->positions[i].size())
|
|
continue;
|
|
|
|
vec3 v22 = 0.0f;
|
|
for (vec3& j : shad->positions[i])
|
|
v22 += j;
|
|
|
|
float_t v29 = (float_t)(int64_t)shad->positions[i].size();
|
|
if (v29 < 0.0f)
|
|
v29 += (float_t)UINT64_MAX;
|
|
v22 *= 1.0f / v29;
|
|
|
|
float_t v30 = 0.0f;
|
|
for (vec3& j : shad->positions[i]) {
|
|
const vec3 v35 = v22 - j;
|
|
const float_t v39 = fabsf(vec3::dot(v35, v86));
|
|
const float_t v38 = fabsf(vec3::dot(v35, v3));
|
|
v30 = max_def(v30, max_def(v38, v39));
|
|
}
|
|
shad->position[i] = v22;
|
|
shad->field_1C8[i] = v30;
|
|
}
|
|
|
|
if (shad->num_shadow > 0) {
|
|
vec3 view_point = 0.0f;
|
|
vec3 interest = 0.0f;
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
if (!shad->shadow_enable[i])
|
|
continue;
|
|
|
|
const vec3 v41 = shad->position[0] - shad->direction * shad->z_half_range;
|
|
const float_t v42 = vec3::distance(shad->view_point[0], v41);
|
|
const float_t v45 = vec3::distance(shad->interest[0], shad->position[0]);
|
|
if (v42 > 0.1f || v45 > 0.1f) {
|
|
shad->view_point[0] = v41;
|
|
shad->interest[0] = shad->position[0];
|
|
}
|
|
|
|
view_point += shad->view_point[i];
|
|
interest += shad->interest[i];
|
|
}
|
|
|
|
shad->view_point_shared = view_point * (1.0f / (float_t)shad->num_shadow);
|
|
shad->interest_shared = interest * (1.0f / (float_t)shad->num_shadow);
|
|
}
|
|
|
|
const float_t v67 = max_def(shad->field_1C8[0], shad->field_1C8[1]);
|
|
shad->separate = 0;
|
|
shad->shadow_range = v67 + MIN_SHADOW_RANGE;
|
|
shad->index[0] = 0;
|
|
shad->index[1] = 1;
|
|
|
|
if (shad->num_shadow >= 2) {
|
|
float_t v2 = 0.0f;
|
|
float_t v68 = 0.0f;
|
|
float_t v69 = 0.0f;
|
|
float_t v70 = 0.0f;
|
|
for (int32_t i = 0; i < 2; i++) {
|
|
if (!shad->shadow_enable[i])
|
|
continue;
|
|
|
|
for (vec3& j : shad->positions[i]) {
|
|
const vec3 v74 = j - shad->interest_shared;
|
|
|
|
const float_t v77 = vec3::dot(v86, v74);
|
|
if (v2 > v77)
|
|
v2 = v77;
|
|
else if (v69 < v77)
|
|
v69 = v77;
|
|
|
|
const float_t v78 = vec3::dot(v3, v74);
|
|
if (v68 > v78)
|
|
v68 = v78;
|
|
else if (v70 < v78)
|
|
v70 = v78;
|
|
}
|
|
}
|
|
|
|
const float_t v79 = max_def(max_def(max_def(-v2, v69), -v68), v70);
|
|
|
|
if (v79 + MIN_SHADOW_RANGE > v67 + SHADOW_RANGE_SEPARATE) {
|
|
shad->shadow_range = v67 + SHADOW_RANGE_SEPARATE;
|
|
shad->separate = true;
|
|
}
|
|
else
|
|
shad->shadow_range = v79 + MIN_SHADOW_RANGE;
|
|
|
|
if (vec3::dot(shad->position[0] - shad->interest_shared, shad->direction)
|
|
< vec3::dot(shad->position[1] - shad->interest_shared, shad->direction)) {
|
|
shad->index[1] = 0;
|
|
shad->index[0] = 1;
|
|
}
|
|
}
|
|
|
|
for (prj::vector<vec3>& i : shad->positions)
|
|
i.clear();
|
|
}
|