mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-22 11:17:05 +02:00
feat: support transparency
This commit is contained in:
1 parent
06a3791ddd
commit
4ab03e56a2
7 files changed
+190
-184
No files matched your search
@@ -31,12 +31,12 @@ export async function tankModels() {
|
||||
|
||||
let index = 0;
|
||||
for (const [tankKey, tank] of entries) {
|
||||
console.log(` ${++index} / ${entries.length} : ${tankKey}`);
|
||||
|
||||
if (tankKey.includes("tutorial_bot")) continue;
|
||||
|
||||
const id = toUniqueId(nation, tank.id);
|
||||
|
||||
console.log(` ${++index} / ${entries.length} : ${tankKey}`);
|
||||
|
||||
const parameters = await readYAMLDVPL<TankParameters>(
|
||||
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
|
||||
);
|
||||
|
||||
@@ -39,82 +39,95 @@ export async function extractModel(data: string, path: string) {
|
||||
const buffer = document.createBuffer();
|
||||
const materials = new Map<bigint, Material | bigint | undefined>();
|
||||
|
||||
// create materials
|
||||
await Promise.all(
|
||||
sc2["#dataNodes"].map(async (node) => {
|
||||
const id = new DataView(node["#id"]).getBigUint64(0, true);
|
||||
for (const node of sc2["#dataNodes"]) {
|
||||
const id = new DataView(node["#id"]).getBigUint64(0, true);
|
||||
|
||||
if (node.parentMaterialKey !== undefined) {
|
||||
/**
|
||||
* material depends on a parent and doesn't seem to have any
|
||||
* properties so we just point it to the parent
|
||||
*/
|
||||
materials.set(id, node.parentMaterialKey);
|
||||
return;
|
||||
if (node.parentMaterialKey !== undefined) {
|
||||
/**
|
||||
* material depends on a parent and doesn't seem to have any
|
||||
* properties so we just point it to the parent
|
||||
*/
|
||||
materials.set(id, node.parentMaterialKey);
|
||||
continue;
|
||||
}
|
||||
|
||||
const material = document.createMaterial(node.materialName);
|
||||
let textures: Textures | undefined = undefined;
|
||||
|
||||
if (node.textures) {
|
||||
textures = node.textures;
|
||||
} else if (typeof node.configCount === "number") {
|
||||
textures = node.configArchive_0.textures;
|
||||
}
|
||||
|
||||
if (textures) {
|
||||
material.setBaseColorTexture(
|
||||
document
|
||||
.createTexture(node.materialName)
|
||||
.setMimeType("image/webp")
|
||||
.setImage(
|
||||
await readBaseColor(
|
||||
`${data}/3d/${dirname(path)}/${textures.baseColorMap ?? textures.albedo}`,
|
||||
textures.miscMap
|
||||
? `${data}/3d/${dirname(path)}/${textures.miscMap}`
|
||||
: undefined
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (node.configCount) {
|
||||
for (
|
||||
let configIndex = 0;
|
||||
configIndex < node.configCount;
|
||||
configIndex++
|
||||
) {
|
||||
const archive = node[`configArchive_${configIndex}`];
|
||||
|
||||
if (
|
||||
archive.configName !== "Default" ||
|
||||
!archive.enabledPresets?.AlphaTest
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
material.setAlphaMode("BLEND").setDoubleSided(true);
|
||||
}
|
||||
}
|
||||
|
||||
const material = document.createMaterial(node.materialName);
|
||||
let textures: Textures | undefined = undefined;
|
||||
|
||||
if (node.textures) {
|
||||
textures = node.textures;
|
||||
} else if (typeof node.configCount === "number") {
|
||||
textures = node.configArchive_0.textures;
|
||||
}
|
||||
|
||||
if (textures) {
|
||||
material.setBaseColorTexture(
|
||||
if (textures.baseRMMap) {
|
||||
material.setMetallicRoughnessTexture(
|
||||
document
|
||||
.createTexture(node.materialName)
|
||||
.setMimeType("image/jpeg")
|
||||
.setMimeType("image/webp")
|
||||
.setImage(
|
||||
await readBaseColor(
|
||||
`${data}/3d/${dirname(path)}/${textures.baseColorMap ?? textures.albedo}`,
|
||||
textures.miscMap
|
||||
? `${data}/3d/${dirname(path)}/${textures.miscMap}`
|
||||
: undefined
|
||||
await readRoughnessMetallic(
|
||||
`${data}/3d/${dirname(path)}/${textures.baseRMMap}`
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (textures.baseRMMap) {
|
||||
material.setMetallicRoughnessTexture(
|
||||
document
|
||||
.createTexture(node.materialName)
|
||||
.setMimeType("image/jpeg")
|
||||
.setImage(
|
||||
await readRoughnessMetallic(
|
||||
`${data}/3d/${dirname(path)}/${textures.baseRMMap}`
|
||||
)
|
||||
if (textures.baseNormalMap ?? textures.normalmap) {
|
||||
const isBase = textures.baseNormalMap !== undefined;
|
||||
|
||||
material.setNormalTexture(
|
||||
document
|
||||
.createTexture(node.materialName)
|
||||
.setMimeType("image/webp")
|
||||
.setImage(
|
||||
await readNormal(
|
||||
`${data}/3d/${dirname(path)}/${
|
||||
textures.baseNormalMap ?? textures.normalmap
|
||||
}`,
|
||||
isBase
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (textures.baseNormalMap ?? textures.normalmap) {
|
||||
const isBase = textures.baseNormalMap !== undefined;
|
||||
|
||||
material.setNormalTexture(
|
||||
document
|
||||
.createTexture(node.materialName)
|
||||
.setMimeType("image/jpeg")
|
||||
.setImage(
|
||||
await readNormal(
|
||||
`${data}/3d/${dirname(path)}/${
|
||||
textures.baseNormalMap ?? textures.normalmap
|
||||
}`,
|
||||
isBase
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
materials.set(
|
||||
new DataView(node["#id"]).getBigUint64(0, true),
|
||||
material
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
materials.set(new DataView(node["#id"]).getBigUint64(0, true), material);
|
||||
}
|
||||
}
|
||||
|
||||
// replace children materials with parents
|
||||
materials.forEach((material, id) => {
|
||||
|
||||
@@ -6,10 +6,7 @@ export async function readBaseColor(path: string, occlusionPath?: string) {
|
||||
const occlusionRaw = occlusionPath
|
||||
? await readTexture(occlusionPath)
|
||||
: undefined;
|
||||
const base = await sharp(baseRaw.data, { raw: baseRaw })
|
||||
.removeAlpha()
|
||||
.raw()
|
||||
.toBuffer();
|
||||
const base = await sharp(baseRaw.data, { raw: baseRaw }).raw().toBuffer();
|
||||
const occlusion = occlusionRaw
|
||||
? await sharp(occlusionRaw.data, { raw: occlusionRaw })
|
||||
.extractChannel(3)
|
||||
@@ -17,7 +14,7 @@ export async function readBaseColor(path: string, occlusionPath?: string) {
|
||||
.toBuffer()
|
||||
: undefined;
|
||||
|
||||
const combined = Buffer.alloc(baseRaw.width * baseRaw.height * 3);
|
||||
const combined = Buffer.alloc(baseRaw.width * baseRaw.height * 4);
|
||||
|
||||
for (let i = 0; i < baseRaw.width * baseRaw.height; i++) {
|
||||
let c = 1;
|
||||
@@ -33,15 +30,16 @@ export async function readBaseColor(path: string, occlusionPath?: string) {
|
||||
c = occlusion![occlusionI] / 255;
|
||||
}
|
||||
|
||||
combined[i * 3 + 0] = Math.round(base[i * 3 + 0] * c);
|
||||
combined[i * 3 + 1] = Math.round(base[i * 3 + 1] * c);
|
||||
combined[i * 3 + 2] = Math.round(base[i * 3 + 2] * c);
|
||||
combined[i * 4 + 0] = Math.round(base[i * 4 + 0] * c);
|
||||
combined[i * 4 + 1] = Math.round(base[i * 4 + 1] * c);
|
||||
combined[i * 4 + 2] = Math.round(base[i * 4 + 2] * c);
|
||||
combined[i * 4 + 3] = base[i * 4 + 3];
|
||||
}
|
||||
|
||||
const image = await sharp(combined, {
|
||||
raw: { width: baseRaw.width, height: baseRaw.height, channels: 3 },
|
||||
raw: { width: baseRaw.width, height: baseRaw.height, channels: 4 },
|
||||
})
|
||||
.jpeg()
|
||||
.webp()
|
||||
.toBuffer();
|
||||
|
||||
return image;
|
||||
|
||||
@@ -25,5 +25,5 @@ export async function readNormal(path: string, isBase: boolean) {
|
||||
raw.data[index + 3] = 255;
|
||||
}
|
||||
|
||||
return await sharp(raw.data, { raw }).jpeg().toBuffer();
|
||||
return await sharp(raw.data, { raw }).webp().toBuffer();
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export async function readRoughnessMetallic(path: string) {
|
||||
const image = await sharp(combined, {
|
||||
raw: { width: raw.width, height: raw.height, channels: 3 },
|
||||
})
|
||||
.jpeg()
|
||||
.webp()
|
||||
.toBuffer();
|
||||
|
||||
return image;
|
||||
|
||||
Reference in new issue
Block a user