Menggunakan RenderTarget sebagai tekstur selepas melukis pada tekstur

Laman dikemaskini :
Tarikh penciptaan halaman :

Persekitaran pengesahan

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

Perihal Sasaran Render

Biasanya, apabila anda melukis, kandungan lukisan dipaparkan pada skrin, tetapi anda boleh menggunakan sasaran render untuk menulis lukisan pada tekstur. Kandungan yang ditulis dalam tekstur boleh digunakan sebagai tekstur seperti itu. Sebagai contoh, jika anda menulis kandungan TV ke tekstur dan kemudian tampal tekstur ke skrin TV, anda boleh memindahkan imej yang berbeza dalam TV. Sudah tentu, ia juga boleh digunakan sebagai imej pegun, dan anda boleh membuat tekstur secara dinamik tanpa menyediakan fail imej untuk tekstur terlebih dahulu.

Menyediakan Imej

Anda tidak memerlukan fail imej untuk menggunakan sasaran render, tetapi saya akan menyediakan fail imej untuk menjadikannya lebih mudah difahami sebagai sampel.

Ia akan digunakan sebagai fail kandungan biasa, jadi sila daftarkannya di MGCB. Texture Tinggalkan nama sebagai .

Bidang

Game1 Mari tulis di dalam kelas. Kod sedia ada tidak akan diubah khususnya, jadi saya hanya akan menerangkan jumlah tambahan tanpa menerangkannya.

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

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

_texture Medan adalah untuk memuatkan imej yang disediakan dan tidak begitu relevan dengan kandungan petua ini.

RenderTarget2D Medan yang ditakrifkan dalam kelas menjadi sasaran render. Oleh kerana perlu GraphicsDevice seketika , ia tidak boleh dibuat pada peringkat ini, jadi ia hanya ditakrifkan.

Pembina Game1

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

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

Tiada apa yang istimewa untuk dilakukan di sini. Buat masa ini, saya telah menentukan resolusi permainan supaya ia dapat dibandingkan dengan sasaran render.

LoadContent

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

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

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

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

Pertama, baca penggunaan Texture2D Content.Load untuk melukis dengan .

GraphicsDevice Sekiranya ada RenderTarget2D , anda boleh menjananya di mana sahaja, tetapi dalam contoh kami akan menciptanya dalam LoadContent kaedah tersebut. Sasaran render adalah tekstur sebenar, jadi ia mempunyai saiz. Pembina GraphicsDevice juga menentukan saiz bersama-sama dengan .

Menarik

Jika anda menggunakan sasaran render, kod di sini adalah yang utama.

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);
}

Oleh kerana lukisan pada dasarnya dilakukan pada GraphicsDevice , walaupun proses lukisan dilakukan seperti sedia ada, ia akan ditarik ke tetingkap utama. GraphicsDevice.SetRenderTarget Dengan menentukan RenderTarget2D kaedah, anda boleh menukar destinasi lukisan kepada tekstur.

Selepas bertukar, proses lukisan dilakukan dengan cara yang sama seperti ketika melukis di tetingkap utama. GraphicsDevice.Clear membersihkan maklumat lukisan dan menarikSpriteBatch sprite. Untuk memeriksa sama ada anda benar-benar melukis pada tekstur, saya sengaja menentukan kedudukan lukisan supaya sprite menonjol kali ini.

Apabila anda selesai melukis ke sasaran render, GraphicsDevice.SetRenderTarget tentukan kaedah. null Ini membolehkan anda mengembalikan sasaran lukisan ke tetingkap utama.

RenderTarget2D boleh digunakan sebagai tekstur seperti itu, jadi SpriteBatch.Draw saya menentukan kaedah untuk _renderTarget melukisnya sebagai sprite.

Pelaksanaan

Setelah anda menulis kod, cuba jalankannya. Jika ia kelihatan seperti angka itu, tidak mengapa.

Warna isian untuk sasaran render dan warna isian untuk tetingkap utama dipisahkan, supaya anda dapat melihat di mana tekstur dicipta sebagai sasaran render. Saya menarik sprite supaya ia menonjol terhadap sasaran render, tetapi saya fikir anda dapat melihat bahawa ia dipotong dengan betul dan tidak ditarik ke arah tetingkap utama.

Itulah semua kod yang mencapai sasaran render. Tidak ada yang sangat sukar. Saya fikir satu-satunya perkara yang saya peduli ialah menguruskan pertukaran destinasi lukisan dan RenderTarget2D pengurusan .

Cuba gerakkannya

Hasil pelaksanaan sebelumnya kelihatan seperti imej hanya dipotong dan dilukis, jadi Seterusnya, saya ingin menggerakkan sprite untuk memastikan ia ditarik dengan betul dalam sasaran render.

Update Oleh kerana kami ingin mengemas kini putaran setiap kali, kami akan menyediakan sudut putaran di lapangan.

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

Update Dalam kaedah ini, meningkatkan _rotate bilangan .

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 Kaedah ini menetapkan sprite untuk _rotate berputar. Anda hanya perlu tahu bahawa ia berputar, jadi nilai lain ditetapkan dengan sewajarnya.

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);
}

Apabila anda menjalankannya, ia harus menarik semasa berputar seperti yang ditunjukkan dalam angka itu.