mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 05:01: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__
|
||||
|
||||
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):
|
||||
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)
|
||||
|
||||
if self.render:
|
||||
shader = world.activate_shader('belt')
|
||||
if not isinstance(models, list):
|
||||
models = [models]
|
||||
|
||||
self.objects = [WavefrontVBO(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
||||
info.get('sz', scale)) for model in models]
|
||||
self.belt = BeltVBO(radius, cross, len(self.objects), count)
|
||||
self.belt = BeltVBO(radius, cross, len(models), count)
|
||||
self.objects = [
|
||||
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))
|
||||
|
||||
|
@ -128,14 +144,7 @@ class Belt(Entity):
|
|||
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||
|
||||
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)
|
||||
shader.deactivate_all_attributes()
|
||||
|
||||
|
||||
class Sky(Entity):
|
||||
|
@ -159,7 +168,6 @@ class Sky(Entity):
|
|||
shader.vertex_attribute('a_direction', self.cube.direction_size, self.cube.type, GL_FALSE,
|
||||
self.cube.stride, self.cube.direction_offset)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
shader.reset_all_attributes()
|
||||
|
||||
def draw(self, options):
|
||||
cam = self.world.cam
|
||||
|
@ -276,7 +284,6 @@ class Body(Entity):
|
|||
glBindBuffer(GL_ARRAY_BUFFER, self.orbit_vbo.vbo)
|
||||
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)
|
||||
shader.reset_all_attributes()
|
||||
|
||||
self.orbit_cache = cache
|
||||
return self.orbit_vbo, self.orbit_vao
|
||||
|
@ -370,7 +377,6 @@ class SphericalBody(Body):
|
|||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
else:
|
||||
raise ValueError('Invalid type: %s' % self.type)
|
||||
shader.reset_all_attributes()
|
||||
|
||||
self.atmosphere = 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,
|
||||
self.clouds.stride, self.clouds.uv_offset)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
shader.reset_all_attributes()
|
||||
|
||||
if atm_texture is not None:
|
||||
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,
|
||||
self.atmosphere.stride, self.atmosphere.u_offset)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
shader.reset_all_attributes()
|
||||
|
||||
if 'ring' in info:
|
||||
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,
|
||||
self.ring.stride, self.ring.u_offset)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
shader.reset_all_attributes()
|
||||
|
||||
def _draw_planet(self):
|
||||
shader = self.world.activate_shader('planet')
|
||||
|
@ -584,8 +587,9 @@ class ModelBody(Body):
|
|||
super(ModelBody, self).__init__(name, world, info, parent)
|
||||
|
||||
scale = info.get('scale', 1)
|
||||
self.vbo = WavefrontVBO(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
|
||||
info.get('sz', scale))
|
||||
shader = world.activate_shader('model')
|
||||
self.vbo = WavefrontVBO(load_model(info['model']), shader, info.get('sx', scale),
|
||||
info.get('sy', scale), info.get('sz', scale))
|
||||
|
||||
def _draw(self, options):
|
||||
shader = self.world.activate_shader('model')
|
||||
|
|
|
@ -9,7 +9,7 @@ from pyglet.gl import *
|
|||
# noinspection PyUnresolvedReferences
|
||||
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
|
||||
|
||||
|
||||
|
@ -197,36 +197,41 @@ def load_model(path):
|
|||
|
||||
|
||||
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
|
||||
|
||||
with self.vao:
|
||||
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)
|
||||
if self.has_normal:
|
||||
shader.vertex_attribute('a_normal', 3, GL_FLOAT, GL_FALSE, stride, 3 * 4)
|
||||
else:
|
||||
shader.vertex_attribute_vec3('a_normal', 0, 0, 0)
|
||||
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)
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
|
||||
def draw(self, shader, instances=None):
|
||||
with self.vao:
|
||||
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)
|
||||
|
||||
shader.deactivate_attributes('a_position', 'a_normal', 'a_uv')
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
|
||||
|
||||
|
||||
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.vbos = []
|
||||
self.scale = (sx, sy, sz)
|
||||
|
@ -240,7 +245,14 @@ class WavefrontVBO(object):
|
|||
normals = model.normals
|
||||
|
||||
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):
|
||||
for mat, vbo in self.vbos:
|
||||
|
|
|
@ -78,8 +78,6 @@ class Program(object):
|
|||
self.program = program
|
||||
self.attributes = self._variable_locations(GL_ACTIVE_ATTRIBUTES, glGetActiveAttrib, glGetAttribLocation)
|
||||
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):
|
||||
location = self.attributes[name]
|
||||
|
@ -87,30 +85,6 @@ class Program(object):
|
|||
glEnableVertexAttribArray(location)
|
||||
if 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):
|
||||
glVertexAttrib2f(self.attributes[name], a, b)
|
||||
|
|
Loading…
Reference in a new issue