Skip to content

Commit

Permalink
merge channels (metallic/Roughness) : use default value
Browse files Browse the repository at this point in the history
  • Loading branch information
julienduroure committed Aug 16, 2023
1 parent 9f8e68d commit e40eb73
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def export_clearcoat(blender_material, export_settings):
clearcoat_texture, clearcoat_texture_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
clearcoat_socket,
clearcoat_roughness_slots,
(),
export_settings,
)
clearcoat_extension['clearcoatTexture'] = clearcoat_texture
Expand All @@ -74,6 +75,7 @@ def export_clearcoat(blender_material, export_settings):
clearcoat_roughness_texture, clearcoat_roughness_texture_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
clearcoat_roughness_socket,
clearcoat_roughness_slots,
(),
export_settings,
)
clearcoat_extension['clearcoatRoughnessTexture'] = clearcoat_roughness_texture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def export_emission_texture(blender_material, export_settings):
emissive = gltf2_blender_get.get_socket(blender_material, "Emissive")
if emissive is None:
emissive = gltf2_blender_get.get_socket_old(blender_material, "Emissive")
emissive_texture, use_actives_uvmap_emissive, _ = gltf2_blender_gather_texture_info.gather_texture_info(emissive, (emissive,), export_settings)
emissive_texture, use_actives_uvmap_emissive, _ = gltf2_blender_gather_texture_info.gather_texture_info(emissive, (emissive,), (), export_settings)
return emissive_texture, ["emissiveTexture"] if use_actives_uvmap_emissive else None

def export_emission_strength_extension(emissive_factor, export_settings):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def export_sheen(blender_material, export_settings):
original_sheenColor_texture, original_sheenColor_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
sheenColor_socket,
(sheenColor_socket,),
(),
export_settings,
)
sheen_extension['sheenColorTexture'] = original_sheenColor_texture
Expand All @@ -74,6 +75,7 @@ def export_sheen(blender_material, export_settings):
original_sheenRoughness_texture, original_sheenRoughness_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
sheenRoughness_socket,
(sheenRoughness_socket,),
(),
export_settings,
)
sheen_extension['sheenRoughnessTexture'] = original_sheenRoughness_texture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def export_original_specular(blender_material, export_settings):
original_specular_texture, original_specular_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
original_specular_socket,
(original_specular_socket,),
(),
export_settings,
)
specular_extension['specularTexture'] = original_specular_texture
Expand All @@ -71,6 +72,7 @@ def export_original_specular(blender_material, export_settings):
original_specularcolor_texture, original_specularcolor_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
original_specularcolor_socket,
(original_specularcolor_socket,),
(),
export_settings,
)
specular_extension['specularColorTexture'] = original_specularcolor_texture
Expand Down Expand Up @@ -162,6 +164,7 @@ def normalize(c):
specularColorTexture, use_active_uvmap, specularColorFactor = gltf2_blender_gather_texture_info.gather_texture_info(
primary_socket,
sockets,
(),
export_settings,
filter_type='ANY')
if specularColorTexture is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def export_transmission(blender_material, export_settings):
combined_texture, use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
transmission_socket,
transmission_slots,
(),
export_settings,
)
if has_transmission_texture:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def export_volume(blender_material, export_settings):
combined_texture, use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
thicknesss_socket,
thickness_slots,
(),
export_settings,
)
if has_thickness_texture:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class FillWhite:
"""Fills a channel with all ones (1.0)."""
pass

class FillWith:
"""Fills a channel with all same values"""
def __init__(self, value):
self.value = value

class StoreData:
def __init__(self, data):
"""Store numeric data (not an image channel"""
Expand Down Expand Up @@ -109,6 +114,9 @@ def store_data(self, identifier, data, type='Image'):
def fill_white(self, dst_chan: Channel):
self.fills[dst_chan] = FillWhite()

def fill_with(self, dst_chan, value):
self.fills[dst_chan] = FillWith(value)

def is_filled(self, chan: Channel) -> bool:
return chan in self.fills

Expand Down Expand Up @@ -193,6 +201,8 @@ def __encode_unhappy(self, export_settings) -> bytes:
for dst_chan, fill in self.fills.items():
if isinstance(fill, FillImage) and fill.image == image:
out_buf[int(dst_chan)::4] = tmp_buf[int(fill.src_chan)::4]
elif isinstance(fill, FillWith):
out_buf[int(dst_chan)::4] = fill.value

tmp_buf = None # GC this

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@
@cached
def gather_image(
blender_shader_sockets: typing.Tuple[bpy.types.NodeSocket],
default_sockets: typing.Tuple[bpy.types.NodeSocket],
export_settings):
if not __filter_image(blender_shader_sockets, export_settings):
return None, None

image_data = __get_image_data(blender_shader_sockets, export_settings)
image_data = __get_image_data(blender_shader_sockets, default_sockets, export_settings)
if image_data.empty():
# The export image has no data
return None, None
Expand Down Expand Up @@ -184,7 +185,7 @@ def __gather_uri(image_data, mime_type, name, export_settings):
return None, None


def __get_image_data(sockets, export_settings) -> ExportImage:
def __get_image_data(sockets, default_sockets, export_settings) -> ExportImage:
# For shared resources, such as images, we just store the portion of data that is needed in the glTF property
# in a helper class. During generation of the glTF in the exporter these will then be combined to actual binary
# resources.
Expand All @@ -194,14 +195,22 @@ def __get_image_data(sockets, export_settings) -> ExportImage:
if any([socket.name == "Specular" and socket.node.type == "BSDF_PRINCIPLED" for socket in sockets]):
return __get_image_data_specular(sockets, results, export_settings)
else:
return __get_image_data_mapping(sockets, results, export_settings)
return __get_image_data_mapping(sockets, default_sockets, results, export_settings)

def __get_image_data_mapping(sockets, results, export_settings) -> ExportImage:
def __get_image_data_mapping(sockets, default_sockets, results, export_settings) -> ExportImage:
"""
Simple mapping
Will fit for most of exported textures : RoughnessMetallic, Basecolor, normal, ...
"""
composed_image = ExportImage()

default_metallic = None
default_roughness = None
if "Metallic" in [s.name for s in default_sockets]:
default_metallic = [s for s in default_sockets if s.name == "Metallic"][0].default_value
if "Roughness" in [s.name for s in default_sockets]:
default_roughness = [s for s in default_sockets if s.name == "Roughness"][0].default_value

for result, socket in zip(results, sockets):
# Assume that user know what he does, and that channels/images are already combined correctly for pbr
# If not, we are going to keep only the first texture found
Expand Down Expand Up @@ -252,9 +261,15 @@ def __get_image_data_mapping(sockets, results, export_settings) -> ExportImage:
# Since metal/roughness are always used together, make sure
# the other channel is filled.
if socket.name == 'Metallic' and not composed_image.is_filled(Channel.G):
composed_image.fill_white(Channel.G)
if default_roughness is not None:
composed_image.fill_with(Channel.G, default_roughness)
else:
composed_image.fill_white(Channel.G)
elif socket.name == 'Roughness' and not composed_image.is_filled(Channel.B):
composed_image.fill_white(Channel.B)
if default_metallic is not None:
composed_image.fill_with(Channel.B, default_metallic)
else:
composed_image.fill_white(Channel.B)
else:
# copy full image...eventually following sockets might overwrite things
composed_image = ExportImage.from_blender_image(result.shader_node.image)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def __gather_orm_texture(blender_material, export_settings):
return None

# Double-check this will past the filter in texture_info
info, info_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(result[0], result, export_settings)
info, info_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(result[0], result, (), export_settings)
if info is None:
return None

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def __gather_base_color_texture(blender_material, export_settings):
if not inputs:
return None, None, None

return gltf2_blender_gather_texture_info.gather_texture_info(inputs[0], inputs, export_settings)
return gltf2_blender_gather_texture_info.gather_texture_info(inputs[0], inputs, (), export_settings)


def __gather_extensions(blender_material, export_settings):
Expand Down Expand Up @@ -139,21 +139,26 @@ def __gather_metallic_roughness_texture(blender_material, orm_texture, export_se
hasMetal = metallic_socket is not None and __has_image_node_from_socket(metallic_socket)
hasRough = roughness_socket is not None and __has_image_node_from_socket(roughness_socket)

default_sockets = ()
if not hasMetal and not hasRough:
metallic_roughness = gltf2_blender_get.get_socket_old(blender_material, "MetallicRoughness")
if metallic_roughness is None or not __has_image_node_from_socket(metallic_roughness):
return None, None, None
texture_input = (metallic_roughness,)
elif not hasMetal:
texture_input = (roughness_socket,)
default_sockets = (metallic_socket,)
elif not hasRough:
texture_input = (metallic_socket,)
default_sockets = (roughness_socket,)
else:
texture_input = (metallic_socket, roughness_socket)
default_sockets = ()

return gltf2_blender_gather_texture_info.gather_texture_info(
texture_input[0],
orm_texture or texture_input,
default_sockets,
export_settings,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def gather_base_color_texture(info, export_settings):
unlit_texture, unlit_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
sockets[0],
sockets,
(),
export_settings,
)
return unlit_texture, ["unlitTexture"] if unlit_use_active_uvmap else None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@cached
def gather_texture(
blender_shader_sockets: typing.Tuple[bpy.types.NodeSocket],
default_sockets: typing.Tuple[bpy.types.NodeSocket],
export_settings):
"""
Gather texture sampling information and image channels from a blender shader texture attached to a shader socket.
Expand All @@ -37,7 +38,7 @@ def gather_texture(
if not __filter_texture(blender_shader_sockets, export_settings):
return None, None

source, factor = __gather_source(blender_shader_sockets, export_settings)
source, factor = __gather_source(blender_shader_sockets, default_sockets, export_settings)

texture = gltf2_io.Texture(
extensions=__gather_extensions(blender_shader_sockets, export_settings),
Expand Down Expand Up @@ -88,8 +89,8 @@ def __gather_sampler(blender_shader_sockets, export_settings):
export_settings)


def __gather_source(blender_shader_sockets, export_settings):
return gltf2_blender_gather_image.gather_image(blender_shader_sockets, export_settings)
def __gather_source(blender_shader_sockets, default_sockets, export_settings):
return gltf2_blender_gather_image.gather_image(blender_shader_sockets, default_sockets, export_settings)

# Helpers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,25 @@
# occlusion the primary_socket would be the occlusion socket, and
# blender_shader_sockets would be the (O,R,M) sockets.

def gather_texture_info(primary_socket, blender_shader_sockets, export_settings, filter_type='ALL'):
return __gather_texture_info_helper(primary_socket, blender_shader_sockets, 'DEFAULT', filter_type, export_settings)
# Default socket parameter is used when there is a mapping between channels, and one of the channel is not a texture
# In that case, we will create a texture with one channel from texture, other from default socket value
# Example: MetallicRoughness

def gather_texture_info(primary_socket, blender_shader_sockets, default_sockets, export_settings, filter_type='ALL'):
return __gather_texture_info_helper(primary_socket, blender_shader_sockets, default_sockets, 'DEFAULT', filter_type, export_settings)

def gather_material_normal_texture_info_class(primary_socket, blender_shader_sockets, export_settings, filter_type='ALL'):
return __gather_texture_info_helper(primary_socket, blender_shader_sockets, 'NORMAL', filter_type, export_settings)
return __gather_texture_info_helper(primary_socket, blender_shader_sockets, (), 'NORMAL', filter_type, export_settings)

def gather_material_occlusion_texture_info_class(primary_socket, blender_shader_sockets, export_settings, filter_type='ALL'):
return __gather_texture_info_helper(primary_socket, blender_shader_sockets, 'OCCLUSION', filter_type, export_settings)
return __gather_texture_info_helper(primary_socket, blender_shader_sockets, (), 'OCCLUSION', filter_type, export_settings)


@cached
def __gather_texture_info_helper(
primary_socket: bpy.types.NodeSocket,
blender_shader_sockets: typing.Tuple[bpy.types.NodeSocket],
default_sockets: typing.Tuple[bpy.types.NodeSocket],
kind: str,
filter_type: str,
export_settings):
Expand All @@ -51,7 +56,7 @@ def __gather_texture_info_helper(

tex_transform, tex_coord, use_active_uvmap = __gather_texture_transform_and_tex_coord(primary_socket, export_settings)

index, factor = __gather_index(blender_shader_sockets, export_settings)
index, factor = __gather_index(blender_shader_sockets, default_sockets, export_settings)

fields = {
'extensions': __gather_extensions(tex_transform, export_settings),
Expand Down Expand Up @@ -146,9 +151,9 @@ def __gather_occlusion_strength(primary_socket, export_settings):
return None


def __gather_index(blender_shader_sockets, export_settings):
def __gather_index(blender_shader_sockets, default_sockets, export_settings):
# We just put the actual shader into the 'index' member
return gltf2_blender_gather_texture.gather_texture(blender_shader_sockets, export_settings)
return gltf2_blender_gather_texture.gather_texture(blender_shader_sockets, default_sockets, export_settings)


def __gather_texture_transform_and_tex_coord(primary_socket, export_settings):
Expand Down

0 comments on commit e40eb73

Please sign in to comment.