Lewati ke konten utama

Satu pos memiliki tag "URP"

Universal Render Pipeline specific content.

Lihat Semua Tag

Volumetric Fog in URP: A Deep Dive

· Satu menit membaca
Thang Le
Senior Lead Engineer

Volumetric Fog

The Atmosphere of Dread

Fog is a staple of the horror genre, famously used in Silent Hill to mask hardware limitations. Today, however, fog is a deliberate stylistic and atmospheric choice. Volumetric Fog—fog that interacts with light sources and casts shadows—is the gold standard for creating "thick" atmosphere.

Raymarching: The Engine of Volume

Most volumetric fog systems in modern engines like Unity URP rely on Raymarching. The shader "marches" a ray from the camera into the scene, sampling the light and density at various points along that ray.

The challenge is the sheer number of samples required. A naive implementation will tank the frame rate. To optimize this, we use a Froxel-based approach (Frustum Voxels). By dividing the camera frustum into a 3D grid of voxels, we can pre-calculate the lighting for each voxel once per frame and then simply sample that grid during the main rendering pass.

Optimizing for URP

Unity's URP doesn't include a robust volumetric fog out of the box (unlike HDRP). To implement this effectively, we use Scriptable Render Features.

  1. Downsampling: Render the volumetric effect at a lower resolution (e.g., half or quarter res) and then upsample it using a bilateral filter to preserve edges.
  2. Temporal Reprojection: Use data from the previous frame to "fill in the blanks," allowing for fewer samples per frame while maintaining a smooth look.
  3. Phase Function: Implementing a Henyey-Greenstein phase function allows for realistic forward and backward scattering, making the fog "glow" when a light source is behind it.

Strategic Implementation

In horror, fog isn't just about visibility; it's about what it hides. By dynamically adjusting fog density based on player location or sanity levels, you can create a shifting sense of claustrophobia. For example, as the player's "Fear" meter rises, the fog's Extinction coefficient can increase, pulling the "wall of mist" closer to the player.

Performance-wise, always keep an eye on your Overdraw. Thick volumes of fog can overlap with other transparent effects (like particles), leading to significant GPU pressure. Balancing the Froxel resolution with the camera's far clip plane is the key to maintaining 60 FPS on mid-range hardware.

Custom Scriptable Render Features for Glitch Effects

· Satu menit membaca
Thang Le
Senior Lead Engineer

Glitch Effects

Disrupting Reality

The "glitch" aesthetic has become synonymous with psychological horror and tech-noir. Whether it's the screen tearing of a found-footage camera or the visual degradation of a character losing their mind, these effects need to be more than just a simple overlay. To achieve high-performance, high-fidelity glitching in Unity's Universal Render Pipeline (URP), we must leverage Scriptable Render Features.

Why Not Just Post-Processing?

While Unity's Post-Processing Stack is powerful, it can be restrictive when you need to inject custom logic into specific parts of the rendering pipeline. Scriptable Render Features allow us to:

  • Draw specific objects with custom shaders.
  • Create multiple passes with intermediate textures.
  • Execute logic before or after specific URP events (e.g., After Transparent, Before Post-Processing).

Building the Glitch Pass

A convincing digital glitch usually consists of three core components:

  1. Chromatic Aberration: Splitting the RGB channels. In a glitch, this should be jittery and non-uniform.
  2. Block Displacement: Shifting random rectangular segments of the screen horizontally.
  3. Scanline Interferences: Adding subtle horizontal lines and "static" noise.

In our custom ScriptableRenderPass, we grab the cameraColorTarget, blit it to a temporary render texture using our "Glitch Shader," and then blit it back.

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get("GlitchPass");
// Execution logic here...
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}

Driving the Sanity Meter

The beauty of a custom Render Feature is how easily it can be tied to gameplay systems. By exposing a glitchIntensity parameter in the Render Feature, we can drive it from a "Sanity" or "Corruption" script in C#. As the player's sanity drops, we increase the frequency and amplitude of the block displacement and the severity of the chromatic aberration.

By using a ComputeBuffer or a simple GlobalFloat, we can update these values once per frame on the GPU, ensuring that even the most chaotic visual meltdowns don't impact our CPU performance. This allows for a seamless transition from a clear image to a fractured, terrifying reality.