Skip to content

Commit

Permalink
FF7: Implemented day-night time cycle
Browse files Browse the repository at this point in the history
  • Loading branch information
CosmosXIII authored and julianxhokaxhiu committed Dec 18, 2022
1 parent de0bcd2 commit 5bdcf82
Show file tree
Hide file tree
Showing 27 changed files with 580 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/misc/${RELEASE_NAME}.vibrate.ff8.battle.toml
${CMAKE_BINARY_DIR}/bin/vibrate/ff8/battle.toml
# time cycle .toml
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/misc/${RELEASE_NAME}.time.toml
${CMAKE_BINARY_DIR}/bin/time/config.toml
)

# CPU INFO
Expand Down
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Renderer: Fixed graphical glitch happening in battle when 3d models rendered in front of UI ( https://github.com/julianxhokaxhiu/FFNx/issues/131 )
- Voice: Add play voice for enemy actions during BATTLE mode ( https://github.com/julianxhokaxhiu/FFNx/pull/502 )
- Widescreen: Allow the buster sword image on new game screen to support 16:9 ratio ( https://github.com/julianxhokaxhiu/FFNx/pull/506 )
- Modding: Added day-night time cycle system that can be controled from field scripts ( https://github.com/julianxhokaxhiu/FFNx/pull/511 )

## FF8

Expand Down
14 changes: 14 additions & 0 deletions misc/FFNx.frag
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ uniform vec4 FSAlphaFlags;
uniform vec4 FSMiscFlags;
uniform vec4 FSHDRFlags;
uniform vec4 FSTexFlags;
uniform vec4 TimeColor;
uniform vec4 TimeData;

#define isTLVertex VSFlags.x > 0.0
#define isFBTexture VSFlags.z > 0.0
Expand All @@ -59,6 +61,9 @@ uniform vec4 FSTexFlags;
#define isHDR FSHDRFlags.x > 0.0
#define monitorNits FSHDRFlags.y

#define isTimeEnabled TimeData.x > 0.0
#define isTimeFilterEnabled TimeData.x > 0.0 && TimeData.y > 0.0

void main()
{
vec4 color = vec4(toLinear(v_color0.rgb), v_color0.a);
Expand Down Expand Up @@ -159,6 +164,15 @@ void main()
}
}

if(isTLVertex)
{
if(isTimeFilterEnabled) color.rgb *= TimeColor.rgb;
}
else
{
color.rgb *= TimeColor.rgb;
}

if (!(isHDR)) {
// SDR screens require the Gamma output to properly render light scenes
color.rgb = toGamma(color.rgb);
Expand Down
4 changes: 4 additions & 0 deletions misc/FFNx.lighting.frag
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ void main()
if(isTLVertex)
{
gl_FragColor = color;
if(isTimeFilterEnabled)
{
gl_FragColor.rgb *= TimeColor.rgb;
}
}
else
{
Expand Down
15 changes: 15 additions & 0 deletions misc/FFNx.lighting.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ SAMPLER2D(tex_9, 9);
uniform vec4 lightDirData;
uniform vec4 lightData;
uniform vec4 ambientLightData;
uniform vec4 TimeColor;
uniform vec4 TimeData;

#define isTimeEnabled TimeData.x > 0.0
#define isTimeFilterEnabled TimeData.x > 0.0 && TimeData.y > 0.0

#define INV_PI 0.31831

Expand Down Expand Up @@ -129,6 +134,11 @@ vec3 calcLuminance(vec3 albedo, vec3 viewSpacePosition, vec3 viewDir, vec3 norma
// Light
float lightIntensity = lightData.w;
vec3 lightColor = toLinear(lightData.rgb);
if(isTimeEnabled)
{
lightColor *= TimeColor.rgb;
}

vec3 lightDir = normalize(lightDirData.xyz);

vec3 F0 = mix(specular * vec3_splat(0.08), albedo, metallic);
Expand Down Expand Up @@ -169,6 +179,11 @@ vec3 CalcConstIndirectLuminance(vec3 albedo)
{
// Ambient
vec3 ambientLightColor = ambientLightData.rgb;
if(isTimeEnabled)
{
ambientLightColor *= TimeColor.rgb;
}

float ambientLightIntensity = ambientLightData.w;
vec3 ambient = ambientLightIntensity * ambientLightColor * INV_PI * albedo.rgb;

Expand Down
50 changes: 50 additions & 0 deletions misc/FFNx.time.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# FFNx Time Cycle config file

### HOW TO: ###################################################################
# Sections may be commented by default with an initial # character.
# Remove the initial # character to set the entire sections block and its flags
# -----------------------------------------------------------------------------
###############################################################################

### SUPPORTED FLAGS: ##########################################################
# sunrise_time : sunrise time in hours
# morning_time : morning time in hours
# midday_time : midday time in hours
# afternoon_time : afternoon time in hours
# night_time : night time in hours

# frames_per_minute : frames per minutes
# (e.g. 5 results in a 8 min cycle, 10 in a 16 min cycle, 15 in 24 min cycle)

# morning_color : RGB filter values for the morning color
# midday_color : RGB filter values for the midday color
# afternoon_color : RGB filter values for the afternoon color
# night_color : RGB filter values for the night color

# options_address : address for pointer to unused game data to store time related options
# (BIT 0: global time cycle flag, BIT 1: update timer flag, BIT 2: Outdoor field flag)

# minutes_address : address for pointer to unused game data to store the minutes
# hours_address : address for pointer to unused game data to store the hours
# days_address : address for pointer to unused game data to store the days
# months_address : address for pointer to unused game data to store the months
###############################################################################

#sunrise_time = 6.0
#morning_time = 7.0
#midday_time = 15.0
#afternoon_time = 19.0
#night_time = 20.0

#frames_per_minute = 5

#morning_color = [ 0.75, 0.5, 0.5 ]
#midday_color = [ 1.0, 1.0, 1.0 ]
#afternoon_color = [ 0.9, 0.4, 0.3 ]
#night_color = [ 0.075, 0.075, 0.25 ]

#options_address = "DC08E6"
#minutes_address = "DC08E8"
#hours_address = "DC08EB"
#days_address = "DC08EA"
#months_address = "DC08E9"
10 changes: 10 additions & 0 deletions misc/FFNx.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ prefer_lighting_cpu_calculations = true
#~~~~~~~~~~~~~~~~~~~~~~~~~~~
external_lighting_path = "lighting"

#[DAY-NIGHT TIME CYCLE]
# Enable day-night time cycle.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~
enable_time_cycle = false

#[EXTERNAL DAY NIGHT CYCLE PATH]
# Path for external day-night time files.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~
external_time_cycle_path = "time"

#[HDR]
# This flag will set the Maximum Luminance nits value of your monitor/TV in order to properly correct colors when rendering.
# By default is set to 0, which means use what has been autodetected via software.
Expand Down
8 changes: 8 additions & 0 deletions src/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ std::string external_ambient_path;
std::vector<std::string> external_ambient_ext;
std::string external_lighting_path;
std::string external_widescreen_path;
std::string external_time_cycle_path;
bool enable_voice_music_fade;
long external_voice_music_fade_volume;
bool enable_voice_auto_text;
Expand Down Expand Up @@ -87,6 +88,7 @@ long enable_antialiasing;
bool enable_anisotropic;
bool enable_lighting;
bool prefer_lighting_cpu_calculations;
bool enable_time_cycle;
bool ff7_external_opening_music;
bool more_debug;
bool ff8_ssigpu_debug;
Expand Down Expand Up @@ -190,6 +192,7 @@ void read_cfg()
external_ambient_ext = get_string_or_array_of_strings(config["external_ambient_ext"]);
external_lighting_path = config["external_lighting_path"].value_or("");
external_widescreen_path = config["external_widescreen_path"].value_or("");
external_time_cycle_path = config["external_time_cycle_path"].value_or("");
save_textures = config["save_textures"].value_or(false);
trace_all = config["trace_all"].value_or(false);
trace_renderer = config["trace_renderer"].value_or(false);
Expand Down Expand Up @@ -228,6 +231,7 @@ void read_cfg()
enable_anisotropic = config["enable_anisotropic"].value_or(true);
enable_lighting = config["enable_lighting"].value_or(false);
prefer_lighting_cpu_calculations = config["prefer_lighting_cpu_calculations"].value_or(true);
enable_time_cycle = config["enable_time_cycle"].value_or(false);
ff7_external_opening_music = config["ff7_external_opening_music"].value_or(false);
more_debug = config["more_debug"].value_or(false);
ff8_ssigpu_debug = config["ff8_ssigpu_debug"].value_or(false);
Expand Down Expand Up @@ -416,6 +420,10 @@ void read_cfg()
if (external_widescreen_path.empty())
external_widescreen_path = "widescreen";

// EXTERNAL TIME CYCLE
if (external_time_cycle_path.empty())
external_time_cycle_path = "time";

// MOD PATH
if (mod_path.empty())
mod_path = "mods/Textures";
Expand Down
2 changes: 2 additions & 0 deletions src/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ extern std::string external_ambient_path;
extern std::vector<std::string> external_ambient_ext;
extern std::string external_lighting_path;
extern std::string external_widescreen_path;
extern std::string external_time_cycle_path;
extern bool enable_voice_music_fade;
extern long external_voice_music_fade_volume;
extern bool enable_voice_auto_text;
Expand Down Expand Up @@ -100,6 +101,7 @@ extern long enable_antialiasing;
extern bool enable_anisotropic;
extern bool enable_lighting;
extern bool prefer_lighting_cpu_calculations;
extern bool enable_time_cycle;
extern bool ff7_external_opening_music;
extern bool more_debug;
extern bool ff8_ssigpu_debug;
Expand Down
4 changes: 4 additions & 0 deletions src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include "game_cfg.h"

#include "ff7/widescreen.h"
#include "ff7/time.h"

#include "ff8/vram.h"
#include "ff8/vibration.h"
Expand Down Expand Up @@ -1140,6 +1141,9 @@ void common_flip(struct game_obj *game_object)
// We need to process Gamepad input on each frame
gamehacks.processGamepadInput();

// Update day night time cycle
if (!ff8 && enable_time_cycle) ff7::time.update();

// FF8 does not clear the screen properly in the card game module
if (ff8)
{
Expand Down
5 changes: 4 additions & 1 deletion src/ff7.h
Original file line number Diff line number Diff line change
Expand Up @@ -2422,6 +2422,7 @@ struct ff7_externals
void (*add_page_tile)(float, float, float, float, float, uint32_t, uint32_t);
double (*field_layer_sub_623C0F)(rotation_matrix*, int, int, int);
void (*field_draw_gray_quads_644E90)();
void (*engine_draw_graphics_object)(ff7_graphics_object*, ff7_game_obj*);
field_trigger_header** field_triggers_header;
rotation_matrix* field_camera_rotation_matrix_CFF3D8;
uint32_t field_load_textures;
Expand Down Expand Up @@ -3004,7 +3005,9 @@ struct ff7_externals
world_event_data** world_event_current_entity_ptr_E3A7CC;
int* is_wait_frames_zero_E39BC0;
uint32_t world_sub_75A1C6;
uint32_t world_sub_75A5D5;
uint32_t world_load_graphics_objects_75A5D5;
uint32_t world_init_load_map_meshes_graphics_objects_75A283;
uint32_t world_wm0_overworld_draw_all_74C179;
uint32_t world_draw_fade_quad_75551A;
uint32_t world_sub_75079D;
uint32_t world_sub_751EFC;
Expand Down
12 changes: 12 additions & 0 deletions src/ff7/field/background.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "../../globals.h"
#include "../widescreen.h"

#include "../../renderer.h"

#include "background.h"
#include "defs.h"
#include "utils.h"
Expand Down Expand Up @@ -882,4 +884,14 @@ namespace ff7::field
compute_pointer_hand_position(field_3d_world_pos, player_model_id);
}
}

// This function should be called at each frame after drawing backgrounds and 3d models
void draw_gray_quads_sub_644E90()
{
ff7_externals.field_draw_gray_quads_644E90();

if (aspect_ratio == AR_WIDESCREEN) widescreen.zoomBackground();

newRenderer.setTimeFilterEnabled(false);
}
}
1 change: 1 addition & 0 deletions src/ff7/field/background.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace ff7::field
void ff7_field_set_world_coordinate_640EB7();
void ff7_field_submit_draw_arrow(field_arrow_graphics_data* arrow_data);
void ff7_field_submit_draw_cursor(field_arrow_graphics_data* arrow_data);
void draw_gray_quads_sub_644E90();
bool is_position_valid(vector2<float> position) {
return position.x != INVALID_VALUE && position.y != INVALID_VALUE;
}
Expand Down

0 comments on commit 5bdcf82

Please sign in to comment.