Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: cg_to_glsl/convert.py

Issue 1595017: A simple script to convert o3d cg shaders to glsl. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:executable
+ *
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 #!/usr/bin/python
2 import optparse
3 import os
4 import re
5 import subprocess
6 import sys
7
8 # This script takes an o3d cg shader from standard input and does the following:
9 #
10 # * it extracts entry points to vertex and fragment shaders as specified by
11 # VertexShaderEntryPoint and PixelShaderEntryPoint instructions;
12 #
13 # * renames NORMAL, TANGENT{,1} and BINORMAL{,1} attributes to ATTR8-12;
14 #
15 # * runs cgc with glslv and glslf profiles with those entry points;
16 #
17 # * renames attributes and uniforms back to their orignal names;
18 #
19 # * changes 'uniform vecN var[N]' to 'uniform matN var';
20 #
21 # * renames gl_Vertex and gl_MultiTexCoordN to position and texcoordsN
22 # respectively and adds attribute declarations;
23 #
24 # * prints the results to standard output, separating them with SplitMarker
25 # instruction and keeping the MatrixLoadOrder instruction as is.
26
27
28 CGC = '/usr/bin/cgc'
29
30 # cgc complains about TANGENT1 and BINORMAL1 semantics, so we hack it by
31 # replacing standard semantics with ATTR8-ATTR12 and then renaming them back to
32 # their original names.
33 ATTRIBUTES_TO_SEMANTICS = dict(
34 attr8 = 'normal',
35 attr9 = 'tangent',
36 attr10 = 'binormal',
37 attr11 = 'tangent1',
38 attr12 = 'binormal1')
39
40
41 def get_input_mapping(header):
42 ret = dict()
43 for l in header.splitlines():
44 if not l.startswith('//var'):
45 continue
46 old_name_and_type, semantic, new_name, _, _ = l.split(' : ')
47 if '[' in new_name:
48 new_name = new_name[:new_name.index('[')]
49 if new_name.startswith('$'):
50 new_name = new_name[1:]
51 ret[new_name] = (semantic.lower() if semantic
52 else old_name_and_type.split(' ')[2])
53 return ret
54
55
56 def fix_glsl_body(body, input_mapping):
57 # Change uniform names back to original.
58 for match in re.findall(r'(?m)^uniform (?:\w+) (\w+)', body):
59 body = re.sub(r'\b%s\b' % match, input_mapping[match], body)
60
61 # Change attribute names back to original.
62 for match in re.findall(r'(?m)^attribute (?:\w+) (\w+)', body):
63 attr_name = input_mapping[match]
64 assert attr_name.startswith('$vin.')
65 orig_name = ATTRIBUTES_TO_SEMANTICS[attr_name[len('$vin.'):]]
66 body = re.sub(r'\b%s\b' % match, orig_name, body)
67
68 # Change vecN blah[N]; to matN blah;
69 body = re.sub(r'(?m)^uniform vec(\d) (\w+)\[\1\];', r'uniform mat\1 \2;',
70 body)
71
72 attributes = []
73 if 'gl_Vertex' in body:
74 # Change gl_Vertex to position and add attribute declaration.
75 body = re.sub(r'\bgl_Vertex\b', 'position', body)
76 attributes.append('attribute vec4 position;')
77
78 for n in xrange(8):
79 if 'gl_MultiTexCoord%d' % n in body:
80 # Change gl_MultiTexCoordN (0<=N<=7) to texcoordsN and add attribute
81 # declaration.
82 body = re.sub(r'\bgl_MultiTexCoord%d\b' % n, 'texcoords%d' % n, body)
83 attributes.append('attribute vec4 texcoords%d;' % n)
84
85 # ATTRIBUTES_TO_SEMANTICS should have taken care of normals.
86 assert 'gl_Normal' not in body
87
88 return '\n'.join(attributes) + '\n\n' + body
89
90
91 def fix_glsl(glsl_shader):
92 header, body = re.split(r'\n\n', glsl_shader, 1)
93 assert all(l.startswith('//') for l in header.splitlines())
94 input_mapping = get_input_mapping(header)
95 return header + '\n\n' + fix_glsl_body(body, input_mapping)
96
97
98 def cg_rename_attributes(cg_shader):
99 for new, old in ATTRIBUTES_TO_SEMANTICS.iteritems():
100 cg_shader = re.sub(r'\b%s\b' % old.upper(), new.upper(), cg_shader)
101 return cg_shader
102
103
104 def cg_to_glsl(cg_shader):
105 cg_shader = cg_rename_attributes(cg_shader)
106
107 vertex_entry = re.search(r'#o3d\s+VertexShaderEntryPoint\s+(\w+)',
108 cg_shader).group(1)
109 p = subprocess.Popen(CGC+' -profile glslv -entry %s' % vertex_entry,
110 shell=True,
111 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
112 glsl_vertex, err_v = p.communicate(cg_shader)
113
114 fragment_entry = re.search(r'#o3d\s+PixelShaderEntryPoint\s+(\w+)',
115 cg_shader).group(1)
116 p = subprocess.Popen(CGC+' -profile glslf -entry %s' % fragment_entry,
117 shell=True,
118 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
119 glsl_fragment, err_f = p.communicate(cg_shader)
120
121 log = (
122 '// glslv profile log:\n' +
123 '\n'.join('// ' + l for l in err_v.splitlines()) + '\n\n'
124 '// glslf profile log:\n' +
125 '\n'.join('// ' + l for l in err_f.splitlines())) + '\n'
126
127 return glsl_vertex, glsl_fragment, log
128
129
130 def get_matrixloadorder(cg_shader):
131 return re.search(r'(?m)^.*#o3d\s+MatrixLoadOrder\b.*$', cg_shader).group(0)
132
133
134 def check_cg():
135 if not os.path.exists(CGC):
136 print >>sys.stderr, CGC+' is not found, use --cgc option to specify its'
137 print >>sys.stderr, 'location. You may need to install nvidia cg toolkit.'
138 print >>sys.stderr, 'In Ubuntu distribution it can be done by running:'
139 print >>sys.stderr, ' "apt-get install nvidia-cg-toolkit"'
140 sys.exit(1)
141
142
143 def main(cg_shader):
144 matrixloadorder = get_matrixloadorder(cg_shader)
145 glsl_vertex, glsl_fragment, log = cg_to_glsl(cg_shader)
146
147 print log
148 print fix_glsl(glsl_vertex)
149 print
150 print '// #o3d SplitMarker'
151 print get_matrixloadorder(cg_shader).strip()
152 print
153 print fix_glsl(glsl_fragment)
154
155
156 if __name__ == '__main__':
157 cmdline_parser = optparse.OptionParser()
158 cmdline_parser.add_option('--cgc', dest='CGC', default='/usr/bin/cgc',
159 help='path to cgc [default: %default]')
160 options, args = cmdline_parser.parse_args()
161 CGC = options.CGC
162 check_cg()
163
164 try:
165 input = sys.stdin.read()
166 except KeyboardInterrupt:
167 input = None
168
169 if not input:
170 cmdline_parser.print_help()
171 else:
172 main(input)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698