-
Notifications
You must be signed in to change notification settings - Fork 0
Tech Art & Optimization
While the City Planner and Architect systems handle the logic and geometry, the visual fidelity and performance of the simulation rely on a robust Technical Art pipeline.
This section details the shader solutions for procedural geometry, the material workflow, and the optimization strategies implemented to maintain real-time frame rates with high object counts.
Key Technologies: Unity Shader Graph, Particle System, Static Batching, GPU Instancing.
A major challenge in procedural generation is UV mapping. Since the building footprints (and therefore roof/pavement meshes) are generated dynamically with irregular shapes and sizes, standard UV unwrap techniques result in severe texture stretching or misalignment.
To solve this, I implemented a Triplanar Mapping solution using Unity Shader Graph.
- Logic: Instead of relying on mesh UVs, the shader projects textures based on the world-space position of the fragments.
- Implementation: The shader samples the texture three times (X, Y, Z axes) and blends them based on the surface normal.
- Result: Roof tiles, cobblestones, and brickwork maintain a consistent physical scale regardless of how large, small, or distorted the underlying procedural mesh becomes.
Attic Roof (Top): Triplanar Shader - Correct | Mansard Roof (Bottom): Stretched UVs - Wrong.
To achieve the specific 18th-century Parisian aesthetic, the system uses a modular asset library created by Environment Artist Stefani Badzheva.
- Substance Workflow: Materials were authored in Substance Designer, exposing parameters for dirt and weathering to break up visual repetition.
- Texture Atlasing: Where possible, modular elements share texture atlases to reduce draw calls and material swaps.
- LOD Groups: High-fidelity props (like the ironwork balconies) are heavy on geometry. I implemented aggressive LOD (Level of Detail) Groups to cull these details at a distance, preserving the silhouette while saving vertex processing costs.
LOD groups implemented for heavy meshes with help of MeshOptimizer plugin.
Generating a city involves creating thousands of GameObjects. Without optimization, this would cripple the CPU. I implemented a multi-layered optimization strategy:
-
Static Batching: The
CitySectorGeneratorautomatically flags generated buildings asStaticimmediately after generation. This allows Unity to batch non-moving geometry into fewer draw calls. - GPU Instancing: For repeated modular props (like chimney pots and window frames) that share materials, GPU Instancing is enabled to render identical meshes in a single pass.
Shadow casting is one of the most expensive rendering operations.
- Problem: Initially, the scene had over 20,000 individual shadow casters, causing massive performance drops.
- Solution: I tuned the shadow settings and disabled shadow casting on small, non-essential details (like small facade ornaments).
- Result: Reduced shadow casters to approximately 1,000, significantly improving the frame rate without a noticeable loss in visual quality.
To handle complex geometry, I integrated the Mesh Optimizer package (based on zeux/meshoptimizer). This tool strips unnecessary vertex data and optimizes the index buffer for better GPU cache locality.
Zoom-In to see performance stats (top-right corner).
To add life to the static geometry, simple particle systems were integrated into the generation logic.
-
Chimney Smoke: When a chimney prefab is instantiated by the
CornerGenerator, it can optionally spawn a lightweight smoke particle system, adding atmospheric depth to the roofline. - Post-Processing: The scene utilizes a custom Volume profile with Fog and Color Grading to unify the procedural elements with the skybox.
End of Documentation.