The first commit, the core and all files is adding to repo
This commit is contained in:
96
renderer/render.mjs
Normal file
96
renderer/render.mjs
Normal file
@@ -0,0 +1,96 @@
|
||||
import { chromium } from "playwright";
|
||||
import { createServer } from "node:http";
|
||||
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
||||
import { resolve, sep } from "node:path";
|
||||
import sharp from "sharp";
|
||||
import { assetsRoot } from "../scripts/assets.mjs";
|
||||
/** @param {import('../shared/protocol').TerrainSnapshot} snapshot
|
||||
* @param {Array<{id:string,x:number,y:number,z:number}>} viewpoints
|
||||
* @param {string} output
|
||||
* @param {{size?:number,signal?:AbortSignal}} [options] */
|
||||
export async function renderSnapshot(
|
||||
snapshot,
|
||||
viewpoints,
|
||||
output,
|
||||
{ size = 1024, signal } = {},
|
||||
) {
|
||||
const start = Date.now();
|
||||
await mkdir(output, { recursive: true });
|
||||
const server = createServer(async (req, res) => {
|
||||
try {
|
||||
const url = new URL(req.url, "http://localhost");
|
||||
let path =
|
||||
url.pathname === "/three.js"
|
||||
? "node_modules/three/build/three.module.js"
|
||||
: url.pathname === "/three.core.js"
|
||||
? "node_modules/three/build/three.core.js"
|
||||
: url.pathname.startsWith("/assets/")
|
||||
? `${assetsRoot}/${url.pathname.slice(8)}`
|
||||
: url.pathname === "/"
|
||||
? "renderer/index.html"
|
||||
: url.pathname.slice(1);
|
||||
path = resolve(path);
|
||||
if (!path.startsWith(process.cwd() + sep))
|
||||
throw new Error("Invalid path");
|
||||
res.setHeader(
|
||||
"Content-Type",
|
||||
path.endsWith(".js")
|
||||
? "text/javascript"
|
||||
: path.endsWith(".json")
|
||||
? "application/json"
|
||||
: path.endsWith(".png")
|
||||
? "image/png"
|
||||
: "text/html",
|
||||
);
|
||||
res.end(await readFile(path));
|
||||
} catch {
|
||||
res.writeHead(404);
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
await new Promise((r) => server.listen(0, "127.0.0.1", r));
|
||||
let browser;
|
||||
try {
|
||||
browser = await chromium.launch({
|
||||
headless: true,
|
||||
args: ["--use-angle=swiftshader", "--enable-unsafe-swiftshader"],
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
page.on("pageerror", (err) => console.error("Renderer:", err.message));
|
||||
await page.goto(`http://127.0.0.1:${server.address().port}`);
|
||||
await page.waitForFunction(() => window.rendererReady);
|
||||
const stats = await page.evaluate((s) => window.buildTerrain(s), snapshot);
|
||||
for (const p of viewpoints) {
|
||||
if (signal?.aborted) throw new Error("Rendering cancelled");
|
||||
await mkdir(`${output}/${p.id}`, { recursive: true });
|
||||
for (const face of ["px", "nx", "py", "ny", "pz", "nz"]) {
|
||||
const data = await page.evaluate(
|
||||
({ p, face, size }) => window.renderFace(p, face, size),
|
||||
{ p, face, size },
|
||||
);
|
||||
const png = Buffer.from(data.split(",")[1], "base64");
|
||||
await sharp(png)
|
||||
.webp({ quality: 85 })
|
||||
.toFile(`${output}/${p.id}/${face}.webp`);
|
||||
if (face === "nz")
|
||||
await sharp(png)
|
||||
.resize(512, 512)
|
||||
.webp({ quality: 76 })
|
||||
.toFile(`${output}/${p.id}/preview.webp`);
|
||||
}
|
||||
}
|
||||
const map = await page.evaluate(() => window.renderMap(1024));
|
||||
await sharp(Buffer.from(map.split(",")[1], "base64"))
|
||||
.webp({ quality: 90 })
|
||||
.toFile(`${output}/map.webp`);
|
||||
stats.renderMs = Date.now() - start;
|
||||
await writeFile(
|
||||
`${output}/render-report.json`,
|
||||
JSON.stringify(stats, null, 2),
|
||||
);
|
||||
return stats;
|
||||
} finally {
|
||||
await browser?.close();
|
||||
await new Promise((r) => server.close(r));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user