-
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.
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.