PSXIFY
Desenvolupador en solitari · Eines de desenvolupament
Anàlisi post mortem d'una eina en Rust que cou models amb molts polígons en assets estil PS1, amb un pipeline de memòries cau per etapes, un lector de Blender que no necessita Blender i el disseny de culling que va sorgir del tractament de transparències.
Stack
Rust, egui, glTF, FBX, meshoptimizer, rayon
Enllaços

Resum
PSXIFY agafa un model amb molts polígons i produeix una malla de baix polígon amb una textura petita de paleta limitada. La part difícil no és un pas concret. Cada etapa depèn de l’anterior, i l’usuari necessita ajustar el resultat en temps real, així que el pipeline no pot refer feina que no ha canviat.
Aquesta anàlisi post mortem repassa com està organitzat el pipeline, els tres problemes que més van canviar el disseny i el que l’eina encara no fa.
Pipeline com a cadena de memòries cau
El processament té tres etapes. Cada una desa el resultat sota una clau formada pels paràmetres que l’afecten:
- Geometria. La malla se solda, es netegen les peces petites, les cares ocultes s’eliminen amb un raycast sobre una BVH i se simplifica amb meshoptimizer. La clau inclou el mode de reducció, l’objectiu, el flag de peces, el llindar de neteja i el mode de culling.
- Bake. Es desenvolupen i s’empaqueten UV noves i es couen albedo, oclusió, normals, metall i emissió des del model original. La clau afegeix la mida de textura, perquè la resolució de bake és quatre vegades la mida final, amb un màxim de 1024.
- Composició i quantització. Els sliders d’AO, relleu i llum s’apliquen sobre el bake desat, la imatge es redueix i la paleta es quantitza amb dither. Aquesta és l’única etapa que es recalcula en moure’ls.
El resultat és que moure el nombre de colors o el dither costa mil·lisegons, perquè es reutilitzen la geometria i el bake. El cost és classificar bé cada paràmetre: si una clau inclou alguna cosa que no afecta l’etapa, es recalcula de més, i si li falta alguna cosa, el resultat desat queda obsolet sense avisar. Per això hi ha proves per a aquests casos límit, per exemple per comprovar que l’objectiu en triangles no invalida la geometria quan el mode actiu és percentatge.
Llegir .blend sense Blender
Els fitxers de Blender són una entrada habitual, i exigir una instal·lació local de Blender hauria deixat l’eina fora de l’abast de qualsevol que no la tingués. Per això l’app llegeix els .blend directament.
Cada fitxer inclou la seva pròpia descripció d’estructures internes (SDNA), així que el lector busca els camps pel nom en lloc d’usar desplaçaments fixos. Això permet que un mateix lector cobreixi dades de malla de Blender 3.x (MVert, MPoly, MLoop) i l’emmagatzematge per atributs de 4.x i 5.x, comprimits o no. El lector cobreix el que el pipeline necessita: dades de malla, jerarquies d’objectes amb els modes de rotació habituals i les entrades del Principled BSDF que alimenten el bake. La resta s’ignora amb un avís visible a l’app, perquè el fracàs no sigui silenciós.
Targetes transparents i culling
El culling de cares ocultes parteix d’una suposició: el que hi ha davant d’una superfície és sòlid. En tanques o fullatge aquesta suposició no es compleix. Una targeta transparent davant d’una superfície la taparia en el test de visibilitat, i s’eliminaria geometria que sí que es veu a través dels retalls.
Per això l’etapa de geometria comprova has_transparency() al model. Si és cert, el culling es desactiva, però la neteja de peces i la simplificació continuen executant-se.
El bake també deixa passar la llum segons l’opacitat, perquè l’AO no enfosqueixi zones que es veuen a través d’un retall. La preview usa profunditat per als texels opacs i composició ordenada per triangles per als transparents. Les superfícies transparents que s’intersequen poden mostrar artefactes, que és la limitació habitual d’aquest ordre.
Reducció que no esborra peces
En simplificar el model complet apareix una fallada previsible: les peces petites i separades, com les targetes d’un fullatge, es poden quedar sense triangles quan el pressupost és ajustat. En mode Pieces cada component connectat conserva almenys quatre triangles, o tots si en tenia menys. Si el decimador baixa d’aquest mínim, el pressupost d’aquella peça s’augmenta fins que sobrevisqui.
La conseqüència és que un objectiu molt baix pot produir més triangles dels demanats. La interfície i el README ho diuen així, perquè l’alternativa era esborrar geometria en silenci. Una prova comprova que deu targetes de dues cares sobreviuen a la reducció, al bake i a un canvi entre modes de memòria cau.
Si la reducció elimina totes les cares, el pipeline retorna un error explícit en lloc d’una malla buida, i el missatge suggereix pujar l’objectiu o activar Pieces.
Resultats
El payphone de Poly Haven que apareix al vídeo promocional és un model de 48.132 triangles amb textures PBR de 2K. El resultat té 798 triangles, una textura de 256 px i 15 colors. Model de Poly Haven, llicència CC0, autoria d’UM JOORIN.
Límits
- Només malles estàtiques. Esquelets, animació i textures UDIM queden fora.
- Els materials procedimentals de Blender no s’avaluen; només s’usa el node de color base.
- Dels modificadors de Blender només s’aplica Mirror. Subdivision, Edge Split, Weighted Normal, Triangulate i Smooth by Angle no canvien el resultat i s’ometen. Els altres s’ignoren amb avís, així que Array, Boolean i Geometry Nodes s’han d’aplicar abans a Blender.
- El build de macOS és universal. Windows i Linux estan marcats com a beta perquè s’han provat menys.
La meva aportació
Vaig dissenyar i desenvolupar l’eina: el pipeline i les seves claus de memòria cau, el lector de .blend, el tractament de transparències, el shader de la preview, els presets d’exportació per a Unity, Unreal, Godot i Blender, la interfície de línia d’ordres i la publicació.
Stack
- Rust, amb
eframe/ egui per a la interfície i la preview ufbxper a FBX i OBJ, igltfper a glTF i GLBmeshopt(meshoptimizer) per a la simplificació,rayonper al paral·lelisme iglamper a les matemàtiquesruzstdper als.blendcomprimits, iimage,pngiexrper a les texturesobjc2i AppKit per als diàlegs natius de macOS