Я думаю, что я в корне неправильно понимаю, как работают цели рендеринга. Насколько я понимаю, RenderTargets - это просто текстуры, к которым обращается вызов spritebatch draw.

Поэтому я попробовал этот код для рендеринга окон графического интерфейса, чтобы убедиться, что они могут рисовать только в своей клиентской области и обрезать ее за ее пределами.

 for (int i = Controls.Count - 1; i >= 0; i--)
        {
            RenderTarget2D oldTarget;
            if (graphics.GetRenderTargets().Count() == 0) oldTarget = null;
            else oldTarget = (RenderTarget2D)graphics.GetRenderTargets()[0].RenderTarget; // Get the old target being used.
            graphics.SetRenderTarget(canvas); //set the target to a temporary RT
            graphics.Clear(Color.Black); // Clear it
            Control c = Controls[i]; // Get the current control (a form in this case)
            c.Draw(spriteBatch, gameTime); // Draw it to the temp RT
            graphics.SetRenderTarget(oldTarget); // Set the RT back to the main RT
            Vector2 dest = c.DrawCoOrds(); // Gets the draw coordinates of the control
            spriteBatch.Begin();
            spriteBatch.Draw(canvas, new Rectangle((int)dest.X, (int)dest.Y, c.Bounds.Width, c.Bounds.Height), new Rectangle((int)dest.X, (int)dest.Y, c.Bounds.Width, c.Bounds.Height), Color.White); 
// take the rect from the temp RT and draw it to the main RT.
            spriteBatch.End();
        }

Однако этот код рисует только последнюю форму в списке, что означает, что он должен каким-то образом очищать основной RT, но я не понимаю, почему. Я вызываю clear только тогда, когда RT установлен на временный холст.

0
Calin Leafshade 30 Авг 2011 в 00:36

2 ответа

Лучший ответ

Я думаю, что лучший способ рисовать элементы управления gui - это ScissorRectangle, потому что позволяет рисовать только внутри этого прямоугольника, который может быть клиентской областью элемента управления gui.

MSDN: GraphicsDevice.ScissorRectangle

Вам необходимо включить эту функциональность через RasterizerState.

 RasterizerState ScissorState = new RasterizerState() 
 { 
     ScissorTestEnabled = true; 
 }

Прежде чем рисовать, вызовите SpriteBatch. Начните с этого состояния.

Видео с моим собственным графическим интерфейсом, работающим на xbox360 :)

0
Blau 31 Авг 2011 в 08:48

Как вы создали цель рендеринга и задний буфер? По умолчанию вы не можете писать в цель рендеринга несколько раз после перехода на другую цель рендеринга. Вот почему:

http://blogs.msdn.com/b/shawnhar/archive/2007/11/21/rendertarget-changes-in-xna-game-studio-2-0.aspx

Вы можете изменить поведение по умолчанию, создав целевые объекты рендеринга с помощью RenderTargetUsage.PreserveContents., а задний буфер, переопределив GraphicsDeviceManager.PrepareDeviceSettings., изменив GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage, как описано в ссылке. Хотя я считаю, что переопределение этих настроек в XNA 4 выполняется по-другому.

При этом изменение поведения по умолчанию связано с соображениями производительности и не рекомендуется. Вы должны найти способ сделать это по-другому. Одна из возможностей - создать отдельную цель рендеринга для каждого из ваших окон, нарисовать их все, переключиться на задний буфер и нарисовать цели рендеринга к нему.

Лучшим вариантом было бы использовать состояние растеризатора прямоугольных ножниц, предложенное @Blau.

0
Dave Carlile 30 Авг 2011 в 16:21