rk_island/game/game.py

252 lines
9.4 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, resources, batch, triangles, generator, environment, sea
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')
terrain_shader = load_shader(b'game/shaders/terrain')
sky_shader = load_shader(b'game/shaders/sky')
print("Loading resources...")
select_shader(terrain_shader)
archive = resources.RuntimeArchive.load('data/rk_island.rkar')
tiles_texture = archive.get_texture('tiles')
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')
heightmap = create_texture(1, b'u_height_sampler',
TEXTURE_FORMAT_32F, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_heights)
normalmap = create_texture(2, b'u_normal_sampler',
TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_normals)
select_vertices(tiles_vertices)
terrain_batch = batch.Batch(
generated.size ** 2, BATCH_TRANSLATION_FORMAT_SHORT, BATCH_ORIENTATION_FORMAT_NONE)
unselect_vertices(tiles_vertices)
terrain_environment_inputs = environment.resolve_inputs()
tests_texture = archive.get_texture('tests')
tests_vertices = archive.get_vertices('tests')
blob = archive.get_model('blob')
cube = archive.get_model('cube')
clouds = archive.get_model('clouds')
select_vertices(tests_vertices)
tests_batch = batch.Batch(3, BATCH_TRANSLATION_FORMAT_FLOAT, BATCH_ORIENTATION_FORMAT_FLOAT)
unselect_vertices(tests_vertices)
unselect_shader(terrain_shader)
#TODO: generator & for real
print("Building tiles...")
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), None)
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)
cube_id = cube.spawn(tests_batch, cube_translation, cube_orientation)
clouds_id = clouds.spawn(tests_batch, (0.0, 0.0, 32.0), clouds_orientation)
proj_hfov = pi * 0.25
proj_ratio = 16.0 / 9.0
proj_near_z = 8.0
proj_far_z = 3000.0
select_shader(sky_shader)
sky_environment_inputs = environment.resolve_inputs()
sea_phase = resolve_input(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))
unselect_shader(sky_shader)
sun_direction = vec3(math.vec3_normalize((1.0, 0.0, 1.0)))
sun_power = 1.0
camera = vec3((0.0, -1200.0, 500.0))
lookat = vec3((0.0, 500.0, -500.0))
start_time = time.monotonic()
current_time = 0.0
up = vec3(vec3_up)
_rotation = mat3()
_camera = vec3()
_lookat = vec3()
_blob_translation = vec3()
_cube_translation = vec3()
_cube_orientation = vec3()
_clouds_orientation = vec3()
print("Running...")
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 x in range(10000):
current_time = time.monotonic() - start_time
begin_frame()
frame_begin = time.thread_time()
mat3_rotation(_rotation, up, (current_time * 0.05) % tau)
mat3_mul_vec3(_camera, _rotation, camera)
mat3_mul_vec3(_lookat, _rotation, lookat)
set_view(_camera, _lookat)
set_projection(proj_hfov, proj_ratio, proj_near_z, proj_far_z)
mat3_rotation(_rotation, up, (current_time * 0.21) % tau)
mat3_mul_vec3(_blob_translation, _rotation, blob_translation)
tests_batch.set_translation(blob_id, _blob_translation)
tests_batch.set_orientation(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_translation(cube_id, _cube_translation)
mat3_rotation(_rotation, up, (current_time * 0.43) % tau)
mat3_mul_vec3(_cube_orientation, _rotation, cube_orientation)
tests_batch.set_orientation(cube_id, _cube_orientation)
mat3_rotation(_rotation, up, (current_time * -0.037) % tau)
mat3_mul_vec3(_clouds_orientation, _rotation, clouds_orientation)
tests_batch.set_orientation(clouds_id, _clouds_orientation)
environment_values = environment.from_sun(sun_direction, sun_power)
select_shader(terrain_shader)
select_texture(heightmap)
select_texture(normalmap)
environment.set_inputs(terrain_environment_inputs, environment_values)
select_texture(tiles_texture)
select_vertices(tiles_vertices)
draw_begin = time.thread_time()
terrain_batch.draw()
draw_end = time.thread_time()
unselect_vertices(tiles_vertices)
unselect_texture(tiles_texture)
select_texture(tests_texture)
select_vertices(tests_vertices)
tests_batch.draw()
unselect_vertices(tests_vertices)
unselect_texture(tests_texture)
unselect_texture(normalmap)
unselect_texture(heightmap)
unselect_shader(terrain_shader)
select_shader(sky_shader)
environment.set_inputs(sky_environment_inputs, environment_values)
set_input_float(sea_phase, (current_time * 0.023) % 1.0)
select_texture(sea_polar_textures)
select_texture(sea_detail_texture)
draw_triangles(sky_triangles)
unselect_texture(sea_detail_texture)
unselect_texture(sea_polar_textures)
unselect_shader(sky_shader)
frame_end = time.thread_time()
end_frame()
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 = vec3((0.0, -1200.0, 500.0))
# lookat = vec3((0.0, 500.0, -500.0))
# for x in range(10000)
# current_time = 0
# Draw * 10000 : min = 0.11 , max = 1.52 , avg = 0.18 ms
# Draw * 10000 : min = 0.12 , max = 1.74 , avg = 0.18 ms
# Draw * 10000 : min = 0.12 , max = 1.92 , avg = 0.18 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(sky_shader)
terminate()