feat: baked ao

This commit is contained in:
TrèsAbhi committed 2025-09-06 00:48:39 -05:00
1 parent 335cd4d699
commit 66cf1fd223
11 files changed
+75 -93

No files matched your search

+12 -14
View File
@@ -1,8 +1,8 @@
import { ReadStream } from '@blitzkit/core'; import { ReadStream } from "@blitzkit/core";
import AdmZip from 'adm-zip'; import AdmZip from "adm-zip";
import { readFile, writeFile } from 'fs/promises'; import { readFile } from "fs/promises";
import { Parser } from 'pickleparser'; import { Parser } from "pickleparser";
import protobuf from 'protobufjs'; import protobuf from "protobufjs";
interface WotbReplayMetaJson { interface WotbReplayMetaJson {
version: string; version: string;
@@ -24,26 +24,24 @@ export class WotbReplayReadStream extends ReadStream {
async wotbReplay() { async wotbReplay() {
const pickleParser = new Parser(); const pickleParser = new Parser();
const zip = new AdmZip(Buffer.from(this.buffer)); const zip = new AdmZip(Buffer.from(this.buffer));
const metaJsonBuffer = zip.getEntry('meta.json')?.getData(); const metaJsonBuffer = zip.getEntry("meta.json")?.getData();
const battleResultsDat = zip.getEntry('battle_results.dat')?.getData(); const battleResultsDat = zip.getEntry("battle_results.dat")?.getData();
if (!metaJsonBuffer || !battleResultsDat) if (!metaJsonBuffer || !battleResultsDat)
throw new SyntaxError('meta.json not found'); throw new SyntaxError("meta.json not found");
const metaJson = JSON.parse( const metaJson = JSON.parse(
metaJsonBuffer.toString(), metaJsonBuffer.toString()
) as WotbReplayMetaJson; ) as WotbReplayMetaJson;
const unpickledBattleResults = pickleParser.parse(battleResultsDat); const unpickledBattleResults = pickleParser.parse(battleResultsDat);
const [, battleResultsString] = unpickledBattleResults as [number, string]; const [, battleResultsString] = unpickledBattleResults as [number, string];
const root = await protobuf.load( const root = await protobuf.load(
`${__dirname}/../../protos/BattleResultsClient.proto`, `${__dirname}/../../protos/BattleResultsClient.proto`
); );
const BattleResults = root.lookupType( const BattleResults = root.lookupType(
'BattleResultsGenerated.BattleResultsClient', "BattleResultsGenerated.BattleResultsClient"
); );
writeFile('test.dat', Buffer.from(battleResultsString));
const reader = protobuf.Reader.create(Buffer.from(battleResultsString)); const reader = protobuf.Reader.create(Buffer.from(battleResultsString));
// const decodedBattleResults = BattleResults.decodeDelimited( // const decodedBattleResults = BattleResults.decodeDelimited(
@@ -53,7 +51,7 @@ export class WotbReplayReadStream extends ReadStream {
} }
} }
const replay = await readFile('temp/test3.wotbreplay'); const replay = await readFile("temp/test3.wotbreplay");
const stream = new WotbReplayReadStream(replay.buffer as ArrayBuffer); const stream = new WotbReplayReadStream(replay.buffer as ArrayBuffer);
stream.wotbReplay(); stream.wotbReplay();
@@ -1,10 +1,11 @@
import { toUniqueId } from "@blitzkit/core"; import { toUniqueId } from "@blitzkit/core";
import { NodeIO } from "@gltf-transform/core"; import { NodeIO } from "@gltf-transform/core";
import { ALL_EXTENSIONS } from "@gltf-transform/extensions"; import { ALL_EXTENSIONS } from "@gltf-transform/extensions";
import { readdir, writeFile } from "fs/promises"; import { readdir } from "fs/promises";
import { extractModel } from "../core/blitz/extractModel"; import { extractModel } from "../core/blitz/extractModel";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { commitAssets } from "../core/github/commitAssets";
import { FileChange } from "../core/github/commitMultipleFiles"; import { FileChange } from "../core/github/commitMultipleFiles";
import { DATA } from "./constants"; import { DATA } from "./constants";
import { VehicleDefinitionList } from "./definitions"; import { VehicleDefinitionList } from "./definitions";
@@ -36,8 +37,6 @@ export async function tankModels() {
const id = toUniqueId(nation, tank.id); const id = toUniqueId(nation, tank.id);
if (id !== 5681) continue;
const parameters = await readYAMLDVPL<TankParameters>( const parameters = await readYAMLDVPL<TankParameters>(
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
); );
@@ -48,13 +47,8 @@ export async function tankModels() {
const content = Buffer.from(await nodeIO.writeBinary(model)); const content = Buffer.from(await nodeIO.writeBinary(model));
changes.push({ path: `3d/tanks/models/${id}.glb`, content }); changes.push({ path: `3d/tanks/models/${id}.glb`, content });
await writeFile(
"C:/Projects/blitzkit/packages/website/public/test.glb",
content
);
} }
// await commitAssets(`tank models ${nation}`, changes); await commitAssets(`tank models ${nation}`, changes);
} }
} }
@@ -12,7 +12,6 @@ import { dirname } from "path";
import { readBaseColor } from "../readBaseColor"; import { readBaseColor } from "../readBaseColor";
import { readDVPLFile } from "../readDVPLFile"; import { readDVPLFile } from "../readDVPLFile";
import { readNormal } from "../readNormal"; import { readNormal } from "../readNormal";
import { readOcclusion } from "../readOcclusion";
import { readRoughnessMetallic } from "../readRoughnessMetallic"; import { readRoughnessMetallic } from "../readRoughnessMetallic";
import { import {
vertexAttributeGLTFName, vertexAttributeGLTFName,
@@ -70,7 +69,10 @@ export async function extractModel(data: string, path: string) {
.setMimeType("image/jpeg") .setMimeType("image/jpeg")
.setImage( .setImage(
await readBaseColor( await readBaseColor(
`${data}/3d/${dirname(path)}/${textures.baseColorMap ?? textures.albedo}` `${data}/3d/${dirname(path)}/${textures.baseColorMap ?? textures.albedo}`,
textures.miscMap
? `${data}/3d/${dirname(path)}/${textures.miscMap}`
: undefined
) )
) )
); );
@@ -88,19 +90,6 @@ export async function extractModel(data: string, path: string) {
); );
} }
if (textures.miscMap) {
material.setOcclusionTexture(
document
.createTexture(node.materialName)
.setMimeType("image/jpeg")
.setImage(
await readOcclusion(
`${data}/3d/${dirname(path)}/${textures.miscMap}`
)
)
);
}
if (textures.baseNormalMap ?? textures.normalmap) { if (textures.baseNormalMap ?? textures.normalmap) {
const isBase = textures.baseNormalMap !== undefined; const isBase = textures.baseNormalMap !== undefined;
@@ -236,10 +225,6 @@ export async function extractModel(data: string, path: string) {
.setBuffer(buffer); .setBuffer(buffer);
primitive.setAttribute(name, attributeAccessor); primitive.setAttribute(name, attributeAccessor);
if (attribute === VertexAttribute.TEXCOORD0) {
primitive.setAttribute("TEXCOORD_2", attributeAccessor);
}
}); });
const mesh = document const mesh = document
@@ -1,7 +1,48 @@
import sharp from "sharp"; import sharp from "sharp";
import { readTexture } from "./readTexture"; import { readTexture } from "./readTexture";
export async function readBaseColor(path: string) { export async function readBaseColor(path: string, occlusionPath?: string) {
const raw = await readTexture(path); const baseRaw = await readTexture(path);
return await sharp(raw.data, { raw }).removeAlpha().jpeg().toBuffer(); const occlusionRaw = occlusionPath
? await readTexture(occlusionPath)
: undefined;
const base = await sharp(baseRaw.data, { raw: baseRaw })
.removeAlpha()
.raw()
.toBuffer();
const occlusion = occlusionRaw
? await sharp(occlusionRaw.data, { raw: occlusionRaw })
.extractChannel(3)
.raw()
.toBuffer()
: undefined;
const combined = Buffer.alloc(baseRaw.width * baseRaw.height * 3);
for (let i = 0; i < baseRaw.width * baseRaw.height; i++) {
let c = 1;
if (occlusionRaw) {
const x = i % baseRaw.width;
const y = Math.floor(i / baseRaw.width);
const u = Math.floor(x * (occlusionRaw.width / baseRaw.width));
const v = Math.floor(y * (occlusionRaw.height / baseRaw.height));
const occlusionI = u + v * occlusionRaw.width;
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);
}
const image = await sharp(combined, {
raw: { width: baseRaw.width, height: baseRaw.height, channels: 3 },
})
.jpeg()
.toBuffer();
return image;
} }
@@ -17,8 +17,7 @@ export async function readNormal(path: string, isBase: boolean) {
*/ */
let x = raw.data[index + 3] * (2 / 255) - 1; let x = raw.data[index + 3] * (2 / 255) - 1;
let y = raw.data[index + 1] * (2 / 255) - 1; let y = raw.data[index + 1] * (2 / 255) - 1;
const underSqrt = 1 - x ** 2 - y ** 2; let z = Math.sqrt(Math.max(0, 1 - x ** 2 - y ** 2));
let z = underSqrt > 0 ? Math.sqrt(underSqrt) : -Math.sqrt(-underSqrt);
raw.data[index] = Math.round((x + 1) * (255 / 2)); raw.data[index] = Math.round((x + 1) * (255 / 2));
raw.data[index + 1] = Math.round((y + 1) * (255 / 2)); raw.data[index + 1] = Math.round((y + 1) * (255 / 2));
@@ -1,25 +0,0 @@
import { writeFile } from "fs/promises";
import sharp from "sharp";
import { readTexture } from "./readTexture";
export async function readOcclusion(path: string) {
const raw = await readTexture(path);
const blitz = sharp(raw.data, { raw: raw });
const occlusion = await blitz?.extractChannel(3).raw().toBuffer();
const combined = Buffer.alloc(raw.width * raw.height * 3);
for (let i = 0; i < raw.width * raw.height; i++) {
combined[i * 3 + 0] = occlusion?.[i] ?? 0;
}
const image = await sharp(combined, {
raw: { width: raw.width, height: raw.height, channels: 3 },
})
.jpeg()
.toBuffer();
writeFile("test.ao.jpg", image);
return image;
}
@@ -1,4 +1,3 @@
import { writeFile } from "fs/promises";
import sharp from "sharp"; import sharp from "sharp";
import { readTexture } from "./readTexture"; import { readTexture } from "./readTexture";
@@ -11,8 +10,8 @@ export async function readRoughnessMetallic(path: string) {
const combined = Buffer.alloc(raw.width * raw.height * 3); const combined = Buffer.alloc(raw.width * raw.height * 3);
for (let i = 0; i < raw.width * raw.height; i++) { for (let i = 0; i < raw.width * raw.height; i++) {
combined[i * 3 + 1] = roughness?.[i] ?? 0; combined[i * 3 + 1] = roughness[i];
combined[i * 3 + 2] = metallicness?.[i] ?? 0; combined[i * 3 + 2] = metallicness[i];
} }
const image = await sharp(combined, { const image = await sharp(combined, {
@@ -21,7 +20,5 @@ export async function readRoughnessMetallic(path: string) {
.jpeg() .jpeg()
.toBuffer(); .toBuffer();
writeFile("test.rm.jpg", image);
return image; return image;
} }
@@ -11,7 +11,7 @@ const LIGHTS_COUNT = 5;
const LIGHT_DISTANCE = 13; const LIGHT_DISTANCE = 13;
const LIGHT_HEIGHT_0 = 4; const LIGHT_HEIGHT_0 = 4;
const LIGHT_HEIGHT_1 = 2; const LIGHT_HEIGHT_1 = 2;
const INTENSITY = 30; const INTENSITY = 35;
const N = 128; const N = 128;
const TARGET_FRAME_RATE = 30; const TARGET_FRAME_RATE = 30;
@@ -64,7 +64,7 @@ export function Lighting() {
position={position} position={position}
intensity={INTENSITY} intensity={INTENSITY}
penumbra={1} penumbra={1}
// castShadow={cast} castShadow={cast}
decay={1} decay={1}
color={color} color={color}
/> />
@@ -1,8 +1,8 @@
import { invalidate, useFrame } from '@react-three/fiber'; import { invalidate, useFrame } from "@react-three/fiber";
import { clamp } from 'lodash-es'; import { clamp } from "lodash-es";
import { Quicklime, type QuicklimeEvent } from 'quicklime'; import { Quicklime, type QuicklimeEvent } from "quicklime";
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from "react";
import { Mesh, MeshStandardMaterial } from 'three'; import { Mesh, MeshStandardMaterial } from "three";
const SIZE = 2 ** 5; const SIZE = 2 ** 5;
@@ -28,13 +28,6 @@ export function TankModel() {
const { gltf } = useModel(protagonist.tank.id); const { gltf } = useModel(protagonist.tank.id);
const nodes = Object.values(gltf.nodes); const nodes = Object.values(gltf.nodes);
nodes.forEach((n) => {
if (n instanceof Mesh && n.material instanceof MeshStandardMaterial) {
n.material.aoMapIntensity = 10;
console.log(n.geometry.attributes);
}
});
useTankTransform(track, turret, turretContainer, gunContainer); useTankTransform(track, turret, turretContainer, gunContainer);
return ( return (
+2 -2
View File
@@ -1,3 +1,4 @@
import { asset } from "@blitzkit/core";
import { type ObjectMap, useLoader } from "@react-three/fiber"; import { type ObjectMap, useLoader } from "@react-three/fiber";
import { Mesh, MeshStandardMaterial } from "three"; import { Mesh, MeshStandardMaterial } from "three";
import { type GLTF, GLTFLoader } from "three-stdlib"; import { type GLTF, GLTFLoader } from "three-stdlib";
@@ -11,8 +12,7 @@ const cache: Record<
> = {}; > = {};
export function useModel(id: number) { export function useModel(id: number) {
// const gltf = useLoader(GLTFLoader, asset(`3d/tanks/models/${id}.glb`)); const gltf = useLoader(GLTFLoader, asset(`3d/tanks/models/${id}.glb`));
const gltf = useLoader(GLTFLoader, `/test.glb`);
if (!cache[id]) { if (!cache[id]) {
cache[id] = { cache[id] = {