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 12 matching lines...) Expand all Loading... |
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 def find_o3d_root(): | 31 def find_o3d_root(): |
32 path = os.path.abspath(sys.path[0]) | 32 path = os.path.abspath(sys.path[0]) |
33 for i in range(0, 5): | 33 for i in range(5): |
34 path = os.path.dirname(path) | 34 path = os.path.dirname(path) |
35 if (os.path.isdir(os.path.join(path, 'o3d')) and | 35 if (os.path.isdir(os.path.join(path, 'o3d')) and |
36 os.path.isdir(os.path.join(path, 'third_party'))): | 36 os.path.isdir(os.path.join(path, 'third_party'))): |
37 return path | 37 return path |
38 return '' | 38 return '' |
39 | 39 |
40 def default_cgc(): | 40 def default_cgc(): |
41 paths = [ '/usr/bin/cgc', | 41 paths = ['/usr/bin/cgc', |
42 'C:/Program Files/NVIDIA Corporation/Cg/bin/cgc.exe', | 42 'C:/Program Files/NVIDIA Corporation/Cg/bin/cgc.exe', |
43 'C:/Program Files (x86)/NVIDIA Corporation/Cg/bin/cgc.exe' ] | 43 'C:/Program Files (x86)/NVIDIA Corporation/Cg/bin/cgc.exe'] |
44 for path in paths: | 44 for path in paths: |
45 if os.path.exists(path): | 45 if os.path.exists(path): |
46 return path | 46 return path |
47 script_path = os.path.abspath(sys.path[0]) | 47 script_path = os.path.abspath(sys.path[0]) |
48 # Try again looking in the current working directory to match | 48 # Try again looking in the current working directory to match |
49 # the layout of the prebuilt o3dConverter binaries. | 49 # the layout of the prebuilt o3dConverter binaries. |
50 cur_dir_paths = [ os.path.join(script_path, 'cgc'), | 50 cur_dir_paths = [os.path.join(script_path, 'cgc'), |
51 os.path.join(script_path, 'cgc.exe') ] | 51 os.path.join(script_path, 'cgc.exe')] |
52 for path in cur_dir_paths: | 52 for path in cur_dir_paths: |
53 if (os.path.exists(path)): | 53 if (os.path.exists(path)): |
54 return path | 54 return path |
55 | 55 |
56 # Last fallback is to use the binaries in o3d/third_party/cg/files. | 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 | 57 # Unfortunately, because we can't rely on the OS name, we have to |
58 # actually try running the cgc executable. | 58 # actually try running the cgc executable. |
59 o3d_root = find_o3d_root(); | 59 o3d_root = find_o3d_root(); |
60 cg_root = os.path.join(o3d_root, 'third_party', 'cg', 'files') | 60 cg_root = os.path.join(o3d_root, 'third_party', 'cg', 'files') |
61 exes = [ os.path.join(cg_root, 'linux', 'bin', 'cgc'), | 61 exe_paths = ['linux/bin/cgc', |
62 os.path.join(cg_root, 'linux', 'bin64', 'cgc'), | 62 'linux/bin64/cgc', |
63 os.path.join(cg_root, 'mac', 'bin', 'cgc'), | 63 'mac/bin/cgc', |
64 os.path.join(cg_root, 'win', 'bin', 'cgc.exe') ] | 64 'win/bin/cgc.exe'] |
65 for exe in exes: | 65 for exe_path in exe_paths: |
66 try: | 66 try: |
67 subprocess.call([exe, '-v'], | 67 exe = os.path.join(cg_root, exe_path) |
68 stdout=open(os.devnull, 'w'), | 68 return_code = subprocess.call([exe, '-v'], |
69 stderr=open(os.devnull, 'w')) | 69 stdout=open(os.devnull, 'w'), |
70 return exe | 70 stderr=open(os.devnull, 'w')) |
| 71 if return_code == 0 or return_code == 1: |
| 72 return exe |
71 except: | 73 except: |
72 pass | 74 pass |
73 | 75 |
74 # We don't know where cgc lives. | 76 # We don't know where cgc lives. |
75 return '' | 77 return '' |
76 | 78 |
77 def check_cgc(CGC): | 79 def check_cgc(cgc_path): |
78 if not os.path.exists(CGC): | 80 if not os.path.exists(cgc_path): |
79 print >>sys.stderr, CGC+' is not found, use --cgc option to specify its' | 81 print >>sys.stderr, (cgc_path + |
| 82 ' is not found, use --cgc option to specify its') |
80 print >>sys.stderr, 'location. You may need to install nvidia cg toolkit.' | 83 print >>sys.stderr, 'location. You may need to install nvidia cg toolkit.' |
81 sys.exit(1) | 84 sys.exit(1) |
82 | 85 |
83 # cgc complains about TANGENT1 and BINORMAL1 semantics, so we hack it by | 86 # cgc complains about TANGENT1 and BINORMAL1 semantics, so we hack it by |
84 # replacing standard semantics with ATTR8-ATTR12 and then renaming them back to | 87 # replacing standard semantics with ATTR8-ATTR12 and then renaming them back to |
85 # their original names. | 88 # their original names. |
86 ATTRIBUTES_TO_SEMANTICS = dict( | 89 ATTRIBUTES_TO_SEMANTICS = dict( |
87 attr8 = 'normal', | 90 attr8 = 'normal', |
88 attr9 = 'tangent', | 91 attr9 = 'tangent', |
89 attr10 = 'binormal', | 92 attr10 = 'binormal', |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 input_mapping = get_input_mapping(header) | 208 input_mapping = get_input_mapping(header) |
206 return header + '\n\n' + fix_glsl_body(body, input_mapping) | 209 return header + '\n\n' + fix_glsl_body(body, input_mapping) |
207 | 210 |
208 | 211 |
209 def cg_rename_attributes(cg_shader): | 212 def cg_rename_attributes(cg_shader): |
210 for new, old in ATTRIBUTES_TO_SEMANTICS.iteritems(): | 213 for new, old in ATTRIBUTES_TO_SEMANTICS.iteritems(): |
211 cg_shader = re.sub(r'\b%s\b' % old.upper(), new.upper(), cg_shader) | 214 cg_shader = re.sub(r'\b%s\b' % old.upper(), new.upper(), cg_shader) |
212 return cg_shader | 215 return cg_shader |
213 | 216 |
214 | 217 |
215 def cg_to_glsl(cg_shader, CGC): | 218 def cg_to_glsl(cg_shader, cgc_path): |
216 cg_shader = cg_rename_attributes(cg_shader) | 219 cg_shader = cg_rename_attributes(cg_shader) |
217 | 220 |
218 vertex_entry = re.search(r'#o3d\s+VertexShaderEntryPoint\s+(\w+)', | 221 vertex_entry = re.search(r'#o3d\s+VertexShaderEntryPoint\s+(\w+)', |
219 cg_shader).group(1) | 222 cg_shader).group(1) |
220 p = subprocess.Popen([CGC]+('-profile glslv -entry %s' % | 223 p = subprocess.Popen([cgc_path]+('-profile glslv -entry %s' % |
221 vertex_entry).split(' '), | 224 vertex_entry).split(' '), |
222 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 225 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
223 glsl_vertex, err_v = p.communicate(cg_shader) | 226 glsl_vertex, err_v = p.communicate(cg_shader) |
224 | 227 |
225 fragment_entry = re.search(r'#o3d\s+PixelShaderEntryPoint\s+(\w+)', | 228 fragment_entry = re.search(r'#o3d\s+PixelShaderEntryPoint\s+(\w+)', |
226 cg_shader).group(1) | 229 cg_shader).group(1) |
227 p = subprocess.Popen([CGC]+('-profile glslf -entry %s' % | 230 p = subprocess.Popen([cgc_path]+('-profile glslf -entry %s' % |
228 fragment_entry).split(' '), | 231 fragment_entry).split(' '), |
229 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 232 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
230 glsl_fragment, err_f = p.communicate(cg_shader) | 233 glsl_fragment, err_f = p.communicate(cg_shader) |
231 | 234 |
232 log = ( | 235 log = ( |
233 '// glslv profile log:\n' + | 236 '// glslv profile log:\n' + |
234 '\n'.join('// ' + l for l in err_v.splitlines()) + '\n\n' | 237 '\n'.join('// ' + l for l in err_v.splitlines()) + '\n\n' |
235 '// glslf profile log:\n' + | 238 '// glslf profile log:\n' + |
236 '\n'.join('// ' + l for l in err_f.splitlines())) + '\n' | 239 '\n'.join('// ' + l for l in err_f.splitlines())) + '\n' |
237 | 240 |
238 return glsl_vertex, glsl_fragment, log | 241 return glsl_vertex, glsl_fragment, log |
239 | 242 |
240 | 243 |
241 def get_matrixloadorder(cg_shader): | 244 def get_matrixloadorder(cg_shader): |
242 return re.search(r'(?m)^.*#o3d\s+MatrixLoadOrder\b.*$', cg_shader).group(0) | 245 return re.search(r'(?m)^.*#o3d\s+MatrixLoadOrder\b.*$', cg_shader).group(0) |
243 | 246 |
244 | 247 |
245 def main(cg_shader, CGC): | 248 def main(cg_shader, cgc_path): |
246 matrixloadorder = get_matrixloadorder(cg_shader) | 249 matrixloadorder = get_matrixloadorder(cg_shader) |
247 glsl_vertex, glsl_fragment, log = cg_to_glsl(cg_shader, CGC) | 250 glsl_vertex, glsl_fragment, log = cg_to_glsl(cg_shader, cgc_path) |
248 | 251 |
249 print log | 252 print log |
250 print fix_glsl(glsl_vertex) | 253 print fix_glsl(glsl_vertex) |
251 print | 254 print |
252 print '// #o3d SplitMarker' | 255 print '// #o3d SplitMarker' |
253 print get_matrixloadorder(cg_shader).strip() | 256 print get_matrixloadorder(cg_shader).strip() |
254 print | 257 print |
255 print fix_glsl(glsl_fragment) | 258 print fix_glsl(glsl_fragment) |
256 | 259 |
257 | 260 |
258 if __name__ == '__main__': | 261 if __name__ == '__main__': |
259 CGC = default_cgc() | 262 cgc_path = default_cgc() |
260 cmdline_parser = optparse.OptionParser() | 263 cmdline_parser = optparse.OptionParser() |
261 cmdline_parser.add_option('-i', dest='file', default=None, | 264 cmdline_parser.add_option('-i', dest='file', default=None, |
262 help='input shader; standard input if omitted') | 265 help='input shader; standard input if omitted') |
263 cmdline_parser.add_option('--cgc', dest='CGC', default=CGC, | 266 cmdline_parser.add_option('--cgc', dest='cgc_path', default=cgc_path, |
264 help='path to cgc [default: %default]') | 267 help='path to cgc [default: %default]') |
265 options, args = cmdline_parser.parse_args() | 268 options, args = cmdline_parser.parse_args() |
266 CGC = options.CGC | 269 cgc_path = options.cgc_path |
267 check_cgc(CGC) | 270 check_cgc(cgc_path) |
268 | 271 |
269 try: | 272 try: |
270 if options.file is None: | 273 if options.file is None: |
271 f = sys.stdin | 274 f = sys.stdin |
272 else: | 275 else: |
273 f = open(options.file) | 276 f = open(options.file) |
274 input = f.read() | 277 input = f.read() |
275 except KeyboardInterrupt: | 278 except KeyboardInterrupt: |
276 input = None | 279 input = None |
277 | 280 |
278 if not input: | 281 if not input: |
279 cmdline_parser.print_help() | 282 cmdline_parser.print_help() |
280 else: | 283 else: |
281 main(input, CGC) | 284 main(input, cgc_path) |
OLD | NEW |