Automatic shader inputs.
This commit is contained in:
		| @ -13,14 +13,7 @@ | ||||
| # You should have received a copy of the GNU Affero General Public License | ||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| from engine import vec3_origin, mat4, mat4_projection, mat4_orbit, resolve_input, set_input_mat4 | ||||
|  | ||||
| class _Inputs: | ||||
|     __slots__ = 'projection', 'view' | ||||
|  | ||||
|     def __init__(self, shader, projection, view): | ||||
|         self.projection = resolve_input(shader, projection) | ||||
|         self.view = resolve_input(shader, view) | ||||
| from engine import vec3_origin, mat4, mat4_projection, mat4_orbit, set_input_mat4 | ||||
|  | ||||
| class Camera: | ||||
|     __slots__ = 'yaw', 'pitch', 'distance', 'projection', 'view' | ||||
| @ -44,9 +37,6 @@ class Camera: | ||||
|     def to_km(self): | ||||
|         mat4_orbit(self.view, vec3_origin, self.yaw, self.pitch, self.distance * 0.001) | ||||
|  | ||||
|     def resolve_inputs(self, shader, projection = b'u_projection', view = b'u_view'): | ||||
|         return _Inputs(shader, projection, view) | ||||
|  | ||||
|     def update_inputs(self, inputs): | ||||
|         set_input_mat4(inputs.projection, self.projection) | ||||
|         set_input_mat4(inputs.view, self.view) | ||||
|     def set_inputs(self, shader): | ||||
|         set_input_mat4(shader.u_projection, self.projection) | ||||
|         set_input_mat4(shader.u_view, self.view) | ||||
|  | ||||
| @ -14,7 +14,7 @@ | ||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| from math import radians, cos | ||||
| from engine import vec3, mat4_mul_vec3, resolve_input, set_input_vec3 | ||||
| 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): | ||||
| @ -62,16 +62,6 @@ def _resolve_color(ranges, c): | ||||
|     w, (a, b) = _resolve(ranges, c) | ||||
|     return vec3_add(a, vec3_scale(b, w)) | ||||
|  | ||||
| class _Inputs: | ||||
|     __slots__ = 'light_direction', 'light_color', 'horizon_color', 'sky_color', 'sun_color' | ||||
|  | ||||
|     def __init__(self, shader): | ||||
|         self.light_direction = resolve_input(shader, b'u_light_direction') | ||||
|         self.light_color = resolve_input(shader, b'u_light_color') | ||||
|         self.horizon_color = resolve_input(shader, b'u_horizon_color') | ||||
|         self.sky_color = resolve_input(shader, b'u_sky_color') | ||||
|         self.sun_color = resolve_input(shader, b'u_sun_color') | ||||
|  | ||||
| class Environment: | ||||
|     __slots__ = 'light_direction', 'light_color', 'horizon_color', 'sky_color', 'sun_color' | ||||
|  | ||||
| @ -91,12 +81,9 @@ class Environment: | ||||
|         self.sky_color.set(*vec3_scale(_resolve_color(_sky_color, c), light_power)) | ||||
|         self.sun_color.set(*_resolve_color(_sun_color, c)) | ||||
|  | ||||
|     def resolve_inputs(self, shader): | ||||
|         return _Inputs(shader) | ||||
|  | ||||
|     def update_inputs(self, inputs): | ||||
|         set_input_vec3(inputs.light_direction, self.light_direction) | ||||
|         set_input_vec3(inputs.light_color, self.light_color) | ||||
|         set_input_vec3(inputs.horizon_color, self.horizon_color) | ||||
|         set_input_vec3(inputs.sky_color, self.sky_color) | ||||
|         set_input_vec3(inputs.sun_color, self.sun_color) | ||||
|     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) | ||||
|  | ||||
							
								
								
									
										48
									
								
								game/game.py
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								game/game.py
									
									
									
									
									
								
							| @ -20,9 +20,9 @@ from ctypes import Structure | ||||
| from engine import * | ||||
|  | ||||
| from game import math | ||||
| from game import shader | ||||
| from game import triangles | ||||
| from game import sea | ||||
| from game.shader import Shader | ||||
| from game.generator import Generator | ||||
| from game.resources import RuntimeArchive | ||||
| from game.batch import Batch | ||||
| @ -53,9 +53,9 @@ def main(): | ||||
|     mouse = Mouse(events, wheel = 60, wheel_min = 20) | ||||
|     keyboard = Keyboard(events) | ||||
|     render_initialize(__debug__) | ||||
|     terrain_shader = shader.load('terrain', 'common') | ||||
|     tests_shader = shader.load('tests', 'common') | ||||
|     sky_shader = shader.load('sky') | ||||
|     terrain_shader = Shader('terrain', 'common') | ||||
|     tests_shader = Shader('tests', 'common') | ||||
|     sky_shader = Shader('sky') | ||||
|  | ||||
|     heightmap = create_texture( | ||||
|         TEXTURE_FORMAT_FLOAT_32, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR, | ||||
| @ -127,21 +127,13 @@ def main(): | ||||
|     cube_id = cube_model.spawn(tests_batch, cube_spawn_translation, mat3_identity) | ||||
|     clouds_id = clouds_model.spawn(tests_batch, vec3(0.0, 0.0, 32.0), mat3_identity) | ||||
|  | ||||
|     sea_phase = resolve_input(sky_shader, b'u_sea_phase') | ||||
|     sea_polar_textures = sea.load_polar_textures(('data/sea_bump1.png', 'data/sea_bump2.png')) | ||||
|     sea_detail_texture = sea.load_detail_texture('data/sea_bump.png') | ||||
|     sky_triangles = create_triangles(triangles.sky_triangles(64, proj_far_z - 0.1, proj_ratio)) | ||||
|  | ||||
|     camera = Camera() | ||||
|     camera.set_projection(proj_hfov, proj_ratio, proj_near_z, proj_far_z) | ||||
|     terrain_camera_inputs = camera.resolve_inputs(terrain_shader) | ||||
|     tests_camera_inputs = camera.resolve_inputs(tests_shader) | ||||
|     sky_camera_inputs = camera.resolve_inputs(sky_shader) | ||||
|  | ||||
|     environment = Environment() | ||||
|     terrain_environment_inputs = environment.resolve_inputs(terrain_shader) | ||||
|     tests_environment_inputs = environment.resolve_inputs(tests_shader) | ||||
|     sky_environment_inputs = environment.resolve_inputs(sky_shader) | ||||
|  | ||||
|     blob_translation = tests_batch.translation[blob_id] | ||||
|     cube_translation = tests_batch.translation[cube_id] | ||||
| @ -176,9 +168,9 @@ def main(): | ||||
|             camera.set_view(camera_yaw, camera_pitch, camera_distance) | ||||
|             environment.from_sun(camera.view, sun_direction, sun_power) | ||||
|  | ||||
|             select_shader(terrain_shader) | ||||
|             camera.update_inputs(terrain_camera_inputs) | ||||
|             environment.update_inputs(terrain_environment_inputs) | ||||
|             terrain_shader.select() | ||||
|             camera.set_inputs(terrain_shader) | ||||
|             environment.set_inputs(terrain_shader) | ||||
|             select_texture(0, tiles_texture) | ||||
|             select_texture(1, heightmap) | ||||
|             select_texture(2, normalmap) | ||||
| @ -188,7 +180,7 @@ def main(): | ||||
|             unselect_texture(0, tiles_texture) | ||||
|             unselect_texture(1, heightmap) | ||||
|             unselect_texture(2, normalmap) | ||||
|             unselect_shader(terrain_shader) | ||||
|             terrain_shader.unselect() | ||||
|  | ||||
|             rotation = mat3() | ||||
|             mat3_rotation(rotation, vec3_up, (current_time * 0.21) % tau) | ||||
| @ -197,9 +189,9 @@ def main(): | ||||
|             mat3_rotation(cube_orientation, vec3_up, (current_time * 0.43) % tau) | ||||
|             mat3_rotation(clouds_orientation, vec3_up, (current_time * -0.037) % tau) | ||||
|  | ||||
|             select_shader(tests_shader) | ||||
|             camera.update_inputs(tests_camera_inputs) | ||||
|             environment.update_inputs(tests_environment_inputs) | ||||
|             tests_shader.select() | ||||
|             camera.set_inputs(tests_shader) | ||||
|             environment.set_inputs(tests_shader) | ||||
|             select_texture(0, tests_texture) | ||||
|             select_texture(1, heightmap) | ||||
|             select_texture(2, normalmap) | ||||
| @ -207,20 +199,20 @@ def main(): | ||||
|             unselect_texture(0, tests_texture) | ||||
|             unselect_texture(1, heightmap) | ||||
|             unselect_texture(2, normalmap) | ||||
|             unselect_shader(tests_shader) | ||||
|             tests_shader.unselect() | ||||
|  | ||||
|             camera.to_km() | ||||
|  | ||||
|             select_shader(sky_shader) | ||||
|             camera.update_inputs(sky_camera_inputs) | ||||
|             environment.update_inputs(sky_environment_inputs) | ||||
|             set_input_float(sea_phase, (current_time * 0.023) % 1.0) | ||||
|             sky_shader.select() | ||||
|             camera.set_inputs(sky_shader) | ||||
|             environment.set_inputs(sky_shader) | ||||
|             set_input_float(sky_shader.u_sea_phase, (current_time * 0.023) % 1.0) | ||||
|             select_texture(0, sea_polar_textures) | ||||
|             select_texture(1, sea_detail_texture) | ||||
|             draw_triangles(sky_triangles) | ||||
|             unselect_texture(0, sea_polar_textures) | ||||
|             unselect_texture(1, sea_detail_texture) | ||||
|             unselect_shader(sky_shader) | ||||
|             sky_shader.unselect() | ||||
|  | ||||
|             frame_end = time.thread_time() | ||||
|             end_frame() | ||||
| @ -272,9 +264,9 @@ def main(): | ||||
|     destroy_texture(normalmap) | ||||
|     destroy_triangles(sky_triangles) | ||||
|     archive.destroy() | ||||
|     destroy_shader(terrain_shader) | ||||
|     destroy_shader(tests_shader) | ||||
|     destroy_shader(sky_shader) | ||||
|     del terrain_shader | ||||
|     del tests_shader | ||||
|     del sky_shader | ||||
|     render_terminate() | ||||
|     del events | ||||
|     destroy_display(display) | ||||
|  | ||||
| @ -15,9 +15,7 @@ | ||||
|  | ||||
| from pathlib import Path | ||||
|  | ||||
| from engine import load_shader | ||||
|  | ||||
| #TODO: preprocessing (at least includes) | ||||
| from engine import load_shader, resolve_input, select_shader, unselect_shader, destroy_shader | ||||
|  | ||||
| def _cleanup(line): | ||||
|     return line.partition('//')[0].strip() | ||||
| @ -34,9 +32,9 @@ def _subst(line): | ||||
|         return lines | ||||
|     return [line] | ||||
|  | ||||
| def _load_source(_path): | ||||
|     assert _path.exists() | ||||
|     lines = filter(_filter, map(_cleanup, open(_path, 'rt'))) | ||||
| def _load_source(path): | ||||
|     assert path.exists() | ||||
|     lines = filter(_filter, map(_cleanup, open(path, 'rt'))) | ||||
|     source = [] | ||||
|     for line in lines: | ||||
|         source.extend(_subst(line)) | ||||
| @ -45,14 +43,41 @@ def _load_source(_path): | ||||
| def _convert(line): | ||||
|     return bytes(line, 'utf-8') + b'\n' | ||||
|  | ||||
| def load(vert_name, frag_name = ''): | ||||
| def _parse(shader, vert_lines, frag_lines): | ||||
|     uniforms = [] | ||||
|     for line in vert_lines: | ||||
|         if line.startswith('uniform '): | ||||
|             uniforms.append(line.split()[-1].strip(';')) | ||||
|     for line in frag_lines: | ||||
|         if line.startswith('uniform '): | ||||
|             name = line.split()[-1].strip(';') | ||||
|             if name not in uniforms: | ||||
|                 uniforms.append(name) | ||||
|     for name in uniforms: | ||||
|         setattr(shader, name, resolve_input(shader._shader, bytes(name, 'utf-8'))) | ||||
|  | ||||
| class Shader: | ||||
|     __slots__ = '_shader', '__dict__' | ||||
|  | ||||
|     def __init__(self, vert_name, frag_name = ''): | ||||
|         path = Path('.') / 'game' / 'shaders' | ||||
|         assert path.exists() | ||||
|         if not frag_name: | ||||
|             frag_name = vert_name | ||||
|         print("Loading vertex shader", vert_name) | ||||
|     vert_lines = list(map(_convert, _load_source(path / (vert_name + '_opengles.vert')))) | ||||
|         vert_lines = _load_source(path / (vert_name + '_opengles.vert')) | ||||
|         assert vert_lines | ||||
|         print("Loading fragment shader", frag_name) | ||||
|     frag_lines = list(map(_convert, _load_source(path / (frag_name + '_opengles.frag')))) | ||||
|         frag_lines = _load_source(path / (frag_name + '_opengles.frag')) | ||||
|         assert frag_lines | ||||
|     return load_shader(vert_lines, frag_lines) | ||||
|         self._shader = load_shader(list(map(_convert, vert_lines)), list(map(_convert, frag_lines))) | ||||
|         _parse(self, vert_lines, frag_lines) | ||||
|  | ||||
|     def __del__(self): | ||||
|         destroy_shader(self._shader) | ||||
|  | ||||
|     def select(self): | ||||
|         select_shader(self._shader) | ||||
|  | ||||
|     def unselect(self): | ||||
|         unselect_shader(self._shader) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user