2

カスタム シェーダーを使用せずに、幅の広い色付きのアウトラインで 2D ポリゴンを描画しようとしています。
(シェーダーに精通していないので、CPU を使用するよりもおそらく遅くなるでしょう)
そうするために、通常のようにポリゴンを描画し、結果として得られる深度バッファーを使用する予定です。同じ展開されたジオメトリを描画するときのステンシル。

XNA の「GraphicsDevice」は、IVertexType インスタンスの任意の配列を指定してプリミティブを描画できます。

DrawUserPrimitives<T>(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int primitiveCount, VertexDeclaration vertexDeclaration) where T : struct;

2D 座標空間の IvertexType を定義しました。

public struct VertexPosition2DColor : IVertexType
{
    public VertexPosition2DColor (Vector2 position, Color color) {
        this.position = position;
        this.color = color;
    }

    public Vector2 position;
    public Color color;

    public static VertexDeclaration declaration = new VertexDeclaration (
        new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0),
        new VertexElement(sizeof(float)*2, VertexElementFormat.Color, VertexElementUsage.Color, 0)
    );

    VertexDeclaration IVertexType.VertexDeclaration {
        get {return declaration;}
    }
}

ポリゴンの頂点、色、およびエッジの法線を格納するための配列クラスを定義しました。
このクラスを GraphicDevice の DrawPrimitives 関数の T[] パラメータとして渡したいと考えています。
目標は、アウトラインの頂点を GPU で計算することです。これは、明らかにそのようなことが得意であるためです。

internal class VertexOutlineArray : Array
{
    internal VertexOutlineArray (Vector2[] positions, Vector2[] normals, Color[] colors, Color[] outlineColors, bool outlineDrawMode) {
        this.positions = positions;
        this.normals = normals;
        this.colors = colors;
        this.outlineColors = outlineColors;
        this.outlineDrawMode = outlineDrawMode;
    }

    internal Vector2[] positions, normals;
    internal Color[] colors, outlineColors;
    internal float outlineWidth;
    internal bool outlineDrawMode;

    internal void SetVertex(int index, Vector2 position, Vector2 normal, Color color, Color outlineColor) {
        positions[index] = position;
        normals[index] = normal;
        colors[index] = color;
        outlineColors[index] = outlineColor;
    }

    internal VertexPosition2DColor this[int i] {
        get {return (outlineDrawMode)? new VertexPosition2DColor(positions[i] + outlineWidth*normals[i], outlineColors[i]) 
                                     : new VertexPosition2DColor(positions[i], colors[i]);
        }
    }
}

シェイプをレンダリングできるようにしたいのですが、アウトラインは次のようになります。 展開されたアウトライナー ジオメトリを描画するときに、深度バッファーがステンシルとして使用されます。

protected override void RenderLocally (GraphicsDevice device)
{
    // Draw shape
    mVertices.outlineDrawMode = true; //mVertices is a VertexOutlineArray instance

    device.RasterizerState = RasterizerState.CullNone;
    device.PresentationParameters.DepthStencilFormat = DepthFormat.Depth16;
    device.Clear(ClearOptions.DepthBuffer, Color.SkyBlue, 0, 0);
    device.DrawUserPrimitives<VertexPosition2DColor>(PrimitiveType.TriangleList, (VertexPosition2DColor[])mVertices, 0, mVertices.Length -2, VertexPosition2DColor.declaration);

    // Draw outline
    mVertices.outlineDrawMode = true;

    device.DepthStencilState = new DepthStencilState {
        DepthBufferWriteEnable = true,
        DepthBufferFunction = CompareFunction.Greater //keeps the outline from writing over the shape
    };
    device.DrawUserPrimitives(PrimitiveType.TriangleList, mVertices.ToArray(), 0, mVertices.Count -2);
}

ただし、VertexArray クラスを T[] として渡すことができないため、これは機能しません。カスタム シェーダーを使用せずに GPU でアウトライン計算を行うという目標を達成するには、どうすればこれを修正できますか?

4

1 に答える 1

1

細い三角形のペアを線として使用してアウトラインを描画するクラスを単純に作成しないのはなぜですか? 2 次元の点と線の幅の入力を受け取り、VertexBuffer を吐き出す一般化されたポリライン ルーチンを作成できます。

これがあなたの質問に答えていないことはわかっていますが、あなたのやり方でやろうとする利点がわかりません。達成したい特定の効果はありますか、それとも非常に頻繁にデータを操作したり、ポリゴンを大量にスケーリングしたりしますか?


おそらく発生している問題は、Windows Phone 7 の XNA4 がカスタム シェーダーをまったくサポートしていないことです。実際、テストする必要のある順列の数が多いため、意図的に定義済みシェーダーのセットに制限しました。現在サポートされているものは次のとおりです。

AlphaTestEffect BasicEffect EnvironmentMapEffect DualTextEffect SkinnedEffect

ここでそれらについて読むことができます:

http://msdn.microsoft.com/en-us/library/bb203872(v=xnagamestudio.40).aspx

Vector2 の位置と法線を使用して IVertexType を作成または使用することをテストしていないため、サポートされているかどうかについてはコメントできません。これを行う場合は、メインのポリゴン シェイプのレンダリングに BasicEffect と VertexPositionNormal のみを使用し、各ポリゴンの DiffuseColor を調整します。アウトラインをレンダリングするには、既存の VertexBuffer を使用し、GraphicsDevice.Viewport.Unproject() を呼び出して適切にスケーリングし、n ピクセルの 2D 画面距離 (アウトライン幅) を生成するために必要な 3D 座標距離を決定します。

BasicEffect やその他のエフェクトを使用する場合は、CurrentTechnique の EffectPass 配列をループして、Draw 呼び出しを行う前にパスごとに Apply() メソッドを呼び出す必要があることに注意してください。

        device.DepthStencilState = DepthStencilState.Default;
        device.BlendState = BlendState.AlphaBlend;
        device.RasterizerState = RasterizerState.CullCounterClockwise;

        //Set the appropriate vertex and indice buffers
        device.SetVertexBuffer(_polygonVertices);
        device.Indices = _polygonIndices;

        foreach (EffectPass pass in _worldEffect.CurrentTechnique.Passes)
        {
            pass.Apply();
            PApp.Graphics.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _polygonVertices.VertexCount, 0, _polygonIndices.IndexCount / 3);
        }
于 2012-10-17T06:19:38.617 に答える