Compare commits
4 Commits
9131523ae7
...
a96ea8bb6b
Author | SHA1 | Date | |
---|---|---|---|
a96ea8bb6b | |||
7219039980 | |||
3344ac7d6c | |||
89e0b99d3a |
2
engine
2
engine
@ -1 +1 @@
|
|||||||
Subproject commit beca8798bf91edba954d31eb4e1a619ec2140c83
|
Subproject commit ed87f292ffa3cf89903cddcdec396115893f7d66
|
@ -15,11 +15,12 @@
|
|||||||
|
|
||||||
from ctypes import c_ubyte, c_uint, c_void_p, addressof
|
from ctypes import c_ubyte, c_uint, c_void_p, addressof
|
||||||
|
|
||||||
from engine import (vec3, mat3, buffer,
|
from engine import (
|
||||||
INSTANCE_FLAG_SPAWNED, BATCH_MAX_SIZE, param_type, params_format, create_batch, draw_batch, destroy_batch)
|
buffer, INSTANCE_FLAG_SPAWNED, BATCH_MAX_SIZE, param_type, params_format,
|
||||||
|
create_batch, fill_batch, draw_batch, destroy_batch)
|
||||||
|
|
||||||
class Batch:
|
class Batch:
|
||||||
__slots__ = '_batch', 'vertices', 'size', 'max_size', 'flags', 'meshes', 'params', '_params', '__dict__'
|
__slots__ = '_batch', '_static', 'vertices', 'size', 'max_size', 'flags', 'meshes', 'params', '_params', '__dict__'
|
||||||
|
|
||||||
def __init__(self, vertices, max_size, max_meshes, **params_decls):
|
def __init__(self, vertices, max_size, max_meshes, **params_decls):
|
||||||
assert max_size <= BATCH_MAX_SIZE
|
assert max_size <= BATCH_MAX_SIZE
|
||||||
@ -27,13 +28,17 @@ class Batch:
|
|||||||
names = params_decls.keys()
|
names = params_decls.keys()
|
||||||
formats = params_decls.values()
|
formats = params_decls.values()
|
||||||
self._batch = create_batch(vertices._vertices, max_size, max_meshes, params_format(*formats))
|
self._batch = create_batch(vertices._vertices, max_size, max_meshes, params_format(*formats))
|
||||||
|
self._static = False
|
||||||
self.vertices = vertices
|
self.vertices = vertices
|
||||||
self.size = 0
|
self.size = 0
|
||||||
self.max_size = max_size
|
self.max_size = max_size
|
||||||
self.flags = buffer(c_ubyte, max_size)
|
self.flags = buffer(c_ubyte, max_size)
|
||||||
self.meshes = buffer(c_uint, max_size)
|
self.meshes = buffer(c_uint, max_size)
|
||||||
self.params = tuple(map(lambda f: buffer(param_type(f), max_size), formats))
|
self.params = tuple(map(lambda f: buffer(param_type(f), max_size), formats))
|
||||||
|
if nparams:
|
||||||
self._params = (c_void_p * nparams)(*map(addressof, self.params))
|
self._params = (c_void_p * nparams)(*map(addressof, self.params))
|
||||||
|
else:
|
||||||
|
self._params = None
|
||||||
for name, value in zip(names, self.params):
|
for name, value in zip(names, self.params):
|
||||||
setattr(self, name, value)
|
setattr(self, name, value)
|
||||||
|
|
||||||
@ -51,5 +56,11 @@ class Batch:
|
|||||||
self.size += 1
|
self.size += 1
|
||||||
return index
|
return index
|
||||||
|
|
||||||
|
def make_static(self):
|
||||||
|
fill_batch(self._batch, self.size, self.flags, self.meshes, self._params)
|
||||||
|
self._static = True
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
draw_batch(self._batch, self.size, self.flags, self.meshes, self._params)
|
if not self._static:
|
||||||
|
fill_batch(self._batch, self.size, self.flags, self.meshes, self._params)
|
||||||
|
draw_batch(self._batch)
|
||||||
|
37
game/game.py
37
game/game.py
@ -33,7 +33,7 @@ from game.environment import Environment
|
|||||||
from game.inputs import InputFloat
|
from game.inputs import InputFloat
|
||||||
from game.batch import Batch
|
from game.batch import Batch
|
||||||
from game.entity import Entity
|
from game.entity import Entity
|
||||||
from game.scene import Node, SceneNode, TextureNode, ShaderNode, InputNode, DrawNode, FuncNode
|
from game.scene import Group, SceneGroup, TextureGroup, ShaderGroup, InputNode, DrawNode, FuncNode
|
||||||
from game import sea
|
from game import sea
|
||||||
|
|
||||||
proj_hfov = pi * 0.25
|
proj_hfov = pi * 0.25
|
||||||
@ -44,11 +44,11 @@ proj_far_z = 3000.0
|
|||||||
sun_direction = math.vec3_normalize((1.0, 0.0, 0.5))
|
sun_direction = math.vec3_normalize((1.0, 0.0, 0.5))
|
||||||
sun_power = 1.0
|
sun_power = 1.0
|
||||||
|
|
||||||
class PerfNode(Node):
|
class PerfGroup(Group):
|
||||||
__slots__ = '_count', '_min', '_max', '_total', '_name'
|
__slots__ = '_count', '_min', '_max', '_total', '_name'
|
||||||
|
|
||||||
def __init__(self, name, *subnodes):
|
def __init__(self, name, *subnodes):
|
||||||
Node.__init__(self, *subnodes)
|
Group.__init__(self, *subnodes)
|
||||||
self._count = None
|
self._count = None
|
||||||
self._min = 10000.0
|
self._min = 10000.0
|
||||||
self._max = 0.0
|
self._max = 0.0
|
||||||
@ -62,7 +62,7 @@ class PerfNode(Node):
|
|||||||
|
|
||||||
def draw(self, time):
|
def draw(self, time):
|
||||||
begin = thread_time()
|
begin = thread_time()
|
||||||
Node.draw(self, time)
|
Group.draw(self, time)
|
||||||
elapsed = (thread_time() - begin) * 1000.0
|
elapsed = (thread_time() - begin) * 1000.0
|
||||||
if self._count is None:
|
if self._count is None:
|
||||||
self._count = 0
|
self._count = 0
|
||||||
@ -166,6 +166,7 @@ def create_scene(keyboard, mouse):
|
|||||||
else:
|
else:
|
||||||
model = rock_model
|
model = rock_model
|
||||||
tiles_batch.spawn(model, vec3(float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0))
|
tiles_batch.spawn(model, vec3(float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0))
|
||||||
|
tiles_batch.make_static()
|
||||||
|
|
||||||
tests_texture = Texture(*archive.get_texture('tests'))
|
tests_texture = Texture(*archive.get_texture('tests'))
|
||||||
tests_vertices = Vertices(*archive.get_vertices('tests'))
|
tests_vertices = Vertices(*archive.get_vertices('tests'))
|
||||||
@ -186,26 +187,30 @@ def create_scene(keyboard, mouse):
|
|||||||
sea_detail_texture = sea.load_detail_texture('data/sea_bump.png')
|
sea_detail_texture = sea.load_detail_texture('data/sea_bump.png')
|
||||||
sea_triangles = sea.sea_triangles(64, proj_far_z - 0.1, proj_ratio)
|
sea_triangles = sea.sea_triangles(64, proj_far_z - 0.1, proj_ratio)
|
||||||
|
|
||||||
return SceneNode(
|
assert tiles_shader.u_height_sampler == tests_shader.u_height_sampler
|
||||||
PerfNode('frame',
|
assert tiles_shader.u_normal_sampler == tests_shader.u_normal_sampler
|
||||||
TextureNode({1: heightmap, 2: normalmap},
|
|
||||||
|
return SceneGroup(
|
||||||
|
PerfGroup('frame',
|
||||||
|
TextureGroup({tiles_shader.u_height_sampler: heightmap, tiles_shader.u_normal_sampler: normalmap},
|
||||||
FuncNode(update_camera, (mouse, camera, environment)),
|
FuncNode(update_camera, (mouse, camera, environment)),
|
||||||
TextureNode({0: tiles_texture},
|
TextureGroup({tiles_shader.u_texture_sampler: tiles_texture},
|
||||||
ShaderNode(tiles_shader,
|
ShaderGroup(tiles_shader,
|
||||||
InputNode(tiles_shader, camera, environment),
|
InputNode(tiles_shader, camera, environment),
|
||||||
PerfNode('tiles_batch',
|
PerfGroup('tiles_batch',
|
||||||
DrawNode(tiles_batch)))),
|
DrawNode(tiles_batch)))),
|
||||||
FuncNode(update_tests, (blob, cube, clouds)),
|
FuncNode(update_tests, (blob, cube, clouds)),
|
||||||
TextureNode({0: tests_texture},
|
TextureGroup({tests_shader.u_texture_sampler: tests_texture},
|
||||||
ShaderNode(tests_shader,
|
ShaderGroup(tests_shader,
|
||||||
InputNode(tests_shader, camera, environment),
|
InputNode(tests_shader, camera, environment),
|
||||||
PerfNode('tests_batch',
|
PerfGroup('tests_batch',
|
||||||
DrawNode(tests_batch))))),
|
DrawNode(tests_batch))))),
|
||||||
FuncNode(update_sea, (camera, sea_phase)),
|
FuncNode(update_sea, (camera, sea_phase)),
|
||||||
TextureNode({0: sea_polar_textures, 1: sea_detail_texture},
|
TextureGroup(
|
||||||
ShaderNode(sea_shader,
|
{sea_shader.u_polar_sampler: sea_polar_textures, sea_shader.u_detail_sampler: sea_detail_texture},
|
||||||
|
ShaderGroup(sea_shader,
|
||||||
InputNode(sea_shader, camera, environment, sea_phase),
|
InputNode(sea_shader, camera, environment, sea_phase),
|
||||||
PerfNode('sea_triangles',
|
PerfGroup('sea_triangles',
|
||||||
DrawNode(sea_triangles))))))
|
DrawNode(sea_triangles))))))
|
||||||
|
|
||||||
def loop(display):
|
def loop(display):
|
||||||
|
@ -13,7 +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/>.
|
||||||
|
|
||||||
class Node:
|
class Group:
|
||||||
__slots__ = '_subnodes'
|
__slots__ = '_subnodes'
|
||||||
|
|
||||||
def __init__(self, *subnodes):
|
def __init__(self, *subnodes):
|
||||||
@ -23,34 +23,34 @@ class Node:
|
|||||||
for subnode in self._subnodes:
|
for subnode in self._subnodes:
|
||||||
subnode.draw(time)
|
subnode.draw(time)
|
||||||
|
|
||||||
class SceneNode(Node):
|
class SceneGroup(Group):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TextureNode(Node):
|
class TextureGroup(Group):
|
||||||
__slots__ = '_textures'
|
__slots__ = '_textures'
|
||||||
|
|
||||||
def __init__(self, textures, *subnodes):
|
def __init__(self, textures, *subnodes):
|
||||||
Node.__init__(self, *subnodes)
|
Group.__init__(self, *subnodes)
|
||||||
self._textures = textures
|
self._textures = textures
|
||||||
|
|
||||||
def draw(self, time):
|
def draw(self, time):
|
||||||
items = self._textures.items()
|
items = self._textures.items()
|
||||||
for slot, texture in items:
|
for slot, texture in items:
|
||||||
texture.select(slot)
|
texture.select(slot)
|
||||||
Node.draw(self, time)
|
Group.draw(self, time)
|
||||||
for slot, texture in items:
|
for slot, texture in items:
|
||||||
texture.unselect(slot)
|
texture.unselect(slot)
|
||||||
|
|
||||||
class ShaderNode(Node):
|
class ShaderGroup(Group):
|
||||||
__slots__ = '_shader'
|
__slots__ = '_shader'
|
||||||
|
|
||||||
def __init__(self, shader, *subnodes):
|
def __init__(self, shader, *subnodes):
|
||||||
Node.__init__(self, *subnodes)
|
Group.__init__(self, *subnodes)
|
||||||
self._shader = shader
|
self._shader = shader
|
||||||
|
|
||||||
def draw(self, time):
|
def draw(self, time):
|
||||||
self._shader.select()
|
self._shader.select()
|
||||||
Node.draw(self, time)
|
Group.draw(self, time)
|
||||||
self._shader.unselect()
|
self._shader.unselect()
|
||||||
|
|
||||||
class InputNode:
|
class InputNode:
|
||||||
|
@ -45,16 +45,27 @@ def _convert(line):
|
|||||||
|
|
||||||
def _parse(shader, vert_lines, frag_lines):
|
def _parse(shader, vert_lines, frag_lines):
|
||||||
uniforms = []
|
uniforms = []
|
||||||
for line in vert_lines:
|
bindings = {}
|
||||||
if line.startswith('uniform '):
|
def collect(line):
|
||||||
uniforms.append(line.split()[-1].strip(';'))
|
|
||||||
for line in frag_lines:
|
|
||||||
if line.startswith('uniform'):
|
if line.startswith('uniform'):
|
||||||
name = line.split()[-1].strip(';')
|
name = line.split()[-1].strip(';')
|
||||||
if name not in uniforms:
|
if name not in uniforms:
|
||||||
uniforms.append(name)
|
uniforms.append(name)
|
||||||
|
elif line.startswith('layout(binding='):
|
||||||
|
name = line.split()[-1].strip(';')
|
||||||
|
value = int(line[line.index('=') + 1 : line.index(')')].strip())
|
||||||
|
if name in bindings:
|
||||||
|
assert value == bindings[name]
|
||||||
|
else:
|
||||||
|
bindings[name] = value
|
||||||
|
for line in vert_lines:
|
||||||
|
collect(line)
|
||||||
|
for line in frag_lines:
|
||||||
|
collect(line)
|
||||||
for name in uniforms:
|
for name in uniforms:
|
||||||
setattr(shader, name, resolve_input(shader._shader, bytes(name, 'utf-8')))
|
setattr(shader, name, resolve_input(shader._shader, bytes(name, 'utf-8')))
|
||||||
|
for name, value in bindings.items():
|
||||||
|
setattr(shader, name, value)
|
||||||
|
|
||||||
class Shader:
|
class Shader:
|
||||||
__slots__ = '_shader', '__dict__'
|
__slots__ = '_shader', '__dict__'
|
||||||
|
@ -28,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
|
||||||
|
|
||||||
layout(binding=0) uniform highp sampler2DArray u_sea_polar_sampler;
|
layout(binding=0) uniform highp sampler2DArray u_polar_sampler;
|
||||||
layout(binding=1) uniform highp sampler2D u_sea_detail_sampler;
|
layout(binding=1) uniform highp sampler2D u_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;
|
||||||
@ -68,13 +68,13 @@ void main(void) {
|
|||||||
}
|
}
|
||||||
float t = sqrt(length(sea_position)); //TODO: more accurate
|
float t = sqrt(length(sea_position)); //TODO: more accurate
|
||||||
vec3 sea_polar1 = normalize(
|
vec3 sea_polar1 = normalize(
|
||||||
c_normal_shift + texture(u_sea_polar_sampler, vec3(s, t + u_sea_phase, 0.0)).xyz * c_normal_scale);
|
c_normal_shift + texture(u_polar_sampler, vec3(s, t + u_sea_phase, 0.0)).xyz * c_normal_scale);
|
||||||
vec3 sea_polar2 = normalize(
|
vec3 sea_polar2 = normalize(
|
||||||
c_normal_shift + texture(u_sea_polar_sampler, vec3(s, t - u_sea_phase, 1.0)).xyz * c_normal_scale);
|
c_normal_shift + texture(u_polar_sampler, vec3(s, t - u_sea_phase, 1.0)).xyz * c_normal_scale);
|
||||||
//TODO: vec2
|
//TODO: vec2
|
||||||
s = (u_sea_phase + dot(sea_position, u_right)) * c_detail_scale;
|
s = (u_sea_phase + dot(sea_position, u_right)) * c_detail_scale;
|
||||||
t = (u_sea_phase + dot(sea_position, u_forward)) * c_detail_scale;
|
t = (u_sea_phase + dot(sea_position, u_forward)) * c_detail_scale;
|
||||||
vec3 sea_detail = normalize(c_normal_shift + texture(u_sea_detail_sampler, vec2(s, t)).xyz * c_normal_scale);
|
vec3 sea_detail = normalize(c_normal_shift + texture(u_detail_sampler, vec2(s, t)).xyz * c_normal_scale);
|
||||||
//TODO: better blending, with earth normal
|
//TODO: better blending, with earth normal
|
||||||
vec4 normal = u_view * vec4(normalize(sea_polar1 + sea_polar2 + sea_detail), 0.0);
|
vec4 normal = u_view * vec4(normalize(sea_polar1 + sea_polar2 + sea_detail), 0.0);
|
||||||
float d = max(0.0, dot(normal.xyz, u_light_direction));
|
float d = max(0.0, dot(normal.xyz, u_light_direction));
|
||||||
|
Loading…
Reference in New Issue
Block a user