top of page

Unknown Whereabout

RESPONSIBILITY

Technical Artist

TRAILER

Unknown-Whereabouts is an immersive maze puzzle game about finding the right direction and exploring the journey "from where I came" to "where I am going". The story follows a traveler trapped in a labyrinth, wandering across endless seas under a starless night. Players rotate the core mechanism to discover the correct orientation and unlock each puzzle box, ultimately escaping the predetermined paths and spaces to reach a so-called freedom. Unlike typical maze games where reaching the exit means victory, this work leads players to realize that the true outcome is not an "answer" but a new "question". Through its mechanics and narrative text, the game interacts with players and viewers, prompting reflection on the constraints of rules and inviting them to question whether true freedom can exist beyond the boundaries of the box.

Work Flow

Stencil Portal Volume

I built a stencil-based portal in Unity 6 HDRP that reveals a full 3D room behind a thin wall. The effect has three layers of logic:

1. Use Custom Pass + Stencil Buffer to draw a boxed interior volume only through a portal opening on the wall.

2. Drive which portal is active with a view-based raycast so overlapping portals never conflict.

3. ​Integrate Unity’s Water Renderer and use different stencil reference values to support multiple, different interior rooms in the same scene.

BREAKDOWN

PART 1

Interior Volume as 6 Planes

  1. ​Build the interior room from six planes: floor, ceiling, left, right, back, and front opening. Make the five inner faces point their normals inward; the front opening plane faces toward the camera.

  2. Put all interior faces (including the back side of the front opening) on a dedicated layer, e.g. StencilR2. Keep the outer wall on the default opaque layer so it is rendered by HDRP like regular level geometry.

This gives me two clearly separated groups: the main wall (default pipeline) and the interior room (rendered only via Custom Pass).

Portal Front Plane and Stencil Marking

Geometry and material

  1. The front opening is a separate plane placed flush with the wall.

  2. It uses a transparent distortion shader built in Shader Graph:

    • Samples Scene Color.​

    • Offsets UVs with scrolling noise to create a refractive “rippling” portal surface.

    • Writes alpha < 1 so the room behind feels like it sits “inside” the wall.

  3. In the material (or via material override in the pass) this plane writes a Stencil reference value (e.g. User Bit 0).

Stencil logic

  1. During the opaque pass, the wall writes its normal color and depth.

  2. In the Custom Pass, the front plane is drawn again (or its stencil is overridden) to stamp the stencil buffer with Ref = Bit 0 on all pixels that belong to the portal opening.

Now the GPU has a mask that precisely defines “portal pixels on the wall”.

Custom Pass Rendering Order – Drawing the Hidden Room

Camera culling

  1. In the main camera, I exclude the StencilR2 layer from the culling mask.

  2. This prevents the interior room from being rendered in the normal HDRP pipeline and guarantees it only appears through my Custom Pass.

Custom Pass setup

  1. Add a Custom Pass Volume (Global).

  2. Set Injection Point to After Opaque and Sky.

  3. Add a Draw Renderers (Custom Pass) that targets only the StencilR2 layer.

Key settings (conceptually)

  1. Depth Test: LessEqual – interior pixels respect the wall’s depth.

  2. Stencil:

    • ​Read Mask: User Bit 0.

    • Comparison: Equal or LessEqual depending on your layering.

  3. Sorting: opaque.

Effect

  1. The wall is drawn first as a solid surface.

  2. In the Custom Pass, interior geometry is rendered only where stencil == Bit 0 and depth test passes, so the room appears cut out of the flat wall while remaining fully 3D inside.

View-Based Portal Activation (Raycast)

​To avoid overlapping portals fighting over the same stencil bit, I gate portal rendering with a simple C#. Each frame, cast a ray from the camera center into the scene., detect which portal front plane is hit first. Only the hit portal is allowed to enable its Custom Pass Volume (or interior room root), and write its stencil mask for that frame. This ensures only the portal actually in view is active, overlapping stencil volumes never black out or override each other unexpectedly.

PART 2

Water Renderer Integration

Pre-refraction injection

  1. Add a second Custom Pass Volume with Injection Point Before Pre Refraction.

  2. Move the interior Draw Renderers pass (for StencilR2) into this volume as well.

HDRP’s water system samples scene color and depth before refraction. By injecting the interior room at that stage, water can bend and distort the room correctly when viewed through the surface.

Ocean Renderer tuning

  1. Enable Caustics and tweak: Resolution, Simulation Band (e.g. Ripples), Tiling Factor and Intensity, Caustic Plane Blend Distance (controls blend between water surface and volume walls).​​

  2. Adjust Refraction / Underwater parameters: Virtual Plane Distance (distance from water surface). Absorption / scattering to match your underwater mood.

PART 3

Multiple Rooms via Different Stencil References

To support several portals leading to different interior rooms in the same scene: 

  1. Reserve different stencil reference values per portal (e.g. User Bit 0 for Room A, User Bit 1 for Room B).

  2. For each portal: The front plane writes its unique stencil reference. Its Custom Pass draws only the interior geometry whose material / pass reads that same reference.

Combined with the view-based activator:

  1. Each portal can show a different boxed 3D world, even if they are placed on the same scene or even the same wall.

  2. The system scales without changing the HDRP source – everything is driven through Custom Pass injection points + stencil references.

Each pass uses the same depth comparison logic (for example Less Equal with Write Depth enabled), but because the stencil references differ, the GPU can cleanly decide which interior volume to render behind each portal opening. Multiple portals can coexist in the same scene and even in the same camera view. Each opening reveals its own 3D space, with no cross-contamination or depth artifacts.

Player-Centered Emission

I built a player-centered glow system that makes building details light up around the character, driven entirely by world space and Material Property Blocks.

BREAKDOWN

Sending the player position to the shader (MPB + C#)

In C#, I use a MaterialPropertyBlock to push the player’s world-space position into all glow materials:

  1. Find or assign the player transform.

  2. Collect all renderers that use the glow shader (or share a material that has _PlayerPosWS).

  3. Each frame, write player.position into a vector property _PlayerPosWS on those renderers via MPB.

Because this uses MPBs instead of duplicated materials, any number of objects can share one glow material and still receive a unique, per-frame player position. Every renderer using this shader knows where the player is in Absolute World space.

Building a mask from the wall pattern

Inside Shader Graph I first isolate where the glow is allowed to appear:

  1. Sample the base color texture of the wall.

  2. Convert it to luminance and apply a threshold + smoothstep to extract bright stripes/panels as a black-and-white mask.

  3. Add controls for threshold and softness so different buildings can reuse the same shader.

This mask defines “which parts of the wall are eligible to glow”.

Computing a player-centered falloff in world space

Next I make the glow follow the player:

  1. Use Position (Absolute World) as the per-pixel world position.

  2. Subtract _PlayerPosWS from it and take the length of the vector to get distance to the player.

  3. Feed that distance into a Smoothstep(InnerRadius, OuterRadius) to build a radial falloff.

    • Inside InnerRadius the falloff is 1, outside OuterRadius it fades to 0.

    • I invert it with One Minus so the glow is strongest near the player and fades away with distance.

Because everything is in world space, this hotspot stays locked to the player even when the camera moves.

Noise, caustics, and final emission

To keep the glow organic instead of a perfect circle, or a spotlight effect:

  1. Modulate the radial falloff with noise (Simple/Gradient Noise or Voronoi):

    • ​Use tiling and speed parameters to create moving, caustic-like patterns.

    • Multiply noise with the mask, so only the masked wall details receive the effect.

  2. Multiply the result by an HDR color and intensity and plug it into the Emission output of the shader.

Only the wall details defined by the mask can emit light. The emission region is a noisy, animated ring centered on the player in world space. As the player moves, the glowing pattern slides across the architecture, giving a readable “area of influence” without any extra gameplay logic.

Cloth Cloak Simulation

Create a physically simulated cloak for the main character using Unity’s built-in Cloth component, driven by the existing character rig.

  • A single-layer cloak mesh skinned to the character rig (head and spine bones), with topology and vertex density tuned specifically for cloth simulation.

  • A Unity Cloth setup on the cloak’s SkinnedMeshRenderer, using capsule/sphere colliders on the body to keep the fabric from clipping through the character.

  • Painted constraint masks that lock the cloak at the attachment ring and gradually increase freedom toward the hem, giving a natural, weighted motion.

BREAKDOWN

DCC Setup

  1. Cleaned the model: froze transforms, reset XForm, collapsed the stack, and ensured scale = 100%.

  2. Used weighted normals / smoothing groups and triangulated the cloak on export.

  3. Modeled the cloak as a single-sided mesh and relied on a two-sided material in Unity, avoiding coplanar inner/outer layers.

  4. Targeted about 1.5k–3k triangles on the cloak, with ≤ ~2k simulated vertices (only vertices with non-zero Max Distance).

  5. Exported as FBX with bones only (dummies converted to bones, tangents/bitangents off so Unity can generate MikkTSpace).

Unity Cloth component

  1. Imported the FBX with settings: Normals = Import, Tangents = Calculate (MikkTSpace), Read/Write Enabled = On.

  2. Added a Cloth component to the cloak’s SkinnedMeshRenderer.

  3. Placed capsule / sphere colliders on key body parts: chest, back, both shoulders, upper arms, optional pelvis, plus a small chest sphere for the overlapping front flap.

  4. If needed, isolated cloth colliders on a dedicated physics layer (e.g. ClothOnly) and disabled collisions with other layers to keep the simulation stable.

Constraint painting and simulation tuning

  1. Painted Fixed / Max Distance = 0 on the attachment ring (neck, shoulders, front lapel top edge, hood rim) so those vertices follow the rig exactly.

  2. Painted a downward gradient for the rest of the cloak (meters in world space), for example:

    • Just under the attachment ring: ~0.01

    • Upper torso: ~0.02

    • Mid chest / back: ~0.03–0.05

    • Hem and lower area: ~0.06–0.08

    • Near armpits and arm contact zones: kept values smaller to reduce penetration.

  3. Tuned core parameters for a responsive but stable cloth:

    • Blending Stiffness = 1 (full influence of painted constraints)

    • Damping ≈ 0.2–0.3 (removes jitter without killing motion)

    • Collision Mass Scale = 1 (keeps cloth mass consistent with character).

The cloak reads as part of the character’s silhouette, attaches firmly around the shoulders and hood, and reacts physically to motion with controlled stretch and minimal clipping.

Pattern-Masked Emissive

I use the cloak’s fabric pattern as a mask to drive a clean, stylized emissive pass.

BREAKDOWN

Mask from texture

  1. Sample the cloak texture and extract the R channel as a grayscale pattern mask.

  2. Pass this channel through a Smoothstep using two exposed thresholds (inner / outer). This gives a controllable hard-edge or soft-edge mask for the embroidered motif.

  3. Use One Minus on that mask when I need the complementary area (non-pattern parts of the cloth) for a secondary effect.

Drive Emission

  1. Multiply the final mask by an HDR color and an exposed intensity and connect the result to Emission.

  2. Optionally, add a separate “Global Emission” scalar so I can tune the overall glow on the entire cloak independently from the pattern mask.

  3. Because everything is mask-based, I can swap patterns or recolor the cloak without changing the shader logic.

Raycast Hover Emission

This effect adds an interactive glow to architecture and UI objects: when the cursor hovers, the object brightens; when the cursor leaves, it fades back to a subtle breathing glow.

BREAKDOWN

Shader Graph

  1. The Shader Graph exposes a single float property (e.g. _BE_GlowIntensity) that multiplies the emissive output.

  2. All targeted materials share this property name so they can be driven by a Material Property Block (MPB).

HoverGlow – per-object controller

  1. A HoverGlow component sits on every object I want to highlight.

  2. Each frame it writes _BE_GlowIntensity via an MPB to its Renderer, so instancing stays intact and no materials are duplicated.

  3. It exposes:

    • ​minIntensity / maxIntensity for idle vs. hover glow levels.

    • riseDuration / fallDuration for how fast the glow ramps up and down.

    • Optional “breath” parameters (min/max, period, curve, phase offset) to run a slow emissive pulse when the object is not hovered.

HoverRaycaster – screen-space picking

  1. A HoverRaycaster component sits on the main camera.

  2. Each frame it casts a ray from the cursor into the scene with:

    • ​cam, maxDistance, and hitLayers defining the ray origin, length, and mask.

    • requireFrontHover, frontDotThreshold, and faceDotThreshold gating hits to mostly front-facing surfaces so side-hits don’t trigger.

  3. When the ray hits an object that has HoverGlow, it tells that instance to go into “hover” state; all others smoothly return to their idle breathing state.​​

This combination of Shader Graph + MPB + raycast gives me a cheap, fully data-driven hover highlight that can be dropped onto any emissive material in the project.​​

bottom of page