「MonoGameでピクセルシェーダーを使ってテクスチャを貼る」の版間の差分

提供: MonoBook
ナビゲーションに移動 検索に移動
imported>Administrator
(ページの作成:「「MonoGameでプログラマブルシェーダーを使う」の実践編として以下をやってみる。 * バーテックスシェーダーでジオメ...」)
 
imported>Administrator
 
(同じ利用者による、間の2版が非表示)
1行目: 1行目:
「[[MonoGameでプログラマブルシェーダーを使う]]」の実践編として以下をやってみる。
+
「[[MonoGameでプログラマブルシェーダーを使う]]」の実践編として以下をやってみる。[[Mac]]でやっているのがミソ。
 +
 
 +
* [[MacOS]]上の[[Visual Studio for Mac]]と[[MonoGame]]を使い
 
* [[バーテックスシェーダー]]で[[ジオメトリ変換]]してみる
 
* [[バーテックスシェーダー]]で[[ジオメトリ変換]]してみる
 
* [[ピクセルシェーダー]]で[[テクスチャマッピング]]してみる。
 
* [[ピクセルシェーダー]]で[[テクスチャマッピング]]してみる。
93行目: 95行目:
 
== HLSLをコンパイルする ==
 
== HLSLをコンパイルする ==
 
[[macOS]]上の[[Visual Studio for Mac]]では[[HLSL]]をコンパイルするには準備の際にいれた「[[InfinitespaceStudios.Pipeline]]」を用いる。
 
[[macOS]]上の[[Visual Studio for Mac]]では[[HLSL]]をコンパイルするには準備の際にいれた「[[InfinitespaceStudios.Pipeline]]」を用いる。
 +
 +
この際にProjectツリーの「Content」を開き「Platform」の設定が間違っていないことを確認すること。[[iOS]]や[[Android]]向けなのに「[[Windows]]」のままコンパイルすると[[OpenGL]]ではなく[[DirectX]]向けのモノができあがり残念なことになる。なお、[[iOS]]と[[Android]]を間違えてもどっちもOpenGL系なので動く。
  
 
== コンテンツファイルを準備 ==
 
== コンテンツファイルを準備 ==
190行目: 194行目:
 
         }
 
         }
 
     }
 
     }
</syntaxhighlight>こんな感じ。[[Mac]]でも[[HLSL]]が使えるとか感動的だね。
+
</syntaxhighlight>
 +
 
 +
== 動かしてみる ==
 +
こんな感じ。[[Mac]]でも[[HLSL]]で書いた[[シェーダー]]が使えてる。なお、[[シェーダーモデル]]3.0までだがSM3.0まであればそこそこなことはできる。。
 
[[ファイル:MonoGameでピクセルシェーダーを使ってテクスチャを貼ってみる.png|なし|サムネイル|640x640ピクセル]]
 
[[ファイル:MonoGameでピクセルシェーダーを使ってテクスチャを貼ってみる.png|なし|サムネイル|640x640ピクセル]]
 +
 +
動画
 +
<movie>https://youtu.be/1LfsaS9wG_o</movie>
  
 
== 関連項目 ==
 
== 関連項目 ==
 
* [[MonoGameでプログラマブルシェーダーを使う]]
 
* [[MonoGameでプログラマブルシェーダーを使う]]
 +
* [[MonoGameでハードウェアインスタンシングしてみる]]
 
* [[MonoGameの3Dモデルを管理描画するクラスを作る]]
 
* [[MonoGameの3Dモデルを管理描画するクラスを作る]]
 
* [[MonoGameでSkiaSharpを使う]]
 
* [[MonoGameでSkiaSharpを使う]]
204行目: 215行目:
 
* [[スリープソート]]
 
* [[スリープソート]]
  
 +
[[category: MonoGame]]
 
[[category: HLSL]]
 
[[category: HLSL]]

2018年9月3日 (月) 09:35時点における最新版

MonoGameでプログラマブルシェーダーを使う」の実践編として以下をやってみる。Macでやっているのがミソ。

準備[編集 | ソースを編集]

HLSLを書く[編集 | ソースを編集]

iOSAndroid向けの場合は強制的に「OPENGL」シンボルが定義されており、HLSLシェーダーモデルは3.0固定にしておけ。

// file: effect1.fx

// ----------------------------------------------------------------
// MonoGame PipelineでOpenGL環境の場合は「OPENGL」シンボルが立っている。
// 以下は定型文だと思ってコピペしとけ。
#if OPENGL
	#define SV_POSITION POSITION
	#define VS_SHADERMODEL vs_3_0
	#define PS_SHADERMODEL ps_3_0
#else
	#define VS_SHADERMODEL vs_4_0_level_9_1
	#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

// ----------------------------------------------------------------
// 呼び出し側から設定されるグローバル変数(シェーダー内では実質定数)

// カメラ座標
float4x4 myView;
float4x4 myProjection;

// テクスチャ
texture  myTexture;

// ----------------------------------------------------------------
// tex2D関数で使うテクスチャサンプラー
// tex2D関数はサンプラーと座標を入力すると、テクスチャからその位置の
// テクセルを抜き出してCOLORが返ってくる。
sampler mySampler = sampler_state 
{
	Texture = <myTexture>;
};

// ----------------------------------------------------------------
// 入出力用の構造体
struct VertexShaderInput
{
	float4 Position : POSITION0;
	float4 TextureCoordinate : TEXCOORD;
};

struct VertexShaderOutput
{
	float4 Position : SV_POSITION;
	float4 TextureCoordinate : TEXCOORD;
};

// ----------------------------------------------------------------
// バーテックスシェーダー
VertexShaderOutput MainVS(in VertexShaderInput input)
{
	// 出力用の頂点
	VertexShaderOutput output = (VertexShaderOutput)0;

    // 頂点をカメラから見た座標に変換
	output.Position = mul(input.Position, mul(myView, myProjection));
	
	// テクスチャ座標をコピー
	output.TextureCoordinate = input.TextureCoordinate;

	return output;
}

// ----------------------------------------------------------------
// ピクセルシェーダー
float4 MainPS(VertexShaderOutput input) : COLOR
{
	// テクスチャサンプラーからピクセルに対応する色を抜き出す
	return tex2D( mySampler, input.TextureCoordinate);
}

// ----------------------------------------------------------------
// テクニック、いわゆるエントリーポイント
technique MyTechnique
{
	pass MyPass
	{
		VertexShader = compile VS_SHADERMODEL MainVS();
		PixelShader  = compile PS_SHADERMODEL MainPS();
	}
};

HLSLをコンパイルする[編集 | ソースを編集]

macOS上のVisual Studio for MacではHLSLをコンパイルするには準備の際にいれた「InfinitespaceStudios.Pipeline」を用いる。

この際にProjectツリーの「Content」を開き「Platform」の設定が間違っていないことを確認すること。iOSAndroid向けなのに「Windows」のままコンパイルするとOpenGLではなくDirectX向けのモノができあがり残念なことになる。なお、iOSAndroidを間違えてもどっちもOpenGL系なので動く。

コンテンツファイルを準備[編集 | ソースを編集]

このサンプルで使っているコンテンツファイルは以下のとおり。

  • texture1.xnb (texture1.pngをコンパイルしたもの。画像は自分で用意してください)
  • effect1.xnb (上記のHLSLをコンパイルしたもの)

C#で呼び出してみる[編集 | ソースを編集]

即席コードなのでバーテックスバッファーインデックスバッファーは使用せずにDrawUserPrimitivesメソッドで描画を行っている。

また、「MonoGameのカメラを作る」で作ったカメラを使っている。CameraクラスはMonoGame標準物ではないので注意。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Camera camera;
        Effect effect;
        Texture texture;

        VertexPositionTexture[] vertices = {
            new VertexPositionTexture(new Vector3( 0, 1, 0), new Vector2(0.5f, 0.0f)),
            new VertexPositionTexture(new Vector3( 1, 0, 0), new Vector2(1.0f, 1.0f)),
            new VertexPositionTexture(new Vector3(-1, 0, 0), new Vector2(0.0f, 1.0f))
        };

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            IsMouseVisible = true;
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // 即席カメラ
            camera = new Camera(this);
            camera.Position = new Vector3(0, -2, 2);
            camera.Target = new Vector3(0, 0, 0);

            // テクスチャ読み込み
            texture = Content.Load<Texture2D>("texture1");

            // エフェクト読み込み
            effect = Content.Load<Effect>("effect1");
        }

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

            // カメラを回転させる
            camera.Angle += 1f;

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // シェーダーのグローバル変数に値をセットする
            effect.Parameters["myView"].SetValue(camera.View);
            effect.Parameters["myProjection"].SetValue(camera.Projection);
            effect.Parameters["myTexture"].SetValue(texture);

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                // パス適用開始(シェーダー有効化)
                pass.Apply();

                // 描画
                graphics.GraphicsDevice.DrawUserPrimitives(
                    primitiveType: PrimitiveType.TriangleList,
                    vertexData: vertices,
                    vertexOffset: 0,
                    primitiveCount: vertices.Length / 3);
            }

            base.Draw(gameTime);
        }
    }

動かしてみる[編集 | ソースを編集]

こんな感じ。MacでもHLSLで書いたシェーダーが使えてる。なお、シェーダーモデル3.0までだがSM3.0まであればそこそこなことはできる。。

MonoGameでピクセルシェーダーを使ってテクスチャを貼ってみる.png

動画

関連項目[編集 | ソースを編集]