# Copyright (C) 2022 RozK # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from math import radians, cos from engine import vec3, mat4_mul_vec3, set_input_vec3 from game.math import vec3_up, vec3_add, vec3_sub, vec3_scale, vec3_mul, vec3_dot def _angles(start, end): cmin = round(cos(radians(start)), 6) cmax = round(cos(radians(end)), 6) return (cmin, cmax, 1.0 / (cmax - cmin)) def _floats(a, b): return (a, b - a) def _colors(a, b): return (a, vec3_sub(b, a)) _light_power = ( (_angles(180.0, 0.0), _floats(1.0, 1.0)), ) _light_color = ( (_angles(180.0, 0.0), _colors((1.0, 1.0, 1.0), (1.0, 1.0, 1.0))), ) _horizon_color = ( (_angles(180.0, 0.0), _colors((0.75, 0.75, 1.0), (0.75, 0.75, 1.0))), ) _sky_color = ( (_angles(180.0, 0.0), _colors((0.0, 0.0, 0.5), (0.0, 0.0, 0.5))), ) _sun_color = ( (_angles(180.0, 0.0), _colors((8.0, 8.0, 4.0), (8.0, 8.0, 4.0))), ) def _resolve(ranges, c): for (cmin, cmax, crng), ab in ranges: if c >= cmin and c <= cmax: return ((c - cmin) * crng, ab) return None def _resolve_float(ranges, c): w, (a, b) = _resolve(ranges, c) return a + (b * w) def _resolve_color(ranges, c): w, (a, b) = _resolve(ranges, c) return vec3_add(a, vec3_scale(b, w)) class Environment: __slots__ = 'light_direction', 'light_color', 'horizon_color', 'sky_color', 'sun_color' def __init__(self): self.light_direction = vec3() self.light_color = vec3() self.horizon_color = vec3() self.sky_color = vec3() self.sun_color = vec3() def from_sun(self, view, sun_direction, sun_power): c = vec3_dot(sun_direction, vec3_up) light_power = _resolve_float(_light_power, c) * sun_power mat4_mul_vec3(self.light_direction, view, vec3(*sun_direction), 0.0) self.light_color.set(*vec3_scale(_resolve_color(_light_color, c), light_power)) self.horizon_color.set(*vec3_scale(_resolve_color(_horizon_color, c), light_power)) self.sky_color.set(*vec3_scale(_resolve_color(_sky_color, c), light_power)) self.sun_color.set(*_resolve_color(_sun_color, c)) def set_inputs(self, shader): set_input_vec3(shader.u_light_direction, self.light_direction) set_input_vec3(shader.u_light_color, self.light_color) set_input_vec3(shader.u_horizon_color, self.horizon_color) set_input_vec3(shader.u_sky_color, self.sky_color) set_input_vec3(shader.u_sun_color, self.sun_color)