roc/shader.py
cecilkorik deaa55d535 working textures!
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.
2011-06-17 19:54:49 -06:00

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