Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'io_scene_gltf2/blender/exp/gltf2_blender_texture_specular.py')
-rw-r--r--io_scene_gltf2/blender/exp/gltf2_blender_texture_specular.py94
1 files changed, 94 insertions, 0 deletions
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_texture_specular.py b/io_scene_gltf2/blender/exp/gltf2_blender_texture_specular.py
new file mode 100644
index 00000000..6321f128
--- /dev/null
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_texture_specular.py
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2018-2022 The glTF-Blender-IO authors.
+
+import bpy
+import numpy as np
+from .gltf2_blender_gather_image import StoreImage, StoreData
+from .gltf2_blender_image import TmpImageGuard, make_temp_image_copy
+
+def specular_calculation(stored):
+
+ # See https://gist.github.com/proog128/d627c692a6bbe584d66789a5a6437a33
+
+ # Find all Blender images used
+ images = []
+ for fill in stored.values():
+ if isinstance(fill, StoreImage):
+ if fill.image not in images:
+ images.append(fill.image)
+
+ if not images:
+ # No ImageFills; use a 1x1 white pixel
+ pixels = np.array([1.0, 1.0, 1.0, 1.0], np.float32)
+ return pixels, 1, 1
+
+ width = max(image.size[0] for image in images)
+ height = max(image.size[1] for image in images)
+
+ buffers = {}
+
+ for identifier, image in [(ident, store.image) for (ident, store) in stored.items() if isinstance(store, StoreImage)]:
+ tmp_buf = np.empty(width * height * 4, np.float32)
+
+ if image.size[0] == width and image.size[1] == height:
+ image.pixels.foreach_get(tmp_buf)
+ else:
+ # Image is the wrong size; make a temp copy and scale it.
+ with TmpImageGuard() as guard:
+ make_temp_image_copy(guard, src_image=image)
+ tmp_image = guard.image
+ tmp_image.scale(width, height)
+ tmp_image.pixels.foreach_get(tmp_buf)
+
+ buffers[identifier] = np.reshape(tmp_buf, [width, height, 4])
+
+ # keep only needed channels
+ ## scalar
+ for i in ['specular', 'specular_tint', 'transmission']:
+ if i in buffers.keys():
+ buffers[i] = buffers[i][:,:,stored[i + "_channel"].data]
+ else:
+ buffers[i] = np.full((width, height, 1), stored[i].data)
+
+ # Vector 3
+ for i in ['base_color']:
+ if i in buffers.keys():
+ if i + "_channel" not in stored.keys():
+ buffers[i] = buffers[i][:,:,:3]
+ else:
+ # keep only needed channel
+ for c in range(3):
+ if c != stored[i+"_channel"].data:
+ buffers[i][:, :, c] = 0.0
+ buffers[i] = buffers[i][:,:,:3]
+ else:
+ buffers[i] = np.full((width, height, 3), stored[i].data[0:3])
+
+ ior = stored['ior'].data
+
+ # calculation
+ stack3 = lambda v: np.dstack([v]*3)
+
+ def normalize(c):
+ luminance = lambda c: 0.3 * c[:,:,0] + 0.6 * c[:,:,1] + 0.1 * c[:,:,2]
+ l = luminance(c)
+ # TODOExt Manage all 0
+ return c / stack3(l)
+
+
+ f0_from_ior = ((ior - 1)/(ior + 1))**2
+ tint_strength = (1 - stack3(buffers['specular_tint'])) + normalize(buffers['base_color']) * stack3(buffers['specular_tint'])
+ out_buf = (1 - stack3(buffers['transmission'])) * (1 / f0_from_ior) * 0.08 * stack3(buffers['specular']) * tint_strength + stack3(buffers['transmission']) * tint_strength
+
+ # Manage values > 1.0 -> Need to apply factor
+ factor = None
+ factors = [np.amax(out_buf[:, :, i]) for i in range(3)]
+
+ if any([f > 1.0 for f in factors]):
+ factor = [1.0 if f < 1.0 else f for f in factors]
+ out_buf /= factor
+
+ out_buf = np.dstack((out_buf, np.ones((width, height)))) # Set alpha (glTF specular) to 1
+ out_buf = np.reshape(out_buf, (width * height * 4))
+
+ return np.float32(out_buf), width, height, [float(f) for f in factor] if factor else None