1
1
import os
2
2
from OpenGL import GL
3
+ import ctypes
3
4
4
5
5
6
class ShaderError (Exception ):
@@ -78,11 +79,13 @@ def set_source(self, source):
78
79
:param source: (string) The shader source
79
80
"""
80
81
self .set_vertex_source (source )
81
- self .set_fragment_source (source )
82
- # TODO: This needs to be solved in a better way
82
+
83
83
if 'GEOMETRY_SHADER' in source :
84
84
self .set_geometry_source (source )
85
85
86
+ if 'FRAGMENT_SHADER' in source :
87
+ self .set_fragment_source (source )
88
+
86
89
def set_vertex_source (self , source ):
87
90
"""
88
91
Set the vertex shader source
@@ -117,9 +120,13 @@ def prepare(self):
117
120
118
121
# Compile the separate shaders
119
122
self .vert_source .compile ()
120
- self . frag_source . compile ()
123
+
121
124
if self .geo_source :
122
125
self .geo_source .compile ()
126
+
127
+ if self .frag_source :
128
+ self .frag_source .compile ()
129
+
123
130
self .link ()
124
131
125
132
# Build internal lookups
@@ -146,11 +153,36 @@ def link(self):
146
153
"""
147
154
self .program = GL .glCreateProgram ()
148
155
GL .glAttachShader (self .program , self .vert_source .shader )
156
+
149
157
if self .geo_source :
150
158
GL .glAttachShader (self .program , self .geo_source .shader )
159
+
151
160
if self .frag_source :
152
161
GL .glAttachShader (self .program , self .frag_source .shader )
162
+
163
+ # If no fragment shader is present we are dealing with transform feedback
164
+ if not self .frag_source :
165
+ # Find out attributes
166
+ # Out attribs is present in geometry shader if present
167
+ if self .geo_source :
168
+ out_attribs = self .geo_source .find_out_attribs ()
169
+ # Otherwise they are specified in vertex shader
170
+ else :
171
+ out_attribs = self .vert_source .find_out_attribs ()
172
+
173
+ print ("Transform feedback attribs:" , out_attribs )
174
+
175
+ # Prepare ctypes data containing attrib names
176
+ array_type = ctypes .c_char_p * len (out_attribs )
177
+ buff = array_type ()
178
+ for i , e in enumerate (out_attribs ):
179
+ buff [i ] = e .encode ()
180
+
181
+ c_text = ctypes .cast (ctypes .pointer (buff ), ctypes .POINTER (ctypes .POINTER (GL .GLchar )))
182
+ GL .glTransformFeedbackVaryings (self .program , len (out_attribs ), c_text , GL .GL_INTERLEAVED_ATTRIBS )
183
+
153
184
GL .glLinkProgram (self .program )
185
+
154
186
status = GL .glGetProgramiv (self .program , GL .GL_LINK_STATUS )
155
187
if not status :
156
188
message = GL .glGetProgramInfoLog (self .program )
@@ -781,6 +813,17 @@ def delete(self, program=None):
781
813
# Now we can delete it
782
814
GL .glDeleteShader (self .shader )
783
815
816
+ def find_out_attribs (self ):
817
+ """
818
+ Get all out attributes in the shader source.
819
+ :return: List of attribute names
820
+ """
821
+ names = []
822
+ for line in self .lines :
823
+ if line .strip ().startswith ("out " ):
824
+ names .append (line .split ()[2 ].replace (';' , '' ))
825
+ return names
826
+
784
827
def print (self ):
785
828
"""Print the shader lines"""
786
829
print ("---[ START {} ]---" .format (self .name ))
0 commit comments