忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


XNA爆発チュートリアル その4 透過

XNA爆発チュートリアル その3 テクスチャを貼るのつづきです。

前回は、爆発を構成する各ポイントにテクスチャが貼られたものの、
テクスチャの爆炎の周りが黒くて、
リアルさよりもシュールさがきわだってしまったようにも思えます。

これを本物に近づけるために、とりあえずこの黒いのを消してみましょう。

アルファ・ブレンディングで透過するのです。

さて、どのようにブレンドするべきでしょうか?
自分で考えるのがめんどうなのでParticle 3D Sampleのやりかたをまねることにします。
ExplosionParticleSystemはどうブレンドしているかというと・・・

SourceBlend = Blend.SourceAlpha;
DestinationBlend = Blend.One;


ですね。
つまり爆炎の色が、透過してるところは無視して、足されるわけです。
たしかにこれなら黒いところが透明になって、爆炎だけ見えるようになるでしょう。

「あれ?"explosion.png"の周りの色は黒なんだから
SourceBlendもBlend.Oneをセットしても同じなんじゃないの?」と思いながらも、
作業を先に進めることにします。
(後になって試してみましたが、やっぱり同じような結果になりました)

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


public class ExplosionTest : Microsoft.Xna.Framework.Game
{
    private GraphicsDeviceManager graphics;

    private BasicEffect effect;
    private VertexPositionColor[] vertices = {
        new VertexPositionColor(new Vector3(0, 0.1f, 0), Color.White),
        new VertexPositionColor(new Vector3(0.1f, 0, 0), Color.White),
        new VertexPositionColor(new Vector3(-0.1f, 0, 0), Color.White)
    };

    private ContentManager content;


    public ExplosionTest()
    {
        graphics = new GraphicsDeviceManager(this);
        content = new ContentManager(Services);
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        if (loadAllContent)
        {
            effect = new BasicEffect(graphics.GraphicsDevice, null);
            graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(
                graphics.GraphicsDevice,
                VertexPositionColor.VertexElements
                );

            effect.Texture = content.Load<Texture2D>("Content/explosion");
            effect.TextureEnabled = true;
        }
    }

    protected override void UnloadGraphicsContent(bool unloadAllContent)
    {
        if (unloadAllContent) { content.Unload(); }
    }

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

        graphics.GraphicsDevice.RenderState.PointSize = 50;
        graphics.GraphicsDevice.RenderState.PointSpriteEnable = true;

        graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
        graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
        graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.One;

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();

            graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.PointList,
                vertices,
                0,
                vertices.Length
                );

            pass.End();
        }

        effect.End();
    }
}

explosionTutorialPointAlphaBlended.jpg

うまくいきました!

爆炎の周りの黒いふちがなくなって、
きちんと爆炎のように見えています。
もはやテクスチャの貼られたタイルではありません!

ただ、黒いのが消えたのはアルファ・ブレンディングを使っているからですが、
これはもしかすると後になって問題を引き起こすかもしれません。

つまり、RenderState.AlphaBlendEnabledをtrueにしっぱなしで、
描画が終わっても元のfalseに戻していないため、
今後普通の透過しないモデル(敵キャラとか)を描画したくなったときに、
それまでも半透明になってしまって、全体として
描画がメチャクチャになってしまう危険性があるのです。
でもそれはそのときになってから考えることにしましょう(笑)


さて、今回の変更はプログラマにとっては小さな一歩ですが、見た目としては大きな飛躍です。
加えたのは数行だけですが、もうこの状態で頂点の位置をダブらせれば本物の爆発っぽく見えるでしょう。
もっとも時間がたつにつれ頂点が動いたりはしないのでそれでもやっぱり限界があるといえます。
進化の袋小路、大きな前進があったものの、これ以上何かをするのは難しいというわけです。

本物の爆発なら時間がたつにつれ、爆炎が周囲に広がって、フェードアウトしていくべきではないでしょうか?
しかしそれをどうやって実現すれば良いでしょう?
Game.Updateメソッド内で各頂点の位置データを動かすべきでしょうか?
それも良いかもしれませんが、もしかしたら後でVertexBufferを使うかもしれない可能性を考えると、
C#側での頻繁な更新は避けたいものです。
もうそろそろHLSLを使ったほうが良いかもしれません。
C#側の頂点は止まっていて、HLSLで書いたエフェクトファイル内で頂点を動かすのです。

HLSLを使えばいったん見た目は後退することになるでしょう。
しかしそれは一時的なことで、すぐに現在以上の見た目になるはずです。

HLSLによって、それぞれの爆炎が「ぶわっ」と動いたり、
フェードアウトしたり、
あるいは大きさが変わったり、
色々することによって、本物の爆発のようになるのです。
(というか、そうなる予定です。)


拍手[0回]

PR

XNA爆発チュートリアル その3 テクスチャを貼る

爆発チュートリアルその2のつづきです。

前回は爆発と言いつつ白いタイルのようなものが3つ表示されるだけでした。
今度はこれに炎のテクスチャを貼ってみましょう。

これから貼り付けるテクスチャはXna Creators Clubの
Particle 3Dから拝借してきたexplosion.pngです。

ebd0a9be.png(explosion.png : Particle 3D Sampleより)

これを白い四角に貼り付ければ少しはましになるのではないでしょうか。

この"explosion.png"をプロジェクトに追加して、
クラスファイルとごっちゃになるのも嫌なので
Contentフォルダを作ってその中に入れましょう。
つまりアセット名は"Content/explosion"になるわけです。

ではこれをContentManagerから読み込み、
BasicEffect.Textureプロパティにセットして、
BasicEffect.TextureEnabledプロパティをtrueにします。
これでうまくいくはず・・・!

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


public class ExplosionTest : Microsoft.Xna.Framework.Game
{
    private GraphicsDeviceManager graphics;

    private BasicEffect effect;
    private VertexPositionColor[] vertices = {
        new VertexPositionColor(new Vector3(0, 0.1f, 0), Color.White),
        new VertexPositionColor(new Vector3(0.1f, 0, 0), Color.White),
        new VertexPositionColor(new Vector3(-0.1f, 0, 0), Color.White)
    };

    private ContentManager content;


    public ExplosionTest()
    {
        graphics = new GraphicsDeviceManager(this);
        content = new ContentManager(Services);
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        if (loadAllContent)
        {
            effect = new BasicEffect(graphics.GraphicsDevice, null);
            graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(
                graphics.GraphicsDevice,
                VertexPositionColor.VertexElements
                );

            effect.Texture = content.Load<Texture2D>("Content/explosion");
            effect.TextureEnabled = true;
        }
    }

    protected override void UnloadGraphicsContent(bool unloadAllContent)
    {
        if (unloadAllContent) { content.Unload(); }
    }

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

        graphics.GraphicsDevice.RenderState.PointSize = 50;

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();

            graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.PointList,
                vertices,
                0,
                vertices.Length
                );

            pass.End();
        }

        effect.End();
    }
}

explosionTutorialTexturedPointFailed.jpg
はい失敗です。(イライラ)

四角の色が白でなくなってはいますが、
ここでやりたかったのはテクスチャを貼り付けることです。
四角の色を変えることではありません。

どうしてこういう失敗をしてしまったのかというと、
レンダーステートのPointSpriteEnabledプロパティをtrueにしていなかったからです。
このプロパティをtrueにすることによって初めて、
ポイントの上にテクスチャが表示されるようになります。
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


public class ExplosionTest : Microsoft.Xna.Framework.Game
{
    private GraphicsDeviceManager graphics;

    private BasicEffect effect;
    private VertexPositionColor[] vertices = {
        new VertexPositionColor(new Vector3(0, 0.1f, 0), Color.White),
        new VertexPositionColor(new Vector3(0.1f, 0, 0), Color.White),
        new VertexPositionColor(new Vector3(-0.1f, 0, 0), Color.White)
    };

    private ContentManager content;


    public ExplosionTest()
    {
        graphics = new GraphicsDeviceManager(this);
        content = new ContentManager(Services);
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        if (loadAllContent)
        {
            effect = new BasicEffect(graphics.GraphicsDevice, null);
            graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(
                graphics.GraphicsDevice,
                VertexPositionColor.VertexElements
                );

            effect.Texture = content.Load<Texture2D>("Content/explosion");
            effect.TextureEnabled = true;
        }
    }

    protected override void UnloadGraphicsContent(bool unloadAllContent)
    {
        if (unloadAllContent) { content.Unload(); }
    }

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

        graphics.GraphicsDevice.RenderState.PointSize = 50;
        graphics.GraphicsDevice.RenderState.PointSpriteEnable = true;

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();

            graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.PointList,
                vertices,
                0,
                vertices.Length
                );

            pass.End();
        }

        effect.End();
    }
}

explosionTutorialPointTextured.jpg(クリックで写真を拡大)

うまくいきました。

たしかに"explosion.png"が貼られています。
四角形の中に爆炎っぽいものが表示されています。
周りが黒くて、とても爆発には見えないという嫌な事実は無視です。
これによってほんのちょっと、完成に近づいたといえるのではないでしょうか!

白いタイルがそれぞれ爆発の頂点のように動いたとしても
ゲームプレイヤーからは爆発には見えずに、「????」となるはずです。
だから、これはとても必要なことだったのです。

これからさらに透過処理して本物の爆炎っぽく見せたり、
それぞれの四角を時間の経過とともに「ぶわっ」と動かしたり、
四角の数自体をふやしたりすることによって、
本物の爆発に近づいていくのです。
(というか、そうなる予定です。)



拍手[0回]


XNA爆発チュートリアル その2

爆発チュートリアルその1のつづきです。

前回は大きさ1の点を表示するだけだったので、
こんどはこれを大きくしてみましょう。

点が周りに広がって動くだけでは
あまりリアルな爆発には見えないでしょうからね。
(もちろん現状ではまだ動いてすらいないのですが・・・)
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


public class ExplosionTest : Microsoft.Xna.Framework.Game
{
    private GraphicsDeviceManager graphics;

    private BasicEffect effect;
    private VertexPositionColor[] vertices = {
        new VertexPositionColor(new Vector3(0, 0.1f, 0), Color.White),
        new VertexPositionColor(new Vector3(0.1f, 0, 0), Color.White),
        new VertexPositionColor(new Vector3(-0.1f, 0, 0), Color.White)
    };


    public ExplosionTest()
    {
        graphics = new GraphicsDeviceManager(this);
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        if (loadAllContent)
        {
            effect = new BasicEffect(graphics.GraphicsDevice, null);
            graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(
                graphics.GraphicsDevice,
                VertexPositionColor.VertexElements
                );
        }
    }

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

        graphics.GraphicsDevice.RenderState.PointSize = 50;

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();

            graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.PointList,
                vertices,
                0,
                vertices.Length
                );

            pass.End();
        }

        effect.End();
    }
}


explosionTutorialPointWithSize.jpg

点が大きくなりました!
スクリーン上のサイズが1から50に大きくなりました。

これで一歩前進です。
どこからどう見ても物が爆発しているようには見えませんが、
前進は前進です。

この白い四角い板みたいなのに爆炎のテクスチャが貼られ、
それぞれが動いたりいろんなことをされることによって
爆発っぽく見えるようになるのです。
(というか、そうなる予定です)

拍手[0回]


XNA爆発チュートリアル その1


Xna Creators ClubのParticle 3D Sampleをもっとよく理解するために
1から爆発のパーティクルを作ってみようと思います。

ついでにこれをチュートリアルとしてブログの記事にしてしまおうという魂胆です。
火の玉の時には最後の結果だけでしたからね。




完成予想図(あくまでもイメージです)
3DParticlesExplosion2.jpg
(Particle 3D Sampleより)

いきなり爆発を描画するのはあまりにハードルが高すぎるので、
最初は簡単なやつからいきましょう。

爆発のパーティクルは結局のところ大きさを持った点に(幾何学的には矛盾のある表現です)
爆炎のテクスチャを貼って動かしているだけなので、
もっともシンプルなものは点を表示するだけプログラムであると言えるでしょう!

なので、もっともシンプルな頂点構造体であるVertexPositionColorを点のデータとして
使い、まずいくつか表示してみることにします。
必要なのは点の位置だけなのでVertexPositionColorではColorメンバが無駄になりますが、
一番シンプルなのはこれなのでこれが現状では最善なのです。

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


public class ExplosionTest : Microsoft.Xna.Framework.Game
{
    private GraphicsDeviceManager graphics;

    private BasicEffect effect;
    private VertexPositionColor[] vertices = {
        new VertexPositionColor(new Vector3(0, 0.1f, 0), Color.White),
        new VertexPositionColor(new Vector3(0.1f, 0, 0), Color.White),
        new VertexPositionColor(new Vector3(-0.1f, 0, 0), Color.White)
    };


    public ExplosionTest()
    {
        graphics = new GraphicsDeviceManager(this);
    }

    protected override void LoadGraphicsContent(bool loadAllContent)
    {
        if (loadAllContent)
        {
            effect = new BasicEffect(graphics.GraphicsDevice, null);
            graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(
                graphics.GraphicsDevice,
                VertexPositionColor.VertexElements
                );
        }
    }

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

        effect.Begin();

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Begin();

            graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(
                PrimitiveType.PointList,
                vertices,
                0,
                vertices.Length
                );

            pass.End();
        }

        effect.End();
    }
}

explosionTutorialSimplePoint.jpg(クリックで拡大:白い点が中央に3つ表示されています。)

シンプルです。
自画自賛したくなるくらいのシンプルさです。

このプログラムはウィンドウのクライアント領域の中央に3つの白い点を表示するだけです。

シンプルすぎてこれが爆発とどう結びつくのかわかりにくいかもしれませんが、
この3つの白い点が、大きくなり、テクスチャが貼られ、数が多くなり、周りに向かって広がって動くようになり、
フェードするようになったり、その他いろいろなことをするようになって、
爆発しているように見えるようになるのです。
・・・・・と言うか、そうなる予定です。

拍手[0回]


XNA爆発

Xna Creators Clubのサンプル、Particle 3D Sampleをいじっていたら
障害(?)っぽいものにぶち当たったので問題とその解決、
事の顛末を書いておきます。

Particle 3D Sampleというのは爆発や煙、炎などを
ポイントスプライトで描画するサンプルなのですが、
どうもカメラの距離によっておかしくなっているように感じられたのです。

Particle 3D Sampleのクラスを取り出して
別のプロジェクトで遊んでいたのですが、
カメラを爆発に近づけすぎるとどうやら変になるようなのです。

まず、カメラを爆発から150離れた位置におくと
次のようにきちんと爆発が起こっているように見えます:

explosion150.jpgカメラからの距離:150

これは爆発です。
これは静止画なのでよくわかりませんが、実際にサンプルを実行すると
爆炎がまわりにゆっくりと広がっていくのがわかります。
ここまでは問題ありません。

しかし、カメラをこの爆発に近づけるとどうもおかしなことになるようです。
次の画像はカメラを先ほどの1/10の距離、つまり15離れた位置に
動かしたときの画像です:

explosion15.jpgカメラからの距離:15

ウィンドウにはいくつもの炎のようなものが映っています。
これは別に複数の爆発を起こしたと言うわけではありません。
ここで映っている爆発は1つだけです。

どうやら爆炎がバラバラになって表示されているようです。
爆発を構成している一つ一つの爆炎が本来よりも小さく表示されているのでしょう。
実際、この一つ一つの爆炎はサンプルで使われている
"explosion.png"と同じものです。

ebd0a9be.png
(explosion.png : Particle 3DのContentフォルダ内より)

つまりここでの問題は
爆発に近づいたときに一つ一つの爆炎のポイントスプライトが拡大されない
ことにあるようです。

そのため、遠くから表示するとうまくいっているように見える一方で、
近づいたら、各々の炎が拡大されないために、本来そうであるべきよりも炎が小さく見え、
バラバラになっているように見えるのでしょう。

ここで考えられるのは
もとのサンプルからクラスを取り出すときに何か間違ったことをしてしまったのではないか
ということです。
しかしどうやら元のサンプルでも同じような現象が起きているようなのです。

3DParticlesExplosion.jpg
Particle 3Dで爆発に近づいた場合。やはり爆発がバラバラになっています。
(※見やすくするために爆発の周りの煙は表示していません。)

ちなみに、サンプルでも爆発を遠くから見ると問題なく表示されます。

3DParticlesExplosion2.jpg


ということはこの問題はサンプルの問題だったのでしょうか?
サンプルがポイントのサイズを固定していたのでしょうか?
HLSLのソースコードを読む限りそうではありませんでした。
きちんと、カメラから離れればサイズが小さく、近づけばサイズが大きくなるように
書かれていました。

これはプログラムの実行によっても検証できます。
カメラを爆発からうんと離してやるのです。
もし各ポイントのサイズが固定されているのなら
どんなに離してもそれ以上爆発が小さくならないような
カメラの距離が存在するはずです。
爆発がexplosion.pngの爆炎より小さくなることはありえないはずです。

smallExplosionCamera1500.jpg

小さくなっていますね・・・。
ということはやはり、各ポイントのサイズはカメラの距離によって変わっているようです。

それではどうして近づきすぎるとおかしくなるのでしょう?
これではまるでポイントのサイズの上限が存在しているようではありませんか!
・・・・・・ポイントのサイズの上限?
そういえばPointSizeMaxというプロパティがあったような気がします。
もしかしたらそれが関係しているのかも!


調べてみるとParticleSystemクラスに次のような行が見つかりました:

renderState.PointSizeMax = 256;

とりあえずこれをコメントアウトして実行してみました。
すると、なんとうまく描画されたのです。

bigExplosion.jpgカメラからの距離:15

よし!

問題は解決です。
解決法は
"renderState.PointSizeMax = 256";をコメントアウトする
です。

・・・しかしちょっと待ってください。
このステートメントはいったい何をしていたのでしょうか?
まさかサンプルを実行する人を困らせるためにこんなことをしたわけではないでしょう。
なにか理由があるはずです。

とりあえずこのプロパティを調べてみることにしました。
msdnによると、これはポイントのサイズの上限を表しているのだそうです。
(「そんなものは最初からわかってる!」という声が聞こえてきそうです。)
さらに、デフォルトの値は64.0fなのだそうです。

なるほど、ポイントのサイズはデフォルトでは64が上限と言うことですね。
読めてきました。
ということは、"renderState.PointSizeMax = 256;"というのは
ポイントのサイズの上限を大きくして、より大きなポイントも表示できるようにした
ということなのでしょう。

しかし、そうだとすると新たな疑問が浮かびます。
なぜ"renderState.PointSizeMax = 256;" をコメントアウトして上手くいったのでしょうか?
ポイントサイズの上限を大きくするステートメントをコメントアウトしたのですから、症状は悪化するはずです。
これではアベコベではありませんか!

もともと、ここでの問題は「ポイントのサイズがもっと大きくならない」
というものでした。
そこで「より大きなポイントも表示できるようにする」ステートメントをコメントアウトしたのなら
問題はますますひどくなるはずです。
しかし実際にはこれで問題が解決したのです。

ひとつの可能性として、「実はデフォルトの値は64.0fではなくもっと大きい値だった
ということが考えられます。
たとえばデフォルトの値が実は512.0fくらいで、"renderState.PointSizeMax = 256;"が
ポイントサイズの上限を引き下げていたのかもしれません。

さっそくかんたんなステートメントを追加して調べてみました。
LoadGraphicsContentメソッド内に次の行を追加したのです。

Window.Title += "maxdefault:" + graphics.GraphicsDevice.RenderState.PointSize;

これでウィンドウのタイトルにPointSizeプロパティのデフォルトの値が表示されるはずです。
結果は"maxdefault:8192"でした。
デフォルトの値は8192です。
・・・あれ、何でこんなに大きいんだろ・・・・・・?
びっくりです。
予想では512、大きくてもせいぜい1024くらいだと思っていたのですがそれを大きく上回りました。
ぼくがこのとき使ったディスプレイの解像度は1920 x 1200ですから上限など無いも同然です。
ディスプレイの4倍以上の大きさのポイントを描画できるわけですからね。
これでは "renderState.PointSizeMax = 256;"なんてしたらおかしくなるのもうなずけます。

気にかかるのはこの値がmsdnの記述と大きくかけ離れている事実です。
8192と64では128倍の差があるではありませんか!
どう考えてもおかしいです。

この理由はわかりませんが、ぼくは次のように考えました:

msdnのPointSizeMaxプロパティのページをさらに見ると、
このプロパティはGraphicsDeviceCapabilities.PointSizeMaxの値を
超えられないとも書いてあります。
グラフィックスデバイスには表示できるポイントの大きさに限界があって、
それをこのプロパティが表しているのでしょう。

ということは、もしかするとRenderState.PointSizeMaxは
グラフィックスデバイスの能力を調べて、自動的に上限を
最大の値にまで引き上げてくれるのかもしれません。

おそらくこのパソコンのグラフィックスデバイスのポイントサイズの上限が8192だったのでしょう。(後で調べてみると、実際そうでした)
それをRenderState.PointSizeMaxは読み取って、
自動的に最大限の機能を発揮できるようにしてくれたのかもしれないというわけです。
別のパソコンならRenderState.PointSizeMaxからはまた違った値が返されるでしょう。

蛇足

msdnのサンプルを参考にして、グラフィックスデバイスのポイントサイズの上限を調べるのに使ったソースコードを書いておきます。
            foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters)
            {
                GraphicsDeviceCapabilities caps = adapter.GetCapabilities(DeviceType.Hardware);
                Window.Title += "max:" + caps.MaxPointSize;
            }

グラフィックスデバイスの能力を調べるには
Microsoft.Xna.Framework.Graphics.GraphicsDeviceCapabilitiesクラスを使います。

[Serializable]
public sealed class GraphicsDeviceCapabilities : IDisposable


このクラスはポイントサイズの上限のほかにも、使用できるテクスチャの大きさの上限や、
頂点のインデックスの上限も調べることが出来ます。

ポイントサイズの上限を表すプロパティは、MaxPointSizeです。

public float MaxPointSize { get; }

このクラスのインスタンスを得るには、GraphicsAdapter.GetCapabilitiesメソッドを使います。

public GraphicsDeviceCapabilities GetCapabilities ( 
        DeviceType deviceType
)


このメソッドは、引数のdeviceTypeに指定された種類の
デバイスの能力を表すGraphicsDeviceCapabilitiesのインスタンスを返します。

DeviceTypeは列挙型で、3つのメンバ、つまりHardware, NullReference, Referenceを持ちます。
ここではHardwareを使いました。

このメソッドを持っているのはグラフィックスアダプタを表す、
Microsoft.Xna.Framework.Graphics.GraphicsAdapterクラスです。(そのまんまですが)

このクラスのインスタンスを得るには、コンストラクタではなく
自分のクラスのAdapters静的プロパティを使います。

public static ReadOnlyCollection<GraphicsAdapter> Adapters { get; }

このプロパティの中にシステムで使うことの出来る全てのグラフィックス・アダプタが入っています。
foreachなんかでまわして使うと良いでしょう。

拍手[0回]