Split vertex shader for terrain and tests.

This commit is contained in:
Roz K 2022-12-18 04:53:28 +01:00
parent a331721dd8
commit 1abfdfadf8
Signed by: roz
GPG Key ID: 51FBF4E483E1C822
5 changed files with 115 additions and 44 deletions

View File

@ -30,18 +30,21 @@ def main():
print("Initializing...") print("Initializing...")
window = initialize(b'RK Island', 1600, 900) window = initialize(b'RK Island', 1600, 900)
terrain_shader = shader.load('terrain') terrain_shader = shader.load('terrain', 'common')
tests_shader = shader.load('tests', 'common')
sky_shader = shader.load('sky') sky_shader = shader.load('sky')
heightmap = create_texture( heightmap = create_texture(
1, TEXTURE_FORMAT_32F, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR, 1, TEXTURE_FORMAT_32F, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_heights) generated.packed_heights)
heightmap_sampler = resolve_input(terrain_shader, b'u_height_sampler') 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( normalmap = create_texture(
2, TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR, 2, TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_normals) generated.packed_normals)
normalmap_sampler = resolve_input(terrain_shader, b'u_normal_sampler') 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...") print("Loading resources...")
archive = resources.RuntimeArchive.load('data/rk_island.rkar') archive = resources.RuntimeArchive.load('data/rk_island.rkar')
@ -90,7 +93,7 @@ def main():
model.spawn(terrain_batch, (float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0)) model.spawn(terrain_batch, (float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0))
tests_texture = archive.get_texture('tests') tests_texture = archive.get_texture('tests')
tests_sampler = resolve_input(terrain_shader, b'u_texture_sampler') tests_sampler = resolve_input(tests_shader, b'u_texture_sampler')
tests_vertices = archive.get_vertices('tests') tests_vertices = archive.get_vertices('tests')
blob = archive.get_model('blob') blob = archive.get_model('blob')
cube = archive.get_model('cube') cube = archive.get_model('cube')
@ -111,11 +114,15 @@ def main():
proj_far_z = 3000.0 proj_far_z = 3000.0
terrain_environment_inputs = environment.resolve_inputs(terrain_shader) terrain_environment_inputs = environment.resolve_inputs(terrain_shader)
terrain_orientation = resolve_param(terrain_shader, b'i_orientation')
terrain_camera = camera.Camera() terrain_camera = camera.Camera()
terrain_camera.set_projection(proj_hfov, proj_ratio, proj_near_z, proj_far_z) terrain_camera.set_projection(proj_hfov, proj_ratio, proj_near_z, proj_far_z)
terrain_camera.resolve_inputs(terrain_shader) terrain_camera.resolve_inputs(terrain_shader)
tests_environment_inputs = environment.resolve_inputs(tests_shader)
tests_camera = camera.Camera()
tests_camera.set_projection(proj_hfov, proj_ratio, proj_near_z, proj_far_z)
tests_camera.resolve_inputs(tests_shader)
sky_environment_inputs = environment.resolve_inputs(sky_shader) sky_environment_inputs = environment.resolve_inputs(sky_shader)
sea_phase = resolve_input(sky_shader, b'u_sea_phase') 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'))
@ -162,6 +169,11 @@ def main():
mat3_mul_vec3(_origin, _rotation, origin) mat3_mul_vec3(_origin, _rotation, origin)
mat3_mul_vec3(_lookat, _rotation, lookat) mat3_mul_vec3(_lookat, _rotation, lookat)
terrain_camera.set_view(_origin, _lookat)
tests_camera.set_view(_origin, _lookat)
sky_camera.set_view(vec3(math.vec3_scale(_origin, 0.001)), vec3(math.vec3_scale(_lookat, 0.001)))
environment_values = environment.from_sun(terrain_camera.view, sun_direction, sun_power)
mat3_rotation(_rotation, up, (current_time * 0.21) % tau) mat3_rotation(_rotation, up, (current_time * 0.21) % tau)
mat3_mul_vec3(_blob_translation, _rotation, blob_translation) mat3_mul_vec3(_blob_translation, _rotation, blob_translation)
tests_batch.set_param(0, blob_id, _blob_translation) tests_batch.set_param(0, blob_id, _blob_translation)
@ -176,39 +188,37 @@ def main():
tests_batch.set_param(1, clouds_id, _clouds_orientation) tests_batch.set_param(1, clouds_id, _clouds_orientation)
select_shader(terrain_shader) select_shader(terrain_shader)
select_texture(heightmap, heightmap_sampler)
select_texture(normalmap, normalmap_sampler)
terrain_camera.set_view(_origin, _lookat)
terrain_camera.update_inputs() terrain_camera.update_inputs()
environment_values = environment.from_sun(terrain_camera.view, sun_direction, sun_power)
environment.update_inputs(terrain_environment_inputs, environment_values) environment.update_inputs(terrain_environment_inputs, environment_values)
select_texture(tiles_texture, tiles_sampler) select_texture(tiles_texture, tiles_sampler)
select_texture(heightmap, terrain_heightmap_sampler)
select_texture(normalmap, terrain_normalmap_sampler)
select_vertices(tiles_vertices) select_vertices(tiles_vertices)
set_param_vec3(terrain_orientation, vec3(vec3_forward))
draw_begin = time.thread_time() draw_begin = time.thread_time()
terrain_batch.draw() terrain_batch.draw()
draw_end = time.thread_time() draw_end = time.thread_time()
unselect_vertices(tiles_vertices) unselect_vertices(tiles_vertices)
unselect_texture(tiles_texture) unselect_texture(tiles_texture)
select_texture(tests_texture, tests_sampler)
select_vertices(tests_vertices)
tests_batch.draw()
unselect_vertices(tests_vertices)
unselect_texture(tests_texture)
unselect_texture(normalmap) unselect_texture(normalmap)
unselect_texture(heightmap) unselect_texture(heightmap)
unselect_shader(terrain_shader) unselect_shader(terrain_shader)
select_shader(tests_shader)
tests_camera.update_inputs()
environment.update_inputs(tests_environment_inputs, environment_values)
select_texture(tests_texture, tests_sampler)
select_texture(heightmap, tests_heightmap_sampler)
select_texture(normalmap, tests_normalmap_sampler)
select_vertices(tests_vertices)
tests_batch.draw()
unselect_vertices(tests_vertices)
unselect_texture(tests_texture)
unselect_texture(normalmap)
unselect_texture(heightmap)
unselect_shader(tests_shader)
select_shader(sky_shader) select_shader(sky_shader)
sky_camera.set_view(
vec3(math.vec3_scale(_origin, 0.001)),
vec3(math.vec3_scale(_lookat, 0.001)))
sky_camera.update_inputs() sky_camera.update_inputs()
environment_values = environment.from_sun(sky_camera.view, sun_direction, sun_power)
environment.update_inputs(sky_environment_inputs, environment_values) environment.update_inputs(sky_environment_inputs, environment_values)
set_input_float(sea_phase, (current_time * 0.023) % 1.0) set_input_float(sea_phase, (current_time * 0.023) % 1.0)
select_texture(sea_polar_textures, sea_polar_sampler) select_texture(sea_polar_textures, sea_polar_sampler)
@ -262,5 +272,6 @@ def main():
destroy_triangles(sky_triangles) destroy_triangles(sky_triangles)
archive.destroy() archive.destroy()
destroy_shader(terrain_shader) destroy_shader(terrain_shader)
destroy_shader(tests_shader)
destroy_shader(sky_shader) destroy_shader(sky_shader)
terminate() terminate()

View File

@ -19,7 +19,10 @@ from engine import load_shader
#TODO: preprocessing (at least includes) #TODO: preprocessing (at least includes)
def load(name): def load(vert_name, frag_name = ''):
path = Path('.') / 'game' / 'shaders'
if not frag_name:
frag_name = vert_name
def _cleanup(_line): def _cleanup(_line):
return _line.partition('//')[0].strip() return _line.partition('//')[0].strip()
def _filter(_line): def _filter(_line):
@ -31,13 +34,13 @@ def load(name):
print("Cannot find", _path) print("Cannot find", _path)
return None return None
return list(map(_convert, filter(_filter, map(_cleanup, open(_path, 'rt'))))) return list(map(_convert, filter(_filter, map(_cleanup, open(_path, 'rt')))))
print("Loading shader", name) print("Loading vertex shader", vert_name)
path = Path('.') / 'game' / 'shaders' vert_lines = load_source(path / (vert_name + '_opengles.vert'))
vert_lines = load_source(path / (name + '_opengles.vert'))
if not vert_lines: if not vert_lines:
print("Error: Vertex shader is empty.") print("Error: Vertex shader is empty.")
return None return None
frag_lines = load_source(path / (name + '_opengles.frag')) print("Loading fragment shader", frag_name)
frag_lines = load_source(path / (frag_name + '_opengles.frag'))
if not frag_lines: if not frag_lines:
print("Error: Fragment shader is empty.") print("Error: Fragment shader is empty.")
return None return None

View File

@ -16,8 +16,8 @@
#version 320 es #version 320 es
precision highp float; precision highp float;
in vec3 v_position; // view space in vec4 v_position; // view space
in vec3 v_normal; // view space in vec4 v_normal; // view space
in vec4 v_terrain_normal; // view space (x, y, z, weight) in vec4 v_terrain_normal; // view space (x, y, z, weight)
in vec4 v_texcoord; // texture space (s, t, pixel_level, material_level) in vec4 v_texcoord; // texture space (s, t, pixel_level, material_level)
@ -36,8 +36,8 @@ void main(void) {
#define m_metallic material.x #define m_metallic material.x
#define m_specular material.y #define m_specular material.y
#define m_roughness material.z #define m_roughness material.z
vec3 normal = normalize(v_normal); vec3 normal = normalize(v_normal.xyz);
vec3 eye_dir = -normalize(v_position); vec3 eye_dir = -normalize(v_position.xyz);
float d = dot(normal, u_light_direction); float d = dot(normal, u_light_direction);
float halfd = 0.5 + d * 0.5; float halfd = 0.5 + d * 0.5;
float td = dot(normalize(v_terrain_normal.xyz), u_light_direction); float td = dot(normalize(v_terrain_normal.xyz), u_light_direction);

View File

@ -21,7 +21,6 @@ layout(location = 1) in vec3 a_normal; // model space
layout(location = 2) in vec3 a_texcoord; // texture space layout(location = 2) in vec3 a_texcoord; // texture space
layout(location = 3) in vec3 i_translation; // per mesh, model space -> world space layout(location = 3) in vec3 i_translation; // per mesh, model space -> world space
layout(location = 4) in vec3 i_orientation; // per mesh, model space -> world space
uniform mat4 u_view; // world space -> view space uniform mat4 u_view; // world space -> view space
uniform mat4 u_projection; // view space -> screen space uniform mat4 u_projection; // view space -> screen space
@ -38,25 +37,21 @@ const float c_weight_scale = 1.0 / 64.f;
const vec3 c_world_forward = vec3(0.0, 1.0, 0.0); const vec3 c_world_forward = vec3(0.0, 1.0, 0.0);
const vec3 c_world_up = vec3(0.0, 0.0, 1.0); const vec3 c_world_up = vec3(0.0, 0.0, 1.0);
out vec3 v_position; // view space out vec4 v_position; // view space
out vec3 v_normal; // view space out vec4 v_normal; // view space
out vec4 v_terrain_normal; // view space (x, y, z, weigth) out vec4 v_terrain_normal; // view space (x, y, z, weigth)
out vec4 v_texcoord; // texture space (s, t, pixel_level, material_level) out vec4 v_texcoord; // texture space (s, t, pixel_level, material_level)
void main(void) { void main(void) {
vec3 orientation = normalize(i_orientation); vec4 world_position = vec4(i_translation + a_position, 1.0);
mat3 rotation = mat3(cross(orientation, c_world_up), orientation, c_world_up);
vec4 world_position = vec4(i_translation.xyz + rotation * a_position, 1.0);
float weight = max(0.0, 1.0 - world_position.z * c_weight_scale);
vec3 world_normal = rotation * normalize(a_normal);
vec2 terrain_coords = c_terrain_shift + world_position.xy * c_terrain_scale; vec2 terrain_coords = c_terrain_shift + world_position.xy * c_terrain_scale;
world_position.z += texture(u_height_sampler, terrain_coords).r; world_position.z += texture(u_height_sampler, terrain_coords).r;
vec4 view_position = u_view * world_position; vec4 view_position = u_view * world_position;
vec3 terrain_normal = normalize(c_normal_shift + texture(u_normal_sampler, terrain_coords).rgb * c_normal_scale); vec3 terrain_normal = normalize(c_normal_shift + texture(u_normal_sampler, terrain_coords).rgb * c_normal_scale);
world_normal = mat3(cross(c_world_forward, terrain_normal), c_world_forward, terrain_normal) * world_normal; vec3 world_normal = mat3(cross(c_world_forward, terrain_normal), c_world_forward, terrain_normal) * normalize(a_normal);
v_position = view_position.xyz; v_position = view_position;
v_normal = (u_view * vec4(world_normal, 0.0)).xyz; v_normal = u_view * vec4(world_normal, 0.0);
v_terrain_normal = vec4((u_view * vec4(terrain_normal, 0.0)).xyz, weight); v_terrain_normal = vec4((u_view * vec4(terrain_normal, 0.0)).xyz, 1.0);
v_texcoord = vec4(a_texcoord.st * c_st_scale, a_texcoord.p, a_texcoord.p + 1.0); v_texcoord = vec4(a_texcoord.st * c_st_scale, a_texcoord.p, a_texcoord.p + 1.0);
gl_Position = u_projection * view_position; gl_Position = u_projection * view_position;
} }

View File

@ -0,0 +1,62 @@
// 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/>.
#version 320 es
precision highp float;
layout(location = 0) in vec3 a_position; // model space
layout(location = 1) in vec3 a_normal; // model space
layout(location = 2) in vec3 a_texcoord; // texture space
layout(location = 3) in vec3 i_translation; // per mesh, model space -> world space
layout(location = 4) in vec3 i_orientation; // per mesh, model space -> world space
uniform mat4 u_view; // world space -> view space
uniform mat4 u_projection; // view space -> screen space
uniform highp sampler2D u_height_sampler;
uniform highp sampler2D u_normal_sampler;
const vec3 c_normal_scale = vec3(2.0, 2.0, 1.0);
const vec3 c_normal_shift = vec3(-1.0, -1.0, 0.0);
const vec2 c_st_scale = vec2(1.0 / 1023.0, 1.0 / 1023.0);
const vec2 c_terrain_scale = vec2(1.0 / 2048.0, -1.0 / 2048.0);
const vec2 c_terrain_shift = vec2(0.5, 0.5);
const float c_weight_scale = 1.0 / 64.f;
const vec3 c_world_forward = vec3(0.0, 1.0, 0.0);
const vec3 c_world_up = vec3(0.0, 0.0, 1.0);
out vec4 v_position; // view space
out vec4 v_normal; // view space
out vec4 v_terrain_normal; // view space (x, y, z, weigth)
out vec4 v_texcoord; // texture space (s, t, pixel_level, material_level)
void main(void) {
vec3 orientation = normalize(i_orientation);
mat3 rotation = mat3(cross(orientation, c_world_up), orientation, c_world_up);
vec4 world_position = vec4(i_translation + rotation * a_position, 1.0);
float weight = max(0.0, 1.0 - world_position.z * c_weight_scale);
vec3 world_normal = rotation * normalize(a_normal);
vec2 terrain_coords = c_terrain_shift + world_position.xy * c_terrain_scale;
world_position.z += texture(u_height_sampler, terrain_coords).r;
vec4 view_position = u_view * world_position;
vec3 terrain_normal = normalize(c_normal_shift + texture(u_normal_sampler, terrain_coords).rgb * c_normal_scale);
world_normal = mat3(cross(c_world_forward, terrain_normal), c_world_forward, terrain_normal) * world_normal;
v_position = view_position;
v_normal = u_view * vec4(world_normal, 0.0);
v_terrain_normal = vec4((u_view * vec4(terrain_normal, 0.0)).xyz, weight);
v_texcoord = vec4(a_texcoord.st * c_st_scale, a_texcoord.p, a_texcoord.p + 1.0);
gl_Position = u_projection * view_position;
}