Compare commits

...

3 Commits

14 changed files with 165 additions and 166 deletions

2
engine

@ -1 +1 @@
Subproject commit 2095e335ead1967fde413b0d61d35e2f3b90461a Subproject commit ae3333e22e36667a0c02817fafb16ab7b8d1341b

View File

@ -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)

View File

@ -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)

View File

@ -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,28 +53,22 @@ 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,
generated.packed_heights) 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( normalmap = create_texture(
TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR, TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_normals) 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...") print("Loading resources...")
archive = RuntimeArchive.load('data/rk_island.rkar') archive = RuntimeArchive.load('data/rk_island.rkar')
print("Building tiles...") print("Building tiles...")
tiles_texture = archive.get_texture('tiles') tiles_texture = archive.get_texture('tiles')
tiles_sampler = resolve_input(terrain_shader, b'u_texture_sampler')
tiles_vertices = archive.get_vertices('tiles') tiles_vertices = archive.get_vertices('tiles')
water_model = archive.get_model('water') water_model = archive.get_model('water')
sand_model = archive.get_model('sand') sand_model = archive.get_model('sand')
@ -117,7 +111,6 @@ def main():
model.spawn(terrain_batch, vec3(float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0)) model.spawn(terrain_batch, vec3(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(tests_shader, b'u_texture_sampler')
tests_vertices = archive.get_vertices('tests') tests_vertices = archive.get_vertices('tests')
blob_model = archive.get_model('blob') blob_model = archive.get_model('blob')
cube_model = archive.get_model('cube') cube_model = archive.get_model('cube')
@ -134,23 +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_polar_sampler = resolve_input(sky_shader, b'u_sea_polar_sampler')
sea_detail_texture = sea.load_detail_texture('data/sea_bump.png') 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)) 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]
@ -185,19 +168,19 @@ 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, tiles_sampler) select_texture(0, tiles_texture)
select_texture(1, heightmap, terrain_heightmap_sampler) select_texture(1, heightmap)
select_texture(2, normalmap, terrain_normalmap_sampler) select_texture(2, normalmap)
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_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)
@ -206,30 +189,30 @@ 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, tests_sampler) select_texture(0, tests_texture)
select_texture(1, heightmap, tests_heightmap_sampler) select_texture(1, heightmap)
select_texture(2, normalmap, tests_normalmap_sampler) select_texture(2, normalmap)
tests_batch.draw() tests_batch.draw()
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, sea_polar_sampler) select_texture(0, sea_polar_textures)
select_texture(1, sea_detail_texture, sea_detail_sampler) 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()
@ -281,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)

View File

@ -15,33 +15,69 @@
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):
return line.partition('//')[0].strip()
def load(vert_name, frag_name = ''): def _filter(line):
path = Path('.') / 'game' / 'shaders' return line
if not frag_name:
frag_name = vert_name def _subst(line):
def _cleanup(_line): if line.startswith('#include '):
return _line.partition('//')[0].strip() path = Path('.') / 'game' / 'shaders'
def _filter(_line): lines = []
return _line for name in line.split()[1:]:
def _convert(_line): lines.extend(_load_source(path / name.strip('"')))
return bytes(_line, 'utf-8') + b'\n' return lines
def load_source(_path): return [line]
if not _path.exists():
print("Cannot find", _path) def _load_source(path):
return None assert path.exists()
return list(map(_convert, filter(_filter, map(_cleanup, open(_path, 'rt'))))) lines = filter(_filter, map(_cleanup, open(path, 'rt')))
print("Loading vertex shader", vert_name) source = []
vert_lines = load_source(path / (vert_name + '_opengles.vert')) for line in lines:
if not vert_lines: source.extend(_subst(line))
print("Error: Vertex shader is empty.") return source
return None
print("Loading fragment shader", frag_name) def _convert(line):
frag_lines = load_source(path / (frag_name + '_opengles.frag')) return bytes(line, 'utf-8') + b'\n'
if not frag_lines:
print("Error: Fragment shader is empty.") def _parse(shader, vert_lines, frag_lines):
return None uniforms = []
return load_shader(vert_lines, frag_lines) 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 = _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)

View File

@ -16,6 +16,8 @@
#version 320 es #version 320 es
precision highp float; precision highp float;
#include "include/environment.glsl"
in vec4 v_position; // view space in vec4 v_position; // view space
in vec4 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)
@ -23,10 +25,7 @@ in vec4 v_texcoord; // texture space (s, t, pixel_level, material_level)
#define v_weight v_terrain_normal.w #define v_weight v_terrain_normal.w
uniform vec3 u_light_direction; // view space (-direction_x, -direction_y, -direction_z) layout(binding=0) uniform highp sampler2DArray u_texture_sampler;
uniform vec3 u_light_color; // (color.r * power, color.g * power, color.b * power)
uniform highp sampler2DArray u_texture_sampler;
layout(location = 0) out vec4 o_color; layout(location = 0) out vec4 o_color;

View File

@ -0,0 +1,7 @@
#ifndef CAMERA_INCLUDED
#define CAMERA_INCLUDED
uniform mat4 u_view; // world space -> view space
uniform mat4 u_projection; // view space -> screen space
#endif // CAMERA_INCLUDED

View File

@ -0,0 +1,20 @@
#ifndef COMMON_INCLUDED
#define COMMON_INCLUDED
layout(binding=1) uniform highp sampler2D u_height_sampler;
layout(binding=2) 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);
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)
#endif // COMMON_INCLUDED

View File

@ -0,0 +1,10 @@
#ifndef ENVIRONMENT_INCLUDED
#define ENVIRONMENT_INCLUDED
uniform vec3 u_light_direction; // view space
uniform vec3 u_light_color;
uniform vec3 u_horizon_color;
uniform vec3 u_sky_color;
uniform vec3 u_sun_color;
#endif // ENVIRONMENT_INCLUDED

View File

@ -0,0 +1,8 @@
#ifndef VERTEX_FORMAT_INCLUDED
#define VERTEX_FORMAT_INCLUDED
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
#endif // VERTEX_FORMAT_INCLUDED

View File

@ -16,14 +16,11 @@
#version 320 es #version 320 es
precision highp float; precision highp float;
#include "include/camera.glsl"
#include "include/environment.glsl"
in vec3 v_position; in vec3 v_position;
uniform mat4 u_view; // world space -> view space, unit = km
uniform vec3 u_light_direction; // view space (-direction_x, -direction_y, -direction_z)
uniform vec3 u_light_color;
uniform vec3 u_horizon_color;
uniform vec3 u_sky_color;
uniform vec3 u_sun_color;
uniform float u_sea_phase; uniform float u_sea_phase;
#define u_right u_view[0].xyz #define u_right u_view[0].xyz
@ -31,8 +28,8 @@ uniform float u_sea_phase;
#define u_up u_view[2].xyz #define u_up u_view[2].xyz
#define u_origin u_view[3].xyz #define u_origin u_view[3].xyz
uniform highp sampler2DArray u_sea_polar_sampler; layout(binding=0) uniform highp sampler2DArray u_sea_polar_sampler;
uniform highp sampler2D u_sea_detail_sampler; layout(binding=1) uniform highp sampler2D u_sea_detail_sampler;
const float c_sea_radius = 637.1; const float c_sea_radius = 637.1;
const float c_sea_radius_sq = c_sea_radius * c_sea_radius; const float c_sea_radius_sq = c_sea_radius * c_sea_radius;

View File

@ -16,9 +16,9 @@
#version 320 es #version 320 es
precision highp float; precision highp float;
layout(location = 0) in vec3 a_position; // view space #include "include/camera.glsl"
uniform mat4 u_projection; // view space -> screen space layout(location = 0) in vec3 a_position; // view space
out vec3 v_position; // view space out vec3 v_position; // view space

View File

@ -16,31 +16,12 @@
#version 320 es #version 320 es
precision highp float; precision highp float;
layout(location = 0) in vec3 a_position; // model space #include "include/vertex_format.glsl"
layout(location = 1) in vec3 a_normal; // model space #include "include/camera.glsl"
layout(location = 2) in vec3 a_texcoord; // texture space #include "include/common.glsl"
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
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);
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) { void main(void) {
vec4 world_position = vec4(i_translation + a_position, 1.0); vec4 world_position = vec4(i_translation + a_position, 1.0);
vec2 terrain_coords = c_terrain_shift + world_position.xy * c_terrain_scale; vec2 terrain_coords = c_terrain_shift + world_position.xy * c_terrain_scale;

View File

@ -16,32 +16,13 @@
#version 320 es #version 320 es
precision highp float; precision highp float;
layout(location = 0) in vec3 a_position; // model space #include "include/vertex_format.glsl"
layout(location = 1) in vec3 a_normal; // model space #include "include/camera.glsl"
layout(location = 2) in vec3 a_texcoord; // texture space #include "include/common.glsl"
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 mat3 i_orientation; // per mesh, model space -> world space layout(location = 4) in mat3 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);
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) { void main(void) {
vec4 world_position = vec4(i_translation + i_orientation * a_position, 1.0); vec4 world_position = vec4(i_translation + i_orientation * a_position, 1.0);
float weight = max(0.0, 1.0 - world_position.z * c_weight_scale); float weight = max(0.0, 1.0 - world_position.z * c_weight_scale);