[Bf-extensions-cvs] [b2b97906] master: glTF exporter: Fix T64760, T65234: preserve alpha when exists, and image exporting enhancements

Julien Duroure noreply at git.blender.org
Fri May 31 07:27:34 CEST 2019


Commit: b2b97906fbe0f7930e1afc3d86bd64bc932b1d48
Author: Julien Duroure
Date:   Fri May 31 07:25:56 2019 +0200
Branches: master
https://developer.blender.org/rBAb2b97906fbe0f7930e1afc3d86bd64bc932b1d48

glTF exporter: Fix T64760, T65234: preserve alpha when exists, and image exporting enhancements

===================================================================

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_image.py
M	io_scene_gltf2/blender/exp/gltf2_blender_image.py
M	io_scene_gltf2/blender/imp/gltf2_blender_material.py

===================================================================

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



More information about the Bf-extensions-cvs mailing list