from ctypes import *
import sys
 
import pygame
from pygame.locals import *
 
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GL.ARB.shader_objects import *
from OpenGL.GL.ARB.vertex_shader import *
from OpenGL.GL.ARB.fragment_shader import *

import sys, traceback

def glLibTestErrors(function):
    try:
        function()
    except Exception, e:
        tb = sys.exc_info()[2]
        traceback.print_exception(e.__class__, e, tb)
        pygame.quit()
        raw_input()
        sys.exit()

def init_globals():
    global glCreateShader,glShaderSource,glCompileShader,glDeleteShader,glCreateProgram
    global glAttachShader,glLinkProgram,glUseProgram, glGetUniformLocation
    glCreateShader = glCreateShaderObjectARB
    glShaderSource = glShaderSourceARB
    glCompileShader = glCompileShaderARB
    glDeleteShader = glDeleteObjectARB
    glCreateProgram = glCreateProgramObjectARB
    glAttachShader = glAttachObjectARB
    glLinkProgram = glLinkProgramARB
    glUseProgram = glUseProgramObjectARB
    glGetUniformLocation = glGetUniformLocation
 
def compile_shader(source, shader_type):
    shader = glCreateShader(shader_type)
    glShaderSource(shader, [source])
    glCompileShader(shader)
    
    return shader
 
def compile_program(vertex_source, fragment_source):
    vertex_shader = None
    fragment_shader = None
    program = glCreateProgram()
 
    if vertex_source:
        vertex_shader = compile_shader(vertex_source, GL_VERTEX_SHADER)
        glAttachShader(program, vertex_shader)
    if fragment_source:
        fragment_shader = compile_shader(fragment_source, GL_FRAGMENT_SHADER)
        glAttachShader(program, fragment_shader)
 
    glLinkProgram(program)
 
    if vertex_shader:
        glDeleteShader(vertex_shader)
    if fragment_shader:
        glDeleteShader(fragment_shader)
 
    return program

def print_log(program):
    errors = glGetInfoLogARB(program)
    print errors
def main():
    glutInit(sys.argv)
    width, height = 640, 480
    pygame.init()
    pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)

    glInitShaderObjectsARB()
    glInitVertexShaderARB()
    glInitFragmentShaderARB()

    init_globals()
 
    program = compile_program('''
    // Vertex program
    varying vec3 pos;
    void main() {
        pos = gl_Vertex.xyz;
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    }
    ''', '''
    // Fragment program
    uniform vec4 colorr;  
    varying vec3 pos;
    void main() {
        gl_FragColor = colorr;
    }
    ''')
    print_log(program)
 
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(90.0, width/float(height), 1.0, 100.0)
    glMatrixMode(GL_MODELVIEW)
    glEnable(GL_DEPTH_TEST)
    
    quit = False
    angle = 0
    while not quit:
        for e in pygame.event.get():
            if e.type in (QUIT, KEYDOWN):
                quit = True
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()

        glTranslate(0.0, 0.0, -2.5)
        glRotate(angle, 0.0, 1.0, 1.0)

        glUseProgram(program)
        colorr_loc = glGetUniformLocation(program, 'colorr')
        print 'colorr_loc =', colorr_loc
        glUniform4f(colorr_loc, 1, 0, 0, 1)

        glutSolidTeapot(1.0)
        angle += 0.5
        pygame.display.flip()
        
if __name__ == '__main__': glLibTestErrors(main)
