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() print("initiated shader mgr: %s" % (mgr,)) mgr = None