Usando RenderTarget como uma textura depois de desenhar em uma textura

Página atualizada :
Data de criação de página :

Ambiente de verificação

Windows
  • Janelas 10
  • Janelas 11
Estúdio Visual
  • Visual Studio 2022
MonoJogo
  • 3.8.1

Sobre destinos de renderização

Normalmente, quando você desenha, o conteúdo do desenho é exibido na tela, mas você pode usar um destino de renderização para gravar o desenho em uma textura. O conteúdo escrito na textura pode ser usado como uma textura como ela é. Por exemplo, se você gravar o conteúdo da TV em uma textura e, em seguida, colar a textura na tela da TV, poderá mover uma imagem diferente na TV. Claro, ele também pode ser usado como uma imagem estática, e você pode criar uma textura dinamicamente sem preparar um arquivo de imagem para a textura com antecedência.

Preparando imagens

Você não precisa de um arquivo de imagem para usar o destino de renderização, mas vou preparar um arquivo de imagem para facilitar o entendimento como um exemplo.

Ele será usado como um arquivo de conteúdo normal, então registre-o no MGCB. Texture Deixe o nome como .

campo

Game1 Vamos escrevê-lo na aula. O código existente não será alterado em particular, então vou apenas descrever a quantidade adicionada sem descrevê-la.

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

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

_texture Os campos são para carregar as imagens preparadas e não são particularmente relevantes para o conteúdo desta dica.

RenderTarget2D Os campos definidos na classe tornam-se destinos de renderização. Uma vez que é necessário GraphicsDevice instanciar , ele não pode ser criado nesta fase, por isso é apenas definido.

Construtor Game1

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

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

Não há nada de especial a fazer aqui. Por enquanto, especifiquei a resolução do jogo para que ele possa ser comparado com o alvo de renderização.

LoadContent

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

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

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

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

Primeiro, leia o uso Texture2D Content.Load para desenhar com .

GraphicsDevice Se houver RenderTarget2D , você pode gerá-lo em qualquer lugar, mas no exemplo vamos criá-lo no LoadContent método. O destino de renderização é uma textura real, por isso tem um tamanho. O GraphicsDevice construtor também especifica o tamanho junto com .

Desenhar

Se você usar um destino de renderização, o código aqui é o principal.

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

Como o desenho é basicamente GraphicsDevice realizado no , mesmo que o processo de desenho seja realizado como está, ele será desenhado contra a janela principal. GraphicsDevice.SetRenderTarget Ao especificar um RenderTarget2D método, você pode alternar o destino do desenho para uma textura.

Após a alternância, o processo de desenho é realizado da mesma forma que ao desenhar na janela principal. GraphicsDevice.Clear limpa as informações do desenho e desenhaSpriteBatch o sprite. A fim de verificar se você está realmente desenhando contra a textura, eu deliberadamente especifiquei a posição do desenho para que o sprite se projete desta vez.

Quando terminar de desenhar para o destino de renderização, GraphicsDevice.SetRenderTarget especifique o null método. Isso permite que você retorne o destino de desenho para a janela principal.

RenderTarget2D pode ser usado como uma textura como ele é, então SpriteBatch.Draw eu especifico o _renderTarget método para desenhá-lo como um sprite.

execução

Depois de escrever o código, tente executá-lo. Se parece com a figura, tudo bem.

A cor de preenchimento para o destino de renderização e a cor de preenchimento para a janela principal são separadas, para que você possa ver onde a textura foi criada como o destino de renderização. Eu desenhei o sprite para que ele se projete contra o alvo de renderização, mas acho que você pode ver que ele está devidamente cortado e não desenhado em direção à janela principal.

Esse é todo o código que atinge o destino de renderização. Não há nada particularmente difícil. Acho que a única coisa que me importa é gerenciar a mudança de destinos de desenho e RenderTarget2D gerenciar.

Tente movê-lo

O resultado da execução anterior parece que a imagem é simplesmente cortada e desenhada, então Em seguida, gostaria de mover o sprite para garantir que ele seja desenhado corretamente no destino de renderização.

Update Como queremos atualizar a rotação toda vez, vamos preparar o ângulo de rotação no campo.

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

Update No método, aumente o _rotate número de .

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 O método define o sprite para _rotate girar. Você só precisa saber que ele está girando, para que os outros valores sejam definidos adequadamente.

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

Quando você executá-lo, ele deve desenhar enquanto gira, como mostrado na figura.