Mercurial > touhou
comparison pytouhou/ui/opengl/shader.pyx @ 513:5e3e0b09a531
Move the OpenGL backend to its own package.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Thu, 05 Dec 2013 02:16:31 +0100 |
parents | pytouhou/ui/shader.pyx@1b56d62250ab |
children | 6e3b3d5d4691 |
comparison
equal
deleted
inserted
replaced
512:b39ad30c6620 | 513:5e3e0b09a531 |
---|---|
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) | |
19 | |
20 from libc.stdlib cimport malloc, free | |
21 | |
22 | |
23 class GLSLException(Exception): | |
24 pass | |
25 | |
26 | |
27 cdef class Shader: | |
28 # vert and frag take arrays of source strings the arrays will be | |
29 # concattenated into one string by OpenGL | |
30 def __init__(self, vert=None, frag=None): | |
31 # create the program handle | |
32 self.handle = glCreateProgram() | |
33 # we are not linked yet | |
34 self.linked = False | |
35 | |
36 # cache the uniforms location | |
37 self.location_cache = {} | |
38 | |
39 # create the vertex shader | |
40 self.create_shader(vert[0], GL_VERTEX_SHADER) | |
41 # create the fragment shader | |
42 self.create_shader(frag[0], GL_FRAGMENT_SHADER) | |
43 | |
44 #TODO: put those elsewhere. | |
45 glBindAttribLocation(self.handle, 0, 'in_position') | |
46 glBindAttribLocation(self.handle, 1, 'in_texcoord') | |
47 glBindAttribLocation(self.handle, 2, 'in_color') | |
48 | |
49 # attempt to link the program | |
50 self.link() | |
51 | |
52 cdef void create_shader(self, const GLchar *string, GLenum shader_type): | |
53 cdef GLint temp | |
54 cdef const GLchar **strings = &string | |
55 | |
56 # create the shader handle | |
57 shader = glCreateShader(shader_type) | |
58 | |
59 # upload the source strings | |
60 glShaderSource(shader, 1, strings, NULL) | |
61 | |
62 # compile the shader | |
63 glCompileShader(shader) | |
64 | |
65 # retrieve the compile status | |
66 glGetShaderiv(shader, GL_COMPILE_STATUS, &temp) | |
67 | |
68 # if compilation failed, print the log | |
69 if not temp: | |
70 # retrieve the log length | |
71 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &temp) | |
72 # create a buffer for the log | |
73 temp_buf = <GLchar*>malloc(temp * sizeof(GLchar)) | |
74 # retrieve the log text | |
75 glGetShaderInfoLog(shader, temp, NULL, temp_buf) | |
76 buf = temp_buf[:temp] | |
77 free(temp_buf) | |
78 # print the log to the console | |
79 raise GLSLException(buf) | |
80 else: | |
81 # all is well, so attach the shader to the program | |
82 glAttachShader(self.handle, shader) | |
83 | |
84 cdef void link(self): | |
85 cdef GLint temp | |
86 | |
87 # link the program | |
88 glLinkProgram(self.handle) | |
89 | |
90 # retrieve the link status | |
91 glGetProgramiv(self.handle, GL_LINK_STATUS, &temp) | |
92 | |
93 # if linking failed, print the log | |
94 if not temp: | |
95 # retrieve the log length | |
96 glGetProgramiv(self.handle, GL_INFO_LOG_LENGTH, &temp) | |
97 # create a buffer for the log | |
98 temp_buf = <GLchar*>malloc(temp * sizeof(GLchar)) | |
99 # retrieve the log text | |
100 glGetProgramInfoLog(self.handle, temp, NULL, temp_buf) | |
101 buf = temp_buf[:temp] | |
102 free(temp_buf) | |
103 # print the log to the console | |
104 raise GLSLException(buf) | |
105 else: | |
106 # all is well, so we are linked | |
107 self.linked = True | |
108 | |
109 cdef GLint get_uniform_location(self, name): | |
110 if name not in self.location_cache: | |
111 loc = glGetUniformLocation(self.handle, name) | |
112 if loc == -1: | |
113 raise GLSLException('Undefined {} uniform.'.format(name)) | |
114 self.location_cache[name] = loc | |
115 return self.location_cache[name] | |
116 | |
117 cdef void bind(self) nogil: | |
118 # bind the program | |
119 glUseProgram(self.handle) | |
120 | |
121 # upload a floating point uniform | |
122 # this program must be currently bound | |
123 cdef void uniform_1(self, name, GLfloat val): | |
124 glUniform1fv(self.get_uniform_location(name), 1, &val) | |
125 | |
126 # upload a vec4 uniform | |
127 cdef void uniform_4(self, name, GLfloat a, GLfloat b, GLfloat c, GLfloat d): | |
128 cdef GLfloat vals[4] | |
129 vals[0] = a | |
130 vals[1] = b | |
131 vals[2] = c | |
132 vals[3] = d | |
133 glUniform4fv(self.get_uniform_location(name), 1, vals) | |
134 | |
135 # upload a uniform matrix | |
136 # works with matrices stored as lists, | |
137 # as well as euclid matrices | |
138 cdef void uniform_matrix(self, name, Matrix mat): | |
139 # obtain the uniform location | |
140 loc = self.get_uniform_location(name) | |
141 # uplaod the 4x4 floating point matrix | |
142 glUniformMatrix4fv(loc, 1, False, mat.data) |