/// <summary> /// Draws the opaque interior of this <see cref="DrawNode"/> and all <see cref="DrawNode"/>s further down the scene graph, invoking <see cref="DrawOpaqueInterior"/> if <see cref="CanDrawOpaqueInterior"/> /// indicates that an opaque interior can be drawn for each relevant <see cref="DrawNode"/>. /// </summary> /// <remarks> /// This is the front-to-back pass. The back-buffer depth test function used is GL_LESS.<br /> /// If an opaque interior is not drawn: the current value of <paramref name="depthValue"/> is stored.<br /> /// If an opaque interior is drawn: <paramref name="depthValue"/> is incremented, stored, and the opaque interior vertices are drawn at the post-incremented depth value. /// Incrementing <paramref name="depthValue"/> at this point allows for early-z testing to also occur within the front-to-back pass.<br /> /// </remarks> /// <param name="depthValue">The previous depth value.</param> /// <param name="vertexAction">The action to be performed on each vertex of the draw node in order to draw it if required. This is primarily used by textured sprites.</param> internal virtual void DrawOpaqueInteriorSubTree(DepthValue depthValue, Action <TexturedVertex2D> vertexAction) { if (!depthValue.CanIncrement || !CanDrawOpaqueInterior) { // The back-to-front pass requires the depth value drawDepth = depthValue; return; } // It is crucial to draw with an incremented depth value, consider the case of a box: // In the front-to-back pass, the inner conservative area is drawn at depth X // In the back-to-front pass, the full area is drawn at depth X, and the depth test function is set to GL_LESS, so the inner conservative area is not redrawn // Furthermore, a back-to-front-drawn object above the box will be visible since it will be drawn with a depth of (X - increment), satisfying the depth test drawDepth = depthValue.Increment(); DrawOpaqueInterior(vertexAction); }
/// <summary> /// Draws the opaque interior of this <see cref="DrawNode"/> and all <see cref="DrawNode"/>s further down the scene graph, invoking <see cref="DrawOpaqueInterior"/> if <see cref="CanDrawOpaqueInterior"/> /// indicates that an opaque interior can be drawn for each relevant <see cref="DrawNode"/>. /// </summary> /// <remarks> /// This is the front-to-back pass. The back-buffer depth test function used is GL_LESS.<br /> /// During this pass, the opaque interior is drawn BELOW ourselves. For this to occur, <see cref="drawDepth"/> is temporarily incremented and then decremented after drawing is complete. /// Other <see cref="DrawNode"/>s behind ourselves receive the incremented depth value before doing the same themselves, allowing early-z to take place during this pass. /// </remarks> /// <param name="depthValue">The previous depth value.</param> /// <param name="vertexAction">The action to be performed on each vertex of the draw node in order to draw it if required. This is primarily used by textured sprites.</param> internal virtual void DrawOpaqueInteriorSubTree(DepthValue depthValue, Action <TexturedVertex2D> vertexAction) { if (!depthValue.CanIncrement || !CanDrawOpaqueInterior) { // The back-to-front pass requires the depth value. drawDepth = depthValue; return; } // For an incoming depth value D, the opaque interior is drawn at depth D+e and the content is drawn at depth D. // As such, when the GL_LESS test function is applied, the content will always pass the depth test for the same DrawNode (D < D+e). // Increment the depth. float previousDepthValue = depthValue; drawDepth = depthValue.Increment(); DrawOpaqueInterior(vertexAction); // Decrement the depth. drawDepth = previousDepthValue; }