]> git.tdb.fi Git - libs/gl.git/blob - blender/io_mspgl/export_material.py
36dbdc690696346b544e2e367518859df60da693
[libs/gl.git] / blender / io_mspgl / export_material.py
1 def create_shadow_method(tech_res, material, resources, detail):
2         from .datafile import Statement
3
4         color_prop = next((p for p in material.properties if p.keyword and "color" in p.keyword), None)
5
6         st = Statement("method", "shadow"+detail)
7         if material.alpha_cutoff>0.0 and color_prop and 'A' in color_prop.tex_channels:
8                 st.sub.append(tech_res.create_reference_statement("shader", resources["occluder{}_masked.shader".format(detail)]))
9                 ss = Statement("texture", "alpha_map")
10
11                 from .export_texture import TextureExporter
12                 from .export_texture import SamplerExporter
13                 texture_export = TextureExporter()
14                 sampler_export = SamplerExporter()
15
16                 tex_res = resources[texture_export.get_texture_name(color_prop.texture, color_prop.tex_channels)]
17                 ss.sub.append(tech_res.create_reference_statement("texture", tex_res))
18                 ss.sub.append(tech_res.create_reference_statement("sampler", resources[sampler_export.get_sampler_name(color_prop.texture)]))
19                 st.sub.append(ss)
20
21                 ss = Statement("uniforms")
22                 ss.sub.append(Statement("uniform", "alpha_cutoff", material.alpha_cutoff))
23                 st.sub.append(ss)
24         else:
25                 st.sub.append(Statement("shader", "occluder{}.glsl.shader".format(detail)))
26
27         return st;
28
29 def create_technique_resource(material, resources):
30         from .datafile import Resource, Statement, Token
31         tech_res = Resource(material.name+".tech", "technique")
32
33         mat_res = resources[material.name+".mat"]
34
35         blend_st = None
36         if material.blend_type=='ALPHA':
37                 blend_st = Statement("blend", Token("SRC_ALPHA"), Token("ONE_MINUS_SRC_ALPHA"))
38         elif material.blend_type=='ADDITIVE':
39                 blend_st = Statement("blend", Token("ONE"), Token("ONE"))
40         elif material.blend_type=='ADDITIVE_ALPHA':
41                 blend_st = Statement("blend", Token("SRC_ALPHA"), Token("ONE"))
42
43         if material.render_mode=='CUSTOM':
44                 for m in material.render_methods:
45                         st = Statement("method", m.tag)
46                         if mat_res and m.use_material:
47                                 st.sub.append(tech_res.create_reference_statement("material", mat_res))
48
49                         if m.tag=="blended" and blend_st:
50                                 st.sub.append(blend_st)
51
52                         shader = m.shader
53                         if shader.endswith(".glsl"):
54                                 shader += ".shader"
55                         st.sub.append(Statement("shader", shader))
56
57                         if material.uniforms:
58                                 ss = Statement("uniforms")
59                                 for u in material.uniforms:
60                                         ss.sub.append(Statement("uniform", u.name, *u.values[:u.size]))
61                                 st.sub.append(ss)
62
63                         tech_res.statements.append(st)
64         else:
65                 base_method = "blended" if material.blend_type!='NONE' else ""
66                 st = Statement("method", base_method)
67                 if mat_res:
68                         st.sub.append(tech_res.create_embed_statement("material", mat_res))
69
70                 if blend_st:
71                         st.sub.append(blend_st)
72                 if material.receive_shadows:
73                         st.sub.append(Statement("receive_shadows", True))
74                 if material.image_based_lighting:
75                         st.sub.append(Statement("image_based_lighting", True))
76
77                 tech_res.statements.append(st)
78
79                 if material.cast_shadows:
80                         tech_res.statements.append(create_shadow_method(tech_res, material, resources, ""));
81                         tech_res.statements.append(create_shadow_method(tech_res, material, resources, "_thsm"));
82
83         return tech_res
84
85 class MaterialExporter:
86         def export_technique_resources(self, ctx, material, resources):
87                 from .export_texture import SamplerExporter, TextureExporter
88                 texture_export = TextureExporter()
89                 sampler_export = SamplerExporter()
90
91                 from .material import Material
92                 if type(material)!=Material:
93                         material = Material(material)
94
95                 textured_props = [p for p in material.properties if p.texture]
96
97                 ctx.set_slices(len(textured_props)+1)
98                 for p in textured_props:
99                         ctx.next_slice(p.texture.image)
100
101                         tex_name = texture_export.get_texture_name(p.texture, p.tex_channels)
102                         if tex_name not in resources:
103                                 resources[tex_name] = texture_export.export_texture(p.texture, p.tex_channels)
104
105                         samp_name = sampler_export.get_sampler_name(p.texture)
106                         if samp_name not in resources:
107                                 resources[samp_name] = sampler_export.export_sampler(p.texture)
108
109                 ctx.next_slice(material)
110                 mat_name = material.name+".mat"
111                 if mat_name not in resources:
112                         if material.type:
113                                 resources[mat_name] = self.export_material(material, resources)
114                         else:
115                                 resources[mat_name] = None
116
117                 if material.cast_shadows and material.alpha_cutoff>0.0:
118                         for detail in ("", "_thsm"):
119                                 shader_name = "occluder{}_masked.shader".format(detail)
120                                 if shader_name not in resources:
121                                         resources[shader_name] = self.export_shader(shader_name, "occluder{}.glsl".format(detail), {"use_alpha_cutoff":True}, resources)
122
123         def export_technique(self, material, resources):
124                 from .material import Material
125                 if type(material)!=Material:
126                         material = Material(material)
127
128                 return create_technique_resource(material, resources)
129
130         def export_material(self, material, resources):
131                 from .datafile import Resource, Statement, Token
132                 mat_res = Resource(material.name+".mat", "material")
133
134                 if material.type!="pbr" and material.type!="unlit":
135                         raise Exception("Can't export material {} of unknown type {}".format(material.name, material.type))
136
137                 mat_res.statements.append(Statement("type", Token(material.type)));
138                 for p in material.properties:
139                         st = self.create_property_statement(mat_res, p, resources)
140                         if st:
141                                 mat_res.statements.append(st)
142                 textures = [p.texture for p in material.properties if p.texture]
143                 if textures:
144                         from .export_texture import SamplerExporter
145                         sampler_export = SamplerExporter()
146                         mat_res.statements.append(mat_res.create_reference_statement("sampler", resources[sampler_export.get_sampler_name(textures[0])]))
147                 if material.alpha_cutoff>0.0:
148                         mat_res.statements.append(Statement("alpha_cutoff", material.alpha_cutoff))
149
150                 return mat_res
151
152         def create_property_statement(self, mat_res, prop, resources):
153                 from .datafile import Statement
154                 if prop.texture:
155                         from .export_texture import TextureExporter
156                         texture_export = TextureExporter()
157                         tex_res = resources[texture_export.get_texture_name(prop.texture, prop.tex_channels)]
158                         return mat_res.create_reference_statement(prop.tex_keyword, tex_res)
159                 elif not prop.keyword:
160                         return
161                 elif type(prop.value)==tuple:
162                         return Statement(prop.keyword, *prop.value)
163                 else:
164                         return Statement(prop.keyword, prop.value)
165
166         def export_shader(self, name, module, spec_values, resources):
167                 from .datafile import Resource, Statement
168                 shader_res = Resource(name, "shader")
169
170                 st = Statement("module", module)
171                 for k, v in spec_values.items():
172                         st.sub.append(Statement("specialize", k, v))
173                 shader_res.statements.append(st)
174
175                 return shader_res
176
177
178 class MaterialAtlasExporter:
179         def __init__(self):
180                 pass
181
182         def export_technique_resources(self, material_atlas, resources):
183                 from .datafile import Resource, Statement, Token
184                 base_color_name = material_atlas.name+"_base_color.tex"
185                 base_color_res = resources.get(base_color_name)
186                 if not base_color_res:
187                         base_color_res = Resource(base_color_name, "texture")
188
189                         base_color_res.statements.append(Statement("type", Token("\\2d")))
190                         base_color_res.statements.append(Statement("storage", Token('SRGB_ALPHA'), *material_atlas.size))
191                         base_color_res.statements.append(Statement("raw_data", material_atlas.base_color_data))
192
193                         resources[base_color_name] = base_color_res
194
195                 sampler_name = "nearest.samp"
196                 sampler_res = resources.get(sampler_name)
197                 if not sampler_res:
198                         sampler_res = Resource(sampler_name, "sampler")
199
200                         sampler_res.statements.append(Statement("filter", Token('NEAREST')))
201
202                         resources[sampler_name] = sampler_res
203
204                 mat_name = material_atlas.name+".mat"
205                 if mat_name not in resources:
206                         mat_res = Resource(mat_name, "material")
207                         mat_res.statements.append(Statement("type", Token('pbr')))
208                         mat_res.statements.append(mat_res.create_reference_statement("base_color_map", base_color_res))
209                         mat_res.statements.append(mat_res.create_reference_statement("sampler", sampler_res))
210
211                         resources[mat_name] = mat_res
212
213         def export_technique(self, material_atlas, resources):
214                 return create_technique_resource(material_atlas, resources)