OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 import optparse | 2 import optparse |
3 import os | 3 import os |
4 import re | 4 import re |
5 import subprocess | 5 import subprocess |
6 import sys | 6 import sys |
7 | 7 |
8 # This script takes an o3d cg shader from standard input and does the following: | 8 # This script takes an o3d cg shader from standard input and does the following: |
9 # | 9 # |
10 # * it extracts entry points to vertex and fragment shaders as specified by | 10 # * it extracts entry points to vertex and fragment shaders as specified by |
(...skipping 10 matching lines...) Expand all Loading... | |
21 # * renames gl_Vertex and gl_MultiTexCoordN to position and texcoordN | 21 # * renames gl_Vertex and gl_MultiTexCoordN to position and texcoordN |
22 # respectively and adds attribute declarations; | 22 # respectively and adds attribute declarations; |
23 # | 23 # |
24 # * prints the results to standard output, separating them with SplitMarker | 24 # * prints the results to standard output, separating them with SplitMarker |
25 # instruction and keeping the MatrixLoadOrder instruction as is. | 25 # instruction and keeping the MatrixLoadOrder instruction as is. |
26 | 26 |
27 # Cygwin lies about the OS name ("posix" instead of "nt"), the line | 27 # Cygwin lies about the OS name ("posix" instead of "nt"), the line |
28 # separator, and perhaps other things. For most robust behavior, try | 28 # separator, and perhaps other things. For most robust behavior, try |
29 # to find cgc on disk. | 29 # to find cgc on disk. |
30 | 30 |
31 CGC = '/usr/bin/cgc' | 31 def find_o3d_root(): |
32 if not os.path.exists(CGC): | 32 path = os.path.abspath(sys.path[0]) |
33 CGC = 'c:/Program Files (x86)/NVIDIA Corporation/Cg/bin/cgc.exe' | 33 for i in range(0, 5): |
Alexey Marinichev
2010/04/27 21:28:16
range(5)
Ken Russell (switch to Gerrit)
2010/04/28 02:30:49
Done. Will send you a separate CL with this and th
| |
34 path = os.path.dirname(path) | |
35 if (os.path.isdir(os.path.join(path, 'o3d')) and | |
36 os.path.isdir(os.path.join(path, 'third_party'))): | |
37 return path | |
38 return '' | |
39 | |
40 def default_cgc(): | |
41 paths = [ '/usr/bin/cgc', | |
Alexey Marinichev
2010/04/27 21:28:16
Does chrome style prefer "[ x ]" over "[x]"?
Ken Russell (switch to Gerrit)
2010/04/28 02:30:49
Not sure. I'll get rid of the surrounding spaces.
| |
42 'C:/Program Files/NVIDIA Corporation/Cg/bin/cgc.exe', | |
43 'C:/Program Files (x86)/NVIDIA Corporation/Cg/bin/cgc.exe' ] | |
44 for path in paths: | |
45 if os.path.exists(path): | |
46 return path | |
47 script_path = os.path.abspath(sys.path[0]) | |
48 # Try again looking in the current working directory to match | |
49 # the layout of the prebuilt o3dConverter binaries. | |
50 cur_dir_paths = [ os.path.join(script_path, 'cgc'), | |
51 os.path.join(script_path, 'cgc.exe') ] | |
52 for path in cur_dir_paths: | |
53 if (os.path.exists(path)): | |
54 return path | |
55 | |
56 # Last fallback is to use the binaries in o3d/third_party/cg/files. | |
57 # Unfortunately, because we can't rely on the OS name, we have to | |
58 # actually try running the cgc executable. | |
59 o3d_root = find_o3d_root(); | |
60 cg_root = os.path.join(o3d_root, 'third_party', 'cg', 'files') | |
Alexey Marinichev
2010/04/27 21:28:16
'third_party/cg/files' would be more readable.
Ken Russell (switch to Gerrit)
2010/04/28 02:30:49
Unclear to me whether that is guaranteed to be fun
| |
61 exes = [ os.path.join(cg_root, 'linux', 'bin', 'cgc'), | |
62 os.path.join(cg_root, 'linux', 'bin64', 'cgc'), | |
63 os.path.join(cg_root, 'mac', 'bin', 'cgc'), | |
64 os.path.join(cg_root, 'win', 'bin', 'cgc.exe') ] | |
65 for exe in exes: | |
Alexey Marinichev
2010/04/27 21:28:16
relative_paths = ['linux/bin/cgc', ....]
for exe i
Alexey Marinichev
2010/04/27 23:24:09
Um, that's not exactly what I meant... You can ca
Ken Russell (switch to Gerrit)
2010/04/28 02:30:49
See above regarding my concern about funcional equ
| |
66 try: | |
67 subprocess.call([exe, '-v'], | |
68 stdout=open(os.devnull, 'w'), | |
69 stderr=open(os.devnull, 'w')) | |
Alexey Marinichev
2010/04/27 21:28:16
Is checking if the path exists not enough? Do you
Ken Russell (switch to Gerrit)
2010/04/28 02:30:49
Unfortunately it's not enough. All three versions
| |
70 return exe | |
71 except: | |
72 pass | |
73 | |
74 # We don't know where cgc lives. | |
75 return '' | |
76 | |
77 def check_cgc(CGC): | |
34 if not os.path.exists(CGC): | 78 if not os.path.exists(CGC): |
35 CGC = 'c:/Program Files (x86)/NVIDIA Corporation/Cg/bin/cgc.exe' | 79 print >>sys.stderr, CGC+' is not found, use --cgc option to specify its' |
36 if not os.path.exists(CGC): | 80 print >>sys.stderr, 'location. You may need to install nvidia cg toolkit.' |
37 script_path = os.path.abspath(sys.path[0]) | 81 sys.exit(1) |
38 # Try again looking in the current working directory to match | |
39 # the layout of the prebuilt o3dConverter binaries. | |
40 CGC = os.path.join(script_path, 'cgc') | |
41 if not os.path.exists(CGC): | |
42 CGC = os.path.join(script_path, 'cgc.exe') | |
43 | 82 |
44 # cgc complains about TANGENT1 and BINORMAL1 semantics, so we hack it by | 83 # cgc complains about TANGENT1 and BINORMAL1 semantics, so we hack it by |
45 # replacing standard semantics with ATTR8-ATTR12 and then renaming them back to | 84 # replacing standard semantics with ATTR8-ATTR12 and then renaming them back to |
46 # their original names. | 85 # their original names. |
47 ATTRIBUTES_TO_SEMANTICS = dict( | 86 ATTRIBUTES_TO_SEMANTICS = dict( |
48 attr8 = 'normal', | 87 attr8 = 'normal', |
49 attr9 = 'tangent', | 88 attr9 = 'tangent', |
50 attr10 = 'binormal', | 89 attr10 = 'binormal', |
51 attr11 = 'tangent1', | 90 attr11 = 'tangent1', |
52 attr12 = 'binormal1') | 91 attr12 = 'binormal1') |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 input_mapping = get_input_mapping(header) | 205 input_mapping = get_input_mapping(header) |
167 return header + '\n\n' + fix_glsl_body(body, input_mapping) | 206 return header + '\n\n' + fix_glsl_body(body, input_mapping) |
168 | 207 |
169 | 208 |
170 def cg_rename_attributes(cg_shader): | 209 def cg_rename_attributes(cg_shader): |
171 for new, old in ATTRIBUTES_TO_SEMANTICS.iteritems(): | 210 for new, old in ATTRIBUTES_TO_SEMANTICS.iteritems(): |
172 cg_shader = re.sub(r'\b%s\b' % old.upper(), new.upper(), cg_shader) | 211 cg_shader = re.sub(r'\b%s\b' % old.upper(), new.upper(), cg_shader) |
173 return cg_shader | 212 return cg_shader |
174 | 213 |
175 | 214 |
176 def cg_to_glsl(cg_shader): | 215 def cg_to_glsl(cg_shader, CGC): |
177 cg_shader = cg_rename_attributes(cg_shader) | 216 cg_shader = cg_rename_attributes(cg_shader) |
178 | 217 |
179 vertex_entry = re.search(r'#o3d\s+VertexShaderEntryPoint\s+(\w+)', | 218 vertex_entry = re.search(r'#o3d\s+VertexShaderEntryPoint\s+(\w+)', |
180 cg_shader).group(1) | 219 cg_shader).group(1) |
181 p = subprocess.Popen([CGC]+('-profile glslv -entry %s' % | 220 p = subprocess.Popen([CGC]+('-profile glslv -entry %s' % |
182 vertex_entry).split(' '), | 221 vertex_entry).split(' '), |
183 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 222 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
184 glsl_vertex, err_v = p.communicate(cg_shader) | 223 glsl_vertex, err_v = p.communicate(cg_shader) |
185 | 224 |
186 fragment_entry = re.search(r'#o3d\s+PixelShaderEntryPoint\s+(\w+)', | 225 fragment_entry = re.search(r'#o3d\s+PixelShaderEntryPoint\s+(\w+)', |
187 cg_shader).group(1) | 226 cg_shader).group(1) |
188 p = subprocess.Popen([CGC]+('-profile glslf -entry %s' % | 227 p = subprocess.Popen([CGC]+('-profile glslf -entry %s' % |
189 fragment_entry).split(' '), | 228 fragment_entry).split(' '), |
190 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 229 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
191 glsl_fragment, err_f = p.communicate(cg_shader) | 230 glsl_fragment, err_f = p.communicate(cg_shader) |
192 | 231 |
193 log = ( | 232 log = ( |
194 '// glslv profile log:\n' + | 233 '// glslv profile log:\n' + |
195 '\n'.join('// ' + l for l in err_v.splitlines()) + '\n\n' | 234 '\n'.join('// ' + l for l in err_v.splitlines()) + '\n\n' |
196 '// glslf profile log:\n' + | 235 '// glslf profile log:\n' + |
197 '\n'.join('// ' + l for l in err_f.splitlines())) + '\n' | 236 '\n'.join('// ' + l for l in err_f.splitlines())) + '\n' |
198 | 237 |
199 return glsl_vertex, glsl_fragment, log | 238 return glsl_vertex, glsl_fragment, log |
200 | 239 |
201 | 240 |
202 def get_matrixloadorder(cg_shader): | 241 def get_matrixloadorder(cg_shader): |
203 return re.search(r'(?m)^.*#o3d\s+MatrixLoadOrder\b.*$', cg_shader).group(0) | 242 return re.search(r'(?m)^.*#o3d\s+MatrixLoadOrder\b.*$', cg_shader).group(0) |
204 | 243 |
205 | 244 |
206 def check_cg(): | 245 def main(cg_shader, CGC): |
Alexey Marinichev
2010/04/27 21:28:16
I used all caps CGC to show it's a constant that's
Ken Russell (switch to Gerrit)
2010/04/28 02:30:49
I like to avoid globals so I've changed it to cgc_
| |
207 if not os.path.exists(CGC): | |
208 print >>sys.stderr, CGC+' is not found, use --cgc option to specify its' | |
209 print >>sys.stderr, 'location. You may need to install nvidia cg toolkit.' | |
210 sys.exit(1) | |
211 | |
212 | |
213 def main(cg_shader): | |
214 matrixloadorder = get_matrixloadorder(cg_shader) | 246 matrixloadorder = get_matrixloadorder(cg_shader) |
215 glsl_vertex, glsl_fragment, log = cg_to_glsl(cg_shader) | 247 glsl_vertex, glsl_fragment, log = cg_to_glsl(cg_shader, CGC) |
216 | 248 |
217 print log | 249 print log |
218 print fix_glsl(glsl_vertex) | 250 print fix_glsl(glsl_vertex) |
219 print | 251 print |
220 print '// #o3d SplitMarker' | 252 print '// #o3d SplitMarker' |
221 print get_matrixloadorder(cg_shader).strip() | 253 print get_matrixloadorder(cg_shader).strip() |
222 print | 254 print |
223 print fix_glsl(glsl_fragment) | 255 print fix_glsl(glsl_fragment) |
224 | 256 |
225 | 257 |
226 if __name__ == '__main__': | 258 if __name__ == '__main__': |
259 CGC = default_cgc() | |
227 cmdline_parser = optparse.OptionParser() | 260 cmdline_parser = optparse.OptionParser() |
228 cmdline_parser.add_option('-i', dest='file', default=None, | 261 cmdline_parser.add_option('-i', dest='file', default=None, |
229 help='input shader; standard input if omitted') | 262 help='input shader; standard input if omitted') |
230 cmdline_parser.add_option('--cgc', dest='CGC', default=CGC, | 263 cmdline_parser.add_option('--cgc', dest='CGC', default=CGC, |
231 help='path to cgc [default: %default]') | 264 help='path to cgc [default: %default]') |
232 options, args = cmdline_parser.parse_args() | 265 options, args = cmdline_parser.parse_args() |
233 CGC = options.CGC | 266 CGC = options.CGC |
234 check_cg() | 267 check_cgc(CGC) |
235 | 268 |
236 try: | 269 try: |
237 if options.file is None: | 270 if options.file is None: |
238 f = sys.stdin | 271 f = sys.stdin |
239 else: | 272 else: |
240 f = open(options.file) | 273 f = open(options.file) |
241 input = f.read() | 274 input = f.read() |
242 except KeyboardInterrupt: | 275 except KeyboardInterrupt: |
243 input = None | 276 input = None |
244 | 277 |
245 if not input: | 278 if not input: |
246 cmdline_parser.print_help() | 279 cmdline_parser.print_help() |
247 else: | 280 else: |
248 main(input) | 281 main(input, CGC) |
OLD | NEW |