Custom camera filters¶
The in-game camera ships with a set of filters, and you can add your own. The simplest kind is a colour lookup table — a single image you drop into a folder, with no tools and no setup.
TODO: verify every path, file name and log message against a shipped client build before setting
status: published. The code is complete and builds; nothing on this page has been walked through end to end yet.
What a filter can and cannot do¶
A filter changes the picture your camera produces — your viewfinder, your photos, and your stream if you are using one.
- It is local to you. Nobody else sees it, it is not uploaded, and it does not travel with a world.
- It works on the finished image, so it can change colour, contrast and appearance, but it cannot add objects to the scene or see anything the camera did not already draw.
- To remove one, delete its file.
Where filters go¶
Look for this folder next to the game's executable. The client creates it for you on first launch, along with a README:
Mods/CameraFilters/
Filters are picked up each time you open the camera, so you can add or change one without restarting.
The easy way: a LUT image¶
Drop a LUT image straight into the folder:
Mods/CameraFilters/MyLook.png
It appears on the camera's Filter page under its file name. That is the whole process.
Making one¶
Any colour-grading tool that exports a "LUT strip" or "HALD image" will do. Grade a screenshot to taste, export the LUT, drop it in.
The image must be a strip LUT, where the width is the height squared:
| Size | Notes |
|---|---|
1024 x 32 |
The common choice |
256 x 16 |
Smaller, slightly less precise |
4096 x 64 |
Larger, very precise |
A wrong size is skipped, not guessed at
If the image is not a valid strip, the filter is skipped and the reason is written to the log rather than silently producing wrong colour.
LUTs cover any colour look — film stocks, duotones, faded or warm tones, black and white. Most filters people want are exactly this.
Shader files do not work¶
Putting a .shader file in the folder will not do anything.
The game cannot compile shaders while it is running
A shader has to be compiled ahead of time and packaged. This is a limitation of the engine, not a setting, and there is no way around it from the filter folder.
For effects that need real shader code — distortion, motion, glitching — use a packaged filter.
Packaged filters¶
For effects that need shader code, the SDK builds the package for you.
- Make a material that uses your shader, and save it in your project.
- Open Social Scape ▸ Tools ▸ Build Camera Filter.
- Pick the material, give the filter a name, and press Build filter….
- Copy the folder it produces into
Mods/CameraFilters/. - Open the camera. Your filter is on the Filter page.
Build on the platform you play on
The tool builds for whichever platform the project is currently set to. A package built for a different platform will not load, and the log says so.
The folder the tool produces looks like this:
Mods/CameraFilters/my-filter/
filter.json
filter.bundle
{
"name": "My Filter",
"author": "Your Name",
"material": "MyFilterMaterial",
"bundle": "filter.bundle",
"strength": 1.0
}
| Field | Meaning |
|---|---|
name |
Shown on the Filter page. Defaults to the folder name |
author |
Informational only |
material |
The name of the material inside the bundle. If the bundle has only one material, it is used regardless |
bundle |
Bundle file name. Defaults to filter.bundle |
strength |
Starting strength, 0–1 |
needs |
Capabilities to compute for this filter — see What your shader can read |
lens |
Optional. The name of a prefab in the bundle to attach to each person — see Lenses |
Packages may contain shaders, materials and textures only
A package containing code is refused and the reason is written to the log. This is not about your own machine — a package that can run code stops being local to you, so it is refused outright.
What your shader can read¶
Everything the built-in filters use is available to yours. There is no privileged set — Spotlight, Wraith and
the rest are ordinary shaders reading the same values. Declare the uniform and it is there.
Always available¶
| Uniform | Type | What it is |
|---|---|---|
_MainTex |
texture | The image so far |
_MainTex_TexelSize |
float4 |
xy = one pixel in UV, zw = image size in pixels |
_FilterStrength |
float |
The strength dial, 0–1 |
_FilterTime |
float |
Seconds. Held steady while a photo is taken, so an animated filter captures the frame you framed |
_CamZoom |
float |
Magnification, 0.5–10 |
_CamFocalLength |
float |
35 mm-equivalent focal length, mm |
_CamAperture |
float |
f-number |
_CamExposureEV |
float |
Exposure compensation, stops |
_CamFocusDistance |
float |
Focus distance, metres |
_CamResolution |
float2 |
Image size in pixels |
_AudioTexture |
texture | AudioLink. Always bound; all-black when the world has no AudioLink running |
Available on request¶
These cost something to produce, so they are only computed for filters that ask. List them in needs:
{ "needs": ["scratch", "subjectMask", "anchors"] }
needs value |
Uniform | What it is |
|---|---|---|
scratch |
_ScratchTex |
Last frame's output. This is what gives a shader memory — trails, decay, accumulation, long exposure. Starts black |
subjectMask |
_SubjectMaskTex |
Who is in the shot. R = person number, G = 1 on a person and 0 on the world |
subjectMask |
_SubjectCount |
How many people are in frame |
anchors |
_AnchorCount |
How many people have a usable anchor |
anchors |
_AnchorHead[8] |
Per person: xy = position on screen (0–1), z = distance in metres, w = 1 when valid |
anchors |
_AnchorState[8] |
Per person: x = how directly they are looking at the camera (0–1), y = 1 while speaking |
Ask for what you use
A uniform you did not ask for is bound to an empty value — the mask reads as all-world, anchors as nobody present.
Your filter will look broken rather than error, so if an effect does nothing, check needs first.
People behind walls are never included
The mask and the anchors only ever contain people the camera can actually see. Someone behind a wall is absent from both. This is not a setting.
Lenses¶
A filter can also carry 3D content attached to each person — ears, a halo, an effect above the head. Put a prefab in the bundle and name it in the manifest:
{ "lens": "MyEars" }
One copy is attached to each person the camera can see, parented to their head.
Only your camera sees it
Lens content is invisible everywhere else — in your own view, and to every other player. It exists for the shot.
Prefabs are checked on use
A prefab is the one part of a filter package that can carry components, so it goes through the same safety pass as every avatar in the platform. Components that are not allowed are removed. Keep lens content to meshes, materials and particles.
Troubleshooting¶
A filter that fails to load is skipped and the log says what was wrong. The camera keeps working either way.
| What you see | What it means |
|---|---|
| The filter is not listed | Close and reopen the camera — the folder is read on each summon |
| A LUT is skipped | The image is not a valid strip; check width equals height squared |
| A package is skipped | The log says how many materials were found. Zero means the bundle was built without one; more than one means material has to name the right one |
| A package is refused | It contains code. Rebuild it with only shaders, materials and textures |
| An effect does nothing | Check needs. A capability you did not ask for is bound empty, so the filter looks broken rather than failing |
| Colours look wrong | Confirm the LUT was exported as a strip, not as a .cube or a HALD square |
If a filter misbehaves in any way, delete its file or folder. That is always a complete fix.