completely overhauled models framework... now loads Model, Mesh, Material, and Texture (plus TextureFile) fixed a number of bugs/inflexibilities in gamedata xml parser refactored the various modules to use "init" functions to better control when they get loaded (ie, before or after OpenGL init) which it turns out is *very important*, because if the shaders and textures get loaded before OpenGL does, they don't work. go figure.
219 lines
6.3 KiB
Python
Executable file
219 lines
6.3 KiB
Python
Executable file
import ctypes
|
|
from OpenGL.GL import *
|
|
try:
|
|
import OpenGL.raw.GL
|
|
raw = OpenGL.raw
|
|
except ImportError:
|
|
pass
|
|
from OpenGL.arrays import GLintArray, GLcharArray, GLsizeiArray, GLcharARBArray
|
|
import sys
|
|
import gamedata
|
|
|
|
|
|
class shader_manager(object):
|
|
def __init__(self):
|
|
# Fixed Pipeline is always zero
|
|
self.shaderlib = {'ffp': 0}
|
|
self.shaderprograms = {}
|
|
|
|
self.initshadersources = []
|
|
self.initmode = 'auto'
|
|
self.initialized = False
|
|
|
|
def use_gl2_shaders(self):
|
|
self.funcs = {
|
|
'create': glCreateShader,
|
|
'source': glShaderSource,
|
|
'compile': glCompileShader,
|
|
'program': glCreateProgram,
|
|
'attach': glAttachShader,
|
|
'link': glLinkProgram,
|
|
'use': glUseProgram,
|
|
'param': glGetShaderiv,
|
|
'uniform': glUniform4f,
|
|
'arraytype': GLcharArray
|
|
}
|
|
def use_raw_shaders(self):
|
|
self.funcs = {
|
|
'create': raw.GL.glCreateShader,
|
|
'source': raw.GL.glShaderSource,
|
|
'compile': raw.GL.glCompileShader,
|
|
'program': raw.GL.glCreateProgram,
|
|
'attach': raw.GL.glAttachShader,
|
|
'link': raw.GL.glLinkProgram,
|
|
'use': raw.GL.glUseProgram,
|
|
'param': raw.GL.glGetShaderiv
|
|
}
|
|
|
|
def use_arb_shaders(self):
|
|
from OpenGL.GL.ARB import shader_objects
|
|
if not shader_objects.glInitShaderObjectsARB():
|
|
raise RuntimeError("ARB Shaders failed to initialize")
|
|
|
|
self.funcs = {
|
|
'create': shader_objects.glCreateShaderObjectARB,
|
|
'source': shader_objects.glShaderSourceARB,
|
|
'compile': shader_objects.glCompileShaderARB,
|
|
'program': shader_objects.glCreateProgramObjectARB,
|
|
'attach': shader_objects.glAttachObjectARB,
|
|
'link': shader_objects.glLinkProgramARB,
|
|
'use': shader_objects.glUseProgramObjectARB,
|
|
'uniform': shader_objects.glUniform4fARB,
|
|
'param': shader_objects.glGetObjectParameterivARB
|
|
}
|
|
def use_arb_new_shaders(self):
|
|
from OpenGL.GL.ARB import shader_objects_new
|
|
shader_objects = shader_objects_new
|
|
if not shader_objects.glInitShaderObjectsARB():
|
|
raise RuntimeError("ARB New Shaders failed to initialize")
|
|
|
|
self.funcs = {
|
|
'create': shader_objects.glCreateShaderObjectARB,
|
|
'source': shader_objects.base_glShaderSourceARB,
|
|
'compile': shader_objects.glCompileShaderARB,
|
|
'program': shader_objects.glCreateProgramObjectARB,
|
|
'attach': shader_objects.glAttachObjectARB,
|
|
'link': shader_objects.glLinkProgramARB,
|
|
'use': shader_objects.glUseProgramObjectARB,
|
|
'param': shader_objects.glGetObjectParameterivARB,
|
|
'arraytype': GLcharARBArray
|
|
}
|
|
|
|
def init_gl(self):
|
|
if self.initialized:
|
|
return
|
|
|
|
self.initialized = True
|
|
import files
|
|
#print glGetString(GL_EXTENSIONS)
|
|
if True:
|
|
self.use_gl2_shaders()
|
|
else:
|
|
self.use_arb_shaders()
|
|
#self.use_gl2_shaders()
|
|
|
|
for name, vertex, fragment in self.initshadersources:
|
|
vf = files.mgr.open('shaders/%s.vert' % (vertex,))
|
|
ff = files.mgr.open('shaders/%s.frag' % (fragment,))
|
|
vs = self.funcs['create'](GL_VERTEX_SHADER)
|
|
fs = self.funcs['create'](GL_FRAGMENT_SHADER)
|
|
self.funcs['source'](vs, vf.read())
|
|
self.funcs['source'](fs, ff.read())
|
|
rv = self.funcs['compile'](vs)
|
|
rv = self.funcs['compile'](fs)
|
|
sp = self.funcs['program']()
|
|
self.funcs['attach'](sp, vs)
|
|
self.funcs['attach'](sp, fs)
|
|
rv = self.funcs['link'](sp)
|
|
self.shaderlib[name] = sp
|
|
self.shaderprograms[name] = (vs, fs)
|
|
|
|
def detect(self):
|
|
shaderlist = [
|
|
('GL2', self.use_gl2_shaders),
|
|
('ARB', self.use_arb_shaders),
|
|
('ARBNEW', self.use_arb_new_shaders),
|
|
('RAW', self.use_raw_shaders)
|
|
]
|
|
|
|
workable_shaders = []
|
|
|
|
for shadername, shaderinit in shaderlist:
|
|
try:
|
|
shaderinit()
|
|
except:
|
|
print "Shader type %s failed to initialize" % (shadername,)
|
|
continue
|
|
try:
|
|
self.select("ffp")
|
|
except:
|
|
print "Shader type %s failed to access the fixed function pipeline" % (shadername,)
|
|
continue
|
|
try:
|
|
self.select("standard")
|
|
except:
|
|
print "Shader type %s failed to load the \"standard\" vertex and fragment shaders" % (shadername,)
|
|
continue
|
|
|
|
workable_shaders.append(shadername)
|
|
|
|
return workable_shaders
|
|
|
|
def autoinit(self):
|
|
shadertypes = self.detect()
|
|
|
|
if not shadertypes:
|
|
raise ValueError, "No working shaders detected"
|
|
|
|
self.init_shadertype(shadertypes[0])
|
|
|
|
def init_shadertype(self, shadertype):
|
|
if shadertype == "GL2":
|
|
self.use_gl2_shaders()
|
|
elif shadertype == "ARB":
|
|
self.use_arb_shaders()
|
|
elif shadertype == "ARBNEW":
|
|
self.use_arb_new_shaders()
|
|
elif shadertype == "RAW":
|
|
self.use_raw_shaders()
|
|
|
|
|
|
|
|
def select(self, shader):
|
|
if self.initshadersources:
|
|
self.init_gl()
|
|
self.initshadersources = []
|
|
if not shader in self.shaderlib:
|
|
self.funcs['use'](0)
|
|
return True
|
|
try:
|
|
self.funcs['use'](self.shaderlib[shader])
|
|
except GLError:
|
|
p = self.shaderlib[shader]
|
|
v, f = self.shaderprograms[shader]
|
|
print "Shader failed to execute: %s" % (shader,)
|
|
print "Vertex shader log:"
|
|
lenarr = GLintArray.zeros(1)
|
|
glGetShaderiv(v, GL_INFO_LOG_LENGTH, lenarr)
|
|
infoarr = GLcharArray.zeros(lenarr[0])
|
|
outsize = GLsizeiArray.zeros(1)
|
|
glGetShaderInfoLog(v, lenarr[0], outsize, infoarr)
|
|
print ''.join([chr(x) for x in infoarr[:outsize[0]]])
|
|
print "Fragment shader log:"
|
|
lenarr = GLintArray.zeros(1)
|
|
glGetShaderiv(f, GL_INFO_LOG_LENGTH, lenarr)
|
|
infoarr = GLcharArray.zeros(lenarr[0])
|
|
outsize = GLsizeiArray.zeros(1)
|
|
glGetShaderInfoLog(f, lenarr[0], outsize, infoarr)
|
|
print ''.join([chr(x) for x in infoarr[:outsize[0]]])
|
|
print "Program info log:"
|
|
lenarr = GLintArray.zeros(1)
|
|
glGetProgramiv(p, GL_INFO_LOG_LENGTH, lenarr)
|
|
infoarr = GLcharArray.zeros(lenarr[0])
|
|
outsize = GLsizeiArray.zeros(1)
|
|
glGetProgramInfoLog(p, lenarr[0], outsize, infoarr)
|
|
print ''.join([chr(x) for x in infoarr[:outsize[0]]])
|
|
glDeleteShader(v)
|
|
glDeleteShader(f)
|
|
glDeleteProgram(p)
|
|
del self.shaderprograms[shader]
|
|
del self.shaderlib[shader]
|
|
glUseProgram(0)
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
def load(self):
|
|
shader_data = gamedata.get('shaders')
|
|
self.load_shaders(shader_data)
|
|
|
|
def load_shaders(self, shaders):
|
|
for shader in shaders.shader:
|
|
self.initshadersources.append((shader['id'], shader['vertex'], shader['fragment']))
|
|
|
|
def init():
|
|
global mgr
|
|
mgr = shader_manager()
|
|
|
|
mgr = None
|