2024-5-20-bakemaster烘焙udim贴图通道打包问题

制作诚宵宫开始碰到面数较高的几何体udim多项线烘培遮罩的问题,bakemaster目前无法channel packing udim贴图,后来我找了ue的channel pack插件诡异的是效果不对,而且要批量处理也是个问题。

再然后我考虑拆分packedATexture把打包的遮罩拆分,但又发现udim烘焙只有1001 1002两个uv单元输出正常其余都丢失了,然而在blender internal中遮罩贴图显示正常,在uvEditor中的image菜单save all images,输出丢失的那些uv单元会被替换从而正常。

目前还有两个问题一个是udim贴图通道打包不成功。另一个问题是bakemaster中Uv Map Type无法保存预设,一直是默认的single。

2024-5-19更新:

Uv Map Type无法保存预设的问题我把bakemaster插件的utils.py默认的排序改了,经测试没有问题。

更新了MaterialConvertInstance实测成功。

通过这段代码可以把选中物体批量做smart uv unwrap。

在smart uv unwrap之后选中物体所有面进入uv editor,uvpackmaster在groups independent模式下可以批量做uv 打包。

一个项目中30多个复杂高面数需要udim unwrap的物体blender应该没有压力。

2024-5-20更新:

经过大半天盘问chatgpt,udim贴图的通道打包通过外部python程序解决了

今天换了个思路折腾了一天,我看在photoshop中通过图层混合选项分组打包通道没有损失于是想如何利用photoshop控制自动批量打包通道,上来先是想python,不过ps并没有自带支持python的脚本编辑器,github上的外部插件没啥社区支持,太难了放弃。ps中文件菜单下有自动批处理、脚本,首先批处理我也想过,但这涉及要操控多个源文件夹,ps的批处理最多设定一个源文件夹,我的应用场景是对多个子文件夹的贴图各自创建文档加载贴图到不同图层然后设置通道显示。要把多个图片加载到同一个ps文档里用批处理是做不到的,这看起来很基本的操作网上也没多少帖子有操作说明,直接让chatgpt写ps的js脚本那是一团糟的不懂装懂,而且ps的js都不好调试,出错了也不知道啥情况。在ps官网讨论上看到,拿了下面的代码试了下,里面有个链接正好包含了打开一个文件夹将所有子文件夹中包含的3个图片加载到一个ps文档且为独立图层。

接着是对图层通道显示设置,我原以为这很容易解决了。没想到这里面设计很复杂的ps内部逻辑api。在这个贴子最下面的代码演示了如何用ps的scriptlistener相关api控制通道显示。我试着让chatgpt在这个基础上修改实现了对当前打开文档的指定图层控制通道显示。

最后就是将两段代码合起来并输出,这里还涉及到一个难点,输出格式要.exr不是简单的在文件名加个.exr后缀就解决了。我发现psd导入ue居然打不开,本来是想偷懒直接用psd完事的,psd打不开我也没想转换tiff、png啥的就咬牙去搜exr的保存方式。

最后就是把bakemaster输出的贴图文件归类子文件夹,这个想想也不算难度太大就是一个正则表达判断文件名,python两下搞定了。

ue实测三通道重复的单一贴图和打包合并的贴图质量一样且资源大小一样,意味着节省了多余的两份贴图。

我把bakemaster 通道打包需要的两个脚本放在这个文件夹下,使用方法是先用blender python脚本对选中的物体smart unwrap,进入面模式用uvpackmaster在group indepentent模式下可以对物体各自做uv packing,确保x顶个设置,uv texel density统一设置100差不多。

对选中物体做smart unwrap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  

import bpy

# 获取当前场景中选择的对象
selected_objects = bpy.context.selected_objects

# 遍历每个选择的对象
for obj in selected_objects:
# 选择当前对象的 Edit 模式
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')

# 选择所有面
bpy.ops.mesh.select_all(action='SELECT')

# 执行 Smart UV Unwrap 操作
bpy.ops.uv.smart_project(angle_limit=66, island_margin=0 , area_weight=0)

# 退出 Edit 模式
bpy.ops.object.mode_set(mode='OBJECT')

bakemaster批量烘焙好贴图后,运行“把物体对应的3个贴图分类子文件夹.py”创建子文件夹归类,打开ps>文件菜单>脚本>浏览,选择”对子文件夹中包含的exr添加到独立图层并保存psd文件.js“在弹出的对话框选择bakemaster输出的贴图目录,js脚本会将贴图打包通道并保存修改文件名至指定文件夹,大功告成。

把物体对应的3个贴图分类子文件夹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  

import os
import re
import shutil

# 定义文件夹路径
folder_path = "F:/mm"

# 遍历文件夹中的文件
for filename in os.listdir(folder_path):
# 匹配文件名中的物体名和数字序列
match = re.match(r'(.+?)(?:_AO|_XYZ|_CURV)?(\.\d+)?\.exr', filename)
if match:
object_name = match.group(1)
sequence = match.group(2) if match.group(2) else ''

# 构建目标文件夹路径
target_folder = os.path.join(folder_path, f"{object_name}{sequence}")

# 如果目标文件夹不存在则创建
if not os.path.exists(target_folder):
os.makedirs(target_folder)

# 移动文件到目标文件夹
shutil.move(os.path.join(folder_path, filename), os.path.join(target_folder, filename))

对子文件夹中包含的exr添加到独立图层并保存psd文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  


#target photoshop;

main();

function main() {
var inputFolder = Folder.selectDialog("请选择包含子文件夹的文件夹");
if (inputFolder == null) return;

var subfolders = inputFolder.getFiles(Folder.SELECT);
for (var i = 0; i < subfolders.length; i++) {
var subfolder = subfolders[i];
if (subfolder instanceof Folder) {
processSubfolder(subfolder);
}
}
}

function processSubfolder(subfolder) {
var fileList = subfolder.getFiles(/\.(exr)$/i);
var files = [];

while (fileList.length > 2) {
for (var a = 0; a < 3; a++) {
files.push(fileList.shift());
}
var name = decodeURI(files[0].name).replace(/\.[^\.]+$/, '');
stackFiles(files, name, subfolder);
files = [];
}
}

function stackFiles(files, name, subfolder) {
var loadLayersFromScript = true;
$.evalFile(app.path + "/" + localize("$$$/ScriptingSupport/InstalledScripts=Presets/Scripts") + "/Load Files into Stack.jsx");
loadLayers.intoStack(files);

// 堆叠后进行通道混合
var doc = app.activeDocument;
if (doc.layers.length >= 3) {
// 第一个图层只显示 G 通道
var layer1 = doc.layers[0];
doc.activeLayer = layer1;
advancedBlend(false, true, false, layer1);

// 第二个图层只显示 B 通道
var layer2 = doc.layers[1];
doc.activeLayer = layer2;
advancedBlend(false, false, true, layer2);

// 第三个图层只显示 R 通道
var layer3 = doc.layers[2];
doc.activeLayer = layer3;
advancedBlend(true, false, false, layer3);

// 保存为 PSD 文件
name = removeSpecialKeywords(name)
var saveFile = new File("F:/UdimChannelPacking/" + name + ".exr");
saveEXR(0, 1, saveFile, false, true);

doc.close(SaveOptions.DONOTSAVECHANGES);
} else {
alert("堆叠后的文档中需要至少三个图层。");
}
}

function savePSD(saveFile) {
var psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
}

// 定义高级图层混合函数
function advancedBlend(RED, GREEN, BLUE, layer) {
function cTID(s) { return app.charIDToTypeID(s); };
function sTID(s) { return app.stringIDToTypeID(s); };

var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
desc.putReference(cTID('null'), ref);
var layerStyleDesc = new ActionDescriptor();
var channelRestrictionsList = new ActionList();
if (RED) {
channelRestrictionsList.putEnumerated(cTID('Chnl'), cTID('Rd '));
}
if (GREEN) {
channelRestrictionsList.putEnumerated(cTID('Chnl'), cTID('Grn '));
}
if (BLUE) {
channelRestrictionsList.putEnumerated(cTID('Chnl'), cTID('Bl '));
}
layerStyleDesc.putList(sTID('channelRestrictions'), channelRestrictionsList);
desc.putObject(cTID('T '), cTID('Lyr '), layerStyleDesc);
executeAction(cTID('setd'), desc, DialogModes.NO);
}

function saveEXR(compression, alphaChannelOptions, savePath, asCopy, lowerCase) {
// Compression: 0 = None | 1 = RLE | 2 = Zlib | 4 = Wavelet | 5 = PIXR24 on 32 bit
function c2t(s) {
return app.charIDToTypeID(s);
}
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putInteger( s2t( "bitDepth" ), 32 );
descriptor2.putInteger( s2t("compression"), compression );
descriptor2.putInteger( s2t( "alphaChannelOptions" ), alphaChannelOptions );
descriptor.putObject( s2t( "as" ), c2t( "EXRf" ), descriptor2 );
descriptor.putPath( s2t( "in" ), savePath );
descriptor.putBoolean( s2t( "copy" ), asCopy );
descriptor.putBoolean( s2t( "lowerCase" ), lowerCase );
descriptor.putEnumerated( s2t( "saveStage" ), s2t( "saveStageType" ), s2t( "saveSucceeded" ));
executeAction( s2t( "save" ), descriptor, DialogModes.NO );
}



function removeSpecialKeywords(name) {
// 使用正则表达式删除特殊关键字
return name.replace(/(_AO|_CURV|_XYZ)/g, "");
}

2024-5-22-SendToUE养性殿 2024-5-9-SendToUE红砖大理石叠墅

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×