diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2019-05-31 08:25:56 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2019-05-31 08:25:56 +0300 |
commit | b2b97906fbe0f7930e1afc3d86bd64bc932b1d48 (patch) | |
tree | 8808231eba162359149b9e63508b699ef7b72945 /io_scene_gltf2 | |
parent | 2bbd76ce994615b918de2866953ff50ade072261 (diff) |
glTF exporter: Fix T64760, T65234: preserve alpha when exists, and image exporting enhancements
Diffstat (limited to 'io_scene_gltf2')
-rwxr-xr-x | io_scene_gltf2/__init__.py | 2 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py | 18 | ||||
-rw-r--r-- | io_scene_gltf2/blender/exp/gltf2_blender_image.py | 27 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_material.py | 3 |
4 files changed, 33 insertions, 17 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index ee910acc..1a64a8be 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -15,7 +15,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (0, 9, 15), + "version": (0, 9, 16), 'blender': (2, 80, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py index 5254bc64..07600fcf 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py @@ -173,18 +173,24 @@ def __get_image_data(sockets_or_slots, export_settings) -> gltf2_blender_image.E image = gltf2_blender_image.ExportImage.from_blender_image(result.shader_node.image) - if composed_image is None: - composed_image = gltf2_blender_image.ExportImage.white_image(image.width, image.height) + target_channel = None # Change target channel for metallic and roughness. if socket.name == 'Metallic': - composed_image[2] = image[source_channel] + target_channel = 2 elif socket.name == 'Roughness': - composed_image[1] = image[source_channel] + target_channel = 1 elif socket.name == 'Occlusion' and len(sockets_or_slots) > 1 and sockets_or_slots[1] is not None: - composed_image[0] = image[source_channel] + target_channel = 0 + + if target_channel is not None: + if composed_image is None: + composed_image = gltf2_blender_image.ExportImage.white_image(image.width, image.height) + + composed_image[target_channel] = image[source_channel] else: - composed_image.update(image) + # If we're not assigning target channels, just return the first valid image. + return image return composed_image diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_image.py b/io_scene_gltf2/blender/exp/gltf2_blender_image.py index 080acd04..24abca62 100644 --- a/io_scene_gltf2/blender/exp/gltf2_blender_image.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_image.py @@ -13,6 +13,7 @@ # limitations under the License. import bpy +import os import typing import numpy as np import tempfile @@ -23,7 +24,8 @@ class ExportImage: # FUTURE_WORK: as a method to allow the node graph to be better supported, we could model some of # the node graph elements with numpy functions - def __init__(self, img: typing.Union[np.ndarray, typing.List[np.ndarray]], max_channels: int = 4): + def __init__(self, img: typing.Union[np.ndarray, typing.List[np.ndarray]], max_channels: int = 4,\ + blender_image: bpy.types.Image = None, has_alpha: bool = False): if isinstance(img, list): np.stack(img, axis=2) @@ -36,12 +38,15 @@ class ExportImage: self._img = img self._max_channels = max_channels + self._blender_image = blender_image + self._has_alpha = has_alpha @classmethod def from_blender_image(cls, blender_image: bpy.types.Image): img = np.array(blender_image.pixels) img = img.reshape((blender_image.size[0], blender_image.size[1], blender_image.channels)) - return ExportImage(img=img) + has_alpha = blender_image.depth == 32 + return ExportImage(img=img, blender_image=blender_image, has_alpha=has_alpha) @classmethod def white_image(cls, width, height, num_channels: int = 4): @@ -90,22 +95,26 @@ class ExportImage: self._img = np.concatenate([self.img, other.img], axis=2) - def update(self, other): - self[:other.channels] = other[:other.channels] - def __add__(self, other): self.append(other) def encode(self, mime_type: typing.Optional[str]) -> bytes: - image = bpy.data.images.new("TmpImage", width=self.width, height=self.height) - pixels = self._img.flatten().tolist() - image.pixels = pixels - file_format = { "image/jpeg": "JPEG", "image/png": "PNG" }.get(mime_type, "PNG") + if self._blender_image is not None and file_format == self._blender_image.file_format: + src_path = bpy.path.abspath(self._blender_image.filepath_raw) + if os.path.isfile(src_path): + with open(src_path, "rb") as f: + encoded_image = f.read() + return encoded_image + + image = bpy.data.images.new("TmpImage", width=self.width, height=self.height, alpha=self._has_alpha) + pixels = self._img.flatten().tolist() + image.pixels = pixels + # we just use blenders built in save mechanism, this can be considered slightly dodgy but currently is the only # way to support with tempfile.TemporaryDirectory() as tmpdirname: diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_material.py b/io_scene_gltf2/blender/imp/gltf2_blender_material.py index 390b84f4..cdfc34c1 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_material.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_material.py @@ -123,7 +123,7 @@ class BlenderMaterial(): material.blend_method = 'BLEND' elif alpha_mode == "MASK": material.blend_method = 'CLIP' - alpha_cutoff = 1.0 - pymaterial.alpha_cutoff if pymaterial.alpha_cutoff is not None else 0.5 + alpha_cutoff = pymaterial.alpha_cutoff if pymaterial.alpha_cutoff is not None else 0.5 material.alpha_threshold = alpha_cutoff node_tree = material.node_tree @@ -175,6 +175,7 @@ class BlenderMaterial(): mult = node_tree.nodes.new('ShaderNodeMath') mult.operation = 'MULTIPLY' if pymaterial.alpha_mode == 'BLEND' else 'GREATER_THAN' mult.location = 500, -250 + # Note that `1.0 - pymaterial.alpha_cutoff` is used due to the invert node above. alpha_cutoff = 1.0 if pymaterial.alpha_mode == 'BLEND' else \ 1.0 - pymaterial.alpha_cutoff if pymaterial.alpha_cutoff is not None else 0.5 mult.inputs[1].default_value = alpha_cutoff |