Exemplo n.º 1
0
        /// <summary>
        /// Overwrites the current render state with the provided state. To Save the previous state, see <see cref="PushRenderState(ref DeviceRenderState)"/>
        /// </summary>
        /// <param name="state"></param>
        public void SetRenderState(ref DeviceRenderState state)
        {
#if DEBUG
            ValidateRenderState();
#endif
            this.visibleState.state = state;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Saves the current render state onto the render state stack, then copies the provided render state in. Reset the state back with a call to <see cref="PopRenderState"/>
        /// </summary>
        /// <remarks><para>If you wish to modify the render state temporarily, then it is best to call this method before making change, then call <see cref="PopRenderState"/> after rendering is complete to restore the previous state.</para><para>This will be a lot more efficient than manually storing the states that are changed</para></remarks>
        public void PushRenderState(ref DeviceRenderState newState)
        {
#if DEBUG
            ValidateRenderState();
#endif
            PushRenderState();
            this.visibleState.state = newState;
        }
Exemplo n.º 3
0
        //each of these 4 methods is more efficient than the previous...

        //this method is the manual method where each state is setup peice by peice
        private void DrawManual(DrawState state)
        {
            //manual render state

            //First, take a copy of current render state..
            DeviceRenderState currentState = state.RenderState;

            //The DeviceRenderState structure stores common render state, it's bit-packed so it's small.
            //The majority of render state is stored, with most commonly used xbox-supported state included.
            //The entire structure is 16 bytes (the size of a Vector4)
            //
            //The DeviceRenderState structure stores four smaller structures:
            //
            //	StencilTestState		StencilTest;      (8 bytes)
            //	AlphaBlendState			AlphaBlend;	      (4 bytes)
            //	AlphaTestState			AlphaTest;        (2 bytes)
            //	DepthColourCullState	DepthColourCull;  (2 bytes)
            //
            //DepthColourCullState combines the three smaller states, Depth testing, Colour masking and FrustumCull mode
            //
            //When geometry is rendered, state.RenderState is compared to the current known device state
            //This comparison is very fast. Any changes detected will be applied at render time.
            //
            //Because of this, changing state.RenderState is very fast and efficient, as actual render state
            //on the GraphicsDevice doesn't change until the geometry is drawn. No logic is run when changing
            //the value.
            //
            //In terms of efficiency, think of setting the DeviceRenderState as equivalent assigning integers.


            //Here the alpha blend state is changed manually...

            //reset the state to default (no blending)
            state.RenderState.AlphaBlend = new AlphaBlendState();                                       //4 bytes assigned to zero, no heap allocations
            //set blending...
            state.RenderState.AlphaBlend.Enabled          = true;                                       //one bit is changed
            state.RenderState.AlphaBlend.SourceBlend      = Blend.SourceAlpha;                          //4 bits are changed
            state.RenderState.AlphaBlend.DestinationBlend = Blend.InverseSourceAlpha;                   //4 bits are changed


            //draw the sphere
            DrawGeometry(state);


            //set the previous state back
            state.SetRenderState(ref currentState);

            //Note:
            //you cannot write:
            //state.RenderState = currentState;
            //you have to call 'SetRenderState()' instead.
        }
Exemplo n.º 4
0
        public void Render(DrawState state, byte clipDepth)
        {
            Element parent = _parent;
            Matrix matrix;
            DeviceContext context = state.Context;

            if (parent == null)
            {
                _clipTest = false;

                DeviceRenderState rstate = new DeviceRenderState();

                rstate.DepthColourCull.DepthWriteEnabled = false;
                rstate.DepthColourCull.DepthTestEnabled = false;

                state.PushRenderState(ref rstate);

                if (_camera == null)
                    _camera = new ElementCamera(true);

                state.PushCamera(_camera);
            }
            else
                _clipTest = parent._clipTest | parent.ClipsChildren;

            StencilTestState stencilState = new StencilTestState();

            if (_clipTest)
            {
                stencilState.Enabled = true;
                stencilState.ReferenceValue = clipDepth;
                stencilState.StencilFunction = Compare.Equal;
                stencilState.StencilPassOperation = StencilOperation.Keep;
            }

            bool clearStencil = false;

            if (ClipsChildren)
            {
                clearStencil = clipDepth == 255;
                clipDepth--;

                if (!_clipTest)
                {
                    stencilState.Enabled = true;
                    stencilState.ReferenceValue = clipDepth;
                    stencilState.StencilPassOperation = StencilOperation.Replace;
                }
                else
                    stencilState.StencilPassOperation = StencilOperation.Decrement;
            }

            Viewport viewport = context.Viewport;
            Vector2 scale = new Vector2(viewport.Width, viewport.Height);

            if ((scale.X != 0 && scale.Y != 0))
            {
                Vector2 size = ElementSize;
                GetDisplayMatrix(out matrix, scale, ref size);

                state.PushWorldMatrixMultiply(ref matrix);

                BindShader(state, false);

                state.RenderState.AlphaBlend = _blendState;
                state.RenderState.StencilTest = stencilState;

                if (!UseSize)
                    size = new Vector2(1, 1);
                else if (IsNormalised)
                {
                    size.X *= scale.X;
                    size.Y *= scale.Y;
                }

                PreDraw(state.Context, size);

                DrawElement(state);

                List<Element> children = Children;
                if (children != null)
                    foreach (Element child in children)
                        if (child.CullTest(state))
                            child.Render(state, clipDepth);

                if (clearStencil)
                {
                    BindShader(state, true);

                    stencilState = new StencilTestState();
                    stencilState.Enabled = true;
                    stencilState.StencilFunction = Compare.Never;
                    stencilState.StencilFailOperation = StencilOperation.Zero;
                    state.RenderState.StencilTest = stencilState;

                    DrawElement(state);
                }

                state.PopWorldMatrix();
            }

            if (parent == null)
            {
                state.PopRenderState();
                state.PopCamera();
            }
        }
Exemplo n.º 5
0
        private void Draw(DrawState state, Vector2 scale, byte clipDepth)
        {
            Element parent = this.parent;


            Matrix         matrix;
            GraphicsDevice device = null;

            if (parent == null)
            {
                if (state.DrawTarget.MultiSampleType != MultiSampleType.None)
                {
                    device = state.BeginGetGraphicsDevice(StateFlag.None);
                    device.RenderState.MultiSampleAntiAlias = false;
                }

                this.clipTestActive = false;

                DeviceRenderState rstate = new DeviceRenderState();
                rstate.DepthColourCull.DepthWriteEnabled = false;
                rstate.DepthColourCull.DepthTestEnabled  = false;

                state.PushRenderState(ref rstate);

                if (camera == null)
                {
                    camera = state.UserValues[cameraID] as Xen.Camera.Camera2D;
                    if (camera == null)
                    {
                        camera = new Xen.Camera.Camera2D(true);
                        state.UserValues[cameraID] = camera;
                    }
                }

                state.PushCamera(camera);
            }
            else
            {
                this.clipTestActive = parent.clipTestActive | parent.ClipsChildren;
            }

            StencilTestState stencilState = new StencilTestState();

            if (clipTestActive)
            {
                stencilState.Enabled              = true;
                stencilState.ReferenceValue       = clipDepth;
                stencilState.StencilFunction      = CompareFunction.Equal;
                stencilState.StencilPassOperation = StencilOperation.Keep;
            }

            bool clearStencil = false;

            if (this.ClipsChildren)
            {
                clearStencil = clipDepth == 255;
                clipDepth--;

                if (!clipTestActive)
                {
                    //check there actually is a stencil buffer
#if DEBUG
                    DepthFormat format = state.DrawTarget.SurfaceDepthFormat ?? DepthFormat.Unknown;

                    if (format != DepthFormat.Depth24Stencil8)
                    {
                        throw new InvalidOperationException("ElementRect.ClipChildren requires the DrawTarget has a valid Depth Buffer with an 8bit Stencil Buffer");
                    }
#endif

                    stencilState.Enabled              = true;
                    stencilState.ReferenceValue       = clipDepth;
                    stencilState.StencilPassOperation = StencilOperation.Replace;
                }
                else
                {
                    stencilState.StencilPassOperation = StencilOperation.Decrement;
                }
            }

            if ((scale.X != 0 && scale.Y != 0))
            {
                Vector2 size = ElementSize;
                GetDisplayMatrix(out matrix, scale, ref size);

                state.PushWorldMatrixMultiply(ref matrix);

                BindShader(state, false);

                state.RenderState.AlphaBlend  = blend;
                state.RenderState.StencilTest = stencilState;


                if (!UseSize)
                {
                    size = new Vector2(1, 1);
                }
                else
                if (IsNormalised)
                {
                    size *= scale;
                }

                PreDraw(size);

                DrawElement(state);

                List <Element> children = Children;
                if (children != null)
                {
                    foreach (Element child in children)
                    {
                        if (((IDraw)child).CullTest(state))
                        {
                            child.Draw(state, size, clipDepth);
                        }
                    }
                }

                if (clearStencil)
                {
                    BindShader(state, true);
                    stencilState                      = new StencilTestState();
                    stencilState.Enabled              = true;
                    stencilState.StencilFunction      = CompareFunction.Never;
                    stencilState.StencilFailOperation = StencilOperation.Zero;
                    state.RenderState.StencilTest     = stencilState;

                    DrawElement(state);
                }

                state.PopWorldMatrix();
            }


            if (parent == null)
            {
                state.PopRenderState();
                state.PopCamera();
            }

            if (device != null)
            {
                device.RenderState.MultiSampleAntiAlias = true;
                state.EndGetGraphicsDevice();
            }
        }