roc/shader.py

219 lines
6.1 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