mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Shader for models. Instanced asteroid belt.
Removed all instances of legacy pipeline, hopefully. (Except for using VAOs, I guess)
This commit is contained in:
parent
510dcb46a6
commit
a46d5a9ff7
|
@ -63,8 +63,12 @@ class Asteroid(Entity):
|
||||||
self.rotation = rx + 1, ry + 1, rz + 1
|
self.rotation = rx + 1, ry + 1, rz + 1
|
||||||
|
|
||||||
def draw(self, options):
|
def draw(self, options):
|
||||||
glLoadMatrixf(self.mv_matrix)
|
shader = self.world.activate_shader('model')
|
||||||
self.model.draw()
|
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||||
|
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
|
||||||
|
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||||
|
self.model.draw(shader)
|
||||||
|
self.world.activate_shader(None)
|
||||||
|
|
||||||
|
|
||||||
class AsteroidManager(object):
|
class AsteroidManager(object):
|
||||||
|
@ -100,10 +104,9 @@ class Belt(Entity):
|
||||||
if not isinstance(models, list):
|
if not isinstance(models, list):
|
||||||
models = [models]
|
models = [models]
|
||||||
|
|
||||||
objects = [WavefrontVBO(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
self.objects = [WavefrontVBO(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
||||||
info.get('sz', scale)) for model in models]
|
info.get('sz', scale)) for model in models]
|
||||||
|
self.belt = BeltVBO(radius, cross, len(self.objects), count)
|
||||||
self.belt_id = compile(belt, radius, cross, objects, count)
|
|
||||||
self.rotation_angle = 360.0 / rotation if rotation else 0
|
self.rotation_angle = 360.0 / rotation if rotation else 0
|
||||||
|
|
||||||
super(Belt, self).__init__(world, name, (x, y, z), (inclination, longitude, argument))
|
super(Belt, self).__init__(world, name, (x, y, z), (inclination, longitude, argument))
|
||||||
|
@ -114,8 +117,21 @@ class Belt(Entity):
|
||||||
self.rotation = pitch, self.world.tick * self.rotation_angle % 360, roll
|
self.rotation = pitch, self.world.tick * self.rotation_angle % 360, roll
|
||||||
|
|
||||||
def draw(self, options):
|
def draw(self, options):
|
||||||
glLoadMatrixf(self.mv_matrix)
|
shader = self.world.activate_shader('belt')
|
||||||
glCallList(self.belt_id)
|
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||||
|
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
|
||||||
|
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()
|
||||||
|
self.world.activate_shader(None)
|
||||||
|
|
||||||
|
|
||||||
class Sky(Entity):
|
class Sky(Entity):
|
||||||
|
@ -155,7 +171,7 @@ class Sky(Entity):
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, self.cube.vertex_count)
|
glDrawArrays(GL_TRIANGLES, 0, self.cube.vertex_count)
|
||||||
|
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
self.world.activate_shader(None)
|
self.world.activate_shader(None)
|
||||||
|
|
||||||
|
@ -261,7 +277,7 @@ class Body(Entity):
|
||||||
shader.vertex_attribute('a_position', orbit.position_size, orbit.type, GL_FALSE,
|
shader.vertex_attribute('a_position', orbit.position_size, orbit.type, GL_FALSE,
|
||||||
orbit.stride, orbit.position_offset)
|
orbit.stride, orbit.position_offset)
|
||||||
glDrawArrays(GL_LINE_LOOP, 0, orbit.vertex_count)
|
glDrawArrays(GL_LINE_LOOP, 0, orbit.vertex_count)
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
|
||||||
if not solid:
|
if not solid:
|
||||||
|
@ -407,7 +423,7 @@ class SphericalBody(Body):
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.sphere.vertex_count)
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.sphere.vertex_count)
|
||||||
|
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
self.world.activate_shader(None)
|
self.world.activate_shader(None)
|
||||||
glActiveTexture(GL_TEXTURE0)
|
glActiveTexture(GL_TEXTURE0)
|
||||||
|
@ -429,7 +445,7 @@ class SphericalBody(Body):
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.sphere.vertex_count)
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.sphere.vertex_count)
|
||||||
|
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
self.world.activate_shader(None)
|
self.world.activate_shader(None)
|
||||||
|
|
||||||
|
@ -462,7 +478,7 @@ class SphericalBody(Body):
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.atmosphere.vertex_count)
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.atmosphere.vertex_count)
|
||||||
|
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
self.world.activate_shader(None)
|
self.world.activate_shader(None)
|
||||||
glDisable(GL_BLEND)
|
glDisable(GL_BLEND)
|
||||||
|
@ -489,7 +505,7 @@ class SphericalBody(Body):
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.clouds.vertex_count)
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.clouds.vertex_count)
|
||||||
|
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
self.world.activate_shader(None)
|
self.world.activate_shader(None)
|
||||||
glDisable(GL_BLEND)
|
glDisable(GL_BLEND)
|
||||||
|
@ -517,7 +533,7 @@ class SphericalBody(Body):
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.ring.vertex_count)
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.ring.vertex_count)
|
||||||
|
|
||||||
shader.deactivate_attributes()
|
shader.deactivate_all_attributes()
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
self.world.activate_shader(None)
|
self.world.activate_shader(None)
|
||||||
glDisable(GL_BLEND)
|
glDisable(GL_BLEND)
|
||||||
|
@ -551,5 +567,9 @@ class ModelBody(Body):
|
||||||
info.get('sz', scale))
|
info.get('sz', scale))
|
||||||
|
|
||||||
def _draw(self, options):
|
def _draw(self, options):
|
||||||
glLoadMatrixf(self.mv_matrix)
|
shader = self.world.activate_shader('model')
|
||||||
self.vbo.draw()
|
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
|
||||||
|
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
|
||||||
|
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
|
||||||
|
self.vbo.draw(shader)
|
||||||
|
self.world.activate_shader(None)
|
||||||
|
|
|
@ -11,30 +11,7 @@ from six.moves import range
|
||||||
|
|
||||||
TWOPI = pi * 2
|
TWOPI = pi * 2
|
||||||
|
|
||||||
__all__ = ['compile', 'belt', 'glRestore', 'FontEngine', 'Matrix4f', 'Disk', 'OrbitVBO',
|
__all__ = ['FontEngine', 'Matrix4f', 'Disk', 'OrbitVBO', 'SimpleSphere', 'TangentSphere', 'Cube', 'Circle', 'BeltVBO']
|
||||||
'SimpleSphere', 'TangentSphere', 'Cube', 'Circle']
|
|
||||||
|
|
||||||
|
|
||||||
class glRestore(object):
|
|
||||||
def __init__(self, flags):
|
|
||||||
self.flags = flags
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
glPushAttrib(self.flags)
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
glPopAttrib()
|
|
||||||
|
|
||||||
|
|
||||||
class glRestoreClient(object):
|
|
||||||
def __init__(self, flags):
|
|
||||||
self.flags = flags
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
glPushClientAttrib(self.flags)
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
glPopClientAttrib()
|
|
||||||
|
|
||||||
|
|
||||||
def array_to_ctypes(arr):
|
def array_to_ctypes(arr):
|
||||||
|
@ -47,16 +24,19 @@ def array_to_ctypes(arr):
|
||||||
}[arr.typecode]))
|
}[arr.typecode]))
|
||||||
|
|
||||||
|
|
||||||
def array_to_gl_buffer(buffer, array_type='f'):
|
def array_to_gl_buffer(buffer):
|
||||||
vbo = c_uint()
|
vbo = c_uint()
|
||||||
glGenBuffers(1, byref(vbo))
|
glGenBuffers(1, byref(vbo))
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.value)
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.value)
|
||||||
buffer = array(array_type, buffer)
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, buffer.itemsize * len(buffer), array_to_ctypes(buffer), GL_STATIC_DRAW)
|
glBufferData(GL_ARRAY_BUFFER, buffer.itemsize * len(buffer), array_to_ctypes(buffer), GL_STATIC_DRAW)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
return vbo.value
|
return vbo.value
|
||||||
|
|
||||||
|
|
||||||
|
def list_to_gl_buffer(buffer, array_type='f'):
|
||||||
|
return array_to_gl_buffer(array(array_type, buffer))
|
||||||
|
|
||||||
|
|
||||||
class Matrix4f(object):
|
class Matrix4f(object):
|
||||||
def __init__(self, matrix):
|
def __init__(self, matrix):
|
||||||
self.matrix = array('f', matrix)
|
self.matrix = array('f', matrix)
|
||||||
|
@ -111,14 +91,6 @@ class Matrix4f(object):
|
||||||
return type(self)(sum(a[i] * b[j] for i, j in zip(r, c)) for c in cols for r in rows)
|
return type(self)(sum(a[i] * b[j] for i, j in zip(r, c)) for c in cols for r in rows)
|
||||||
|
|
||||||
|
|
||||||
def compile(pointer, *args, **kwargs):
|
|
||||||
display = glGenLists(1)
|
|
||||||
glNewList(display, GL_COMPILE)
|
|
||||||
pointer(*args, **kwargs)
|
|
||||||
glEndList()
|
|
||||||
return display
|
|
||||||
|
|
||||||
|
|
||||||
class Circle(object):
|
class Circle(object):
|
||||||
type = GL_FLOAT
|
type = GL_FLOAT
|
||||||
stride = 2 * 4
|
stride = 2 * 4
|
||||||
|
@ -132,7 +104,7 @@ class Circle(object):
|
||||||
for i in range(segs):
|
for i in range(segs):
|
||||||
theta = delta * i
|
theta = delta * i
|
||||||
buffer[2*i:2*i+2] = [cos(theta) * r, sin(theta) * r]
|
buffer[2*i:2*i+2] = [cos(theta) * r, sin(theta) * r]
|
||||||
self.vbo = array_to_gl_buffer(buffer)
|
self.vbo = list_to_gl_buffer(buffer)
|
||||||
|
|
||||||
|
|
||||||
class Disk(object):
|
class Disk(object):
|
||||||
|
@ -154,7 +126,7 @@ class Disk(object):
|
||||||
x, y = cos(theta), sin(theta)
|
x, y = cos(theta), sin(theta)
|
||||||
buffer[6*i:6*i+6] = [rinner * x, rinner * y, 0, router * x, router * y, 1]
|
buffer[6*i:6*i+6] = [rinner * x, rinner * y, 0, router * x, router * y, 1]
|
||||||
buffer[6*res:6*res+6] = buffer[:6]
|
buffer[6*res:6*res+6] = buffer[:6]
|
||||||
self.vbo = array_to_gl_buffer(buffer)
|
self.vbo = list_to_gl_buffer(buffer)
|
||||||
|
|
||||||
|
|
||||||
class SimpleSphere(object):
|
class SimpleSphere(object):
|
||||||
|
@ -190,7 +162,7 @@ class SimpleSphere(object):
|
||||||
index += 10
|
index += 10
|
||||||
reverse ^= True
|
reverse ^= True
|
||||||
|
|
||||||
self.vbo = array_to_gl_buffer(buffer)
|
self.vbo = list_to_gl_buffer(buffer)
|
||||||
|
|
||||||
|
|
||||||
class TangentSphere(object):
|
class TangentSphere(object):
|
||||||
|
@ -231,7 +203,7 @@ class TangentSphere(object):
|
||||||
]
|
]
|
||||||
index += 14
|
index += 14
|
||||||
reverse ^= True
|
reverse ^= True
|
||||||
self.vbo = array_to_gl_buffer(buffer)
|
self.vbo = list_to_gl_buffer(buffer)
|
||||||
|
|
||||||
|
|
||||||
class Cube(object):
|
class Cube(object):
|
||||||
|
@ -242,7 +214,7 @@ class Cube(object):
|
||||||
vertex_count = 36
|
vertex_count = 36
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.vbo = array_to_gl_buffer([
|
self.vbo = list_to_gl_buffer([
|
||||||
-1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1,
|
-1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1,
|
||||||
-1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1,
|
-1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1,
|
1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1,
|
||||||
|
@ -263,7 +235,7 @@ class OrbitVBO(object):
|
||||||
x, z, y = orbit.orbit(theta)
|
x, z, y = orbit.orbit(theta)
|
||||||
buffer[3*theta:3*theta+3] = [x, y, z]
|
buffer[3*theta:3*theta+3] = [x, y, z]
|
||||||
|
|
||||||
self.vbo = array_to_gl_buffer(buffer)
|
self.vbo = list_to_gl_buffer(buffer)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.vbo is not None:
|
if self.vbo is not None:
|
||||||
|
@ -322,17 +294,28 @@ class FontEngine(object):
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
|
||||||
|
|
||||||
def belt(radius, cross, object, count):
|
class BeltVBO(object):
|
||||||
for i in range(count):
|
type = GL_FLOAT
|
||||||
theta = TWOPI * random()
|
stride = 4 * 4
|
||||||
r = gauss(radius, cross)
|
location_offset = 0
|
||||||
x, y, z = cos(theta) * r, gauss(0, cross), sin(theta) * r
|
location_size = 3
|
||||||
|
scale_offset = location_size * 4
|
||||||
|
scale_size = 1
|
||||||
|
|
||||||
glPushMatrix()
|
def __init__(self, radius, cross, objects, count):
|
||||||
glTranslatef(x, y, z)
|
arrays = [array('f') for i in range(objects)]
|
||||||
scale = gauss(1, 0.5)
|
|
||||||
if scale < 0:
|
for i in range(count):
|
||||||
scale = 1
|
theta = TWOPI * random()
|
||||||
glScalef(scale, scale, scale)
|
r = gauss(radius, cross)
|
||||||
choice(object).draw()
|
x, y, z = cos(theta) * r, gauss(0, cross), sin(theta) * r
|
||||||
glPopMatrix()
|
scale = gauss(1, 0.5)
|
||||||
|
if scale < 0:
|
||||||
|
scale = 1
|
||||||
|
choice(arrays).extend((x, y, z, scale))
|
||||||
|
|
||||||
|
self.vbo = []
|
||||||
|
self.sizes = []
|
||||||
|
for a in arrays:
|
||||||
|
self.vbo.append(array_to_gl_buffer(a))
|
||||||
|
self.sizes.append(len(a) // 4)
|
||||||
|
|
|
@ -8,7 +8,6 @@ import pyglet
|
||||||
from pyglet.gl import *
|
from pyglet.gl import *
|
||||||
from six.moves import zip_longest
|
from six.moves import zip_longest
|
||||||
|
|
||||||
from punyverse.glgeom import glRestore
|
|
||||||
from punyverse.world import World
|
from punyverse.world import World
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,39 +35,40 @@ class glSection(object):
|
||||||
|
|
||||||
|
|
||||||
def progress_bar(x, y, width, height, filled):
|
def progress_bar(x, y, width, height, filled):
|
||||||
with glRestore(GL_ENABLE_BIT):
|
glPushAttrib(GL_ENABLE_BIT)
|
||||||
glDisable(GL_TEXTURE_2D)
|
glDisable(GL_TEXTURE_2D)
|
||||||
glDisable(GL_BLEND)
|
glDisable(GL_BLEND)
|
||||||
x1 = x
|
x1 = x
|
||||||
x2 = x + width
|
x2 = x + width
|
||||||
y1 = y
|
y1 = y
|
||||||
y2 = y - height
|
y2 = y - height
|
||||||
y3 = 0.65 * y1 + 0.35 * y2
|
y3 = 0.65 * y1 + 0.35 * y2
|
||||||
y4 = 0.25 * y1 + 0.75 * y2
|
y4 = 0.25 * y1 + 0.75 * y2
|
||||||
|
|
||||||
glColor3f(0.6, 0.6, 0.6)
|
glColor3f(0.6, 0.6, 0.6)
|
||||||
with glSection(GL_LINE_LOOP):
|
with glSection(GL_LINE_LOOP):
|
||||||
glVertex2f(x1, y1)
|
glVertex2f(x1, y1)
|
||||||
glVertex2f(x1, y2)
|
glVertex2f(x1, y2)
|
||||||
glVertex2f(x2, y2)
|
glVertex2f(x2, y2)
|
||||||
glVertex2f(x2, y1)
|
glVertex2f(x2, y1)
|
||||||
|
|
||||||
x1 += 1
|
x1 += 1
|
||||||
y1 -= 1
|
y1 -= 1
|
||||||
x2 = x + width * filled - 1
|
x2 = x + width * filled - 1
|
||||||
|
|
||||||
with glSection(GL_TRIANGLE_STRIP):
|
with glSection(GL_TRIANGLE_STRIP):
|
||||||
glColor3f(0.81, 1, 0.82)
|
glColor3f(0.81, 1, 0.82)
|
||||||
glVertex2f(x1, y1)
|
glVertex2f(x1, y1)
|
||||||
glVertex2f(x2, y1)
|
glVertex2f(x2, y1)
|
||||||
glColor3f(0, 0.83, 0.16)
|
glColor3f(0, 0.83, 0.16)
|
||||||
glVertex2f(x1, y3)
|
glVertex2f(x1, y3)
|
||||||
glVertex2f(x2, y3)
|
glVertex2f(x2, y3)
|
||||||
glVertex2f(x1, y4)
|
glVertex2f(x1, y4)
|
||||||
glVertex2f(x2, y4)
|
glVertex2f(x2, y4)
|
||||||
glColor3f(0.37, 0.92, 0.43)
|
glColor3f(0.37, 0.92, 0.43)
|
||||||
glVertex2f(x1, y2)
|
glVertex2f(x1, y2)
|
||||||
glVertex2f(x2, y2)
|
glVertex2f(x2, y2)
|
||||||
|
glPopAttrib()
|
||||||
|
|
||||||
|
|
||||||
def get_context_info(context):
|
def get_context_info(context):
|
||||||
|
|
|
@ -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 array_to_gl_buffer, glRestoreClient, glRestore
|
from punyverse.glgeom import list_to_gl_buffer
|
||||||
from punyverse.texture import load_texture
|
from punyverse.texture import load_texture
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,25 +199,30 @@ 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')
|
||||||
|
|
||||||
def draw(self):
|
def draw(self, shader, instances=None):
|
||||||
with glRestoreClient(GL_CLIENT_VERTEX_ARRAY_BIT):
|
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)
|
glBindBuffer(GL_ARRAY_BUFFER, self.data_buf)
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.index_buf)
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.index_buf)
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY)
|
shader.vertex_attribute('a_position', 3, GL_FLOAT, GL_FALSE, stride, 0)
|
||||||
glVertexPointer(3, GL_FLOAT, stride, 0)
|
if self.has_normal:
|
||||||
if self.has_normal:
|
shader.vertex_attribute('a_normal', 3, GL_FLOAT, GL_FALSE, stride, 3 * 4)
|
||||||
glEnableClientState(GL_NORMAL_ARRAY)
|
else:
|
||||||
glNormalPointer(GL_FLOAT, stride, 3 * 4)
|
shader.vertex_attribute_vec3('a_normal', 0, 0, 0)
|
||||||
if self.has_texture:
|
if self.has_texture:
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
shader.vertex_attribute('a_uv', 2, GL_FLOAT, GL_FALSE, stride, (6 if self.has_normal else 3) * 4)
|
||||||
glTexCoordPointer(3, GL_FLOAT, stride, (6 if self.has_normal else 3) * 4)
|
else:
|
||||||
|
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)
|
glDrawElements(GL_TRIANGLES, self.vertex_count, self.offset_type, 0)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
|
shader.deactivate_attributes('a_position', 'a_normal', 'a_uv')
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
|
||||||
|
|
||||||
|
|
||||||
class WavefrontVBO(object):
|
class WavefrontVBO(object):
|
||||||
|
@ -237,31 +242,39 @@ class WavefrontVBO(object):
|
||||||
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)))
|
self.vbos.append((group.material, self.process_group(group, vertices, normals, textures)))
|
||||||
|
|
||||||
def draw(self, fv4=GLfloat * 4):
|
def draw(self, shader, instances=None):
|
||||||
with glRestore(GL_TEXTURE_BIT | GL_ENABLE_BIT):
|
for mat, vbo in self.vbos:
|
||||||
for mat, vbo in self.vbos:
|
tex_id = self._tex_cache[mat.texture] if mat and mat.texture else 0
|
||||||
tex_id = self._tex_cache[mat.texture] if mat and mat.texture else 0
|
|
||||||
|
|
||||||
if tex_id:
|
if tex_id:
|
||||||
glEnable(GL_TEXTURE_2D)
|
glActiveTexture(GL_TEXTURE0)
|
||||||
glBindTexture(GL_TEXTURE_2D, tex_id)
|
glBindTexture(GL_TEXTURE_2D, tex_id)
|
||||||
else:
|
shader.uniform_bool('u_material.hasDiffuse', True)
|
||||||
glBindTexture(GL_TEXTURE_2D, 0)
|
shader.uniform_texture('u_material.diffuseMap', 0)
|
||||||
glDisable(GL_TEXTURE_2D)
|
else:
|
||||||
|
shader.uniform_bool('u_material.hasDiffuse', False)
|
||||||
|
|
||||||
if mat:
|
if mat and mat.Ka:
|
||||||
if mat.Ka:
|
shader.uniform_vec3('u_material.ambient', *mat.Ka)
|
||||||
kx, ky, kz = mat.Ka
|
else:
|
||||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, fv4(kx, ky, kz, 1))
|
shader.uniform_vec3('u_material.ambient', 0.2, 0.2, 0.2)
|
||||||
if mat.Kd:
|
|
||||||
kx, ky, kz = mat.Kd
|
|
||||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fv4(kx, ky, kz, 1))
|
|
||||||
if mat.Ks:
|
|
||||||
kx, ky, kz = mat.Ks
|
|
||||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(kx, ky, kz, 1))
|
|
||||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat.shininess)
|
|
||||||
|
|
||||||
vbo.draw()
|
if mat and mat.Kd:
|
||||||
|
shader.uniform_vec3('u_material.diffuse', *mat.Kd)
|
||||||
|
else:
|
||||||
|
shader.uniform_vec3('u_material.diffuse', 0.8, 0.8, 0.8)
|
||||||
|
|
||||||
|
if mat and mat.Ks:
|
||||||
|
shader.uniform_vec3('u_material.specular', *mat.Ks)
|
||||||
|
else:
|
||||||
|
shader.uniform_vec3('u_material.specular', 0, 0, 0)
|
||||||
|
|
||||||
|
if mat:
|
||||||
|
shader.uniform_float('u_material.shininess', mat.shininess)
|
||||||
|
else:
|
||||||
|
shader.uniform_float('u_material.shininess', 0)
|
||||||
|
|
||||||
|
vbo.draw(shader, instances=instances)
|
||||||
|
|
||||||
def merge_groups(self, model):
|
def merge_groups(self, model):
|
||||||
by_mat = defaultdict(list)
|
by_mat = defaultdict(list)
|
||||||
|
@ -313,8 +326,8 @@ class WavefrontVBO(object):
|
||||||
result.has_normal = has_normal
|
result.has_normal = has_normal
|
||||||
result.has_texture = has_texture
|
result.has_texture = has_texture
|
||||||
result.offset_type = GL_UNSIGNED_SHORT if len(offsets) < 65536 else GL_UNSIGNED_INT
|
result.offset_type = GL_UNSIGNED_SHORT if len(offsets) < 65536 else GL_UNSIGNED_INT
|
||||||
result.data_buf = array_to_gl_buffer(buffer, 'f')
|
result.data_buf = list_to_gl_buffer(buffer, 'f')
|
||||||
result.index_buf = array_to_gl_buffer(indices, {
|
result.index_buf = list_to_gl_buffer(indices, {
|
||||||
GL_UNSIGNED_SHORT: 'H',
|
GL_UNSIGNED_SHORT: 'H',
|
||||||
GL_UNSIGNED_INT: 'I',
|
GL_UNSIGNED_INT: 'I',
|
||||||
}[result.offset_type])
|
}[result.offset_type])
|
||||||
|
|
|
@ -79,17 +79,40 @@ class Program(object):
|
||||||
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.active_attributes = set()
|
||||||
|
self.divisor_attributes = set()
|
||||||
|
|
||||||
def vertex_attribute(self, name, size, type, normalized, stride, offset):
|
def vertex_attribute(self, name, size, type, normalized, stride, offset, divisor=None):
|
||||||
location = self.attributes[name]
|
location = self.attributes[name]
|
||||||
glVertexAttribPointer(location, size, type, normalized, stride, offset)
|
glVertexAttribPointer(location, size, type, normalized, stride, offset)
|
||||||
glEnableVertexAttribArray(location)
|
glEnableVertexAttribArray(location)
|
||||||
|
if divisor:
|
||||||
|
glVertexAttribDivisor(location, divisor)
|
||||||
|
self.divisor_attributes.add(location)
|
||||||
self.active_attributes.add(location)
|
self.active_attributes.add(location)
|
||||||
|
|
||||||
def deactivate_attributes(self):
|
def deactivate_all_attributes(self):
|
||||||
for location in self.active_attributes:
|
for location in self.active_attributes:
|
||||||
glDisableVertexAttribArray(location)
|
glDisableVertexAttribArray(location)
|
||||||
|
for location in self.divisor_attributes:
|
||||||
|
glVertexAttribDivisor(location, 0)
|
||||||
self.active_attributes.clear()
|
self.active_attributes.clear()
|
||||||
|
self.divisor_attributes.clear()
|
||||||
|
|
||||||
|
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 vertex_attribute_vec2(self, name, a, b):
|
||||||
|
glVertexAttrib2f(self.attributes[name], a, b)
|
||||||
|
|
||||||
|
def vertex_attribute_vec3(self, name, a, b, c):
|
||||||
|
glVertexAttrib3f(self.attributes[name], a, b, c)
|
||||||
|
|
||||||
def uniform_mat4(self, name, matrix):
|
def uniform_mat4(self, name, matrix):
|
||||||
glUniformMatrix4fv(self.uniforms[name], 1, GL_FALSE, matrix)
|
glUniformMatrix4fv(self.uniforms[name], 1, GL_FALSE, matrix)
|
||||||
|
|
28
punyverse/shaders/belt.vertex.glsl
Normal file
28
punyverse/shaders/belt.vertex.glsl
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec3 a_position;
|
||||||
|
in vec3 a_normal;
|
||||||
|
in vec2 a_uv;
|
||||||
|
in vec3 a_translate;
|
||||||
|
in float a_scale;
|
||||||
|
|
||||||
|
out vec2 v_uv;
|
||||||
|
out vec3 v_normal;
|
||||||
|
out vec3 v_position;
|
||||||
|
out vec3 v_camDirection;
|
||||||
|
|
||||||
|
uniform mat4 u_mvpMatrix;
|
||||||
|
uniform mat4 u_mvMatrix;
|
||||||
|
uniform mat4 u_modelMatrix;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mat4 matrix = mat4(mat3(a_scale));
|
||||||
|
matrix[3].xyz = a_translate;
|
||||||
|
mat4 modelMatrix = u_modelMatrix * matrix;
|
||||||
|
|
||||||
|
gl_Position = u_mvpMatrix * matrix * vec4(a_position, 1);
|
||||||
|
v_normal = normalize(vec3(modelMatrix * vec4(a_normal, 0)));
|
||||||
|
v_uv = a_uv;
|
||||||
|
v_position = (modelMatrix * vec4(a_position, 1)).xyz;
|
||||||
|
v_camDirection = (u_mvMatrix * matrix * vec4(a_position, 1)).xyz;
|
||||||
|
}
|
43
punyverse/shaders/model.fragment.glsl
Normal file
43
punyverse/shaders/model.fragment.glsl
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec2 v_uv;
|
||||||
|
in vec3 v_normal;
|
||||||
|
in vec3 v_position;
|
||||||
|
in vec3 v_camDirection;
|
||||||
|
|
||||||
|
out vec4 o_fragColor;
|
||||||
|
|
||||||
|
struct Material {
|
||||||
|
bool hasDiffuse;
|
||||||
|
sampler2D diffuseMap;
|
||||||
|
vec3 ambient;
|
||||||
|
vec3 diffuse;
|
||||||
|
vec3 specular;
|
||||||
|
float shininess;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sun {
|
||||||
|
vec3 ambient;
|
||||||
|
vec3 diffuse;
|
||||||
|
vec3 specular;
|
||||||
|
vec3 position;
|
||||||
|
float intensity;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform Sun u_sun;
|
||||||
|
uniform Material u_material;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 incident = normalize(u_sun.position - v_position);
|
||||||
|
vec3 reflected = normalize(reflect(-incident, v_normal));
|
||||||
|
|
||||||
|
float diffuseIntensity = max(dot(v_normal, incident), 0.0);
|
||||||
|
float shininess = pow(max(dot(normalize(v_camDirection), reflected), 0), u_material.shininess);
|
||||||
|
|
||||||
|
vec3 diffuse = u_material.hasDiffuse ? texture2D(u_material.diffuseMap, v_uv).rgb : vec3(1);
|
||||||
|
vec3 ambient = u_material.ambient * u_sun.ambient * diffuse;
|
||||||
|
vec3 specular = u_material.specular * u_sun.specular * max(shininess, 0) * diffuseIntensity;
|
||||||
|
diffuse *= u_material.diffuse * u_sun.diffuse * diffuseIntensity;
|
||||||
|
|
||||||
|
o_fragColor = vec4((ambient + diffuse + specular) * u_sun.intensity, 1);
|
||||||
|
}
|
22
punyverse/shaders/model.vertex.glsl
Normal file
22
punyverse/shaders/model.vertex.glsl
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec3 a_position;
|
||||||
|
in vec3 a_normal;
|
||||||
|
in vec2 a_uv;
|
||||||
|
|
||||||
|
out vec2 v_uv;
|
||||||
|
out vec3 v_normal;
|
||||||
|
out vec3 v_position;
|
||||||
|
out vec3 v_camDirection;
|
||||||
|
|
||||||
|
uniform mat4 u_mvpMatrix;
|
||||||
|
uniform mat4 u_mvMatrix;
|
||||||
|
uniform mat4 u_modelMatrix;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_mvpMatrix * vec4(a_position, 1);
|
||||||
|
v_normal = normalize(vec3(u_modelMatrix * vec4(a_normal, 0)));
|
||||||
|
v_uv = a_uv;
|
||||||
|
v_position = (u_modelMatrix * vec4(a_position, 1)).xyz;
|
||||||
|
v_camDirection = (u_mvMatrix * vec4(a_position, 1)).xyz;
|
||||||
|
}
|
|
@ -127,21 +127,6 @@ class Punyverse(pyglet.window.Window):
|
||||||
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW)
|
|
||||||
|
|
||||||
glEnable(GL_LIGHTING)
|
|
||||||
glEnable(GL_LIGHT0)
|
|
||||||
glEnable(GL_LIGHT1)
|
|
||||||
|
|
||||||
fv4 = GLfloat * 4
|
|
||||||
|
|
||||||
glLightfv(GL_LIGHT0, GL_POSITION, fv4(.5, .5, 1, 0))
|
|
||||||
glLightfv(GL_LIGHT0, GL_SPECULAR, fv4(.5, .5, 1, 1))
|
|
||||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4(1, 1, 1, 1))
|
|
||||||
glLightfv(GL_LIGHT1, GL_POSITION, fv4(1, 0, .5, 0))
|
|
||||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
|
|
||||||
glLightfv(GL_LIGHT1, GL_SPECULAR, fv4(1, 1, 1, 1))
|
|
||||||
|
|
||||||
self.info_engine = FontEngine()
|
self.info_engine = FontEngine()
|
||||||
self.circle = Circle(10, 20)
|
self.circle = Circle(10, 20)
|
||||||
|
|
||||||
|
@ -214,12 +199,8 @@ class Punyverse(pyglet.window.Window):
|
||||||
if not width or not height:
|
if not width or not height:
|
||||||
# Sometimes this happen for no reason?
|
# Sometimes this happen for no reason?
|
||||||
return
|
return
|
||||||
|
|
||||||
glViewport(0, 0, width, height)
|
glViewport(0, 0, width, height)
|
||||||
glMatrixMode(GL_PROJECTION)
|
|
||||||
self.world.resize(width, height)
|
self.world.resize(width, height)
|
||||||
glLoadMatrixf(self.world.projection_matrix())
|
|
||||||
glMatrixMode(GL_MODELVIEW)
|
|
||||||
|
|
||||||
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
|
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
|
||||||
self.world.cam.speed += scroll_y * 50 + scroll_x * 500
|
self.world.cam.speed += scroll_y * 50 + scroll_x * 500
|
||||||
|
@ -240,12 +221,9 @@ class Punyverse(pyglet.window.Window):
|
||||||
|
|
||||||
def on_draw(self):
|
def on_draw(self):
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||||
glLoadMatrixf(self.world.view_matrix())
|
|
||||||
|
|
||||||
c = self.world.cam
|
c = self.world.cam
|
||||||
x, y, z = c.x, c.y, c.z
|
x, y, z = c.x, c.y, c.z
|
||||||
|
|
||||||
glEnable(GL_LIGHTING)
|
|
||||||
world = self.world
|
world = self.world
|
||||||
get_distance = entity_distance(x, y, z)
|
get_distance = entity_distance(x, y, z)
|
||||||
if x != world.x or y != world.y or z != world.z:
|
if x != world.x or y != world.y or z != world.z:
|
||||||
|
@ -256,12 +234,8 @@ class Punyverse(pyglet.window.Window):
|
||||||
for entity in world.tracker:
|
for entity in world.tracker:
|
||||||
entity.draw(self)
|
entity.draw(self)
|
||||||
|
|
||||||
glColor4f(1, 1, 1, 1)
|
|
||||||
glDisable(GL_TEXTURE_2D)
|
|
||||||
|
|
||||||
width, height = self.get_size()
|
|
||||||
|
|
||||||
if self.info:
|
if self.info:
|
||||||
|
width, height = self.get_size()
|
||||||
projection = Matrix4f([
|
projection = Matrix4f([
|
||||||
2 / width, 0, 0, 0,
|
2 / width, 0, 0, 0,
|
||||||
0, -2 / height, 0, 0,
|
0, -2 / height, 0, 0,
|
||||||
|
|
|
@ -294,7 +294,7 @@
|
||||||
"radius": "2.362 * AU",
|
"radius": "2.362 * AU",
|
||||||
"cross": 1000,
|
"cross": 1000,
|
||||||
"scale": 30,
|
"scale": 30,
|
||||||
"count": 256,
|
"count": 4096,
|
||||||
"rotation": 114536500
|
"rotation": 114536500
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,6 +26,8 @@ class World(object):
|
||||||
'atmosphere': ('atmosphere.vertex.glsl', 'atmosphere.fragment.glsl'),
|
'atmosphere': ('atmosphere.vertex.glsl', 'atmosphere.fragment.glsl'),
|
||||||
'text': ('text.vertex.glsl', 'text.fragment.glsl'),
|
'text': ('text.vertex.glsl', 'text.fragment.glsl'),
|
||||||
'line': ('line.vertex.glsl', 'line.fragment.glsl'),
|
'line': ('line.vertex.glsl', 'line.fragment.glsl'),
|
||||||
|
'model': ('model.vertex.glsl', 'model.fragment.glsl'),
|
||||||
|
'belt': ('belt.vertex.glsl', 'model.fragment.glsl'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, file, callback):
|
def __init__(self, file, callback):
|
||||||
|
@ -51,12 +53,13 @@ class World(object):
|
||||||
for entity in self.tracker:
|
for entity in self.tracker:
|
||||||
entity.update()
|
entity.update()
|
||||||
|
|
||||||
shader = self.activate_shader('planet')
|
for name in ('planet', 'model', 'belt'):
|
||||||
shader.uniform_vec3('u_sun.ambient', 0.1, 0.1, 0.1)
|
shader = self.activate_shader(name)
|
||||||
shader.uniform_vec3('u_sun.diffuse', 1, 1, 1)
|
shader.uniform_vec3('u_sun.ambient', 0.1, 0.1, 0.1)
|
||||||
shader.uniform_vec3('u_sun.specular', 0.5, 0.5, 0.5)
|
shader.uniform_vec3('u_sun.diffuse', 1, 1, 1)
|
||||||
shader.uniform_vec3('u_sun.position', 0, 0, 0)
|
shader.uniform_vec3('u_sun.specular', 0.5, 0.5, 0.5)
|
||||||
shader.uniform_float('u_sun.intensity', 1)
|
shader.uniform_vec3('u_sun.position', 0, 0, 0)
|
||||||
|
shader.uniform_float('u_sun.intensity', 1)
|
||||||
|
|
||||||
shader = self.activate_shader('clouds')
|
shader = self.activate_shader('clouds')
|
||||||
shader.uniform_vec3('u_sun', 0, 0, 0)
|
shader.uniform_vec3('u_sun', 0, 0, 0)
|
||||||
|
|
Loading…
Reference in a new issue