11import os
22from OpenGL import GL
3+ import ctypes
34
45
56class ShaderError (Exception ):
@@ -78,11 +79,13 @@ def set_source(self, source):
7879 :param source: (string) The shader source
7980 """
8081 self .set_vertex_source (source )
81- self .set_fragment_source (source )
82- # TODO: This needs to be solved in a better way
82+
8383 if 'GEOMETRY_SHADER' in source :
8484 self .set_geometry_source (source )
8585
86+ if 'FRAGMENT_SHADER' in source :
87+ self .set_fragment_source (source )
88+
8689 def set_vertex_source (self , source ):
8790 """
8891 Set the vertex shader source
@@ -117,9 +120,13 @@ def prepare(self):
117120
118121 # Compile the separate shaders
119122 self .vert_source .compile ()
120- self . frag_source . compile ()
123+
121124 if self .geo_source :
122125 self .geo_source .compile ()
126+
127+ if self .frag_source :
128+ self .frag_source .compile ()
129+
123130 self .link ()
124131
125132 # Build internal lookups
@@ -146,11 +153,36 @@ def link(self):
146153 """
147154 self .program = GL .glCreateProgram ()
148155 GL .glAttachShader (self .program , self .vert_source .shader )
156+
149157 if self .geo_source :
150158 GL .glAttachShader (self .program , self .geo_source .shader )
159+
151160 if self .frag_source :
152161 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+
153184 GL .glLinkProgram (self .program )
185+
154186 status = GL .glGetProgramiv (self .program , GL .GL_LINK_STATUS )
155187 if not status :
156188 message = GL .glGetProgramInfoLog (self .program )
@@ -781,6 +813,17 @@ def delete(self, program=None):
781813 # Now we can delete it
782814 GL .glDeleteShader (self .shader )
783815
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+
784827 def print (self ):
785828 """Print the shader lines"""
786829 print ("---[ START {} ]---" .format (self .name ))
0 commit comments