Add color space option for texture export

This commit is contained in:
Lubos Lenco
2021-03-29 16:27:52 +02:00
parent a3771087c0
commit 0a3cd8777e
8 changed files with 73 additions and 60 deletions
+5 -5
View File
@@ -1,9 +1,9 @@
{
"textures": [
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"] },
{ "name": "nor", "channels": ["nor_r", "nor_g", "nor_b", "1.0"] },
{ "name": "occ", "channels": ["occ", "occ", "occ", "1.0"] },
{ "name": "rough", "channels": ["rough", "rough", "rough", "1.0"] },
{ "name": "metal", "channels": ["metal", "metal", "metal", "1.0"] }
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"], "color_space": "linear" },
{ "name": "nor", "channels": ["nor_r", "nor_g", "nor_b", "1.0"], "color_space": "linear" },
{ "name": "occ", "channels": ["occ", "occ", "occ", "1.0"], "color_space": "linear" },
{ "name": "rough", "channels": ["rough", "rough", "rough", "1.0"], "color_space": "linear" },
{ "name": "metal", "channels": ["metal", "metal", "metal", "1.0"], "color_space": "linear" }
]
}
+3 -3
View File
@@ -1,7 +1,7 @@
{
"textures": [
{ "name": "", "channels": ["base_r", "base_g", "base_b", "1.0"] },
{ "name": "normal", "channels": ["nor_r", "nor_g", "nor_b", "1.0"] },
{ "name": "mer", "channels": ["metal", "emis", "rough", "1.0"] }
{ "name": "", "channels": ["base_r", "base_g", "base_b", "1.0"], "color_space": "linear" },
{ "name": "normal", "channels": ["nor_r", "nor_g", "nor_b", "1.0"], "color_space": "linear" },
{ "name": "mer", "channels": ["metal", "emis", "rough", "1.0"], "color_space": "linear" }
]
}
+4 -4
View File
@@ -1,8 +1,8 @@
{
"textures": [
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"] },
{ "name": "nor", "channels": ["nor_r", "nor_g", "0.0", "1.0"] },
{ "name": "sh", "channels": ["metal", "rough", "0.0", "1.0"] },
{ "name": "occ", "channels": ["occ", "0.0", "0.0", "1.0"] }
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"], "color_space": "linear" },
{ "name": "nor", "channels": ["nor_r", "nor_g", "0.0", "1.0"], "color_space": "linear" },
{ "name": "sh", "channels": ["metal", "rough", "0.0", "1.0"], "color_space": "linear" },
{ "name": "occ", "channels": ["occ", "0.0", "0.0", "1.0"], "color_space": "linear" }
]
}
+4 -4
View File
@@ -1,8 +1,8 @@
{
"textures": [
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"] },
{ "name": "nor", "channels": ["nor_r", "nor_g", "nor_b", "1.0"] },
{ "name": "mos", "channels": ["metal", "occ", "1.0", "smooth"] },
{ "name": "height", "channels": ["0.0", "height", "0.0", "1.0"] }
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"], "color_space": "linear" },
{ "name": "nor", "channels": ["nor_r", "nor_g", "nor_b", "1.0"], "color_space": "linear" },
{ "name": "mos", "channels": ["metal", "occ", "1.0", "smooth"], "color_space": "linear" },
{ "name": "height", "channels": ["0.0", "height", "0.0", "1.0"], "color_space": "linear" }
]
}
+3 -3
View File
@@ -1,7 +1,7 @@
{
"textures": [
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"] },
{ "name": "nor", "channels": ["nor_r", "nor_g", "nor_b", "1.0"] },
{ "name": "orm", "channels": ["occ", "rough", "metal", "1.0"] }
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "1.0"], "color_space": "linear" },
{ "name": "nor", "channels": ["nor_r", "nor_g", "nor_b", "1.0"], "color_space": "linear" },
{ "name": "orm", "channels": ["occ", "rough", "metal", "1.0"], "color_space": "linear" }
]
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"textures": [
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "rough"] },
{ "name": "nor", "channels": ["nor_r", "nor_g", "smooth", "metal"] }
{ "name": "base", "channels": ["base_r", "base_g", "base_b", "rough"], "color_space": "linear" },
{ "name": "nor", "channels": ["nor_r", "nor_g", "smooth", "metal"], "color_space": "linear" }
]
}
+40 -34
View File
@@ -20,6 +20,8 @@ import arm.Enums;
class ExportTexture {
static inline var gamma = 1.0 / 2.2;
public static function run(path: String, bakeMaterial = false) {
#if arm_debug
var timer = iron.system.Time.realTime();
@@ -267,48 +269,48 @@ class ExportTexture {
var c = t.channels;
var tex_name = t.name != "" ? "_" + t.name : "";
var singleChannel = c[0] == c[1] && c[1] == c[2] && c[3] == "1.0";
if (c[0] == "base_r" && c[1] == "base_g" && c[2] == "base_b" && c[3] == "1.0") {
if (c[0] == "base_r" && c[1] == "base_g" && c[2] == "base_b" && c[3] == "1.0" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint, 1);
}
else if (c[0] == "nor_r" && c[1] == "nor_g" && c[2] == "nor_b" && c[3] == "1.0") {
else if (c[0] == "nor_r" && c[1] == "nor_g" && c[2] == "nor_b" && c[3] == "1.0" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint_nor, 1);
}
else if (c[0] == "occ" && c[1] == "rough" && c[2] == "metal" && c[3] == "1.0") {
else if (c[0] == "occ" && c[1] == "rough" && c[2] == "metal" && c[3] == "1.0" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint_pack, 1);
}
else if (singleChannel && c[0] == "occ") {
else if (singleChannel && c[0] == "occ" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint_pack, 2, 0);
}
else if (singleChannel && c[0] == "rough") {
else if (singleChannel && c[0] == "rough" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint_pack, 2, 1);
}
else if (singleChannel && c[0] == "metal") {
else if (singleChannel && c[0] == "metal" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint_pack, 2, 2);
}
else if (singleChannel && c[0] == "height") {
else if (singleChannel && c[0] == "height" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint_pack, 2, 3);
}
else if (singleChannel && c[0] == "opac") {
else if (singleChannel && c[0] == "opac" && t.color_space == "linear") {
writeTexture(path + Path.sep + f + tex_name + ext, pixpaint, 2, 3);
}
else {
if (pix == null) pix = Bytes.alloc(textureSizeX * textureSizeY * 4 * Std.int(bits / 8));
for (i in 0...4) {
var c = t.channels[i];
if (c == "base_r") copyChannel(pixpaint, 0, pix, i); // copyChannelGamma
else if (c == "base_g") copyChannel(pixpaint, 1, pix, i); // copyChannelGamma
else if (c == "base_b") copyChannel(pixpaint, 2, pix, i); // copyChannelGamma
else if (c == "height") copyChannel(pixpaint_pack, 3, pix, i);
else if (c == "metal") copyChannel(pixpaint_pack, 2, pix, i);
else if (c == "nor_r") copyChannel(pixpaint_nor, 0, pix, i);
else if (c == "nor_g") copyChannel(pixpaint_nor, 1, pix, i);
else if (c == "nor_b") copyChannel(pixpaint_nor, 2, pix, i);
else if (c == "occ") copyChannel(pixpaint_pack, 0, pix, i);
else if (c == "opac") copyChannel(pixpaint, 3, pix, i);
else if (c == "rough") copyChannel(pixpaint_pack, 1, pix, i);
else if (c == "smooth") copyChannelInv(pixpaint_pack, 1, pix, i);
else if (c == "emis") extractChannel(pixpaint_nor, 3, pix, i, 255);
else if (c == "subs") extractChannel(pixpaint_nor, 3, pix, i, 254);
if (c == "base_r") copyChannel(pixpaint, 0, pix, i, t.color_space == "linear");
else if (c == "base_g") copyChannel(pixpaint, 1, pix, i, t.color_space == "linear");
else if (c == "base_b") copyChannel(pixpaint, 2, pix, i, t.color_space == "linear");
else if (c == "height") copyChannel(pixpaint_pack, 3, pix, i, t.color_space == "linear");
else if (c == "metal") copyChannel(pixpaint_pack, 2, pix, i, t.color_space == "linear");
else if (c == "nor_r") copyChannel(pixpaint_nor, 0, pix, i, t.color_space == "linear");
else if (c == "nor_g") copyChannel(pixpaint_nor, 1, pix, i, t.color_space == "linear");
else if (c == "nor_b") copyChannel(pixpaint_nor, 2, pix, i, t.color_space == "linear");
else if (c == "occ") copyChannel(pixpaint_pack, 0, pix, i, t.color_space == "linear");
else if (c == "opac") copyChannel(pixpaint, 3, pix, i, t.color_space == "linear");
else if (c == "rough") copyChannel(pixpaint_pack, 1, pix, i, t.color_space == "linear");
else if (c == "smooth") copyChannelInv(pixpaint_pack, 1, pix, i, t.color_space == "linear");
else if (c == "emis") extractChannel(pixpaint_nor, 3, pix, i, 255, t.color_space == "linear");
else if (c == "subs") extractChannel(pixpaint_nor, 3, pix, i, 254, t.color_space == "linear");
else if (c == "0.0") setChannel(0, pix, i);
else if (c == "1.0") setChannel(255, pix, i);
}
@@ -369,34 +371,37 @@ class ExportTexture {
Krom.fileSaveBytes(file, out.getBytes().getData(), out.getBytes().length);
}
static function copyChannel(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int) {
static function copyChannel(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int, linear = true) {
for (i in 0...Std.int(to.length / 4)) {
to.set(i * 4 + toChannel, from.get(i * 4 + fromChannel));
}
if (!linear) toSrgb(to, toChannel);
}
static inline var gamma = 1.0 / 2.2;
static function copyChannelGamma(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int) {
for (i in 0...Std.int(to.length / 4)) {
to.set(i * 4 + toChannel, Std.int(Math.pow(from.get(i * 4 + fromChannel) / 255, gamma) * 255));
}
}
static function copyChannelInv(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int) {
static function copyChannelInv(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int, linear = true) {
for (i in 0...Std.int(to.length / 4)) {
to.set(i * 4 + toChannel, 255 - from.get(i * 4 + fromChannel));
}
if (!linear) toSrgb(to, toChannel);
}
static function setChannel(value: Int, to: Bytes, toChannel: Int) {
static function extractChannel(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int, mask: Int, linear = true) {
for (i in 0...Std.int(to.length / 4)) {
to.set(i * 4 + toChannel, from.get(i * 4 + fromChannel) == mask ? 255 : 0);
}
if (!linear) toSrgb(to, toChannel);
}
static function setChannel(value: Int, to: Bytes, toChannel: Int, linear = true) {
for (i in 0...Std.int(to.length / 4)) {
to.set(i * 4 + toChannel, value);
}
if (!linear) toSrgb(to, toChannel);
}
static function extractChannel(from: Bytes, fromChannel: Int, to: Bytes, toChannel: Int, mask: Int) {
static function toSrgb(to: Bytes, toChannel: Int) {
for (i in 0...Std.int(to.length / 4)) {
to.set(i * 4 + toChannel, from.get(i * 4 + fromChannel) == mask ? 255 : 0);
to.set(i * 4 + toChannel, Std.int(Math.pow(to.get(i * 4 + toChannel) / 255, gamma) * 255));
}
}
}
@@ -408,4 +413,5 @@ typedef TExportPreset = {
typedef TExportPresetTexture = {
public var name: String;
public var channels: Array<String>;
public var color_space: String;
}
+12 -5
View File
@@ -18,6 +18,7 @@ class BoxExport {
public static var files: Array<String> = null;
public static var preset: TExportPreset = null;
static var channels = ["base_r", "base_g", "base_b", "height", "metal", "nor_r", "nor_g", "nor_b", "occ", "opac", "rough", "smooth", "emis", "subs", "0.0", "1.0"];
static var colorSpaces = ["linear", "srgb"];
public static function showTextures() {
UIBox.showCustom(function(ui: Zui) {
@@ -32,7 +33,7 @@ class BoxExport {
tabPresets(ui);
tabAtlases(ui);
}, 500, 310);
}, 540, 310);
}
public static function showBakeMaterial() {
@@ -47,7 +48,7 @@ class BoxExport {
tabExportTextures(ui, tr("Bake to Textures"), true);
tabPresets(ui);
}, 500, 310);
}, 540, 310);
}
static function tabExportTextures(ui: Zui, title: String, bakeMaterial = false) {
@@ -158,16 +159,17 @@ class BoxExport {
// Texture list
ui.separator(10, false);
ui.row([0.2, 0.2, 0.2, 0.2, 0.2]);
ui.row([1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6]);
ui.text(tr("Texture"));
ui.text(tr("R"));
ui.text(tr("G"));
ui.text(tr("B"));
ui.text(tr("A"));
ui.text(tr("Color Space"));
ui.changed = false;
for (i in 0...preset.textures.length) {
var t = preset.textures[i];
ui.row([0.2, 0.2, 0.2, 0.2, 0.2]);
ui.row([1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6]);
var htex = hpreset.nest(i);
htex.text = t.name;
t.name = ui.textInput(htex);
@@ -199,6 +201,11 @@ class BoxExport {
if (hb.changed) t.channels[2] = channels[hb.position];
ui.combo(ha, channels, tr("A"));
if (ha.changed) t.channels[3] = channels[ha.position];
var hspace = htex.nest(4);
hspace.position = colorSpaces.indexOf(t.color_space);
ui.combo(hspace, colorSpaces, tr("Color Space"));
if (hspace.changed) t.color_space = colorSpaces[hspace.position];
}
if (ui.changed) {
@@ -207,7 +214,7 @@ class BoxExport {
ui.row([1 / 8]);
if (ui.button(tr("Add"))) {
preset.textures.push({name: "base", channels: ["base_r", "base_g", "base_b", "1.0"]});
preset.textures.push({name: "base", channels: ["base_r", "base_g", "base_b", "1.0"], color_space: "linear"});
@:privateAccess hpreset.children = null;
savePreset();
}