Render chain: 1) render HUD elements to textures 2) render the scene from primary light source to depthbuffers 3) render cockpit 4) render terrain and other objects in front of ship 5) deferred lighting 6) render HUD 6.1) render cockpit glass cracks and smudges 6.2) render HUD elements using textures from step 1. Their number depends on what to draw (radar, number of targers around, ...) 6.3) render some lights, no idea why this is happening here. It's not lighting, it looks more like decals or camera lenses 7) postprocessing, described below HUD notes: They use both depth buffer and stencil buffer when rendering HUD. Depth buffer values increase when close to screen, that's why they use GREATER EQUAL depth test. Depth write mask is zero when rendering HUD. Stencil buffer describes what is rendered in a particular pixel. Dark HUD elements, ship hologram and target hologram don't use stencil buffer at all. HUD element with orbital cruise and surface flight, mouse dot info and mouse direction arrow are the only HUD element which is rendered with both depth test and stencil disabled. 3rd LSB is set for pixels which have HUD rendered on it. Stencil function is ALWAYS for all HUD elements. Only front face PassOp is REPLACE, all others are KEEP. Blending state: BlendOp = ADD, SrcBlend = ONE, DestBlend = INV_SRC_ALPHA HUD radar notes: Different blending state than the rest of HUD!! Depth test and stencil are both disabled for all radar parts Orange circles, blue POI circles, lines which go from radar plane to radar icons, circles of radar icons on radar plane and < > around target use: Blending state: BlendOp = ADD, SrcBlend = SRC_ALPHA, DestBlend = ONE Radar icons (triangles, squares) and POI circle highlights use: Blending state: BlendOp = ADD, SrcBlend = ONE, DestBlend = ONE Player ship icon in the middle of radar and radar zoom level indicator uses: Blending state: BlendOp = ADD, SrcBlend = SRC_ALPHA, DestBlend = INV_SRC_ALPHA Postprocessing: Texture sizes after each downscale draw (my screen size is 1920 x 1080): 960 x 540 480 x 270 240 x 135 120 x 67 60 x 33 The first image (size 960 x 540) uses different shader then other images. All other downscale draws use the same shader, it has 1 input texture, which is the output from previous draw. After downscaling another shader generates second image of size 60 x 33. After that, new image is upscaled. All upsacle draws use the same shader, it has 2 input textures, one is the output from previous upscale shader and second is downscale shader output of the size equal to the size produced by upscale shader. For ex. second upscale draw takes downscale texture 240 x 135 and upscale texture 120 x 67 as input and produces upscale texture 240 x 135. After upscaling, very simple shader is called. it produces 480 x 270 image from 960 x 540 and all it does is sample one texel at correct position. xxxxxxxx For some reason this image has higher contrast than upscaled one of the same size The reason is that upscaling shader has almost identical code to downscaling shader, except it reads less samples from textures and multiplies the results by a number from constant buffer. That number is different for each draw call and it is what makes the images have higher contrast in each upscaling step. Upscaling shader reads many samples from the texture from downscaling shader (the same resolution as this shader output) and adds 1 sample from upscaling shader texture from the last draw. After that the multiplication by constant takes place. After that, the shader which composes the final image with correct colors is executed. This shader has 3 textures as input: - 16 x 16 x 16 texture, no idea what this 3D texture is used for yet First slice looks like color gradient with these colors in corners: |---------------| |black red| | | | | | | | | |green yellow| |---------------| I guess the third dimension contains gradient in blue color, not sure though, can't open that dimension in debugger - 1920 x 1080 texture of the whole scene with wrong colors, this is what we get right after rendering HUD - 480 x 270 texture from the simple shader right after the last upscaling shader Separate HUD elements: Assuming blending state: BlendOp = ADD, SrcBlend = ONE, DestBlend = INV_SRC_ALPHA Shader exporter uses the same blending state as ED renderer. Variables: PC = pixel color PA = pixel alpha DC = destination color DA = destination alpha (not used, RT uses pixel format without alpha) EC = exported color EA = exported alpha SC = separate hud image color SA = separate hud image alpha Game rendering: DC = PC + (1-PA) * DC DA undefined Exporting shader output for overlapping pixels: EC = PC + (1-PA) * EC EA = PA + EA Exporting shader output for non-overlapping pixels (EC and EA are zero before export): EC = PC EA = PA Applying exported pixel shader values directly to hud-off image: DC = EC + (1-EA) * DC DA undefined 1) for overlapping pixels DC = PC + (1-PA) * EC + (1-EA) * DC = PC + (1-PA) * EC + (1-(PA + EA)) * DC = ... Recursive due to EA, until we get to first pixel, in which case EA = PA. 2) for non-overlapping pixels DC = PC + (1-PA) * DC That is correct formula. Applying exported pixel shader values to separate HUD images: SC = EC + (1-EA) * SC SA = EA + SA non-overlapping pixels or first pixel of overlapping pixels SC = EC SA = EA Applying separate HUD images to hud-off image: DC = SC + (1-SA) * DC = EC + (1-EA) * SC + (1-(EA + SA)) * DC DA undefined Formula for DC should be in form DC = PC + (1-PA) * DC. EC and EA cannot be changed (it would break hologram HUD elements) 1) changing SC blending mode to ADD DC = SC + (1-SA) * DC = EC + SC + (1-(EA + SA)) * DC Assuming non-overlapping pixels DC = SC + (1-SA) * DC = EC + (1-EA) * DC = PC + (1-PA) * DC