Używanie elementu RenderTarget jako tekstury po narysowaniu na teksturze

Strona zaktualizowana :
Data utworzenia strony :

Środowisko weryfikacji

Windows
  • Okna 10
  • Okna 11
Visual Studio
  • Visual Studio 2022
MonoGame
  • 3.8.1

Informacje o obiektach docelowych renderowania

Zwykle podczas rysowania zawartość rysunku jest wyświetlana na ekranie, ale można użyć celu renderowania, aby zapisać rysunek do tekstury. Zawartość zapisana w teksturze może być używana jako tekstura taka, jaka jest. Jeśli na przykład zawartość telewizora zostanie zapisana w teksturze, a następnie wkleisz ją na ekranie telewizora, możesz przenieść inny obraz w telewizorze. Oczywiście może być również używany jako nieruchomy obraz i można dynamicznie tworzyć teksturę bez wcześniejszego przygotowywania pliku obrazu dla tekstury.

Przygotowywanie obrazów

Nie potrzebujesz pliku obrazu, aby użyć celu renderowania, ale przygotuję plik obrazu, aby ułatwić zrozumienie go jako przykład.

Będzie używany jako zwykły plik treści, więc zarejestruj go w MGCB. Texture Pozostaw nazwę jako .

pole

Game1 Napiszmy to w klasie. Istniejący kod nie zostanie zmieniony w szczególności, więc opiszę tylko dodaną kwotę bez jej opisywania.

/// <summary>描画するテクスチャー画像。</summary>
private Texture2D _texture;

/// <summary>描画対象となるレンダーターゲット。</summary>
private RenderTarget2D _renderTarget;

_texture Pola służą do ładowania przygotowanych obrazów i nie są szczególnie istotne dla treści tej wskazówki.

RenderTarget2D Pola zdefiniowane w klasie stają się celami renderowania. Ponieważ konieczne GraphicsDevice jest utworzenie instancji , nie można go utworzyć na tym etapie, więc jest tylko zdefiniowany.

Konstruktor Game1 —

public Game1()
{
  _graphics = new GraphicsDeviceManager(this);
  Content.RootDirectory = "Content";
  IsMouseVisible = true;

  // ゲームの解像度の設定
  _graphics.PreferredBackBufferWidth = 1280;
  _graphics.PreferredBackBufferHeight = 720;
}

Nie ma tu nic specjalnego do zrobienia. Na razie określiłem rozdzielczość gry, aby można ją było porównać z celem renderowania.

LoadContent

protected override void LoadContent()
{
  _spriteBatch = new SpriteBatch(GraphicsDevice);

  // TODO: this.Content を使用してゲーム コンテンツをここに読み込みます

  // コンテンツからテクスチャーを読み込みます
  _texture = Content.Load<Texture2D>("Texture");

  _renderTarget = new RenderTarget2D(GraphicsDevice, 540, 360);
}

Najpierw przeczytaj użycie Texture2D Content.Load do rysowania za pomocą .

GraphicsDevice Jeśli jest RenderTarget2D , możesz go wygenerować w dowolnym miejscu, ale w przykładzie utworzymy go w LoadContent metodzie. Cel renderowania jest prawdziwą teksturą, więc ma rozmiar. Konstruktor GraphicsDevice określa również rozmiar wraz z .

Rysować

Jeśli używasz celu renderowania, kod tutaj jest główny.

protected override void Draw(GameTime gameTime)
{
  // TODO: ここに描画コードを追加します

  // 描画先対象をレンダーターゲットに設定
  GraphicsDevice.SetRenderTarget(_renderTarget);

  // テクスチャーの情報をクリアし単色で塗りつぶします
  GraphicsDevice.Clear(Color.LightYellow);

  // スプライトバッチを使用してスプライトを書き込みます
  // レンダーターゲットの外に影響ないことを確認するためにわざと領域をはみ出るように描画しています
  _spriteBatch.Begin();
  for (int i = 0; i < 4; i++)
  {
    _spriteBatch.Draw(_texture, new Vector2((i / 2) * 200 - 50, (i % 2) * 200 - 50), Color.White);
  }
  _spriteBatch.End();

  // レンダーターゲットを解除します。これ以降の描画処理はメインウインドウに対して行われます
  GraphicsDevice.SetRenderTarget(null);

  // メインウィンドウの描画情報をクリアし単色で塗りつぶします
  GraphicsDevice.Clear(Color.CornflowerBlue);

  // メインウィンドウに対してレンダーターゲットをテクスチャーとして描画します
  _spriteBatch.Begin();
  _spriteBatch.Draw(_renderTarget, new Vector2(100, 100), Color.White);
  _spriteBatch.End();

  base.Draw(gameTime);
}

Ponieważ rysowanie jest zasadniczo GraphicsDevice wykonywane na , nawet jeśli proces rysowania jest wykonywany tak, jak jest, zostanie narysowany w głównym oknie. GraphicsDevice.SetRenderTarget Określając metodę RenderTarget2D , można przełączyć miejsce docelowe rysowania na teksturę.

Po przełączeniu proces rysowania odbywa się w taki sam sposób, jak podczas rysowania w oknie głównym. GraphicsDevice.Clear Usuwa informacje o rysunku i rysujeSpriteBatch duszka. Aby sprawdzić, czy rzeczywiście rysujesz na tle tekstury, celowo określiłem pozycję rysowania, aby tym razem duszek wystawał.

Po zakończeniu rysowania do celu GraphicsDevice.SetRenderTarget renderowania określ metodę null . Umożliwia to powrót celu rysunkowego do okna głównego.

RenderTarget2D może być używany jako tekstura taka, jaka jest, więc SpriteBatch.Draw określam _renderTarget metodę rysowania jej jako duszka.

egzekucja

Po napisaniu kodu spróbuj go uruchomić. Jeśli wygląda jak rysunek, jest OK.

Kolor wypełnienia dla celu renderowania i kolor wypełnienia dla okna głównego są rozdzielone, dzięki czemu można zobaczyć, gdzie tekstura została utworzona jako cel renderowania. Narysowałem duszka tak, aby wystawał w kierunku celu renderowania, ale myślę, że widać, że jest odpowiednio przycięty i nie jest rysowany w kierunku głównego okna.

To cały kod, który osiąga cel renderowania. Nie ma nic szczególnie trudnego. Myślę, że jedyne, na czym mi zależy, to zarządzanie przełączaniem miejsc docelowych rysowania i RenderTarget2D zarządzanie .

Spróbuj go przenieść

Wynik poprzedniego wykonania wygląda tak, jakby obraz został po prostu przycięty i narysowany, więc Następnie chciałbym przenieść duszka, aby upewnić się, że jest poprawnie narysowany w celu renderowania.

Update Ponieważ chcemy za każdym razem aktualizować rotację, przygotujemy kąt obrotu w terenie.

/// <summary>テクスチャーを回転させる角度。</summary>
private float _rotate;

Update W metodzie zwiększ _rotate liczbę plików .

protected override void Update(GameTime gameTime)
{
  if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
    Exit();

  // TODO: ここに更新ロジックを追加します

  // テクスチャーの回転角度を更新します
  _rotate += 0.01f;

  base.Update(gameTime);
}

Draw Metoda ustawia ikonkę do _rotate obracania. Musisz tylko wiedzieć, że się obraca, więc inne wartości są odpowiednio ustawione.

protected override void Draw(GameTime gameTime)
{
  // 中略

  // スプライトバッチを使用してスプライトを書き込みます
  // レンダーターゲットの外に影響ないことを確認するためにわざと領域をはみ出るように描画しています
  _spriteBatch.Begin();
  for (int i = 0; i < 4; i++)
  {
    _spriteBatch.Draw(_texture, new Vector2((i / 2) * 200 + 32, (i % 2) * 200 + 32),
      null, Color.White, _rotate * i, new Vector2(64, 64), 1, SpriteEffects.None, 0);
  }
  _spriteBatch.End();

  // 中略

  // メインウィンドウに対してレンダーターゲットをテクスチャーとして描画します
  _spriteBatch.Begin();
  _spriteBatch.Draw(_renderTarget, new Vector2(400, 400), null, Color.White,
    _rotate, new Vector2(_renderTarget.Width / 2, _renderTarget.Height / 2), 1, SpriteEffects.None, 0);
  _spriteBatch.End();

  base.Draw(gameTime);
}

Po uruchomieniu powinien rysować podczas obracania, jak pokazano na rysunku.