4 def pixels_to_rgba(pixels):
5 return (int(p*255) for p in pixels)
7 def pixels_to_rgb(pixels):
8 for i in range(0, len(pixels), 4):
9 yield int(pixels[i]*255)
10 yield int(pixels[i+1]*255)
11 yield int(pixels[i+2]*255)
13 def pixels_to_rgb_invert(pixels, mask):
14 for i in range(0, len(pixels), 4):
15 r = int(pixels[i]*255)
16 yield 255-r if mask&1 else r
17 g = int(pixels[i+1]*255)
18 yield 255-g if mask&2 else g
19 b = int(pixels[i+2]*255)
20 yield 255-b if mask&4 else b
22 def pixels_to_gray(pixels):
23 for i in range(0, len(pixels), 4):
24 yield int((pixels[i]+pixels[i+1]+pixels[i+2])*255/3)
26 def pixels_to_single_channel(pixels, channel):
27 for i in range(0, len(pixels), 4):
28 yield int(pixels[i+channel]*255)
30 class TextureExporter:
31 def export_texture(self, tex_node, channels=['R', 'G', 'B']):
32 image = tex_node.image
33 from .datafile import RawData, Resource, Statement, Token
34 tex_res = Resource(self.get_texture_name(tex_node, channels), "texture")
36 tex_res.statements.append(Statement("type", Token("\\2d")))
38 if tex_node.use_mipmap:
39 tex_res.statements.append(Statement("generate_mipmap", True))
41 from .texture import Texture
42 texture = Texture(tex_node, channels)
44 invert_mask = sum(1<<i for i, c in enumerate(channels) if c[0]=='~')
46 fn = bpy.path.basename(image.filepath)
47 native_channels = None
49 abs_path = bpy.path.abspath(image.filepath)
50 if os.path.exists(abs_path):
52 native_bpp = imbuf.load(bpy.path.abspath(image.filepath)).planes
54 native_channels = ['R', 'G', 'B', 'A']
56 native_channels = ['R', 'G', 'B']
58 native_channels = ['Y']
60 if not invert_mask and channels==native_channels:
61 if not tex_node.use_mipmap:
62 tex_res.statements.append(Statement("mipmap_levels", 1))
63 srgb = "_srgb" if texture.srgb else ""
64 tex_res.statements.append(Statement("external_image"+srgb, fn))
66 tex_res.statements.append(Statement("storage", Token(texture.pixelformat), texture.width, texture.height))
68 pixels = tuple(image.pixels)
71 texdata = pixels_to_rgba(pixels)
72 elif len(channels)==1:
74 texdata = pixels_to_gray(pixels)
76 texdata = pixels_to_single_channel(pixels, "RGBA".index(channels[0]))
78 texdata = pixels_to_rgb_invert(pixels, invert_mask)
80 texdata = pixels_to_rgb(pixels)
82 data = RawData(os.path.splitext(tex_res.name)[0]+".mdr", bytes(texdata))
83 tex_res.statements.append(tex_res.create_reference_statement("external_data", data))
87 def get_texture_name(self, tex_node, channels):
88 image_name = tex_node.image.name
89 if len(channels)==1 and channels[0]!='Y':
90 image_name += "_"+channels[0]
91 return image_name+".tex"
93 class SamplerExporter:
94 def export_sampler(self, tex_node):
95 from .datafile import Resource, Statement, Token
96 samp_res = Resource(self.get_sampler_name(tex_node), "sampler")
98 use_interpolation = tex_node.interpolation!='Closest'
100 if tex_node.use_mipmap:
101 samp_res.statements.append(Statement("filter", Token('LINEAR_MIPMAP_LINEAR')))
103 samp_res.statements.append(Statement("filter", Token('LINEAR')))
104 samp_res.statements.append(Statement("max_anisotropy", tex_node.max_anisotropy))
106 if tex_node.use_mipmap:
107 samp_res.statements.append(Statement("filter", Token('NEAREST_MIPMAP_NEAREST')))
109 samp_res.statements.append(Statement("filter", Token('NEAREST')))
111 if tex_node.extension=="REPEAT":
112 samp_res.statements.append(Statement("wrap", Token('REPEAT')))
113 elif tex_node.extension=="EXTEND":
114 samp_res.statements.append(Statement("wrap", Token('CLAMP_TO_EDGE')))
115 elif tex_node.extension=="CLIP":
116 samp_res.statements.append(Statement("wrap", Token('CLAMP_TO_BORDER')))
117 samp_res.statements.append(Statement("border_color", 0.0, 0.0, 0.0, 0.0))
121 def get_sampler_name(self, tex_node):
124 use_interpolation = tex_node.interpolation!='Closest'
125 name_parts.append("linear" if use_interpolation else "nearest")
126 if tex_node.use_mipmap:
127 name_parts.append("mip")
128 if use_interpolation and tex_node.max_anisotropy>1:
129 name_parts.append("aniso{:g}x".format(tex_node.max_anisotropy))
130 if tex_node.extension!="REPEAT":
131 name_parts.append("clip" if tex_node.extension=="CLIP" else "clamp")
133 return "_".join(name_parts)+".samp"