diff --git a/shaders/reign.f.glsl b/shaders/reign.f.glsl index 0bcb1af..a0cedcb 100644 --- a/shaders/reign.f.glsl +++ b/shaders/reign.f.glsl @@ -50,7 +50,7 @@ in vec3 light_dir[NR_DIR_LIGHTS]; uniform vec3 global_ambient; -vec3 dir_lights_diffuse(vec3 norm) +vec3 compute_diffuse(vec3 norm) { vec3 diffuse = vec3(0.0); for (int i = 0; i < NR_DIR_LIGHTS; i++) { @@ -60,11 +60,29 @@ vec3 dir_lights_diffuse(vec3 norm) return diffuse; } -#else // ENGINE == REIGN_ENGINE +#elif ENGINE == SEAL_ENGINE const vec3 global_ambient = vec3(0.0); -vec3 dir_lights_diffuse(vec3 norm) +// Hemisphere lighting (sky/middle/ground). +uniform vec3 hemi_light_dir; +uniform vec3 hemi_sky_color; +uniform vec3 hemi_mid_color; +uniform vec3 hemi_ground_color; + +vec3 compute_diffuse(vec3 norm) +{ + float t = 0.5 * dot(norm, hemi_light_dir) + 0.5; + vec3 low_mid = mix(hemi_ground_color, hemi_mid_color, t); + vec3 mid_high = mix(hemi_mid_color, hemi_sky_color, t); + return mix(low_mid, mid_high, t); +} + +#else // TAPIR_ENGINE + +const vec3 global_ambient = vec3(0.0); + +vec3 compute_diffuse(vec3 norm) { return vec3(1.0); } @@ -138,7 +156,7 @@ void main() { texel = mix(texel, texture(blend_tex, blend_tex_coord), blend_weight); } if (diffuse_type != DIFFUSE_EMISSIVE) { - diffuse = dir_lights_diffuse(norm); + diffuse = compute_diffuse(norm); if (diffuse_type == DIFFUSE_LIGHT_MAP) { diffuse *= texture(light_texture, light_tex_coord).rgb; } diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index f857520..70bb028 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -188,6 +188,10 @@ struct RE_renderer { GLint ls_light_dir; GLint ls_light_color; GLint ls_sun_color; + GLint hemi_light_dir; + GLint hemi_sky_color; + GLint hemi_mid_color; + GLint hemi_ground_color; GLint alpha_mode; GLint alpha_texture; GLint uv_scroll; diff --git a/src/3d/renderer.c b/src/3d/renderer.c index a213bf6..e8d2b1c 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -259,6 +259,10 @@ struct RE_renderer *RE_renderer_new(void) r->ls_light_dir = glGetUniformLocation(r->program, "ls_light_dir"); r->ls_light_color = glGetUniformLocation(r->program, "ls_light_color"); r->ls_sun_color = glGetUniformLocation(r->program, "ls_sun_color"); + r->hemi_light_dir = glGetUniformLocation(r->program, "hemi_light_dir"); + r->hemi_sky_color = glGetUniformLocation(r->program, "hemi_sky_color"); + r->hemi_mid_color = glGetUniformLocation(r->program, "hemi_mid_color"); + r->hemi_ground_color = glGetUniformLocation(r->program, "hemi_ground_color"); r->alpha_mode = glGetUniformLocation(r->program, "alpha_mode"); r->alpha_texture = glGetUniformLocation(r->program, "alpha_texture"); r->uv_scroll = glGetUniformLocation(r->program, "uv_scroll"); @@ -1133,6 +1137,26 @@ static void setup_light_scattering(struct RE_plugin *plugin) } } +static void setup_hemisphere_light(struct RE_plugin *plugin) +{ + struct RE_renderer *r = plugin->renderer; + const float *lp = plugin->light_params; + vec3 hemi_dir = { + -lp[SEAL_LP_HEMI_VEC], -lp[SEAL_LP_HEMI_VEC + 1], lp[SEAL_LP_HEMI_VEC + 2] + }; + glm_vec3_normalize(hemi_dir); + glUniform3fv(r->hemi_light_dir, 1, hemi_dir); + glUniform3fv(r->hemi_sky_color, 1, &lp[SEAL_LP_HEMI_SKY_COLOR]); + glUniform3fv(r->hemi_mid_color, 1, &lp[SEAL_LP_HEMI_MID_COLOR]); + glUniform3fv(r->hemi_ground_color, 1, &lp[SEAL_LP_HEMI_GROUND_COLOR]); + // SealEngine's specular uses the hemisphere light vector. hemi_dir points + // toward the light, but the shader's specular formula expects the light + // propagation direction. + vec3 spec_dir; + glm_vec3_negate_to(hemi_dir, spec_dir); + glUniform3fv(r->specular_light_dir, 1, spec_dir); +} + static void setup_lights(struct RE_plugin *plugin) { struct RE_renderer *r = plugin->renderer; @@ -1168,6 +1192,9 @@ static void setup_lights(struct RE_plugin *plugin) glUniform3fv(r->dir_lights[light_index].diffuse, 1, zero); glUniform3fv(r->dir_lights[light_index].globe_diffuse, 1, zero); } + + if (re_plugin_version >= RE_SEAL_PLUGIN) + setup_hemisphere_light(plugin); } static int cmp_instances_by_z(const void *lhs, const void *rhs)