Exploring the State of the Visual Field in the Age of Extreme Augmentation
Human perception has long been influenced by technological breakthroughs. An intimate mediation of technology lies in between our direct perceptions. Through three extreme ideal types of perceptual machines, this project defamiliarizes and questions the habitual ways in which we interpret, operate, and understand the visual world intervened by digital media.
Hyperallergenic Vision
We have observed an increase in allergies and intolerances in modern society. Hypersensitivities are emerging not only medically but also mentally. Digital media reinforce people’s tendency to overreact through the viral spread of information and amplification of opinions, making us hypersensitive to our sociopolitical environment. By creating an artificial allergy to the color red, this machine manifests the nonsensical hypersensitivity created by digital media. In nocebo mode, red expands, which is similar to social media’s amplification effect; in placebo mode, red shrinks, like our filtered communication landscape where we can unfollow people with different opinions.
Tactile Vision
Obsessively searching online for one thing is like looking through a pinhole where we build up everything without an overview. This machine helps to make the wearer conscious of how we navigate the internet naturally narrows our views of the world. The silicon mask breathes gently when the light is far away, while rapidly when the light gets closer. The wearer can navigate in space and find each other in total darkness with this tactile vision, like a dating App for cave animals. Similar to searching, when you are only looking for one thing, you lose the capacity to see things in context to make more informed decisions.
Commoditized Vision
Our visual field is packed with so much information that our perception has become a commodity with real estate value. By creating tension between the meditative state and the consumptive state, this machine contemplates how our perception has become part of the value chain in this particular socioeconomic context. You can earn money by looking at advertisements, and spend money to see an ads free world.
TransVision is an AR mobile application where we implemented Hyperallergenic Vision for expanding red zone.
iPhone 12 or above, iOS 27 or later.
You can download the app from app store by searching "TransVision".
- Mono Mode
In this mode, users can interactive with TransVision without HoloKit. - Stereo Mode
In this mode, user can get a more immersive AR experience with HoloKit.
In short: every frame, the app takes the picture from the iPhone's back camera, finds the red parts, bends the picture so the red spreads and moves like a liquid, and shows the result. In Mono the result fills the phone screen. In Stereo it is shown on a virtual screen 1 m in front of you inside HoloKit.
The whole app is one Unity scene. The image work runs on the phone's GPU, in small programs called shaders.
flowchart TD
accTitle: TransVision frame pipeline
accDescr: Each frame the ARKit camera image is converted to RGB, its red areas are found and blurred, a ripple simulation advances one step, and a composite pass bends the picture. The AR camera view gets the result full frame, which Mono shows and the recorder captures; Stereo shows it on a plane 1 m ahead.
camera["iPhone camera frame from ARKit<br/>(brightness + colour planes)"]
step0["Step 0: convert to RGB and turn it to match the screen<br/>1920 x 1080"]
field["Step 1: find red<br/>240 x 135 red map"]
blur["Step 2: blur the red map"]
waves["Step 3: move the ripples one step<br/>320 x 180 wave map"]
composite["Step 4: bend the picture<br/>1920 x 1080 result"]
ar_view["AR camera view:<br/>the result copied over the whole frame"]
mono["Mono: shown on the phone screen"]
recorder["Recording: the HoloKit SDK recorder<br/>captures the AR camera view"]
stereo["Stereo: the result on a virtual screen 1 m ahead,<br/>seen by the left and right eye cameras"]
camera --> step0 --> field --> blur --> waves --> composite
step0 --> composite
composite --> ar_view
ar_view --> mono
ar_view --> recorder
composite --> stereo
- Texture: an image the GPU can read. A render texture is one the GPU can also draw into.
- Shader: a small program that runs on the GPU once for every pixel, all pixels at the same time.
- UV: a position inside a texture, from (0, 0) at one corner to (1, 1) at the other.
- Pass: one shader run that reads some textures and writes one texture.
ARKit gives each camera frame as two textures: a brightness image (Y) and a colour image (CbCr). This is how video is usually stored. TransVisionCameraImage.shader combines them into normal RGB colours.
The camera sensor does not match the screen: its image is a different shape and may be rotated. ARKit provides a "display transform", a small matrix that says which point of the camera image belongs at each point of the screen. The shader uses it so the picture comes out the right way up and cropped like the screen. The app reads this matrix from the AR background material just before rendering, after the HoloKit SDK has corrected it. On iOS 27 the matrix inside the raw frame is wrong, and using it shows the picture in the wrong orientation.
In the Unity Editor there is no camera, so a still test image is used instead.
"Red" here means a colour whose hue is within about 20 degrees of pure red and that is not greyish. Checking only "is the R value high" would also catch white, orange and skin. So the shader converts each colour to brightness plus two colour-difference values (Cb and Cr), the same split video uses, and measures the direction and strength of the colour in that Cb/Cr plane.
This runs on a small 240 x 135 map; each cell averages 16 camera samples. The result is a "red map" from 0 (no red) to 1 (fully red), like a heat map. Two blur passes, one horizontal and one vertical, then soften its edges so the effect has no hard border.
Ripples come from a classic 2D wave simulation on a 320 x 180 height map. Every frame, each cell's next height is (the sum of its four neighbours) / 2 minus its height one frame ago, multiplied by 0.975 so waves die out. Six times a second, random "drops" fall inside the red and start new waves. The map keeps the last two frames, so three textures take turns.
This is the main trick. To bend an image, each output pixel reads the camera picture from a slightly shifted position. Shifting where you read is what water or wavy glass does to the light. The shift for each pixel is the sum of five parts:
| Part | What you see | How it is computed |
|---|---|---|
| Spread | Red grows outward (nocebo) | Shift along the slope of the blurred red map, toward more red. A negative strength makes red shrink (placebo). |
| Flow | Inside the red, the picture keeps swirling | Two layers of drifting noise, one bending the other |
| Ripples | Rings spreading from drops in the red | The slope of the wave map from Step 3 |
| Bubbles | Round lenses drifting inside the red, with a dark rim and a highlight | A pre-made bubble texture, two layers that fade into each other |
| Still warp | The rest of the view is slightly wavy but does not move | The same noise as Flow, without time |
Flow, ripples and bubbles fade out toward the red's edge. So the red parts move like liquid while everything else stays still with only a small, fixed warp.
The noise and bubble textures (256 x 256) are generated once when the app starts (LiquidTextures.cs).
Unity's Universal Render Pipeline (URP) draws each camera with a list of passes. CameraImageProcessor adds one extra pass, EffectPass, to the first camera that renders each frame, and that pass runs Steps 0 to 4. Stereo has two eye cameras, but the effect still runs only once per frame. Only the input and the result are full size; the red map and the wave map are small, which keeps the GPU work low.
The result already has the screen's layout, because Step 0 used the screen's display transform. So DisplayPass copies it over the whole screen after the normal camera background. The buttons are drawn on top afterwards.
In Stereo, the phone screen is split into a left and a right image, and you look at them through HoloKit's lenses. The HoloKit SDK renders them with two eye cameras, placed where your eyes are.
The problem is that the picture comes from the phone's camera, not from your eyes. The camera sits 7.8 cm in front of your eyes and 6.2 cm above them, and the app has no depth information, so it cannot know how far away each pixel is.
The solution is a virtual screen, ResultPlane, that shows the camera picture and fills exactly the camera's field of view at a distance of 1 m:
iPhone camera o----------------- 1 m ----------------|
| | virtual screen:
6.2 cm | | the camera picture,
| | exactly as wide and tall
your eyes o---------------------+ | as the camera sees at 1 m
|<----- 7.8 cm ------>|
PlanePlacer.cs sizes it from the camera's projection matrix, which describes how wide and tall the camera sees. At distance d, the screen is 2d / m00 wide and 2d / m11 tall, and slightly off centre (m02, m12), because the lens centre of an iPhone camera is not exactly in the middle of the image. The screen is attached to the camera, so it follows your head without delay.
Because the screen is flat, objects exactly 1 m away line up with the real world. Nearer objects look a little lower and larger, and farther ones a little higher and smaller. At 1 m the error stays within about 4 degrees and 11% for anything from 0.4 m to 4 m away. No LiDAR is used, so this works on every supported iPhone.
On an iPhone 15 Pro, the phone screen shows only 61.5% of the camera image's height (34.5 of 53.6 degrees), while each eye in HoloKit sees 41 degrees. So in Stereo, Step 0 uses the camera's whole image instead of the screen's crop. Otherwise the lower part of what each eye sees would have no picture.
Recording uses the HoloKit SDK's recorder and buttons, the same as EchoVision: Record, HD60 (60 fps) or 4K30 (ARKit's 4K camera, 30 fps), with microphone sound. The recorder renders the AR camera into its own texture. The full-screen copy belongs to that camera, so recordings contain the effect. A recording made in Stereo is a normal 16:9 video of the camera view, not the split left/right image.
The first version of the effect is still in the project as Classic: four Shader Graph steps in ShaderGraph/ (red mask, blur, offset map, distortion). Select it with Effect on the CameraImageProcessor object.
Select CameraImageProcessor in the scene. Its Inspector has these settings:
| Setting | Default | What it changes |
|---|---|---|
| Effect | Liquid | Liquid, or the original Classic effect |
| Shrink | off | On: red shrinks (placebo) instead of spreading (nocebo) |
| Bulge | 0.35 | How far red spreads or shrinks |
| Ripples | 0.03 | Strength of the ripples |
| Bubbles | 0.03 | Strength of the bubbles |
| Wobble | 0.003 | The small, still warp outside the red |
| Red Wobble | 0.02 | The flowing warp inside the red |
The Stereo screen distance (PlaneDistance, 1 m) and its zoom (PictureZoom, 1.0) are constants in PlanePlacer.cs.
All paths are inside Packages/org.realitydeslab.transvision/.
| File | What it does |
|---|---|
Runtime/CameraImageProcessor.cs |
Receives ARKit frames, picks the display transform, adds the passes to the cameras |
Runtime/CameraImageProcessor.Pass.cs |
EffectPass: runs Steps 0 to 4 every frame |
Runtime/CameraImageProcessor.Liquid.cs |
The liquid settings above and the small textures they use |
Runtime/CameraImageProcessor.Display.cs |
DisplayPass: the full-screen copy in Mono |
Runtime/Resources/TransVisionCameraImage.shader |
Step 0: camera picture to RGB |
Runtime/Resources/TransVisionLiquid.shader |
Steps 1 to 4: red map, blur, wave step, bending |
Runtime/LiquidTextures.cs |
Makes the noise and bubble textures at startup |
Runtime/PlanePlacer.cs |
Places and sizes the Stereo virtual screen |
ShaderGraph/ |
The Classic effect |
Tests/Editor/ |
Tests for the effect, the Stereo screen and the project setup |
- Unity Version: 6000.3 (Unity 6.3 LTS), Universal Render Pipeline 17.3
- HoloKit Unity SDK 0.6.0, from the holokit-unity-sdk tag
0.6.0-preview.1(seePackages/manifest.json) - Open
Packages/org.realitydeslab.transvision/Scenes/transvision.unity - Change build target to iOS in
Project Setting/Player settings - Enable "Requires ARKit Support" in
Project Setting/Player settings - Enable "Apple ARKit" in
Project Setting/XR Plug-in Management
Packages/org.realitydeslab.transvision: the app (scripts inRuntime/, scene, shader graphs, materials, tests)Assets: project configuration only (URP assets, XR settings, TextMesh Pro)
See Packages/org.realitydeslab.transvision/CHANGELOG.md.
EditMode tests live in Packages/org.realitydeslab.transvision/Tests/Editor. Run them from Window > General > Test Runner, or headless:
unity test . --mode EditMode
