1from ctypes import *
2import sys
3
4import pygame
5from pygame.locals import *
6
7try:
8 # For OpenGL-ctypes
9 from OpenGL import platform
10 gl = platform.OpenGL
11except ImportError:
12 try:
13 # For PyOpenGL
14 gl = cdll.LoadLibrary('libGL.so')
15 except OSError:
16 # Load for Mac
17 from ctypes.util import find_library
18 # finds the absolute path to the framework
19 path = find_library('OpenGL')
20 gl = cdll.LoadLibrary(path)
21
22from OpenGL.GL import *
23from OpenGL.GLU import *
24
25glCreateShader = gl.glCreateShader
26glShaderSource = gl.glShaderSource
27glShaderSource.argtypes = [c_int, c_int, POINTER(c_char_p), POINTER(c_int)]
28glCompileShader = gl.glCompileShader
29glGetShaderiv = gl.glGetShaderiv
30glGetShaderiv.argtypes = [c_int, c_int, POINTER(c_int)]
31glGetShaderInfoLog = gl.glGetShaderInfoLog
32glGetShaderInfoLog.argtypes = [c_int, c_int, POINTER(c_int), c_char_p]
33glGetUniformLocation = gl.glGetUniformLocation
34glUniform1i = gl.glUniform1i
35glDeleteShader = gl.glDeleteShader
36glCreateProgram = gl.glCreateProgram
37glAttachShader = gl.glAttachShader
38glLinkProgram = gl.glLinkProgram
39glGetError = gl.glGetError
40glUseProgram = gl.glUseProgram
41
42GL_FRAGMENT_SHADER = 0x8B30
43GL_VERTEX_SHADER = 0x8B31
44GL_COMPILE_STATUS = 0x8B81
45GL_LINK_STATUS = 0x8B82
46GL_INFO_LOG_LENGTH = 0x8B84
47
48def compile_shader(source, shader_type):
49 shader = glCreateShader(shader_type)
50 source = c_char_p(source)
51 length = c_int(-1)
52 glShaderSource(shader, 1, byref(source), byref(length))
53 glCompileShader(shader)
54
55 status = c_int()
56 glGetShaderiv(shader, GL_COMPILE_STATUS, byref(status))
57 if not status.value:
58 print_log(shader)
59 glDeleteShader(shader)
60 raise ValueError, 'Shader compilation failed'
61 return shader
62
63def compile_program(vertex_src, fragment_src):
64 '''
65 Compile a Shader program given the vertex
66 and fragment sources
67 '''
68
69 shaders = []
70
71 program = glCreateProgram()
72
73 for shader_type, src in ((GL_VERTEX_SHADER, vertex_src),
74 (GL_FRAGMENT_SHADER, fragment_src)):
75 shader = compile_shader(src, shader_type)
76 glAttachShader(program, shader)
77 shaders.append(shader)
78
79 glLinkProgram(program)
80
81 for shader in shaders:
82 glDeleteShader(shader)
83
84 return program
85
86def print_log(shader):
87 length = c_int()
88 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(length))
89
90 if length.value > 0:
91 log = create_string_buffer(length.value)
92 glGetShaderInfoLog(shader, length, byref(length), log)
93 print >> sys.stderr, log.value
94
95if __name__ == '__main__':
96
97 from OpenGL.GLUT import glutInit, glutSolidTeapot
98 glutInit(sys.argv)
99 width, height = 640, 480
100 pygame.init()
101 pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)
102
103 program = compile_program('''
104 // Vertex program
105 varying vec3 pos;
106 void main() {
107 pos = gl_Vertex.xyz;
108 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
109 }
110 ''', '''
111 // Fragment program
112 varying vec3 pos;
113 void main() {
114 gl_FragColor.rgb = pos.xyz;
115 }
116 ''')
117
118 glMatrixMode(GL_PROJECTION)
119 glLoadIdentity()
120 gluPerspective(90.0, width / float(height), 1.0, 100.0)
121 glMatrixMode(GL_MODELVIEW)
122 glEnable(GL_DEPTH_TEST)
123
124 quit = False
125 angle = 0
126 while not quit:
127 for e in pygame.event.get():
128 if e.type in (QUIT, KEYDOWN):
129 quit = True
130 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
131 glLoadIdentity()
132 glTranslate(0.0, 0.0, - 2.5)
133 glRotate(angle, 0.0, 1.0, 0.0)
134 glUseProgram(program)
135 glutSolidTeapot(1.0)
136 angle += 0.1
137 pygame.display.flip()