Skip to content

Commit 7658abf

Browse files
committed
Automatically parse/pass in transform feedback attributes to shader program
1 parent 3aea144 commit 7658abf

File tree

1 file changed

+46
-3
lines changed

1 file changed

+46
-3
lines changed

demosys/opengl/shader.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
from OpenGL import GL
3+
import ctypes
34

45

56
class 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

Comments
 (0)