Browse Source

Fix lightmap baking with "Receive Transparent"

Due to our disabling of texture baking when lightmapping, Blender would
not be able to cast light through transparent materials. Now, we revert
back to something resembling the manual method of lightmapping from the
bad old days of PyPRP.

Do note that because we attempt to batch object baking as much as
possible, I have disabled baking lightmaps to transparent objects.
This is because the transparent objects would need its textures disabled
for it to be baked to, but with the textures disabled, the renderer
would be unable to correctly determine the object's transparency. D'oh!
It would be possible, I suppose, to move them into their own batch, but
that makes the state machine a bit more complex. It would be better to
wait for someone to need that functionality, I think.
pull/103/head
Adam Johnson 6 years ago
parent
commit
b8414394da
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 23
      korman/exporter/etlight.py
  2. 1
      korman/render.py
  3. 26
      korman/ui/modifiers/render.py

23
korman/exporter/etlight.py

@ -51,9 +51,12 @@ class LightBaker(_MeshManager):
def _apply_render_settings(self, toggle, vcols): def _apply_render_settings(self, toggle, vcols):
render = bpy.context.scene.render render = bpy.context.scene.render
toggle.track(render, "use_textures", False)
# Remember, lightmaps carefully control the enabled textures such that light
# can be cast through transparent materials. See diatribe in lightmap prep.
toggle.track(render, "use_textures", not vcols)
toggle.track(render, "use_shadows", True) toggle.track(render, "use_shadows", True)
toggle.track(render, "use_envmaps", False) toggle.track(render, "use_envmaps", True)
toggle.track(render, "use_raytrace", True) toggle.track(render, "use_raytrace", True)
toggle.track(render, "bake_type", "FULL") toggle.track(render, "bake_type", "FULL")
toggle.track(render, "use_bake_clear", True) toggle.track(render, "use_bake_clear", True)
@ -243,6 +246,18 @@ class LightBaker(_MeshManager):
modifier = bo.plasma_modifiers.lightmap modifier = bo.plasma_modifiers.lightmap
uv_textures = mesh.uv_textures uv_textures = mesh.uv_textures
# Previously, we told Blender to just ignore textures althogether when baking
# VCols or lightmaps. This is easy, but it prevents us from doing tricks like
# using the "Receive Transparent" option, which allows for light to be cast
# through sections of materials that are transparent. Therefore, on objects
# that are lightmapped, we will disable all the texture slots...
# Due to our batching, however, materials that are transparent cannot be lightmapped.
for material in (i for i in mesh.materials if i is not None):
if material.use_transparency:
raise ExportError("'{}': Cannot lightmap material '{}' because it is transparnt".format(bo.name, material.name))
for slot in (j for j in material.texture_slots if j is not None):
toggle.track(slot, "use", False)
# Create a special light group for baking # Create a special light group for baking
if not self._generate_lightgroup(bo, modifier.lights): if not self._generate_lightgroup(bo, modifier.lights):
return False return False
@ -357,7 +372,7 @@ class LightBaker(_MeshManager):
for i in bpy.data.objects: for i in bpy.data.objects:
if i == objs: if i == objs:
# prevents proper baking to texture # prevents proper baking to texture
for mat in i.data.materials: for mat in (j for j in i.data.materials if j is not None):
toggle.track(mat, "use_vertex_color_paint", False) toggle.track(mat, "use_vertex_color_paint", False)
i.select = True i.select = True
else: else:
@ -370,7 +385,7 @@ class LightBaker(_MeshManager):
value = i in objs value = i in objs
if value: if value:
# prevents proper baking to texture # prevents proper baking to texture
for mat in i.data.materials: for mat in (j for j in i.data.materials if j is not None):
toggle.track(mat, "use_vertex_color_paint", False) toggle.track(mat, "use_vertex_color_paint", False)
toggle.track(i, "hide_render", False) toggle.track(i, "hide_render", False)
elif isinstance(i.data, bpy.types.Mesh) and not self._has_valid_material(i): elif isinstance(i.data, bpy.types.Mesh) and not self._has_valid_material(i):

1
korman/render.py

@ -33,6 +33,7 @@ properties_material.MATERIAL_PT_specular.COMPAT_ENGINES.add("PLASMA_GAME")
properties_material.MATERIAL_PT_options.COMPAT_ENGINES.add("PLASMA_GAME") properties_material.MATERIAL_PT_options.COMPAT_ENGINES.add("PLASMA_GAME")
properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add("PLASMA_GAME") properties_material.MATERIAL_PT_preview.COMPAT_ENGINES.add("PLASMA_GAME")
properties_material.MATERIAL_PT_transp.COMPAT_ENGINES.add("PLASMA_GAME") properties_material.MATERIAL_PT_transp.COMPAT_ENGINES.add("PLASMA_GAME")
properties_material.MATERIAL_PT_shadow.COMPAT_ENGINES.add("PLASMA_GAME")
del properties_material del properties_material
from bl_ui import properties_data_mesh from bl_ui import properties_data_mesh

26
korman/ui/modifiers/render.py

@ -87,17 +87,21 @@ def lightmap(modifier, layout, context):
layout.prop(modifier, "lights") layout.prop(modifier, "lights")
layout.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures") layout.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures")
operator = layout.operator("object.plasma_lightmap_preview", "Preview Lightmap", icon="RENDER_STILL") # Lightmaps can only be applied to objects with opaque materials.
if any((i.use_transparency for i in modifier.id_data.data.materials if i is not None)):
# Kind of clever stuff to show the user a preview... layout.label("Transparent objects cannot be lightmapped.", icon="ERROR")
# We can't show images, so we make a hidden ImageTexture called LIGHTMAPGEN_PREVIEW. We check else:
# the backing image name to see if it's for this lightmap. If so, you have a preview. If not, operator = layout.operator("object.plasma_lightmap_preview", "Preview Lightmap", icon="RENDER_STILL")
# well... It was nice knowing you!
tex = bpy.data.textures.get("LIGHTMAPGEN_PREVIEW") # Kind of clever stuff to show the user a preview...
if tex is not None and tex.image is not None: # We can't show images, so we make a hidden ImageTexture called LIGHTMAPGEN_PREVIEW. We check
im_name = "{}_LIGHTMAPGEN.png".format(context.active_object.name) # the backing image name to see if it's for this lightmap. If so, you have a preview. If not,
if tex.image.name == im_name: # well... It was nice knowing you!
layout.template_preview(tex, show_buttons=False) tex = bpy.data.textures.get("LIGHTMAPGEN_PREVIEW")
if tex is not None and tex.image is not None:
im_name = "{}_LIGHTMAPGEN.png".format(context.active_object.name)
if tex.image.name == im_name:
layout.template_preview(tex, show_buttons=False)
def rtshadow(modifier, layout, context): def rtshadow(modifier, layout, context):
split = layout.split() split = layout.split()

Loading…
Cancel
Save