rk_island/game/game.py

283 lines
11 KiB
Python

# 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 <http://www.gnu.org/licenses/>.
import time
from math import pi, tau, dist
from engine import *
from game import math
from game import generator
from game import shader
from game import resources
from game import batch
from game import triangles
from game import sea
from game.camera import Camera
from game.environment import Environment
proj_hfov = pi * 0.25
proj_ratio = 16.0 / 9.0
proj_near_z = 8.0
proj_far_z = 3000.0
camera_origin = (0.0, -1200.0, 500.0)
camera_lookat = (0.0, 500.0, -500.0)
sun_direction = math.vec3_normalize((1.0, 0.0, 1.0))
sun_power = 1.0
def main():
print("Generating terrain...")
gen_begin = time.process_time()
generated = generator.Generator(256)
gen_end = time.process_time()
print("Done: ", round(gen_end - gen_begin, 2), "seconds")
print("Initializing...")
window = initialize(b'RK Island', 1600, 900)
terrain_shader = shader.load('terrain', 'common')
tests_shader = shader.load('tests', 'common')
sky_shader = shader.load('sky')
heightmap = create_texture(
TEXTURE_FORMAT_32F, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_heights)
terrain_heightmap_sampler = resolve_input(terrain_shader, b'u_height_sampler')
tests_heightmap_sampler = resolve_input(tests_shader, b'u_height_sampler')
normalmap = create_texture(
TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_normals)
terrain_normalmap_sampler = resolve_input(terrain_shader, b'u_normal_sampler')
tests_normalmap_sampler = resolve_input(tests_shader, b'u_normal_sampler')
print("Loading resources...")
archive = resources.RuntimeArchive.load('data/rk_island.rkar')
print("Building tiles...")
tiles_texture = archive.get_texture('tiles')
tiles_sampler = resolve_input(terrain_shader, b'u_texture_sampler')
tiles_vertices = archive.get_vertices('tiles')
water = archive.get_model('water')
sand = archive.get_model('sand')
grass = archive.get_model('grass')
forest = archive.get_model('forest')
rock = archive.get_model('rock')
mud = archive.get_model('mud')
lava = archive.get_model('lava')
terrain_batch = batch.Batch(tiles_vertices, generated.size ** 2, params_format(PARAM_FORMAT_VEC3_SHORT))
#TODO: generator & for real
vc = generated.volcano_c
vr = generated.volcano_r
for my, mx in generated.map_coords:
vd = dist((mx + 0.5, my + 0.5), vc)
nx, ny, nz, h = generated.unpack(my, mx)
r = generated.rivers[my * generated.size + mx]
if h == 0.0:
continue
if r > 0.0:
model = water
elif h < 2.0:
model = sand
elif h < 180:
if nz > 0.9:
if ny < -0.01 and nz > 0.93:
model = forest
else:
model = grass
else:
model = rock
elif vd < vr - 3.0 and nz > 0.999:
model = lava
elif vd < vr + 2.0:
model = mud
elif vd < vr + 6.0 and nz < 0.67:
model = mud
else:
model = rock
model.spawn(terrain_batch, (float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0))
tests_texture = archive.get_texture('tests')
tests_sampler = resolve_input(tests_shader, b'u_texture_sampler')
tests_vertices = archive.get_vertices('tests')
blob = archive.get_model('blob')
cube = archive.get_model('cube')
clouds = archive.get_model('clouds')
tests_batch = batch.Batch(tests_vertices, 3,
params_format(PARAM_FORMAT_VEC3_FLOAT, PARAM_FORMAT_VEC3_INT10 | PARAM_FORMAT_NORMALIZE))
blob_translation = vec3((-100.0, -500.0, 0.0))
cube_translation = vec3((100.0, -500.0, 0.0))
cube_orientation = vec3(vec3_forward)
clouds_orientation = vec3(vec3_forward)
blob_id = blob.spawn(tests_batch, blob_translation, vec3_forward)
cube_id = cube.spawn(tests_batch, cube_translation, cube_orientation)
clouds_id = clouds.spawn(tests_batch, (0.0, 0.0, 32.0), clouds_orientation)
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_sampler = resolve_input(sky_shader, b'u_sea_polar_sampler')
sea_detail_texture = sea.load_detail_texture('data/sea_bump.png')
sea_detail_sampler = resolve_input(sky_shader, b'u_sea_detail_sampler')
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)
up = vec3(vec3_up)
_rotation = mat3()
_origin = vec3()
_lookat = vec3()
_blob_translation = vec3()
_cube_translation = vec3()
_cube_orientation = vec3()
_clouds_orientation = vec3()
print("Running...")
start_time = time.monotonic()
current_time = 0.0
frame_min = 10000.0
frame_max = 0.0
frame_avg = 0.0
draw_min = 10000.0
draw_max = 0.0
draw_avg = 0.0
perf_count = 0
try:
for frame in range(10000):
current_time = time.monotonic() - start_time
begin_frame()
frame_begin = time.thread_time()
mat3_rotation(_rotation, up, (current_time * 0.21) % tau)
mat3_mul_vec3(_blob_translation, _rotation, blob_translation)
tests_batch.set_param(0, blob_id, _blob_translation)
tests_batch.set_param(1, blob_id, vec3(math.vec3_normalize((sun_direction[0], sun_direction[1], 0.0))))
mat3_mul_vec3(_cube_translation, _rotation, cube_translation)
tests_batch.set_param(0, cube_id, _cube_translation)
mat3_rotation(_rotation, up, (current_time * 0.43) % tau)
mat3_mul_vec3(_cube_orientation, _rotation, cube_orientation)
tests_batch.set_param(1, cube_id, _cube_orientation)
mat3_rotation(_rotation, up, (current_time * -0.037) % tau)
mat3_mul_vec3(_clouds_orientation, _rotation, clouds_orientation)
tests_batch.set_param(1, clouds_id, _clouds_orientation)
mat3_rotation(_rotation, up, (current_time * 0.05) % tau)
mat3_mul_vec3(_origin, _rotation, vec3(camera_origin))
mat3_mul_vec3(_lookat, _rotation, vec3(camera_lookat))
camera.set_view(_origin, _lookat)
environment.from_sun(camera.view, vec3(sun_direction), sun_power)
select_shader(terrain_shader)
camera.update_inputs(terrain_camera_inputs)
environment.update_inputs(terrain_environment_inputs)
select_texture(0, tiles_texture, tiles_sampler)
select_texture(1, heightmap, terrain_heightmap_sampler)
select_texture(2, normalmap, terrain_normalmap_sampler)
select_vertices(tiles_vertices)
draw_begin = time.thread_time()
terrain_batch.draw()
draw_end = time.thread_time()
unselect_vertices(tiles_vertices)
unselect_texture(0, tiles_texture)
unselect_texture(1, heightmap)
unselect_texture(2, normalmap)
unselect_shader(terrain_shader)
select_shader(tests_shader)
camera.update_inputs(tests_camera_inputs)
environment.update_inputs(tests_environment_inputs)
select_texture(0, tests_texture, tests_sampler)
select_texture(1, heightmap, tests_heightmap_sampler)
select_texture(2, normalmap, tests_normalmap_sampler)
select_vertices(tests_vertices)
tests_batch.draw()
unselect_vertices(tests_vertices)
unselect_texture(0, tests_texture)
unselect_texture(1, heightmap)
unselect_texture(2, normalmap)
unselect_shader(tests_shader)
camera.set_view(vec3(math.vec3_scale(_origin, 0.001)), vec3(math.vec3_scale(_lookat, 0.001)))
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)
select_texture(0, sea_polar_textures, sea_polar_sampler)
select_texture(1, sea_detail_texture, sea_detail_sampler)
draw_triangles(sky_triangles)
unselect_texture(0, sea_polar_textures)
unselect_texture(1, sea_detail_texture)
unselect_shader(sky_shader)
frame_end = time.thread_time()
end_frame()
if frame > 0:
draw_ms = draw_end - draw_begin
draw_min = min(draw_min, draw_ms)
draw_max = max(draw_max, draw_ms)
draw_avg += draw_ms
frame_ms = frame_end - frame_begin
frame_min = min(frame_min, frame_ms)
frame_max = max(frame_max, frame_ms)
frame_avg += frame_ms
perf_count += 1
except KeyboardInterrupt:
pass
print("\rDraw *", perf_count,
": min =", round(draw_min * 1000.0, 2),
", max =", round(draw_max * 1000.0, 2),
", avg =", round((draw_avg / perf_count) * 1000.0, 2), "ms")
print("\rFrame *", perf_count,
": min =", round(frame_min * 1000.0, 2),
", max =", round(frame_max * 1000.0, 2),
", avg =", round((frame_avg / perf_count) * 1000.0, 2), "ms")
# seed 666
# camera_origin = vec3((0.0, -1200.0, 500.0))
# camera_lookat = vec3((0.0, 500.0, -500.0))
# for x in range(10000)
# current_time = 0
# Draw * 9999 : min = 0.2 , max = 2.16 , avg = 0.26 ms
# Draw * 9999 : min = 0.2 , max = 2.77 , avg = 0.27 ms
# Draw * 9999 : min = 0.2 , max = 2.00 , avg = 0.27 ms
print("Quitting...")
del tests_batch
del terrain_batch
destroy_texture(sea_polar_textures)
destroy_texture(sea_detail_texture)
destroy_texture(heightmap)
destroy_triangles(sky_triangles)
archive.destroy()
destroy_shader(terrain_shader)
destroy_shader(tests_shader)
destroy_shader(sky_shader)
terminate()