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