mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Use VAOs for everything.
This commit is contained in:
parent
bf1daf5437
commit
f135856762
|
@ -80,7 +80,8 @@ class AsteroidManager(object):
|
||||||
__nonzero__ = __bool__
|
__nonzero__ = __bool__
|
||||||
|
|
||||||
def load(self, file):
|
def load(self, file):
|
||||||
self.asteroids.append(WavefrontVBO(load_model(file), 5, 5, 5))
|
shader = self.world.activate_shader('model')
|
||||||
|
self.asteroids.append(WavefrontVBO(load_model(file), shader, 5, 5, 5))
|
||||||
|
|
||||||
def new(self, location, direction):
|
def new(self, location, direction):
|
||||||
return Asteroid(self.world, random.choice(self.asteroids), location, direction)
|
return Asteroid(self.world, random.choice(self.asteroids), location, direction)
|
||||||
|
@ -104,12 +105,27 @@ class Belt(Entity):
|
||||||
self.render = gl_info.have_version(3, 3)
|
self.render = gl_info.have_version(3, 3)
|
||||||
|
|
||||||
if self.render:
|
if self.render:
|
||||||
|
shader = world.activate_shader('belt')
|
||||||
if not isinstance(models, list):
|
if not isinstance(models, list):
|
||||||
models = [models]
|
models = [models]
|
||||||
|
|
||||||
self.objects = [WavefrontVBO(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
self.belt = BeltVBO(radius, cross, len(models), count)
|
||||||
info.get('sz', scale)) for model in models]
|
self.objects = [
|
||||||
self.belt = BeltVBO(radius, cross, len(self.objects), count)
|
WavefrontVBO(load_model(model), shader, info.get('sx', scale),
|
||||||
|
info.get('sy', scale), info.get('sz', scale))
|
||||||
|
for model in models
|
||||||
|
]
|
||||||
|
|
||||||
|
def callback():
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo)
|
||||||
|
shader.vertex_attribute('a_translate', self.belt.location_size, self.belt.type, GL_FALSE,
|
||||||
|
self.belt.stride, self.belt.location_offset, divisor=1)
|
||||||
|
shader.vertex_attribute('a_scale', self.belt.scale_size, self.belt.type, GL_FALSE,
|
||||||
|
self.belt.stride, self.belt.scale_offset, divisor=1)
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
|
||||||
|
for model, vbo, count in zip(self.objects, self.belt.vbo, self.belt.sizes):
|
||||||
|
model.additional_attributes(callback)
|
||||||
|
|
||||||
super(Belt, self).__init__(world, name, (x, y, z), (inclination, longitude, argument))
|
super(Belt, self).__init__(world, name, (x, y, z), (inclination, longitude, argument))
|
||||||
|
|
||||||
|
@ -128,14 +144,7 @@ class Belt(Entity):
|
||||||
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||||
|
|
||||||
for object, vbo, count in zip(self.objects, self.belt.vbo, self.belt.sizes):
|
for object, vbo, count in zip(self.objects, self.belt.vbo, self.belt.sizes):
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo)
|
|
||||||
shader.vertex_attribute('a_translate', self.belt.location_size, self.belt.type, GL_FALSE,
|
|
||||||
self.belt.stride, self.belt.location_offset, divisor=1)
|
|
||||||
shader.vertex_attribute('a_scale', self.belt.scale_size, self.belt.type, GL_FALSE,
|
|
||||||
self.belt.stride, self.belt.scale_offset, divisor=1)
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
|
||||||
object.draw(shader, instances=count)
|
object.draw(shader, instances=count)
|
||||||
shader.deactivate_all_attributes()
|
|
||||||
|
|
||||||
|
|
||||||
class Sky(Entity):
|
class Sky(Entity):
|
||||||
|
@ -159,7 +168,6 @@ class Sky(Entity):
|
||||||
shader.vertex_attribute('a_direction', self.cube.direction_size, self.cube.type, GL_FALSE,
|
shader.vertex_attribute('a_direction', self.cube.direction_size, self.cube.type, GL_FALSE,
|
||||||
self.cube.stride, self.cube.direction_offset)
|
self.cube.stride, self.cube.direction_offset)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
shader.reset_all_attributes()
|
|
||||||
|
|
||||||
def draw(self, options):
|
def draw(self, options):
|
||||||
cam = self.world.cam
|
cam = self.world.cam
|
||||||
|
@ -276,7 +284,6 @@ class Body(Entity):
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, self.orbit_vbo.vbo)
|
glBindBuffer(GL_ARRAY_BUFFER, self.orbit_vbo.vbo)
|
||||||
shader.vertex_attribute('a_position', self.orbit_vbo.position_size, self.orbit_vbo.type, GL_FALSE,
|
shader.vertex_attribute('a_position', self.orbit_vbo.position_size, self.orbit_vbo.type, GL_FALSE,
|
||||||
self.orbit_vbo.stride, self.orbit_vbo.position_offset)
|
self.orbit_vbo.stride, self.orbit_vbo.position_offset)
|
||||||
shader.reset_all_attributes()
|
|
||||||
|
|
||||||
self.orbit_cache = cache
|
self.orbit_cache = cache
|
||||||
return self.orbit_vbo, self.orbit_vao
|
return self.orbit_vbo, self.orbit_vao
|
||||||
|
@ -370,7 +377,6 @@ class SphericalBody(Body):
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
else:
|
else:
|
||||||
raise ValueError('Invalid type: %s' % self.type)
|
raise ValueError('Invalid type: %s' % self.type)
|
||||||
shader.reset_all_attributes()
|
|
||||||
|
|
||||||
self.atmosphere = None
|
self.atmosphere = None
|
||||||
self.clouds = None
|
self.clouds = None
|
||||||
|
@ -403,7 +409,6 @@ class SphericalBody(Body):
|
||||||
shader.vertex_attribute('a_uv', self.clouds.uv_size, self.clouds.type, GL_FALSE,
|
shader.vertex_attribute('a_uv', self.clouds.uv_size, self.clouds.type, GL_FALSE,
|
||||||
self.clouds.stride, self.clouds.uv_offset)
|
self.clouds.stride, self.clouds.uv_offset)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
shader.reset_all_attributes()
|
|
||||||
|
|
||||||
if atm_texture is not None:
|
if atm_texture is not None:
|
||||||
self.atm_texture = load_texture_1d(atm_texture, clamp=True)
|
self.atm_texture = load_texture_1d(atm_texture, clamp=True)
|
||||||
|
@ -417,7 +422,6 @@ class SphericalBody(Body):
|
||||||
shader.vertex_attribute('a_u', self.atmosphere.u_size, self.atmosphere.type, GL_FALSE,
|
shader.vertex_attribute('a_u', self.atmosphere.u_size, self.atmosphere.type, GL_FALSE,
|
||||||
self.atmosphere.stride, self.atmosphere.u_offset)
|
self.atmosphere.stride, self.atmosphere.u_offset)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
shader.reset_all_attributes()
|
|
||||||
|
|
||||||
if 'ring' in info:
|
if 'ring' in info:
|
||||||
distance = world.evaluate(info['ring'].get('distance', self.radius * 1.2))
|
distance = world.evaluate(info['ring'].get('distance', self.radius * 1.2))
|
||||||
|
@ -441,7 +445,6 @@ class SphericalBody(Body):
|
||||||
shader.vertex_attribute('a_u', self.ring.u_size, self.ring.type, GL_FALSE,
|
shader.vertex_attribute('a_u', self.ring.u_size, self.ring.type, GL_FALSE,
|
||||||
self.ring.stride, self.ring.u_offset)
|
self.ring.stride, self.ring.u_offset)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
shader.reset_all_attributes()
|
|
||||||
|
|
||||||
def _draw_planet(self):
|
def _draw_planet(self):
|
||||||
shader = self.world.activate_shader('planet')
|
shader = self.world.activate_shader('planet')
|
||||||
|
@ -584,8 +587,9 @@ class ModelBody(Body):
|
||||||
super(ModelBody, self).__init__(name, world, info, parent)
|
super(ModelBody, self).__init__(name, world, info, parent)
|
||||||
|
|
||||||
scale = info.get('scale', 1)
|
scale = info.get('scale', 1)
|
||||||
self.vbo = WavefrontVBO(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
|
shader = world.activate_shader('model')
|
||||||
info.get('sz', scale))
|
self.vbo = WavefrontVBO(load_model(info['model']), shader, info.get('sx', scale),
|
||||||
|
info.get('sy', scale), info.get('sz', scale))
|
||||||
|
|
||||||
def _draw(self, options):
|
def _draw(self, options):
|
||||||
shader = self.world.activate_shader('model')
|
shader = self.world.activate_shader('model')
|
||||||
|
|
|
@ -9,7 +9,7 @@ from pyglet.gl import *
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from six.moves import range, zip
|
from six.moves import range, zip
|
||||||
|
|
||||||
from punyverse.glgeom import list_to_gl_buffer
|
from punyverse.glgeom import list_to_gl_buffer, VAO
|
||||||
from punyverse.texture import load_texture
|
from punyverse.texture import load_texture
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,36 +197,41 @@ def load_model(path):
|
||||||
|
|
||||||
|
|
||||||
class ModelVBO(object):
|
class ModelVBO(object):
|
||||||
__slots__ = ('has_normal', 'has_texture', 'data_buf', 'index_buf', 'offset_type', 'vertex_count')
|
__slots__ = ('has_normal', 'has_texture', 'data_buf', 'index_buf', 'offset_type', 'vertex_count', 'vao')
|
||||||
|
|
||||||
def draw(self, shader, instances=None):
|
def __init__(self):
|
||||||
|
self.vao = VAO()
|
||||||
|
|
||||||
|
def build_vao(self, shader):
|
||||||
stride = (3 + self.has_normal * 3 + self.has_texture * 2) * 4
|
stride = (3 + self.has_normal * 3 + self.has_texture * 2) * 4
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, self.data_buf)
|
with self.vao:
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.index_buf)
|
glBindBuffer(GL_ARRAY_BUFFER, self.data_buf)
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.index_buf)
|
||||||
|
|
||||||
shader.vertex_attribute('a_position', 3, GL_FLOAT, GL_FALSE, stride, 0)
|
shader.vertex_attribute('a_position', 3, GL_FLOAT, GL_FALSE, stride, 0)
|
||||||
if self.has_normal:
|
if self.has_normal:
|
||||||
shader.vertex_attribute('a_normal', 3, GL_FLOAT, GL_FALSE, stride, 3 * 4)
|
shader.vertex_attribute('a_normal', 3, GL_FLOAT, GL_FALSE, stride, 3 * 4)
|
||||||
else:
|
if self.has_texture:
|
||||||
shader.vertex_attribute_vec3('a_normal', 0, 0, 0)
|
shader.vertex_attribute('a_uv', 2, GL_FLOAT, GL_FALSE, stride, (6 if self.has_normal else 3) * 4)
|
||||||
if self.has_texture:
|
|
||||||
shader.vertex_attribute('a_uv', 2, GL_FLOAT, GL_FALSE, stride, (6 if self.has_normal else 3) * 4)
|
|
||||||
else:
|
|
||||||
shader.vertex_attribute_vec2('a_uv', 0, 0)
|
|
||||||
|
|
||||||
if instances:
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
glDrawElementsInstanced(GL_TRIANGLES, self.vertex_count, self.offset_type, 0, instances)
|
|
||||||
else:
|
|
||||||
glDrawElements(GL_TRIANGLES, self.vertex_count, self.offset_type, 0)
|
|
||||||
|
|
||||||
shader.deactivate_attributes('a_position', 'a_normal', 'a_uv')
|
def draw(self, shader, instances=None):
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
with self.vao:
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
|
if not self.has_normal:
|
||||||
|
shader.vertex_attribute_vec3('a_normal', 0, 0, 0)
|
||||||
|
|
||||||
|
if not self.has_texture:
|
||||||
|
shader.vertex_attribute_vec2('a_uv', 0, 0)
|
||||||
|
if instances:
|
||||||
|
glDrawElementsInstanced(GL_TRIANGLES, self.vertex_count, self.offset_type, 0, instances)
|
||||||
|
else:
|
||||||
|
glDrawElements(GL_TRIANGLES, self.vertex_count, self.offset_type, 0)
|
||||||
|
|
||||||
|
|
||||||
class WavefrontVBO(object):
|
class WavefrontVBO(object):
|
||||||
def __init__(self, model, sx=1, sy=1, sz=1):
|
def __init__(self, model, shader, sx=1, sy=1, sz=1):
|
||||||
self._tex_cache = {}
|
self._tex_cache = {}
|
||||||
self.vbos = []
|
self.vbos = []
|
||||||
self.scale = (sx, sy, sz)
|
self.scale = (sx, sy, sz)
|
||||||
|
@ -240,7 +245,14 @@ class WavefrontVBO(object):
|
||||||
normals = model.normals
|
normals = model.normals
|
||||||
|
|
||||||
for group in self.merge_groups(model):
|
for group in self.merge_groups(model):
|
||||||
self.vbos.append((group.material, self.process_group(group, vertices, normals, textures)))
|
processed = self.process_group(group, vertices, normals, textures)
|
||||||
|
self.vbos.append((group.material, processed))
|
||||||
|
processed.build_vao(shader)
|
||||||
|
|
||||||
|
def additional_attributes(self, callback):
|
||||||
|
for _, group in self.vbos:
|
||||||
|
with group.vao:
|
||||||
|
callback()
|
||||||
|
|
||||||
def draw(self, shader, instances=None):
|
def draw(self, shader, instances=None):
|
||||||
for mat, vbo in self.vbos:
|
for mat, vbo in self.vbos:
|
||||||
|
|
|
@ -78,8 +78,6 @@ class Program(object):
|
||||||
self.program = program
|
self.program = program
|
||||||
self.attributes = self._variable_locations(GL_ACTIVE_ATTRIBUTES, glGetActiveAttrib, glGetAttribLocation)
|
self.attributes = self._variable_locations(GL_ACTIVE_ATTRIBUTES, glGetActiveAttrib, glGetAttribLocation)
|
||||||
self.uniforms = self._variable_locations(GL_ACTIVE_UNIFORMS, glGetActiveUniform, glGetUniformLocation)
|
self.uniforms = self._variable_locations(GL_ACTIVE_UNIFORMS, glGetActiveUniform, glGetUniformLocation)
|
||||||
self.active_attributes = set()
|
|
||||||
self.divisor_attributes = set()
|
|
||||||
|
|
||||||
def vertex_attribute(self, name, size, type, normalized, stride, offset, divisor=None):
|
def vertex_attribute(self, name, size, type, normalized, stride, offset, divisor=None):
|
||||||
location = self.attributes[name]
|
location = self.attributes[name]
|
||||||
|
@ -87,30 +85,6 @@ class Program(object):
|
||||||
glEnableVertexAttribArray(location)
|
glEnableVertexAttribArray(location)
|
||||||
if divisor:
|
if divisor:
|
||||||
glVertexAttribDivisor(location, divisor)
|
glVertexAttribDivisor(location, divisor)
|
||||||
self.divisor_attributes.add(location)
|
|
||||||
self.active_attributes.add(location)
|
|
||||||
|
|
||||||
def deactivate_all_attributes(self):
|
|
||||||
for location in self.active_attributes:
|
|
||||||
glDisableVertexAttribArray(location)
|
|
||||||
for location in self.divisor_attributes:
|
|
||||||
glVertexAttribDivisor(location, 0)
|
|
||||||
self.reset_all_attributes()
|
|
||||||
|
|
||||||
def deactivate_attributes(self, *attributes):
|
|
||||||
for attr in attributes:
|
|
||||||
location = self.attributes[attr]
|
|
||||||
if location in self.active_attributes:
|
|
||||||
glDisableVertexAttribArray(location)
|
|
||||||
if location in self.divisor_attributes:
|
|
||||||
glVertexAttribDivisor(location, 0)
|
|
||||||
self.active_attributes.discard(location)
|
|
||||||
self.divisor_attributes.discard(location)
|
|
||||||
|
|
||||||
def reset_all_attributes(self):
|
|
||||||
# Call this when you bound to a VAO.
|
|
||||||
self.active_attributes.clear()
|
|
||||||
self.divisor_attributes.clear()
|
|
||||||
|
|
||||||
def vertex_attribute_vec2(self, name, a, b):
|
def vertex_attribute_vec2(self, name, a, b):
|
||||||
glVertexAttrib2f(self.attributes[name], a, b)
|
glVertexAttrib2f(self.attributes[name], a, b)
|
||||||
|
|
Loading…
Reference in a new issue