Browse Source

Ensure alpha textures have transparency

pull/8/head
Adam Johnson 10 years ago
parent
commit
290408847c
  1. 6
      korman/exporter/logger.py
  2. 45
      korman/exporter/material.py

6
korman/exporter/logger.py

@ -29,12 +29,14 @@ class ExportAnalysis:
# TODO # TODO
pass pass
def port(self, message): def port(self, message, indent=0):
self._porting.append(message) self._porting.append(message)
print(" " * indent, end="")
print("PORTING: {}".format(message)) print("PORTING: {}".format(message))
def warn(self, message): def warn(self, message, indent=0):
self._warnings.append(message) self._warnings.append(message)
print(" " * indent, end="")
print("WARNING: {}".format(message)) print("WARNING: {}".format(message))

45
korman/exporter/material.py

@ -67,12 +67,13 @@ class _GLTexture:
# It will simplify our state tracking a bit. # It will simplify our state tracking a bit.
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_GENERATE_MIPMAP, 1) bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_GENERATE_MIPMAP, 1)
def get_level_data(self, level, calc_alpha=False, bgra=False): def get_level_data(self, level=0, calc_alpha=False, bgra=False, quiet=False):
"""Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha """Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha
channel from the image color data channel from the image color data
""" """
width = self._get_tex_param(bgl.GL_TEXTURE_WIDTH, level) width = self._get_tex_param(bgl.GL_TEXTURE_WIDTH, level)
height = self._get_tex_param(bgl.GL_TEXTURE_HEIGHT, level) height = self._get_tex_param(bgl.GL_TEXTURE_HEIGHT, level)
if not quiet:
print(" Level #{}: {}x{}".format(level, width, height)) print(" Level #{}: {}x{}".format(level, width, height))
# Grab the image data # Grab the image data
@ -106,7 +107,7 @@ class _GLTexture:
class _Texture: class _Texture:
def __init__(self, texture=None, image=None): def __init__(self, texture=None, image=None, use_alpha=None):
assert (texture or image) assert (texture or image)
if texture is not None: if texture is not None:
@ -118,8 +119,12 @@ class _Texture:
self.calc_alpha = False self.calc_alpha = False
self.mipmap = False self.mipmap = False
self.image = image if use_alpha is None:
self.use_alpha = (image.channels == 4 and image.use_alpha) self.use_alpha = (image.channels == 4 and image.use_alpha)
else:
self.use_alpha = use_alpha
self.image = image
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, _Texture): if not isinstance(other, _Texture):
@ -162,6 +167,7 @@ class MaterialConverter:
self._obj2mat = {} self._obj2mat = {}
self._exporter = weakref.ref(exporter) self._exporter = weakref.ref(exporter)
self._pending = {} self._pending = {}
self._alphatest = {}
def export_material(self, bo, bm): def export_material(self, bo, bm):
"""Exports a Blender Material as an hsGMaterial""" """Exports a Blender Material as an hsGMaterial"""
@ -224,7 +230,10 @@ class MaterialConverter:
"""Exports a Blender ImageTexture to a plLayer""" """Exports a Blender ImageTexture to a plLayer"""
# Does the image have any alpha at all? # Does the image have any alpha at all?
has_alpha = (texture.image.channels == 4 and texture.image.use_alpha) or texture.use_calculate_alpha has_alpha = texture.use_calculate_alpha or self._test_image_alpha(texture.image)
if (texture.image.use_alpha and texture.use_alpha) and not has_alpha:
warning = "'{}' wants to use alpha, but '{}' is opaque".format(texture.name, texture.image.name)
self._exporter().report.warn(warning, indent=3)
# First, let's apply any relevant flags # First, let's apply any relevant flags
state = layer.state state = layer.state
@ -242,7 +251,7 @@ class MaterialConverter:
if texture.image is None: if texture.image is None:
bitmap = self.add_object(plDynamicTextMap, name="{}_DynText".format(layer.key.name), bl=bo) bitmap = self.add_object(plDynamicTextMap, name="{}_DynText".format(layer.key.name), bl=bo)
else: else:
key = _Texture(texture=texture) key = _Texture(texture=texture, use_alpha=has_alpha)
if key not in self._pending: if key not in self._pending:
print(" Stashing '{}' for conversion as '{}'".format(texture.image.name, str(key))) print(" Stashing '{}' for conversion as '{}'".format(texture.image.name, str(key)))
self._pending[key] = [layer,] self._pending[key] = [layer,]
@ -371,3 +380,29 @@ class MaterialConverter:
if image.bindcode != 0: if image.bindcode != 0:
image.gl_free() image.gl_free()
image.gl_load() image.gl_load()
def _test_image_alpha(self, image):
"""Tests to see if this image has any alpha data"""
# In the interest of speed, let's see if we've already done this one...
result = self._alphatest.get(image, None)
if result is not None:
return result
if image.channels != 4:
result = False
elif not image.use_alpha:
result = False
else:
# Using bpy.types.Image.pixels is VERY VERY VERY slow...
with _GLTexture(image) as glimage:
data = glimage.get_level_data(quiet=True)
for i in range(3, len(data), 4):
if data[i] != 255:
result = True
break
else:
result = False
self._alphatest[image] = result
return result

Loading…
Cancel
Save