EDGE Layer System ================= The screen is composed of many layers, and each layer exists at a certain depth: 0 is the lowest depth, and is drawn first, higher values are drawn later (and thus can obscure anything at a lower depth). A dirty rectange system is used to only redraw layers (or parts of layers) when necessary (for performance). The table below describes the proposed order for all the various layers that EDGE needs. Some of the layers are always present (e.g. final background), others are only drawn under certain circumstances (e.g. console is active). For simplicity, most code will prefer to enable/disable layers rather than adding/removing them. Layers can be recursive (e.g. main rendering window contains many sub-layers), but for simplicity the initial system will only use two depth levels (i.e. no sub-sub-layers). Sub-layers are shown below using the ##.# notation for the depth. For the most part, the set of layers should be considered as a flat list (with sub-layers grouped together) rather than a tree. Each layer occupies a certain rectangular area of the screen (possibly the whole screen, e.g. for wiping). Sub-layers are restricted to their parent rectangles, and top-level layers are restricted to the whole screen. Each layer or sub-layer may be flagged as being "solid" -- e.g. the player main rendering window -- allowing better performance since stuff behind the solid area doesn't need to be re-drawn. All non-solid layers are assumed to be see-through (or have see-through parts). NOTE: clipping to solid areas is not compulsory. NOTE: some of this logic assumes the screen buffer remains unchanged between frames. If this isn't true (e.g. double buffering into video memory, prolly isn't true for OpenGL either), then the dirty matrix can be assumed to be totally dirty all of the time. (The solid rectangle logic still applies though). How it all works ---------------- There is a dirty rectangle matrix that marks each MxN block of on-screen pixels (e.g. 16x16 blocks) as being either dirty or clean. Clean blocks don't need to be redrawn, only the dirty blocks. Initially the dirty matrix is marked totally dirty. After each render process, the dirty matrix is marked totally clean. Any layers that get added/removed or enabled/disabled or changed in some way (moved, resized, or new contents) before the next render process causes the corresponding area in the dirty matrix to be marked dirty. For example: if a layer moves, then both the original area and the new area are marked as dirty. The render process consist of two passes, the first one is "Query" and the second one is "Draw". The Query pass traverses the layer list from TOP->BOTTOM. It marks as dirty any layers flagged as "volatile" (e.g. camera windows). This pass also creates a list of solid rectangles, adding any layer flagged as "solid" to the list. During the query pass, layers that lie completely under a solid rectangle are marked as "invisible" and are subsequently ignored. NOTE: Tests against the dirty region cannot happen during the QUERY pass since the dirty region can be changed during the pass, invalidating previous tests on higher layers. For each visible layer, an index into the solid rectangle list is stored within it -- so all solid rectangles ABOVE the current layer will be known. The query pass can terminate early if a solid rectangle which covers the whole screen is encountered (all lower layers will be marked as invisible). The Draw pass traverses the layer list from BOTTOM->TOP, skipping any layers that are marked as invisible. When drawing a layer, it uses the dirty matrix (and usually the ABOVE solid rectangles) to only draw where necessary. Layers are NOT allowed to draw outside of their parent layer, NOR anywhere that is marked as clean. Layers can be flagged as "non-clippable". Such layers cannot (or not easily) be clipped to the clean areas (which can be arbitrary). For example, clipping the player tip message is non-trivial. When reached in the Query pass, non-clippable layers which are visible are added *WHOLLY* to the dirty matrix. NOTE: all layers must still be clipped to their parent layer. Video Interface --------------- This section describes the interface used to render all the layers (and hence everything that the user will see) on the screen. It is designed to allow both software and hardware rendering systems. Higher-level concepts (like drawing rows of text), including clipping to the dirty matrix and/or solid areas, will be implemented elsewhere using these primitive operations. Primitive Operations: 1. Render a scene as the view from a specified object (e.g. the player mobj) inside a given rectangle. No clipping needs to be down (except for restricting drawing to inside the rectangle, of course). 2. Draw a solid colour box inside a given rectangle. Can be translucent. Also provided is the parent rectangle, the box must be clipped to it. 3. Draw a graphic image inside a given rectangle, with texture coordinates that give a sub-area of the image to draw, usually just (0.0, 0.0) to (1.0, 1.0). Texture coords can be outside of the [0-1] range, in which case the image should tile. For tiling, the image is guaranteed to be a power of two size in the dimension of tiling. Can be translucent. Also provided is the parent rectangle, the image must be clipped to it. ISSUE: source/format of image data ? 4. Draw a solid colour line between two points. Can be translucent. Also provided is the parent rectangle, the line must be clipped to it. 5. Read the screen contents into an off-screen image. This is needed for (a) wiping effects and (b) making snapshots. 6. Set an overall "wash" colour, for palette effects like pain and item-pickup. The whole screen is affected. 7. Set the overall gamma, for the F11 key. The whole screen is affected. May be very slow, therefore cannot be used for speciai effects. 8. Set/Change the video mode. IDEA TO EXPLORE --------------- Use the layers for event propagation as well (rather than being hardcoded like it is now). Traversal is TOP->BOTTOM, so higher layers can eat events and thus starve lower layers of them. ISSUE: send events to layers marked as "invisible" ? Yes. ISSUE: does this system need dummy (never drawn) layers which are just there for events ? Prolly not, but the concept can be supported rather easily (and thus should be). Layer Table ----------- Depth Contains ===================================================================== 0 The final background, either: - a solid colour, - a flat (or texture) that will be tiled. - an image that will be stretched to fit. It covers the whole screen. There is nothing drawn underneath, so images with transparent parts should not be used. --------------------------------------------------------------------- 10 Full-screen automap. --------------------------------------------------------------------- 15 Intermission camera rendering window (usually fullscreen, though could be optionally smaller). --------------------------------------------------------------------- 20 Intermission animation sprites (the splats and you-are-here images for DOOM I). Also used for the cast sprites. |---------------------------------------------------------------- 20.1 Intermission text, such as the end-of-level stats, pre-level and post-level text, and text for the DOOM 2 cast parade. --------------------------------------------------------------------- 30 Status bar container image. |---------------------------------------------------------------- 30.1 Status bar text & icons. --------------------------------------------------------------------- 40 Player main rendering window. There may be multiple of these (for split-screen multi-user play), though they all have the same depth (so overlapping is not allowed, with undefined results if attempted). Includes border. |---------------------------------------------------------------- 40.1 Player PSprites (weapon & crosshair). |---------------------------------------------------------------- 40.2 Player Automap overlay. |-------------------------------------------------------------------- 42 Player overlaid HUD items (like health/ammo/clipsize). |-------------------------------------------------------------------- 44 Player messages (for pickup, etc). Includes the `idinfo' message box. --------------------------------------------------------------------- 46 Player tip message. --------------------------------------------------------------------- 50 Alternative rendering windows. Could be used to provide another view from the player (e.g. rear vision mirrors), or to provide small views from other players in a multiplayer game. Includes borders. |---------------------------------------------------------------- 50.1 Alternative rendering PSprites (if shown). --------------------------------------------------------------------- 60 The "PAUSED" icon when the game is paused. --------------------------------------------------------------------- 70 Wipe effect overlay. --------------------------------------------------------------------- 75 Console background, either: - none, - a solid colour, - a flat (or texture) that will be tiled, - an imaged that will be stretched to fit. Allowed to be translucent for a see-through console effect. |---------------------------------------------------------------- 75.1 Console text. --------------------------------------------------------------------- 80 Menu background, either: - none, - a solid colour, - a flat (or texture) that will be tiled, - an imaged that will be stretched to fit. Allowed to be translucent for a see-through menu effect. Solid colour (black) + translucency (50%) is used to emulate the current darkening effect. |---------------------------------------------------------------- 80.1 Menu text. --------------------------------------------------------------------- 85 Pop-up requestor background (same options as the other backgrounds). Includes border. |---------------------------------------------------------------- 85.1 Pop-up requestor text. --------------------------------------------------------------------- 90 The "DISK" icon when loading/saving occurs. ---------------------------------------------------------------------