示例#1
0
文件: Graphics.cs 项目: thomaswp/RTS
        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        /// <param name="graphics">The <see cref="Microsoft.Xna.Framework.Graphics.GraphicsDeviceManager">
        /// Microsoft.Xna.Framework.Graphics.GraphicsDeviceManager</see> used to draw the frame.</param>
        /// <param name="spriteBatch">The <see cref="Microsoft.Xna.Framework.Graphics.SpriteBatch">
        /// Microsoft.Xna.Framework.Graphics.SpriteBatch</see> used to draw the frame.</param>
        public static Texture2D Draw(bool textureOut)
        {
            if (Frozen || GraphicsDevice == null || DeviceManager == null || SpriteBatch == null || Effects == null)
            {
                return(lastFrame);
            }

            if (!viewportsMap.ContainsKey(Viewport.Default))
            {
                viewportsMap.Add(Viewport.Default, GraphicsDevice.Viewport);
            }

            RenderTarget2D target = null, oldTarget = null;

            if (textureOut)
            {
                RenderTargetBinding[] rts = GraphicsDevice.GetRenderTargets();
                target    = rts.Length == 0 ? null : (RenderTarget2D)rts[0].RenderTarget;
                oldTarget = target;
                PresentationParameters pp = GraphicsDevice.PresentationParameters;
                target = new RenderTarget2D(GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight, false, SurfaceFormat.Rg32, DepthFormat.Depth24);
                GraphicsDevice.SetRenderTarget(target);
            }

            GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.Black);

            Microsoft.Xna.Framework.Color color;
            Texture2D     texture;
            int           totalAlpha;
            SpriteEffects sEffects = SpriteEffects.None;

            BlendState blendState = BlendState.AlphaBlend, lastBlendState = BlendState.AlphaBlend;

            SpriteBatch.Begin(SpriteSortMode.Immediate, blendState);

            int t = 0;

            Viewports.Sort();
            foreach (Viewport viewport in Viewports)
            {
                if (viewport == null || viewport.Disposed || !viewport.Visible)
                {
                    continue;
                }

                viewport.Sprites.Sort();
                GraphicsDevice.Viewport = GetViewport(viewport);

                List <Sprite> remove = new List <Sprite>();

                foreach (Sprite sprite in viewport.Sprites)
                {
                    t++;

                    if (sprite == null || sprite.Disposed || sprite.Bitmap == null)
                    {
                        remove.Add(sprite);
                        continue;
                    }

                    if (!sprite.Visible)
                    {
                        continue;
                    }

                    totalAlpha = sprite.Color.Alpha + sprite.Viewport.Color.Alpha;
                    if (totalAlpha == 0)
                    {
                        color = new Microsoft.Xna.Framework.Color(255, 255, 255, sprite.Opacity);
                    }
                    else
                    {
                        color = new Microsoft.Xna.Framework.Color(
                            (byte)((sprite.Color.Red * sprite.Color.Alpha + viewport.Color.Red * viewport.Color.Alpha) / totalAlpha),
                            (byte)((sprite.Color.Green * sprite.Color.Alpha + viewport.Color.Green * viewport.Color.Alpha) / totalAlpha),
                            (byte)((sprite.Color.Blue * sprite.Color.Alpha + viewport.Color.Blue * viewport.Color.Alpha) / totalAlpha));
                    }

                    color.R += (byte)(sprite.Tone.Red + viewport.Tone.Red);
                    color.G += (byte)(sprite.Tone.Green + viewport.Tone.Green);
                    color.B += (byte)(sprite.Tone.Blue + viewport.Tone.Blue);

                    if (sprite.Opacity < 255)
                    {
                        color *= sprite.Opacity / 255f;
                    }

                    Rect rect = sprite.Rect;
                    rect.X -= viewport.OX;
                    rect.Y -= viewport.OY;

                    switch (sprite.FlipMode)
                    {
                    case FlipModes.None:
                    {
                        sEffects = SpriteEffects.None;
                        break;
                    }

                    case FlipModes.Horizontally:
                    {
                        sEffects = SpriteEffects.FlipHorizontally;
                        break;
                    }

                    case FlipModes.Vertically:
                    {
                        sEffects = SpriteEffects.FlipVertically;
                        break;
                    }
                    }

                    //still need to do a better job of negative blending
                    blendState = sprite.BlendType == 1 ? BlendState.Additive : BlendState.AlphaBlend;

                    if (sprite.Bitmap.NeedRefresh)
                    {
                        sprite.Bitmap.Texture     = CreateTextureFromBitmap(sprite.Bitmap.SystemBitmap);
                        sprite.Bitmap.NeedRefresh = false;
                    }
                    texture = sprite.Bitmap.Texture;

                    //There's still a problem with a lot of consecutive sprites using effect
                    //Which I'll need to fix once I have a good laggy test case
                    EffectGray      = (sprite.Tone.Gray + viewport.Tone.Gray) / 255.0f;
                    EffectColor     = color;
                    EffectBlendType = sprite.BlendType;
                    bool useEffect =
                        (sprite.Tone.Gray + viewport.Tone.Gray > 0) ||
                        // (color != Colors.White.ToXNAColor()) ||
                        (sprite.BlendType == 2);



                    //DeviceManager.GraphicsDevice.Textures[1] = texture;
                    //Effects.Parameters["width"].SetValue(sprite.Width);
                    //Effects.Parameters["height"].SetValue(sprite.Height);
                    //Effects.Parameters["bushDepth"].SetValue(sprite.BushDepth);
                    //Effects.Parameters["blur"].SetValue(sprite.Blur);
                    //Effects.Parameters["bubbleX"].SetValue(sprite.Bubble.X);
                    //Effects.Parameters["bubbleY"].SetValue(sprite.Bubble.Y);
                    //Effects.Parameters["bubbleRad"].SetValue((sprite.BubbleRadius));


                    if (blendState != lastBlendState)
                    {
                        if (!useEffect)
                        {
                            SpriteBatch.End();
                            SpriteBatch.Begin(SpriteSortMode.Immediate, blendState);
                        }
                        lastBlendState = blendState;
                    }

                    if (useEffect)
                    {
                        SpriteBatch.End();
                        SpriteBatch.Begin(SpriteSortMode.Immediate, blendState);

                        // TODO: The Effects shader is still messed up, at least for rotation/scaling
                        // so we can't use it right now
                        //Effects.CurrentTechnique.Passes[0].Apply();
                    }

                    try
                    {
                        SpriteBatch.Draw(
                            texture,
                            rect.ToXNARect(),
                            sprite.BmpSourceRect.ToXNARect(),
                            color,
                            (float)(sprite.Rotation * 2 * Math.PI),
                            new Vector2(sprite.OX, sprite.OY),
                            sEffects,
                            0);
                    }
                    catch
                    {
                        MsgBox.Show("Graphics Error!");
                        throw new Exception("Graphics Error!");
                    }

                    if (useEffect)
                    {
                        SpriteBatch.End();
                        SpriteBatch.Begin(SpriteSortMode.Immediate, blendState);
                    }
                }

                foreach (Sprite sprite in remove)
                {
                    viewport.Sprites.Remove(sprite);
                }
            }
            SpriteBatch.End();

            //Console.WriteLine(t);

            if (Math.Abs(fading) > 0)
            {
                GraphicsDevice.Textures[1] = transitionTexture;
                TransEffect.Parameters["opacity"].SetValue((float)faded);

                SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);

                if (!blankTransition)
                {
                    TransEffect.CurrentTechnique.Passes[0].Apply();
                }

                color = new Microsoft.Xna.Framework.Color((byte)255, (byte)255, (byte)255, (byte)(255.0 * faded));
                SpriteBatch.Draw(
                    lastFrame,
                    ScreenRect.ToXNARect(),
                    color);

                SpriteBatch.End();

                faded += fading;
                if (faded <= 0)
                {
                    faded  = 0;
                    fading = 0;
                }
                else if (faded >= 1)
                {
                    faded  = 1;
                    fading = 0;
                }
            }

            if (textureOut)
            {
                GraphicsDevice.SetRenderTarget(oldTarget);
                return((Texture2D)target);
            }
            else
            {
                return(null);
            }
        }