diff --git a/include/reign.h b/include/reign.h index c5acbe8..f1226e7 100644 --- a/include/reign.h +++ b/include/reign.h @@ -271,6 +271,8 @@ bool RE_instance_calc_path_finder_intersect_eye_vec(struct RE_instance *instance bool RE_plugin_transform_pos_to_view_pos(struct RE_plugin *plugin, float x, float y, float z, int *view_x, int *view_y); bool RE_plugin_get_camera_z_vector(struct RE_plugin *plugin, vec3 out); void RE_plugin_reset_light_param(struct RE_plugin *plugin); +bool RE_plugin_set_fog_type(struct RE_plugin *plugin, int type); +int RE_plugin_get_fog_type(struct RE_plugin *plugin); int RE_motion_get_state(struct motion *motion); bool RE_motion_set_state(struct motion *motion, int state); diff --git a/shaders/reign.f.glsl b/shaders/reign.f.glsl index 1889c5f..0bcb1af 100644 --- a/shaders/reign.f.glsl +++ b/shaders/reign.f.glsl @@ -24,13 +24,15 @@ #define ALPHA_MAP_BLEND 2 #define ALPHA_MAP_TEST 3 +#define FOG_LINEAR 1 +#define FOG_LIGHT_SCATTERING 2 + #define ENABLE_SPECULAR (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE) +#define ENABLE_LIGHT_SCATTERING (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE) #if ENGINE == REIGN_ENGINE #define NR_DIR_LIGHTS 3 -#define FOG_LINEAR 1 -#define FOG_LIGHT_SCATTERING 2 struct dir_light { vec3 dir; @@ -41,13 +43,10 @@ struct dir_light { uniform dir_light dir_lights[NR_DIR_LIGHTS]; uniform float rim_exponent; uniform vec3 rim_color; -uniform int fog_type; uniform float fog_near; uniform float fog_far; uniform vec3 fog_color; in vec3 light_dir[NR_DIR_LIGHTS]; -in vec3 ls_ex; -in vec3 ls_in; uniform vec3 global_ambient; @@ -72,6 +71,12 @@ vec3 dir_lights_diffuse(vec3 norm) #endif // ENGINE == REIGN_ENGINE +#if ENABLE_LIGHT_SCATTERING +uniform int fog_type; +in vec3 ls_ex; +in vec3 ls_in; +#endif + #if ENABLE_SPECULAR uniform sampler2D specular_texture; uniform vec3 specular_color; @@ -165,7 +170,11 @@ void main() { if (fog_type == FOG_LINEAR) { float fog_factor = clamp((dist - fog_near) / (fog_far - fog_near), 0.0, 1.0); frag_rgb = mix(frag_rgb, fog_color, fog_factor); - } else if (fog_type == FOG_LIGHT_SCATTERING) { + } +#endif + +#if ENABLE_LIGHT_SCATTERING + if (fog_type == FOG_LIGHT_SCATTERING) { frag_rgb = frag_rgb * ls_ex + ls_in; } #endif diff --git a/shaders/reign.v.glsl b/shaders/reign.v.glsl index 0d4ccfa..60fd555 100644 --- a/shaders/reign.v.glsl +++ b/shaders/reign.v.glsl @@ -16,12 +16,14 @@ const float PI = 3.14159265358979323846; +#define FOG_LIGHT_SCATTERING 2 + #define ENABLE_SPECULAR (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE) +#define ENABLE_LIGHT_SCATTERING (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE) #if ENGINE == REIGN_ENGINE #define NR_DIR_LIGHTS 3 -#define FOG_LIGHT_SCATTERING 2 struct dir_light { vec3 dir; @@ -30,14 +32,7 @@ struct dir_light { }; uniform dir_light dir_lights[NR_DIR_LIGHTS]; -uniform int fog_type; -uniform vec4 ls_params; // (beta_r, beta_m, g, distance) -uniform vec3 ls_light_dir; -uniform vec3 ls_light_color; -uniform vec3 ls_sun_color; out vec3 light_dir[NR_DIR_LIGHTS]; -out vec3 ls_ex; -out vec3 ls_in; const vec2 uv_scroll = vec2(0.0); @@ -47,6 +42,16 @@ uniform vec2 uv_scroll; #endif // ENGINE == REIGN_ENGINE +#if ENABLE_LIGHT_SCATTERING +uniform int fog_type; +uniform vec4 ls_params; // (beta_r, beta_m, g, distance) +uniform vec3 ls_light_dir; +uniform vec3 ls_light_color; +uniform vec3 ls_sun_color; +out vec3 ls_ex; +out vec3 ls_in; +#endif + #if ENABLE_SPECULAR uniform vec3 specular_light_dir; out vec3 specular_dir; @@ -143,7 +148,8 @@ void main() { light_dir[0] = TBN * dir_lights[0].dir; light_dir[1] = TBN * dir_lights[1].dir; light_dir[2] = TBN * dir_lights[2].dir; - +#endif +#if ENABLE_LIGHT_SCATTERING if (fog_type == FOG_LIGHT_SCATTERING) { float beta_r = ls_params.x; float beta_m = ls_params.y; diff --git a/src/3d/reign.c b/src/3d/reign.c index 1e47f90..0a3f6bf 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -808,6 +808,45 @@ void RE_plugin_reset_light_param(struct RE_plugin *plugin) lit_reset(plugin->light_params); } +bool RE_plugin_set_fog_type(struct RE_plugin *plugin, int type) +{ + if (re_plugin_version == RE_REIGN_PLUGIN) { + switch (type) { + case 0: plugin->fog_type = RE_FOG_NONE; return true; + case 1: plugin->fog_type = RE_FOG_LINEAR; return true; + case 2: plugin->fog_type = RE_FOG_LIGHT_SCATTERING; return true; + default: break; + } + } else { + switch (type) { + case 0: plugin->fog_type = RE_FOG_NONE; return true; + case 1: plugin->fog_type = RE_FOG_LIGHT_SCATTERING; return true; + default: break; + } + } + WARNING("unknown fog type %d", type); + return false; +} + +int RE_plugin_get_fog_type(struct RE_plugin *plugin) +{ + if (re_plugin_version == RE_REIGN_PLUGIN) { + switch (plugin->fog_type) { + case RE_FOG_NONE: return 0; + case RE_FOG_LINEAR: return 1; + case RE_FOG_LIGHT_SCATTERING: return 2; + default: break; + } + } else { + switch (plugin->fog_type) { + case RE_FOG_NONE: return 0; + case RE_FOG_LIGHT_SCATTERING: return 1; + default: break; + } + } + ERROR("[BUG] unexpected fog type %d", plugin->fog_type); +} + void RE_instance_update_local_transform(struct RE_instance *inst) { vec3 euler = { diff --git a/src/3d/renderer.c b/src/3d/renderer.c index 8a43631..a213bf6 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -424,8 +424,11 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); } - glUniform1i(r->fog_type, (inst->plugin->fog_mode && !(mesh->flags & MESH_NOLIGHTING)) - ? inst->plugin->fog_type : 0); + int fog_type = inst->plugin->fog_type; + if (!inst->plugin->fog_mode || (re_plugin_version == RE_REIGN_PLUGIN && (mesh->flags & MESH_NOLIGHTING))) { + fog_type = RE_FOG_NONE; + } + glUniform1i(r->fog_type, fog_type); GLboolean use_specular_map = GL_FALSE; if (inst->plugin->specular_mode && !(mesh->flags & MESH_NOLIGHTING)) { @@ -1111,6 +1114,25 @@ static void render_back_cg(struct texture *dst, struct RE_back_cg *bcg, struct R gfx_copy_stretch_blend_amap_alpha(dst, bcg->x, bcg->y, sw * bcg->mag, sh * bcg->mag, &bcg->texture, 0, 0, sw, sh, bcg->blend_rate * 255); } +static void setup_light_scattering(struct RE_plugin *plugin) +{ + struct RE_renderer *r = plugin->renderer; + if (re_plugin_version >= RE_SEAL_PLUGIN) { + const float *lp = plugin->light_params; + glUniform4f(r->ls_params, lp[SEAL_LP_LS_BETA_R], lp[SEAL_LP_LS_BETA_M], + lp[SEAL_LP_LS_G], lp[SEAL_LP_LS_DISTANCE]); + glUniform3f(r->ls_light_dir, lp[SEAL_LP_LS_LIGHT_VEC], + lp[SEAL_LP_LS_LIGHT_VEC + 1], -lp[SEAL_LP_LS_LIGHT_VEC + 2]); + glUniform3fv(r->ls_light_color, 1, &lp[SEAL_LP_LS_LIGHT_COLOR]); + glUniform3fv(r->ls_sun_color, 1, &lp[SEAL_LP_LS_SUN_COLOR]); + } else { + glUniform4f(r->ls_params, plugin->ls_beta_r, plugin->ls_beta_m, plugin->ls_g, plugin->ls_distance); + glUniform3fv(r->ls_light_dir, 1, plugin->ls_light_dir); + glUniform3fv(r->ls_light_color, 1, plugin->ls_light_color); + glUniform3fv(r->ls_sun_color, 1, plugin->ls_sun_color); + } +} + static void setup_lights(struct RE_plugin *plugin) { struct RE_renderer *r = plugin->renderer; @@ -1253,10 +1275,7 @@ void RE_render(struct sact_sprite *sp) glUniform3fv(r->fog_color, 1, plugin->fog_color); break; case RE_FOG_LIGHT_SCATTERING: - glUniform4f(r->ls_params, plugin->ls_beta_r, plugin->ls_beta_m, plugin->ls_g, plugin->ls_distance); - glUniform3fv(r->ls_light_dir, 1, plugin->ls_light_dir); - glUniform3fv(r->ls_light_color, 1, plugin->ls_light_color); - glUniform3fv(r->ls_sun_color, 1, plugin->ls_sun_color); + setup_light_scattering(plugin); break; } } diff --git a/src/hll/ReignEngine.c b/src/hll/ReignEngine.c index 808aaf4..f63f7cf 100644 --- a/src/hll/ReignEngine.c +++ b/src/hll/ReignEngine.c @@ -1179,14 +1179,7 @@ static bool ReignEngine_SetShadowMapResolutionLevel(int plugin, int level) static bool ReignEngine_SetFogType(int plugin, int type) { struct RE_plugin *p = get_plugin(plugin); - if (!p) - return false; - if (type != RE_FOG_LINEAR && type != RE_FOG_LIGHT_SCATTERING) { - WARNING("unknown fog type %d", type); - return false; - } - p->fog_type = type; - return true; + return p ? RE_plugin_set_fog_type(p, type) : false; } static bool ReignEngine_SetFogNear(int plugin, float near) @@ -1221,7 +1214,7 @@ static bool ReignEngine_SetFogColor(int plugin, float r, float g, float b) static int ReignEngine_GetFogType(int plugin) { struct RE_plugin *p = get_plugin(plugin); - return p ? p->fog_type : 0; + return p ? RE_plugin_get_fog_type(p) : 0; } static float ReignEngine_GetFogNear(int plugin)