Repository navigation
Scene Pipeline
How a scene wallpaper goes from files on disk to pixels: format loaders, values and bindings, content building, the Metal renderer, the effect graph, render targets and text.
Plain Decodable models with no side effects.
| Loader | Reads |
|---|---|
PKGParser |
WE's PKGV archives (scene.pkg) |
TEXParser, TEXImageFormat, TEXSpriteFrames
|
.tex textures (TEXV0005 containers: embedded JPEG/PNG, raw R8/RG88/RGBA8888, DXT1/3/5 mipmaps) and TEXS sprite timelines |
SceneDocument, SceneObject, SceneFlexibleValues, TolerantJSON
|
scene.json, whose fields may be plain values or {"value", "user", "script", "animation"} objects |
EffectDocument, MaterialDocument, SceneMaterial
|
effect.json and materials |
SceneParticles, SceneModel, Model/
|
Particle systems and .mdl models |
SceneLight, SceneLightConfig, SceneCameraLayer, SceneCameraPath, SceneProjection
|
Lights, cameras and projection |
SceneSound, SceneTimelineDocument, SceneAnimationLayer
|
Sounds, timelines, animation layers |
WETextDefaults, WETextEffectFields
|
Text defaults and font effects |
TextureReduction |
WE's Texture Resolution rule |
Collections decode element by element, so one bad entry doesn't drop its siblings.
Every value that can be user-, script- or animation-bound is resolved through SceneValueSource and SceneValueResolver, never read raw. Key pieces:
-
SceneUserBindings,SceneUserPropertyService,SceneUserPropertyStores: user properties per wallpaper instance and display, with conditions. -
ShaderConstantResolver,MaterialPassConstantSources: a pass's constants (literals or bound values), withusershadervaluesmapping and annotation defaults. -
SceneAnimationSetand friends: timelines (see Timelines and the SceneClock). -
SceneGeneralSettings,SceneCameraSettings,SceneFogSettings,SceneColorCorrectionSettings,SceneLightValues: thegeneralblock with WE's defaults. -
SceneParticleOverrides: particleinstanceoverridevalues, resolved every frame.
Priority: a timeline beats the static and user value; a script's return wins for its frame. A Scene Edit / Export edit replaces only the static base (SceneValueSource.replacingBase), so bindings survive.
SceneWallpaperViewModel and SceneWallpaperInstance load a wallpaper and build its content:
-
SceneEffectPlanresolves each effect:effect.json, its materials, combos, textures and constants per pass, and the translated shader variant. -
ImageMaterialPlan,ParticleMaterialPlan,ModelMaterialPlan: materials through WE's own shaders (genericimage*,genericparticle, model shaders). -
ParticleSystemBuilder(+ initializer and operator builders),ParticleBudget. -
SceneModelBuilder,SceneSoundContentBuilder,SceneFontResolver. -
WorkshopAssetResolverfinds files from a wallpaper's Workshop dependencies. -
WEImageBlendModes: WE's 33 blend modes.
Layers keep their authored object order and full parent transform.
SceneMetalRenderer draws each frame:
- Advance the wallpaper's
SceneClock, collect script output, evaluate timelines. - Step particles (GPU), prepare lights and shadows, the reflection pass.
- Run each layer's effect graph, then draw the layer with its transform and blending in the scene pass.
- Post-process (bloom, HDR chain), then present to each display.
Built-in uniforms (g_Time, g_Screen, g_Texture*Resolution, g_PointerPosition, g_PointerPositionLast, g_PointerState, g_ParallaxPosition, g_AudioSpectrum*, g_Daytime, …) are written per frame by UniformWriter, which maps NaN to 0 for integer uniforms.
EffectGraphRenderer runs WE effects on a layer's image with WE's own shaders:
- The image goes through the passes using two ping-pong targets at the layer's size. A pass without a
targetrenders into the other buffer and becomes the current image; a pass with atargetrenders into that effect's FBO.previousis the effect's input. - Declared
fbos(including half/quarter scales),bindandtargetare honoured;_rt_FullFrameBuffer,_rt_imageLayerComposite_<id>_aand the mip-mapped frame buffer are provided. - A chain's static prefix is kept and reused while its inputs, colour, alpha, script revision and live-bound values hold (
StaticChainKey). - Effect Detail: Match Display runs a layer's effects at its on-screen size on an area-averaged copy, while built-ins report the full-size chain's sizes so texel-sized kernels span the same image.
SceneRenderTargetPool hands out scratch targets bucketed by size, format and usage:
- Frame leases (returned at
endFrame()) and persistent leases (feedback targets, never evicted). - Free targets are evicted least-recently-used past a 256 MB budget and after 10 s idle. A request always gets a texture.
- Effect chains keep spare targets by bytes and idle time, so a clock whose text size changes reuses its targets.
TextLayout lays text out as WE does: glyph size from pointsize at 300 dpi in scene units, advances floored to whole units, wrapping only with limitwidth, limitrows with ellipsis, and blockalign justification. Text is rasterised at its on-screen density (SceneTextRasterScale) and can carry effects (SceneTextEffects) and font effects (outline, blur, drop shadow).
The scene target size is set by Render Resolution alone (SceneRenderResolution): the display's own pixels, 4K at its shape, or the wallpaper's own size; Upscaling then draws 75, 67 or 50 % of each side and scales it up. With several displays the frame renders once at the largest target any display needs and each display presents it with its own size and placement.
User guide: Scene wallpapers and Settings › Performance
Open Wallpaper Engine · GPL-3.0 · Released by Deepratna Awale · Based on Open Wallpaper Engine by Haren Chen and MrWindDog · Not affiliated with Wallpaper Engine or Valve · Home · User Guide · Developer Guide