2022年7月25日月曜日

VertexBufferなしでレンダリング

遅延レンダリングとかで、1枚絵に対してレンダリングを行う際でもわざわざ頂点バッファとUVの情報を用意していた。

	tF4 nVData[] = {
		//  x      y      z     u     v
		-1.0f,  1.0f,  0.0f, 0.0f, 0.0f,	// 0:左上
		 1.0f,  1.0f,  0.0f, 1.0f, 0.0f,	// 1:右上
		-1.0f, -1.0f,  0.0f, 0.0f, 1.0f,	// 2:左下
		 1.0f, -1.0f,  0.0f, 1.0f, 1.0f,	// 3:右下
	} ;
	tU4 nIndex[] {	// 時計回り
		0, 1, 2,	3, 2, 1,
	} ;

この頂点バッファと、インデックスバッファでPostレンダリングしていたんだけど、このバッファを用意しなくてもレンダリングができるらしい。

	D3D12_GRAPHICS_PIPELINE_STATE_DESC	oGPSD = {} ;
	oGPSD.InputLayout = { nullptr, 0 } ;

Inputレイアウトは何もなしで初期化する。

	pGCL->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ) ;
	pGCL->IASetVertexBuffers( 0, 0, nullptr ) ;
	pGCL->DrawInstanced( 4, 1, 0, 0 ) ;

描画時、IASetVertexBuffersも空指定で、IASetPrimitiveTopologyにD3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP、DrawInstancedに4を指定する。
struct Input {
    uint VID : SV_VertexID ;
} ;

struct Output {
    float4 Pos : SV_POSITION ;
    float2 UV  : TEXCOORD ;
} ;

Output VSMain( Input In )
{
    Output Out ;

    Out.UV = float2( In.VID & 1, In.VID >> 1 ) ;
    Out.Pos = float4(
    	2.0f * Out.UV.x - 1.0f,
        1.0f - 2.0f * Out.UV.y,
        0.0f,
        1.0f
    ) ;

    return Out ;
}

そうすると、VertexShaderのInputのVIDに0~3の値が入って呼ばれる。
VID    u    v
0        0 0
1        1 0
2        0 1
3        1 1
VIDを使って、このUVを作り出している
個人的にLayoutなし、頂点データなしでも描画できることに驚き。

System-Valueセマンティクスにはいくつも種類があって、DirectX10からの機能みたい。
今回は渡すデータなしで試したけど他のデータを渡した場合でも使えて、Inputに「SV_」の引数を付け加えれば、自動的に渡してくれる。

ちなみにピクセルシェーダではPosは使わないので、OutputのPosをなくしてみたら実行時エラーが出たのでSV_POSITIONは必須なのかな。

D3D12 ERROR: ID3D12Device::CreateGraphicsPipelineState: Rasterization Unit is enabled (PixelShader is not NULL or Depth/Stencil test is enabled and RasterizedStream is not D3D12_SO_NO_RASTERIZED_STREAM) but position is not provided by the last shader before the Rasterization Unit. [ STATE_CREATION ERROR #682: CREATEGRAPHICSPIPELINESTATE_POSITION_NOT_PRESENT]

0 件のコメント:

コメントを投稿