summaryrefslogtreecommitdiff
path: root/third_party/freetype-py/examples/shader.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/freetype-py/examples/shader.py')
-rw-r--r--third_party/freetype-py/examples/shader.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/third_party/freetype-py/examples/shader.py b/third_party/freetype-py/examples/shader.py
new file mode 100644
index 0000000..998dd8b
--- /dev/null
+++ b/third_party/freetype-py/examples/shader.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# -----------------------------------------------------------------------------
+# Copyright (C) 2009-2010 Nicolas P. Rougier
+#
+# Distributed under the terms of the BSD License. The full license is in
+# the file COPYING, distributed as part of this software.
+# -----------------------------------------------------------------------------
+#
+# Copyright Tristam Macdonald 2008.
+#
+# Distributed under the Boost Software License, Version 1.0
+# (see http://www.boost.org/LICENSE_1_0.txt)
+#
+''' Base shader class.
+
+ Example:
+ --------
+ shader = Shader()
+
+ shader.bind()
+ glActiveTexture(GL_TEXTURE1)
+ glBindTexture(lut.target, lut.id)
+ shader.uniformi('lut', 1)
+
+ glActiveTexture(GL_TEXTURE0)
+ glBindTexture(texture.target, texture.id)
+ shader.uniformi('texture', 0)
+ shader.uniformf('pixel', 1.0/texture.width, 1.0/texture.height)
+
+ texture.blit(x,y,w,h)
+ shader.unbind()
+'''
+import os
+import OpenGL.GL as gl
+import ctypes
+
+class Shader:
+ ''' Base shader class. '''
+
+ def __init__(self, vert = None, frag = None, name=''):
+ ''' vert, frag and geom take arrays of source strings
+ the arrays will be concatenated into one string by OpenGL.'''
+
+ self.uniforms = {}
+ self.name = name
+ # create the program handle
+ self.handle = gl.glCreateProgram()
+ # we are not linked yet
+ self.linked = False
+ # create the vertex shader
+ self._build_shader(vert, gl.GL_VERTEX_SHADER)
+ # create the fragment shader
+ self._build_shader(frag, gl.GL_FRAGMENT_SHADER)
+ # the geometry shader will be the same, once pyglet supports the
+ # extension self.createShader(frag, GL_GEOMETRY_SHADER_EXT) attempt to
+ # link the program
+ self._link()
+
+ def _build_shader(self, strings, stype):
+ ''' Actual building of the shader '''
+
+ count = len(strings)
+ # if we have no source code, ignore this shader
+ if count < 1:
+ return
+
+ # create the shader handle
+ shader = gl.glCreateShader(stype)
+
+ # Upload shader code
+ gl.glShaderSource(shader, strings)
+
+ # compile the shader
+ gl.glCompileShader(shader)
+
+ # retrieve the compile status
+ status = gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS)
+
+ # if compilation failed, print the log
+ if not status:
+ # display the log
+ print gl.glGetShaderInfoLog(shader)
+ else:
+ # all is well, so attach the shader to the program
+ gl.glAttachShader(self.handle, shader)
+
+ def _link(self):
+ ''' Link the program '''
+
+ gl.glLinkProgram(self.handle)
+ # retrieve the link status
+ temp = ctypes.c_int(0)
+ gl.glGetProgramiv(self.handle, gl.GL_LINK_STATUS, ctypes.byref(temp))
+
+ # if linking failed, print the log
+ if not temp:
+ # retrieve the log length
+ gl.glGetProgramiv(self.handle,
+ gl.GL_INFO_LOG_LENGTH, ctypes.byref(temp))
+ # create a buffer for the log
+ #buffer = ctypes.create_string_buffer(temp.value)
+ # retrieve the log text
+ log = gl.glGetProgramInfoLog(self.handle) #, temp, None, buffer)
+ # print the log to the console
+ print log
+ else:
+ # all is well, so we are linked
+ self.linked = True
+
+ def bind(self):
+ ''' Bind the program, i.e. use it. '''
+ gl.glUseProgram(self.handle)
+
+ def unbind(self):
+ ''' Unbind whatever program is currently bound - not necessarily this
+ program, so this should probably be a class method instead. '''
+ gl.glUseProgram(0)
+
+ def uniformf(self, name, *vals):
+ ''' Uploads float uniform(s), program must be currently bound. '''
+
+ loc = self.uniforms.get(name,
+ gl.glGetUniformLocation(self.handle,name))
+ self.uniforms[name] = loc
+
+ # Check there are 1-4 values
+ if len(vals) in range(1, 5):
+ # Select the correct function
+ { 1 : gl.glUniform1f,
+ 2 : gl.glUniform2f,
+ 3 : gl.glUniform3f,
+ 4 : gl.glUniform4f
+ # Retrieve uniform location, and set it
+ }[len(vals)](loc, *vals)
+
+ def uniformi(self, name, *vals):
+ ''' Upload integer uniform(s), program must be currently bound. '''
+
+ loc = self.uniforms.get(name,
+ gl.glGetUniformLocation(self.handle,name))
+ self.uniforms[name] = loc
+
+ # Checks there are 1-4 values
+ if len(vals) in range(1, 5):
+ # Selects the correct function
+ { 1 : gl.glUniform1i,
+ 2 : gl.glUniform2i,
+ 3 : gl.glUniform3i,
+ 4 : gl.glUniform4i
+ # Retrieves uniform location, and set it
+ }[len(vals)](loc, *vals)
+
+
+ def uniform_matrixf(self, name, mat):
+ ''' Upload uniform matrix, program must be currently bound. '''
+
+ loc = self.uniforms.get(name,
+ gl.glGetUniformLocation(self.handle,name))
+ self.uniforms[name] = loc
+
+ # Upload the 4x4 floating point matrix
+ gl.glUniformMatrix4fv(loc, 1, False, (ctypes.c_float * 16)(*mat))