Mercurial > touhou
comparison pytouhou/ui/shader.pyx @ 424:f4d76d3d6f2a
Make the Shader class use cython too.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 16 Jul 2013 21:07:15 +0200 |
parents | pytouhou/ui/shader.py@346614f788f1 |
children | 878273a984c4 |
comparison
equal
deleted
inserted
replaced
423:d8630c086926 | 424:f4d76d3d6f2a |
---|---|
1 # -*- encoding: utf-8 -*- | |
2 # | |
3 # Copyright Tristam Macdonald 2008. | |
4 # Copyright Emmanuel Gil Peyrot 2012. | |
5 # | |
6 # Distributed under the Boost Software License, Version 1.0 | |
7 # (see http://www.boost.org/LICENSE_1_0.txt) | |
8 # | |
9 # Source: https://swiftcoder.wordpress.com/2008/12/19/simple-glsl-wrapper-for-pyglet/ | |
10 # | |
11 | |
12 from pytouhou.lib.opengl cimport \ | |
13 (glCreateProgram, glCreateShader, GL_VERTEX_SHADER, | |
14 GL_FRAGMENT_SHADER, glShaderSource, glCompileShader, glGetShaderiv, | |
15 GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH, glGetShaderInfoLog, | |
16 glAttachShader, glLinkProgram, glGetProgramiv, glGetProgramInfoLog, | |
17 GL_LINK_STATUS, glUseProgram, glGetUniformLocation, glUniform1fv, | |
18 glUniform4fv, glUniformMatrix4fv, glBindAttribLocation, GLint, | |
19 GLuint, GLchar, GLfloat, GLenum) | |
20 | |
21 from libc.stdlib cimport malloc, free | |
22 from pytouhou.utils.matrix cimport Matrix, matrix_to_floats | |
23 | |
24 | |
25 class GLSLException(Exception): | |
26 pass | |
27 | |
28 | |
29 cdef class Shader: | |
30 cdef GLuint handle | |
31 cdef bint linked | |
32 cdef dict location_cache | |
33 | |
34 # vert and frag take arrays of source strings the arrays will be | |
35 # concattenated into one string by OpenGL | |
36 def __init__(self, vert=None, frag=None): | |
37 # create the program handle | |
38 self.handle = glCreateProgram() | |
39 # we are not linked yet | |
40 self.linked = False | |
41 | |
42 # cache the uniforms location | |
43 self.location_cache = {} | |
44 | |
45 # create the vertex shader | |
46 self.create_shader(vert[0], GL_VERTEX_SHADER) | |
47 # create the fragment shader | |
48 self.create_shader(frag[0], GL_FRAGMENT_SHADER) | |
49 | |
50 #TODO: put those elsewhere. | |
51 glBindAttribLocation(self.handle, 0, 'in_position') | |
52 glBindAttribLocation(self.handle, 1, 'in_texcoord') | |
53 glBindAttribLocation(self.handle, 2, 'in_color') | |
54 | |
55 # attempt to link the program | |
56 self.link() | |
57 | |
58 cdef void create_shader(self, const GLchar *string, GLenum shader_type): | |
59 cdef GLint temp | |
60 cdef const GLchar **strings = &string | |
61 | |
62 # create the shader handle | |
63 shader = glCreateShader(shader_type) | |
64 | |
65 # upload the source strings | |
66 glShaderSource(shader, 1, strings, NULL) | |
67 | |
68 # compile the shader | |
69 glCompileShader(shader) | |
70 | |
71 # retrieve the compile status | |
72 glGetShaderiv(shader, GL_COMPILE_STATUS, &temp) | |
73 | |
74 # if compilation failed, print the log | |
75 if not temp: | |
76 # retrieve the log length | |
77 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &temp) | |
78 # create a buffer for the log | |
79 temp_buf = <GLchar*>malloc(temp * sizeof(GLchar)) | |
80 # retrieve the log text | |
81 glGetShaderInfoLog(shader, temp, NULL, temp_buf) | |
82 buf = temp_buf[:temp] | |
83 free(temp_buf) | |
84 # print the log to the console | |
85 raise GLSLException(buf) | |
86 else: | |
87 # all is well, so attach the shader to the program | |
88 glAttachShader(self.handle, shader) | |
89 | |
90 cdef void link(self): | |
91 cdef GLint temp | |
92 | |
93 # link the program | |
94 glLinkProgram(self.handle) | |
95 | |
96 # retrieve the link status | |
97 glGetProgramiv(self.handle, GL_LINK_STATUS, &temp) | |
98 | |
99 # if linking failed, print the log | |
100 if not temp: | |
101 # retrieve the log length | |
102 glGetProgramiv(self.handle, GL_INFO_LOG_LENGTH, &temp) | |
103 # create a buffer for the log | |
104 temp_buf = <GLchar*>malloc(temp * sizeof(GLchar)) | |
105 # retrieve the log text | |
106 glGetProgramInfoLog(self.handle, temp, NULL, temp_buf) | |
107 buf = temp_buf[:temp] | |
108 free(temp_buf) | |
109 # print the log to the console | |
110 raise GLSLException(buf) | |
111 else: | |
112 # all is well, so we are linked | |
113 self.linked = True | |
114 | |
115 cdef GLint get_uniform_location(self, name): | |
116 if name not in self.location_cache: | |
117 loc = glGetUniformLocation(self.handle, name) | |
118 if loc == -1: | |
119 raise GLSLException('Undefined {} uniform.'.format(name)) | |
120 self.location_cache[name] = loc | |
121 return self.location_cache[name] | |
122 | |
123 def bind(self): | |
124 # bind the program | |
125 glUseProgram(self.handle) | |
126 | |
127 # upload a floating point uniform | |
128 # this program must be currently bound | |
129 def uniform_1(self, name, GLfloat val): | |
130 glUniform1fv(self.get_uniform_location(name), 1, &val) | |
131 | |
132 # upload a vec4 uniform | |
133 def uniform_4(self, name, GLfloat a, GLfloat b, GLfloat c, GLfloat d): | |
134 cdef GLfloat vals[4] | |
135 vals[0] = a | |
136 vals[1] = b | |
137 vals[2] = c | |
138 vals[3] = d | |
139 glUniform4fv(self.get_uniform_location(name), 1, vals) | |
140 | |
141 # upload a uniform matrix | |
142 # works with matrices stored as lists, | |
143 # as well as euclid matrices | |
144 def uniform_matrix(self, name, Matrix mat): | |
145 # obtain the uniform location | |
146 loc = self.get_uniform_location(name) | |
147 # uplaod the 4x4 floating point matrix | |
148 glUniformMatrix4fv(loc, 1, False, matrix_to_floats(mat)) |