Browse Source

Fixing anki texture

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
56d8be81d3
3 changed files with 80 additions and 54 deletions
  1. 2 1
      include/anki/gl/Texture.h
  2. 5 0
      src/gl/Texture.cpp
  3. 73 53
      tools/texture/ankitexture.py

+ 2 - 1
include/anki/gl/Texture.h

@@ -123,7 +123,8 @@ private:
 	/// Texture units
 	/// Texture units
 	Vector<Unit> units;
 	Vector<Unit> units;
 
 
-	/// XXX
+	/// A map that goes from a texture name to it's bound unit. We don't keep 
+	/// the unit in the texture because it could be different for each context
 	Vector<I8> texIdToUnitId;
 	Vector<I8> texIdToUnitId;
 
 
 	/// The active texture unit
 	/// The active texture unit

+ 5 - 0
src/gl/Texture.cpp

@@ -370,6 +370,11 @@ void Texture::create(const Initializer& init)
 	{
 	{
 		glGenerateMipmap(target);
 		glGenerateMipmap(target);
 	}
 	}
+	else
+	{
+		// Make sure that the texture is complete
+		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, init.mipmapsCount - 1);
+	}
 
 
 	// Set filtering type
 	// Set filtering type
 	setFilteringNoBind(init.filteringType);
 	setFilteringNoBind(init.filteringType);

+ 73 - 53
tools/texture/ankitexture.py

@@ -6,25 +6,30 @@ import re
 import os
 import os
 import struct
 import struct
 import copy
 import copy
+import tempfile
+import shutil
 
 
 #
 #
 # AnKi texture
 # AnKi texture
 #
 #
 
 
-TYPE_NONE = 0
-TYPE_2D = 1
-TYPE_CUBE = 2
-TYPE_3D = 3
-TYPE_2D_ARRAY = 4
+# Texture type
+TT_NONE = 0
+TT_2D = 1
+TT_CUBE = 2
+TT_3D = 3
+TT_2D_ARRAY = 4
 
 
-COLOR_FORMAT_NONE = 0
-COLOR_FORMAT_RGB8 = 1
-COLOR_FORMAT_RGBA8 = 2
+# Color format
+CF_NONE = 0
+CF_RGB8 = 1
+CF_RGBA8 = 2
 
 
-COMPRESSION_NONE = 0
-COMPRESSION_RAW = 1 << 0
-COMPRESSION_ETC2 = 1 << 1
-COMPRESSION_S3TC = 1 << 2
+# Data compression
+DC_NONE = 0
+DC_RAW = 1 << 0
+DC_ETC2 = 1 << 1
+DC_S3TC = 1 << 2
 
 
 #
 #
 # DDS
 # DDS
@@ -155,10 +160,6 @@ def parse_commandline():
 
 
 	parser.add_option("-o", "--output", dest = "out",
 	parser.add_option("-o", "--output", dest = "out",
 			type = "string", help = "specify new image. ")
 			type = "string", help = "specify new image. ")
-	
-	parser.add_option("-d", "--tmp-dir", dest = "tmp_dir",
-			type = "string", default = False, 
-			help = "temporary directory")
 
 
 	parser.add_option("-t", "--type", dest = "type",
 	parser.add_option("-t", "--type", dest = "type",
 			type = "string", default = "2D", 
 			type = "string", default = "2D", 
@@ -174,27 +175,27 @@ def parse_commandline():
 
 
 	(options, args) = parser.parse_args()
 	(options, args) = parser.parse_args()
 
 
-	if not options.inp or not options.tmp_dir:
+	if not options.inp or not options.out:
 		parser.error("argument is missing")
 		parser.error("argument is missing")
 
 
 	if options.type == "2D":
 	if options.type == "2D":
-		typ = TYPE_2D
+		typ = TT_2D
 	elif options.type == "cube":
 	elif options.type == "cube":
-		typ = TYPE_CUBE
+		typ = TT_CUBE
 	elif options.type == "3D":
 	elif options.type == "3D":
-		typ = TYPE_3D
+		typ = TT_3D
 	elif options.type == "2DArray":
 	elif options.type == "2DArray":
-		typ = TYPE_2D_ARRAY
+		typ = TT_2D_ARRAY
 	else:
 	else:
 		parser.error("Unrecognized type: " + options.type)
 		parser.error("Unrecognized type: " + options.type)
 
 
-	return (options.inp.split(":"), options.out, options.tmp_dir, options.fast,
+	return (options.inp.split(":"), options.out, options.fast,
 			typ, options.normal)
 			typ, options.normal)
 
 
 def get_internal_format_and_size(in_file):
 def get_internal_format_and_size(in_file):
 	""" Return the size of the input image and the internal format """
 	""" Return the size of the input image and the internal format """
 
 
-	internal_format = COLOR_FORMAT_NONE
+	internal_format = CF_NONE
 	width = 0
 	width = 0
 	height = 0
 	height = 0
 
 
@@ -209,9 +210,9 @@ def get_internal_format_and_size(in_file):
 
 
 	print("-- Colorspace: %s" % reg.group(1))
 	print("-- Colorspace: %s" % reg.group(1))
 	if reg.group(1) == "RGB":
 	if reg.group(1) == "RGB":
-		internal_format = COLOR_FORMAT_RGB8
+		internal_format = CF_RGB8
 	elif reg.group(1) == "RGBA":
 	elif reg.group(1) == "RGBA":
-		internal_format = COLOR_FORMAT_RGBA8
+		internal_format = CF_RGBA8
 	else:
 	else:
 		raise Exception("Unrecognized color format")
 		raise Exception("Unrecognized color format")
 
 
@@ -244,7 +245,7 @@ def create_mipmaps(in_file, tmp_dir, orig_size, internal_format):
 
 
 		args = ["convert", in_file, "-resize", size_str, "-alpha"]
 		args = ["convert", in_file, "-resize", size_str, "-alpha"]
 
 
-		if internal_format == COLOR_FORMAT_RGB8:
+		if internal_format == CF_RGB8:
 			args.append("deactivate")
 			args.append("deactivate")
 		else:
 		else:
 			args.append("activate")
 			args.append("activate")
@@ -280,7 +281,7 @@ def create_etc_images(mips_fnames, tmp_dir, fast, internal_format):
 			args.append("fast")
 			args.append("fast")
 
 
 		args.append("-f")
 		args.append("-f")
-		if internal_format == COLOR_FORMAT_RGB8:
+		if internal_format == CF_RGB8:
 			args.append("RGB")
 			args.append("RGB")
 		else:
 		else:
 			args.append("RGBA")
 			args.append("RGBA")
@@ -294,7 +295,14 @@ def create_dds_images(mips_fnames, tmp_dir, fast, internal_format, \
 	print("-- Creating DDS images")
 	print("-- Creating DDS images")
 
 
 	for fname in mips_fnames:
 	for fname in mips_fnames:
+		# Unfortunately we need to flip the image. Use convert again
 		in_fname = fname + ".tga"
 		in_fname = fname + ".tga"
+		flipped_fname = fname + "_flip.tga"
+		args = ["convert", in_fname, "-flip", flipped_fname]
+		subprocess.check_call(args)
+		in_fname = flipped_fname
+
+		# Continue
 		out_fname = os.path.join(tmp_dir, os.path.basename(fname) + ".dds")
 		out_fname = os.path.join(tmp_dir, os.path.basename(fname) + ".dds")
 
 
 		print("  -- %s" % out_fname)
 		print("  -- %s" % out_fname)
@@ -304,12 +312,12 @@ def create_dds_images(mips_fnames, tmp_dir, fast, internal_format, \
 		if fast:
 		if fast:
 			args.append("-fast")
 			args.append("-fast")
 
 
-		if internal_format == COLOR_FORMAT_RGB8:
+		if internal_format == CF_RGB8:
 			if not normal:
 			if not normal:
 				args.append("-bc1")
 				args.append("-bc1")
 			else:
 			else:
 				args.append("-bc1n")
 				args.append("-bc1n")
-		elif internal_format == COLOR_FORMAT_RGBA8:
+		elif internal_format == CF_RGBA8:
 			if not normal:
 			if not normal:
 				args.append("-bc3")
 				args.append("-bc3")
 			else:
 			else:
@@ -341,8 +349,8 @@ def write_raw(tex_file, fname, width, height, internal_format):
 	img_height = header6[3] * 256 + header6[2]
 	img_height = header6[3] * 256 + header6[2]
 	img_bpp = header6[4];
 	img_bpp = header6[4];
 
 
-	if (internal_format != COLOR_FORMAT_RGB8 or img_bpp != 24) \
-			and (internal_format != COLOR_FORMAT_RGBA8 or img_bpp != 32):
+	if (internal_format != CF_RGB8 or img_bpp != 24) \
+			and (internal_format != CF_RGBA8 or img_bpp != 32):
 		raise Exception("Unexpected bpp")
 		raise Exception("Unexpected bpp")
 		
 		
 	if img_width != width or img_height != height:
 	if img_width != width or img_height != height:
@@ -350,7 +358,7 @@ def write_raw(tex_file, fname, width, height, internal_format):
 
 
 	# Read the data
 	# Read the data
 	data_size = width * height
 	data_size = width * height
-	if internal_format == COLOR_FORMAT_RGB8:
+	if internal_format == CF_RGB8:
 		data_size *= 3
 		data_size *= 3
 	else:
 	else:
 		data_size *= 4
 		data_size *= 4
@@ -374,6 +382,7 @@ def write_s3tc(out_file, fname, width, height, internal_format):
 	""" Append s3tc data to the AnKi texture file """
 	""" Append s3tc data to the AnKi texture file """
 
 
 	# Read header
 	# Read header
+	print("  -- Appending %s" % fname)
 	in_file = open(fname, "rb")
 	in_file = open(fname, "rb")
 
 
 	dds_header = DdsHeader(in_file.read(DdsHeader.get_size()))
 	dds_header = DdsHeader(in_file.read(DdsHeader.get_size()))
@@ -381,16 +390,16 @@ def write_s3tc(out_file, fname, width, height, internal_format):
 	if dds_header.dwWidth != width or dds_header.dwHeight != height:
 	if dds_header.dwWidth != width or dds_header.dwHeight != height:
 		raise Exception("Incorrect width")
 		raise Exception("Incorrect width")
 
 
-	if internal_format == COLOR_FORMAT_RGB8 \
+	if internal_format == CF_RGB8 \
 			and dds_header.dwFourCC != "DXT1":
 			and dds_header.dwFourCC != "DXT1":
 		raise Exception("Incorrect format. Expecting DXT1")
 		raise Exception("Incorrect format. Expecting DXT1")
 
 
-	if internal_format == COLOR_FORMAT_RGBA8 \
+	if internal_format == CF_RGBA8 \
 			and dds_header.dwFourCC != "DXT5":
 			and dds_header.dwFourCC != "DXT5":
 		raise Exception("Incorrect format. Expecting DXT5")
 		raise Exception("Incorrect format. Expecting DXT5")
 
 
 	# Read and write the data
 	# Read and write the data
-	if internal_format == COLOR_FORMAT_RGB8:
+	if internal_format == CF_RGB8:
 		block_size = 8
 		block_size = 8
 	else:
 	else:
 		block_size = 16
 		block_size = 16
@@ -420,21 +429,8 @@ def write_etc(out_file, fname, width, height, internal_format):
 	data = in_file.read(data_size)
 	data = in_file.read(data_size)
 	out_file.write(data)
 	out_file.write(data)
 
 
-def main():
-	""" The main """
-
-	# Parse cmd line args
-	(in_files, out, tmp_dir, fast, typ, normal) = parse_commandline();
-	tmp_dir = os.path.abspath(tmp_dir)
-
-	if typ == TYPE_CUBE and len(in_files) != 6:
-		raise Exception("Not enough images for cube generation")
-
-	if (typ == TYPE_3D or typ == TYPE_2D_ARRAY) and len(in_files) < 2:
-		raise Exception("Not enough images for 2DArray/3D texture")
-
-	if typ == TYPE_2D and len(in_files) != 1:
-		raise Exception("Only one image for 2D textures needed")
+def convert(in_files, out, fast, typ, normal, tmp_dir):
+	""" This is the function that does all the work """
 
 
 	# Invoke app named "identify" to get internal format and width and height
 	# Invoke app named "identify" to get internal format and width and height
 	(internal_format, width, height) = get_internal_format_and_size(in_files[0])
 	(internal_format, width, height) = get_internal_format_and_size(in_files[0])
@@ -445,7 +441,7 @@ def main():
 	if not is_power2(width):
 	if not is_power2(width):
 		raise Exception("Image should power of 2")
 		raise Exception("Image should power of 2")
 
 
-	if internal_format == COLOR_FORMAT_RGBA8 and normal:
+	if internal_format == CF_RGBA8 and normal:
 		raise Exception("RGBA image and normal does not make much sense")
 		raise Exception("RGBA image and normal does not make much sense")
 
 
 	for i in range(1, len(in_files)):
 	for i in range(1, len(in_files)):
@@ -468,7 +464,7 @@ def main():
 
 
 	# Open file
 	# Open file
 	fname = out
 	fname = out
-	fname = os.path.join(tmp_dir,  fname)
+	print("-- Writing %s" % fname)
 	tex_file = open(fname, "wb")
 	tex_file = open(fname, "wb")
 
 
 	# Write header
 	# Write header
@@ -481,7 +477,7 @@ def main():
 			len(in_files),
 			len(in_files),
 			typ,
 			typ,
 			internal_format,
 			internal_format,
-			COMPRESSION_RAW | COMPRESSION_S3TC | COMPRESSION_ETC2,
+			DC_RAW | DC_S3TC | DC_ETC2,
 			normal,
 			normal,
 			len(mips_fnames))
 			len(mips_fnames))
 
 
@@ -523,6 +519,30 @@ def main():
 							internal_format)
 							internal_format)
 				
 				
 				size = size / 2
 				size = size / 2
+
+def main():
+	""" The main """
+
+	# Parse cmd line args
+	(in_files, out, fast, typ, normal) = parse_commandline();
+
+	if typ == TT_CUBE and len(in_files) != 6:
+		raise Exception("Not enough images for cube generation")
+
+	if (typ == TT_3D or typ == TT_2D_ARRAY) and len(in_files) < 2:
+		raise Exception("Not enough images for 2DArray/3D texture")
+
+	if typ == TT_2D and len(in_files) != 1:
+		raise Exception("Only one image for 2D textures needed")
+
+	# Setup the temp dir
+	tmp_dir = tempfile.mkdtemp("_ankitex")
+
+	# Do the work
+	try:
+		convert(in_files, out, fast, typ, normal, tmp_dir)
+	finally:
+		shutil.rmtree(tmp_dir)
 		
 		
 	# Done
 	# Done
 	print("-- Done!")
 	print("-- Done!")