<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>39</title>
	<atom:link href="http://www4.atword.jp/cathy39/feed/" rel="self" type="application/rss+xml" />
	<link>http://www4.atword.jp/cathy39</link>
	<description>About 3D graphics programming</description>
	<pubDate>Sat, 11 Dec 2010 16:38:43 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/feed/" />
		<item>
		<title>memo : Gatherがサンプリングする位置</title>
		<link>http://www4.atword.jp/cathy39/2010/05/19/gather_jp/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/19/gather_jp/#comments</comments>
		<pubDate>Tue, 18 May 2010 15:20:57 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[Direct3D11]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=188</guid>
		<description><![CDATA[
GatherはDirectX10.1から使える機能の１つで４サンプルを１度にとってこられるものです。
Gatherを使うと4つのピクセルのRGBを３命令でとってくることができます。

今までは
Sample( samp [...]]]></description>
			<content:encoded><![CDATA[<p>
GatherはDirectX10.1から使える機能の１つで４サンプルを１度にとってこられるものです。<br />
Gatherを使うと4つのピクセルのRGBを３命令でとってくることができます。<br />
<br />
今までは<br />
Sample( sampler, uv )<br />
Sample( sampler, uv + offset0 )<br />
Sample( sampler, uv + offset1 )<br />
Sample( sampler, uv + offset2 )<br />
とやっていたのが<br />
GatherRed( sampler, uv );<br />
GatherGreen( sampler, uv );<br />
GatherBlue( sampler, uv );<br />
で取れるということです。<br />
<br />
が、いざ使ってみようと思ったら、<br />
Gatherに指定するuvとフェッチされるサンプルの位置についての記述が見当たりません。<br />
どこに書いてあるんですか？？<br />
<br />
仕方ないので調べてみる。<br />
まず普通にテクスチャを描画。<br />
<img class="alignnone size-medium wp-image-194" title="original" src="http://www4.atword.jp/cathy39/files/2010/05/original.jpg" alt="" width="272" height="294" />
テクスチャは16x16です。(ポイントフィルタで描画)<br />
<br />
次に、Gatherでサンプリングした結果を復元して描画<br />
<br />
<strong>Rチャンネル</strong><br />
uvが0.5ずつ左下にずれている<br />
<img class="alignnone size-medium wp-image-194" title="gatherx" src="http://www4.atword.jp/cathy39/files/2010/05/gatherx.jpg" alt="" width="272" height="294" />
<strong>Gチャンネル</strong><br />
uvが0.5ずつ右下にずれている<br />
<img class="alignnone size-medium wp-image-194" title="gathery" src="http://www4.atword.jp/cathy39/files/2010/05/gathery.jpg" alt="" width="272" height="294" />
<strong>Bチャンネル</strong><br />
uvが0.5ずつ右上にずれている<br />
<img class="alignnone size-medium wp-image-195" title="gatherz" src="http://www4.atword.jp/cathy39/files/2010/05/gatherz.jpg" alt="" width="272" height="294" />
<strong>Aチャンネル</strong><br />
uvが0.5ずつ左上にずれている<br />
<img class="alignnone size-medium wp-image-196" title="gatherw" src="http://www4.atword.jp/cathy39/files/2010/05/gatherw.jpg" alt="" width="272" height="294" />
<br />
ということで、<br />
- Gatherに指定するuv → 中心<br />
- Gatherでサンプリングする位置 → 中心±0.5テクセルの位置<br />
<br />
Gatherに指定するuvをPとすると、<br />
RGBA各チャンネルのサンプリングポイントは以下の図のようになる<br />
<img class="alignnone size-medium wp-image-197" title="gather_texcoord" src="http://www4.atword.jp/cathy39/files/2010/05/gather_texcoord.gif" alt="" width="255" height="222" />
<br />
まあ予想通りというか普通な結果ですが、<br />
指定したuvはサンプリングされないということです。<br />
それと、Gatherを使う場合はリニアフィルタが利かないです。</p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/19/gather_jp/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/19/gather_jp/" />
	</item>
		<item>
		<title>Linked Listを利用したOIT - 4</title>
		<link>http://www4.atword.jp/cathy39/2010/05/08/linked-list-oit-japanese-4/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/08/linked-list-oit-japanese-4/#comments</comments>
		<pubDate>Sat, 08 May 2010 04:33:38 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT(Japanese)]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=172</guid>
		<description><![CDATA[
[前回のつづき]

今回は２パス目、フラグメントのソートと描画パスの実装についての解説です。


3. ソートと描画パスの実装

このパスではピクセルごとにLinked Listをたどって全てのフラグメントデータを取り出し、深度値でソートして奥のフラグメントから順にブレンディング、結果をフレームバッファに出力します。

3-a. シェーダの実装

新しいhlslファイルを作成します。今回はピクセルシェーダだけでなくフルスクリーンを描画するための頂点シェーダも必要です。
ピクセルシェーダでは全てのフラグメントデータをテンポラリ配列に一度コピーし、それから深度値でソートします。これはメモリアクセスを抑えるためです。



StructuredBuffer&#60;SFragmentLink&#62; FragmentLinkSRV : register(t0);
Buffer StartOffsetSRV : register(t1);

struct QuadVS_Output
{
&#160;&#160;&#160;&#160;float4 pos   : SV_POSITION;
};


float4 SortFragmentsPS( QuadVS_Output _input ) : SV_Target0
{
&#160;&#160;&#160;&#160;uint uIndex = (uint)_input.pos.y * g_nFrameWidth + (uint)_input.pos.x;

&#160;&#160;&#160;&#160;// Read and store linked list data to the tempolary buffer.
&#160;&#160;&#160;&#160;SFragment aData[32];
&#160;&#160;&#160;&#160;int anIndex[32];
&#160;&#160;&#160;&#160;uint uNumFragment = 0;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;uint uNext = StartOffsetSRV[uIndex];
&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;while ( uNext != 0xFFFFFFFF ) {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SFragmentLink element = [...]]]></description>
			<content:encoded><![CDATA[<p>
[前回のつづき]<br />
<br />
今回は２パス目、フラグメントのソートと描画パスの実装についての解説です。<br />
<br />
<br />
<b>3. ソートと描画パスの実装</b><br />
<br />
このパスではピクセルごとにLinked Listをたどって全てのフラグメントデータを取り出し、深度値でソートして奥のフラグメントから順にブレンディング、結果をフレームバッファに出力します。<br />
<br />
<b>3-a. シェーダの実装</b><br />
<br />
新しいhlslファイルを作成します。今回はピクセルシェーダだけでなくフルスクリーンを描画するための頂点シェーダも必要です。<br />
ピクセルシェーダでは全てのフラグメントデータをテンポラリ配列に一度コピーし、それから深度値でソートします。これはメモリアクセスを抑えるためです。<br />
<br />
<div class="code-surround"><div class="code-main">
<code><br />
StructuredBuffer&lt;SFragmentLink&gt; FragmentLinkSRV : register(t0);<br />
Buffer StartOffsetSRV : register(t1);<br />
<br />
struct QuadVS_Output<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;float4 pos   : SV_POSITION;<br />
};<br />
<br />
<br />
float4 SortFragmentsPS( QuadVS_Output _input ) : SV_Target0<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uIndex = (uint)_input.pos.y * g_nFrameWidth + (uint)_input.pos.x;<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Read and store linked list data to the tempolary buffer.</div>
&nbsp;&nbsp;&nbsp;&nbsp;SFragment aData[32];<br />
&nbsp;&nbsp;&nbsp;&nbsp;int anIndex[32];<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uNumFragment = 0;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uNext = StartOffsetSRV[uIndex];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;while ( uNext != 0xFFFFFFFF ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SFragmentLink element = FragmentLinkSRV[uNext];<br />
		<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aData[uNumFragment] = element.fragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[uNumFragment] = uNumFragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++uNumFragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uNext = element.uNext;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint N2 = 1 &lt;&lt; (int)(ceil(log2(uNumFragment)));<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// fill initial data</div>
&nbsp;&nbsp;&nbsp;&nbsp;for(int i = uNumFragment; i &lt; N2; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[i] = i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aData[i].fDepth = 1.1f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Bitonic sort. copied from OIT_CS.hlsl</div>
&nbsp;&nbsp;&nbsp;&nbsp;for( int k = 2; k &gt;1; j &gt; 0 ; j = j&gt;&gt;1 ) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for( int i = 0; i  i )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float dixj = aData[ anIndex[ ixj ] ].fDepth;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( ( i&amp;k ) == 0 &amp;&amp; di &gt; dixj )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp = anIndex[ i ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ i ] = anIndex[ ixj ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ ixj ] = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( ( i&amp;k ) != 0 &amp;&amp; di &lt; dixj )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp = anIndex[ i ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ i ] = anIndex[ ixj ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ ixj ] = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Output the final result to the frame buffer<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Accumulate fragments into final result</div>
&nbsp;&nbsp;&nbsp;&nbsp;float4 result = 0.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;for( int x = uNumFragment-1; x &gt;= 0; x-- )<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint uColor = aData[ anIndex[ x ] ].uColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float4 color;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.r = ( (uColor &gt;&gt; 0)  &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.g = ( (uColor &gt;&gt; 8)  &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.b = ( (uColor &gt;&gt; 16) &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.a = ( (uColor &gt;&gt; 24) &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = lerp( result, color, color.a );<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;result.a = 1.0f;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;return result;<br />
}<br />
<br />
</code></div></div>
<br />
<p>
Start Offset バッファはここではふつうにuintバッファとして参照されます。OIT11サンプルでは不透明プリミティブが存在しません。なので、ブレンディングの初期値はクリアカラー＝０となっています。実際には不透明プリミティブを描画したテクスチャを初期値とするべきです。また、テンポラリ配列を使用しているため、１つのピクセルが対処できるフラグメントの数に制限がかかります。つまりこの例だと３２個しかフラグメントを持つことはできません。このプログラムはかなり適当なのですが、本当はフラグメントデータのコピー時にセーフティーを入れる必要があります。でないとオーバーランする可能性があります。<br />
<br />
<br />
<b>3-b. Shader Resource Viewの追加</b><br />
<br />
このパスでは２つのバッファはShader Resource Viewとして参照されます。<em>OIT::OnD3D11ResizedSwapChain</em>関数に以下のコードを追加して、SRVを作っておきます。<br />
<br />
</p>
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Create Shader Resource Views</div>
D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;<br />
descSRV.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;<br />
descSRV.Buffer.FirstElement = 0;<br />
<br />
descSRV.Format = DXGI_FORMAT_UNKNOWN;<br />
descSRV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * 8;<br />
V_RETURN( pDevice-&gt;CreateShaderResourceView( m_pFragmentLinkBuffer, &amp;descSRV, &amp;m_pFragmentLinkSRV ) );<br />
<br />
descSRV.Format = DXGI_FORMAT_R32_UINT;<br />
descSRV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height;<br />
V_RETURN( pDevice-&gt;CreateShaderResourceView( m_pStartOffsetBuffer, &amp;descSRV, &amp;m_pStartOffsetSRV ) );<br />
</code></div></div>
<p>
<br />
ついでに、フルスクリーン描画のための頂点バッファと入力レイアウトを<em>OIT::OnD3D11CreateDevice</em>関数内で作っておきましょう。<br />
<br />
<br />
<b>3-c.ソートと描画関数の実装</b><br />
<br />
<em>OIT::SortAndRender</em>関数に作成した頂点バッファと入力レイアウト、Shader Resource Viewをセットして描画するコードを実装します。<br />
</p>
<br />
<div class="code-surround"><div class="code-main">
<code><br />
ID3D11ShaderResourceView* ppSRVs[] = {<br />
&nbsp;&nbsp;&nbsp;&nbsp;m_pFragmentLinkSRV,<br />
&nbsp;&nbsp;&nbsp;&nbsp;m_pStartOffsetSRV,<br />
};<br />
pD3DContext-&gt;PSSetShaderResources( 0, sizeof(ppSRVs)/sizeof(ppSRVs[0]), ppSRVs );<br />
<br />
pD3DContext-&gt;VSSetShader( m_pSortAndRenderVS, NULL, 0 );<br />
pD3DContext-&gt;PSSetShader( m_pSortAndRenderPS, NULL, 0 );<br />
<br />
<br />
<div class="code-comment">// Draw a screen quad by a large triangle.</div>
pD3DContext-&gt;IASetInputLayout( m_pIL );<br />
UINT uStrides = sizeof( SQuadVertex );<br />
UINT uOffsets = 0;<br />
pD3DContext-&gt;IASetVertexBuffers( 0, 1, &amp;m_pVB, &amp;uStrides, &amp;uOffsets );<br />
pD3DContext-&gt;IASetIndexBuffer( NULL, DXGI_FORMAT_R32_UINT, 0 );<br />
pD3DContext-&gt;IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );<br />
<br />
pD3DContext-&gt;Draw( 3, 0 );<br />
<br />
<div class="code-comment">// Unbind SRVs</div>
ID3D11ShaderResourceView* ppSRVNULL[] = {<br />
&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br />
};<br />
pD3DContext-&gt;PSSetShaderResources( 0, sizeof(ppSRVs)/sizeof(ppSRVs[0]), ppSRVNULL );<br />
<br />
</code></div></div>
<p>
あともちろんこのパスではZテストを無効にしましょう。<br />
<br />
<br />
4.　まとめ<br />
Linked List OITは高速でしかも実装が簡単でした。ただし、今回の実装はOIT11との速度比較が目的だったこともあり、あまり実用的とはいえません。たとえば不透明プリミティブを無視している、ブレンディングモードが１種類に限定されている、アンチエイリアシングはサポートしていないなどです。今後時間があればもうすこし実用的な実装も試してみたいです。<br />
<br />
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/08/linked-list-oit-japanese-4/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/08/linked-list-oit-japanese-4/" />
	</item>
		<item>
		<title>Linked Listを利用したOIT - 3</title>
		<link>http://www4.atword.jp/cathy39/2010/05/07/linked-list-oit-japanese-3/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/07/linked-list-oit-japanese-3/#comments</comments>
		<pubDate>Thu, 06 May 2010 15:46:04 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT(Japanese)]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=112</guid>
		<description><![CDATA[
[前回のつづき]


今回はLinked List OITの1パスめ、Linked Listの作成パスの実装について解説します。


2.Linked Listの作成パスの実装

OIT11サンプルでは３つのバッファと [...]]]></description>
			<content:encoded><![CDATA[<p>
[<a href="http://www4.atword.jp/cathy39/2010/05/06/linked-list-oit-japanese-2/">前回</a>のつづき]<br />
<br />
<br />
今回はLinked List OITの1パスめ、Linked Listの作成パスの実装について解説します。<br />
<br />
<br />
<b>2.Linked Listの作成パスの実装</b><br />
<br />
OIT11サンプルでは３つのバッファと１つの２Dテクスチャを利用していますが、Linked List OITでは２つのバッファを使用します。<br />
<br />
・Fragment Link バッファ<br />
全てのフラグメントデータを格納するためのStructured バッファ。<br />
各フラグメントデータはカラー、深度値に加えて次のフラグメントデータのインデックスを持っています。次のフラグメントデータがない場合、リストの終わりを示す特定の値を格納することになります。今回の実装では0xffffffffを使います。<br />
ピクセルシェーダにおけるフラグメントデータの宣言は以下のようになります。カラーはuintにパックしています。<br />
</p>
<div class="code-surround"><div class="code-main"><code><br />
struct SFragment {<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint  uColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;float fDepth;<br />
};<br />
<br />
struct SFragmentLink {<br />
&nbsp;&nbsp;&nbsp;&nbsp;SFragment fragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint      uNext;<br />
};<br />
</code></div></div>
<p>
<br />
・Start Offset バッファ<br />
各ピクセルにおけるリストの先頭を指すuintバッファ。毎フレーム描画の前に0xffffffffで初期化されます。<br />
<br />
<br />
Linked Listの作成パスでは、追加するフラグメントデータをリストの先頭として挿入していきます。つまり、追加されるフラグメントデータが指す次のインデックスにはStart Offsetバッファに含まれていた値を入れ、Start Offset バッファには追加されたフラグメントデータのインデックスを入れます。この部分はスライドのアニメーション"Linked List Creation(2a)~(2d)"を見ると非常にわかりやすいと思います。　<br />
<br />
<br />
<b>2-a. Linked List作成シェーダの実装</b><br />
<br />
Constant Bufferがそのまま使えるので、Linked Listの作成パスはOIT_PS.hlslを改造して実装することにします。Fragment Link バッファとStart Offsetは以下のように宣言します。両方とも書き込みが必要なのでRW…がつきます。<br />
</p>
<div class="code-surround">
<div class="code-main"><code><div class="code-comment">// Fragment And Link Buffer</div>
RWStructuredBuffer FLBuffer&lt;SFragmentLink&gt; : register( u0 );<br />
<div class="code-comment">// Start Offset Buffer</div>
</code><code>RWByteAddressBuffer StartOffsetBuffer : register( u1 );<br />
</code></div>
</div>
<p>
Fragment Linkバッファは構造体のバッファなので、RWStructuredBufferとなります。<br />
Start Offsetバッファは<em>RWByteAddressBuffer</em>として宣言します。描画対象ピクセルの現在の値（リストの先頭のインデックス）を読み、追加するフラグメントデータのインデックスを書き込む（更新する）際に<em>RWByteAddressBuffer::InterlockedExchange</em>を利用するためです。<br />
<br />
つづいてエントリポイント関数の実装です。<br />
</p>
<div class="code-surround">
<div class="code-main"><code>[earlydepthstencil]<br />
void StoreFragments( SceneVS_Output input )<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint x = input.pos.x;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint y = input.pos.y;<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Create fragment data.</div>
&nbsp;&nbsp;&nbsp;&nbsp;uint4 ucolor = saturate( input.color ) * 255;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SFragmentLink element;<br />
&nbsp;&nbsp;&nbsp;&nbsp;element.fragment.uColor = (ucolor.x) | (ucolor.y &lt;&lt; 8) | (ucolor.z &lt;&lt; 16) | (ucolor.a &lt;&lt; 24);<br />
&nbsp;&nbsp;&nbsp;&nbsp;element.fragment.fDepth = input.pos.z;<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Increment and get current pixel count.</div>
&nbsp;&nbsp;&nbsp;&nbsp;uint uPixelCount = FLBuffer.IncrementCounter();<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Read and update Start Offset Buffer.</div>
&nbsp;&nbsp;&nbsp;&nbsp;uint uIndex = y * g_nFrameWidth + x;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uStartOffsetAddress = 4 * uIndex;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uOldStartOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;StartOffsetBuffer.InterlockedExchange( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uStartOffsetAddress, uPixelCount, uOldStartOffset );<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Store fragment link.</div>
&nbsp;&nbsp;&nbsp;&nbsp;element.uNext = uOldStartOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;FLBuffer[uPixelCount] = element;<br />
}<br />
</code></div>
</div>
<p>
Fragment Linkバッファの書き込み先のインデックスは、カウンターサポートを利用して計算しています。<br />
また、Start Offset バッファはByteAddressBufferなので、インデックスはバイトオフセットで指定する点に注意が必要です。<br />
<br />
<br />
<b>2-b. バッファの作成</b><br />
<br />
シェーダができたので、このシェーダに必要なバッファを新たに作成します。バッファ本体とバッファのViewを作成します。RW…バッファはUnordered Access Viewとなります。<br />
<br />
以下のようなコードを<em>OIT::OnD3D11ResizedSwapChain</em>に実装して各バッファとUAVを作成します。<br />
</p>
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Create Fragment and Link buffer.</div>
descBuf.StructureByteStride = sizeof(float) + sizeof(BYTE) * 4 * 2;<br />
descBuf.ByteWidth = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * 8 * descBuf.StructureByteStride;<br />
descBuf.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;<br />
V_RETURN( pDevice-&gt;CreateBuffer( &amp;descBuf, NULL, &amp;m_pFragmentLinkBuffer ));<br />
<br />
<div class="code-comment">// Create Start Offset buffer</div>
descBuf.StructureByteStride = 4 * sizeof(BYTE);<br />
descBuf.ByteWidth = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * descBuf.StructureByteStride;<br />
descBuf.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;<br />
V_RETURN( pDevice-&gt;CreateBuffer( &amp;descBuf, NULL, &amp;m_pStartOffsetBuffer ));<br />
<br />
<div class="code-comment">// Create Unordered Access Views</div>
D3D11_UNORDERED_ACCESS_VIEW_DESC descUAV;<br />
descUAV.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;<br />
descUAV.Buffer.FirstElement = 0;<br />
<br />
descUAV.Format = DXGI_FORMAT_UNKNOWN;<br />
descUAV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * 8;<br />
descUAV.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER;<br />
V_RETURN( pDevice-&gt;CreateUnorderedAccessView( m_pFragmentLinkBuffer, &amp;descUAV, &amp;m_pFragmentLinkUAV ) );<br />
<br />
descUAV.Format = DXGI_FORMAT_R32_TYPELESS;<br />
descUAV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height;<br />
descUAV.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;<br />
V_RETURN( pDevice-&gt;CreateUnorderedAccessView( m_pStartOffsetBuffer, &amp;descUAV, &amp;m_pStartOffsetUAV ) );<br />
<br />
</code></div></div>
<p>
Fragment Linkバッファは全てのフラグメントデータを含まなければならないので、スクリーンサイズよりも大きなサイズが必要です。ここではもともとのOIT11サンプルと同じ、スクリーンサイズの８倍のフラグメントデータを格納できるようにしています。また、Fragment LinkバッファはStructured Bufferなので、作成時に<em>D3D11_RESOURCE_MISC_BUFFER_STRUCTURED</em>を指定します。<br />
<br />
Start Offsetバッファはスクリーンサイズと同じです。また、ByteAddressBufferとして使用するため、<em>D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS</em>フラグが必要です。<br />
<br />
Fragment LinkバッファのUAVはカウンターサポートが必要なので、<em>D3D11_BUFFER_UAV_FLAG_COUNTER</em>を指定します。さらに、StructuredBufferのUAVフォーマットは<em>DXGI_FORMAT_UNKNOWN</em>でなければなりません。<br />
<br />
同様に、Start OffsetバッファのUAVはByteAddressBufferとなるので<em>D3D11_BUFFER_UAV_FLAG_RAW</em>と<em>DXGI_FORMAT_R32_TYPELESS</em>を指定します。<br />
<br />
<br />
<b>2-c. Linked List作成関数の実装</b><br />
<br />
Linked List作成関数は<em>OIT::FillDeepBuffer</em>を改造して実装します。Constant Bufferをそのまま利用するためです。<br />
Start Offsetバッファを0xffffffffで初期化し、２つのUnordered Access Viewをシェーダに記述した順にセットします。<br />
カラーレンダーターゲットをセットする必要はありません。<br />
</p>
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Clear the start offset buffer by magic value.<br />
// Start Offsetバッファを初期化</div>
static const UINT clearValueUINT[1] = { 0xffffffff };<br />
pD3DContext-&gt;ClearUnorderedAccessViewUint( m_pStartOffsetUAV, clearValueUINT );<br />
<br />
<div class="code-comment">// Bind UAVs.<br />
// No render target is required.<br />
// UAVのバインド。レンダーターゲットは不要</div>
ID3D11UnorderedAccessView* pUAVs[] = {<br />
	m_pFragmentLinkUAV,<br />
	m_pStartOffsetUAV,<br />
};<br />
<div class="code-comment">// Initialize the counter with 0.<br />
// カウンターを０で初期化.</div>
UINT anInitIndices[] = { 0, 0 };<br />
pD3DContext-&gt;OMSetRenderTargetsAndUnorderedAccessViews( 0, NULL, pDSV, 0, sizeof(pUAVs)/sizeof(pUAVs[0]), pUAVs, anInitIndices );<br />
<br />
<div class="code-comment">// Set Pixel Shader and shader constants.</div>
pD3DContext-&gt;PSSetShader( m_pCreateFragmentLinkPS, NULL, 0 );<br />
<br />
HRESULT hr;<br />
D3D11_MAPPED_SUBRESOURCE MappedResource;<br />
V( pD3DContext-&gt;Map( m_pPS_CB, 0, D3D11_MAP_WRITE_DISCARD, 0, &amp;MappedResource ) );<br />
PS_CB* pPS_CB = ( PS_CB* )MappedResource.pData;  <br />
pPS_CB-&gt;nFrameWidth = m_nFrameWidth;<br />
pPS_CB-&gt;nFrameHeight = m_nFrameHeight;<br />
pD3DContext-&gt;Unmap( m_pPS_CB, 0 );<br />
pD3DContext-&gt;PSSetConstantBuffers( 0, 1, &amp;m_pPS_CB );<br />
<br />
pScene-&gt;D3D11Render( mWorldViewProjection, pD3DContext );<br />
<br />
<div class="code-comment">// Unbind UAVs.</div>
ID3D11UnorderedAccessView* pUAVsNULL[] = { NULL, NULL, NULL, NULL };<br />
pD3DContext-&gt;OMSetRenderTargetsAndUnorderedAccessViews( 0, NULL, pDSV, 0, sizeof(pUAVs)/sizeof(pUAVs[0]), pUAVsNULL, NULL );<br />
<br />
</code></div></div>
<p>
Unordered Access Viewのセットの際に、カウンターを０で初期化するのを忘れないでください。また、シェーダコードで[earlydepthstencil]を指定した場合、描画の前にdepth writeをOFFにする必要があります。これをしないと一部のフラグメントデータがZテストではじかれてしまい、正しく描画できません。<br />
<br />
<br />
<br />
これでLinked Listの作成ができました。次回は２パス目、Linked Listを読んでソートとブレンディングを行うパスについて解説します。<br />
<br />
<br />
[つづく]<br />
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/07/linked-list-oit-japanese-3/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/07/linked-list-oit-japanese-3/" />
	</item>
		<item>
		<title>Linked Listを利用したOIT - 2</title>
		<link>http://www4.atword.jp/cathy39/2010/05/06/linked-list-oit-japanese-2/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/06/linked-list-oit-japanese-2/#comments</comments>
		<pubDate>Wed, 05 May 2010 17:38:10 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT(Japanese)]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=90</guid>
		<description><![CDATA[
[前回の続き]

今回からはOIT11をどのように改造してLinked List OITを実装するのかを説明していきます。
説明が足りないところは前述のスライドやOIT11サンプルを参照していただけるとわかると思います [...]]]></description>
			<content:encoded><![CDATA[<p>
[<a href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-japanese-1/">前回</a>の続き]<br />
<br />
今回からはOIT11をどのように改造してLinked List OITを実装するのかを説明していきます。<br />
説明が足りないところは前述のスライドやOIT11サンプルを参照していただけるとわかると思います。特にスライドはアニメーションがあったりするので英語が読めなくてもなんとなくわかります。また、スライドにはシェーダコードも記載されています。実装は非常に簡単なのでスライドが読めればできたも同然です。<br />
<br />
<br />
<b>1.　描画フローの変更</b><br />
<br />
通常の半透明プリミティブの描画フローでは、<br />
半透明プリミティブの描画時にZテストをパスしたらアルファブレンドしてフレームバッファを更新<br />
という流れですが、<br />
OITではプリミティブの描画時にはZテストは行わず、フレームバッファも更新しません。その代わり、全ての半透明のフラグメントデータを別の大きなバッファに格納します。フラグメントデータは、最低でも深度値とカラーを持ち、スクリーン上のどこかのピクセルに属しています。半透明ポリゴンが重なるところでは、１つのピクセルに複数のフラグメントデータが存在する状態になります。<br />
半透明の描画終了後、各ピクセルごとにフラグメントデータを深度値でソートしてブレンディングを行い、結果のカラーをフレームバッファに描きこみます。<br />
<br />
この「別の大きなバッファに格納する」方法がDirectXのOIT11サンプルとLinked List版とで異なります。<br />
<br />
OIT11サンプルではフラグメントデータを各ピクセルごとに順番につめていきます。<br />
つまり、スクリーンの左上から<br />
０番目のピクセルに描画されるフラグメントデータ1,2,3…<br />
１番目のピクセルに描画されるフラグメントデータ1,2,…<br />
というようにピクセル順に複数のフラグメントデータをバッファに格納します。<br />
<br />
このため、フラグメントデータを保存する前に、あらかじめ各ピクセルに描画されるフラグメントデータの数や、各ピクセルの格納先インデックスがわかっていなければなりません。<br />
<em>OIT::Render</em>関数を見てみると全体の流れがわかります。<br />
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Create a count of the number of fragments at each pixel location<br />
// １．各ピクセルに描画されるフラグメントデータの数を数える</div>
CreateFragmentCount( pD3DContext, pScene, mWorldViewProjection, pRTV, pDSV );<br />
<br />
<div class="code-comment">// Create a prefix sum of the fragment counts.  Each pixel location will hold<br />
// a count of the total number of fragments of every preceding pixel location.<br />
// ２．各ピクセルにおけるはじめのインデックスを計算</div>
CreatePrefixSum( pD3DContext );<br />
<br />
<div class="code-comment">// Fill in the deep frame buffer with depth and color values.  Use the prefix<br />
// sum to determine where in the deep buffer to place the current fragment.<br />
// ３．フラグメントデータを保存</div>
FillDeepBuffer( pD3DContext, pRTV, pDSV, pScene, mWorldViewProjection );<br />
<br />
<div class="code-comment">// Sort and render the fragments.  Use the prefix sum to determine where the <br />
// fragments for each pixel reside.<br />
// ４．保存してあるフラグメントデータをピクセルごとにソートして描画</div>
SortAndRenderFragments( pD3DContext, pDevice, pRTV );<br />
</code></div></div>
<p>
１と３はプリミティブを描画するため、ピクセルシェーダで実装されています。その他のパスはCompute Shaderで実装されています。<br />
<br />
Linked Listを利用したOITでは各フラグメントデータを描画された順にバッファにつめこんでいきます。なので、上記の１、２の処理は必要ありません。その代わり、フラグメントデータ自体に、そのピクセルにおける次のフラグメントデータのインデックスを含めておき、１つのピクセルに属するフラグメントデータが１つのリストとしてつながるように格納します。<br />
ということで、<em>OIT::Render</em>関数は以下のように書き換えられます。<br />
</p>
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Fragment and Link creation.<br />
// １．Linked Listの作成</div>
CreateFragmentLink( pD3DContext, pRTV, pDSV, pScene, mWorldViewProjection );<br />
<br />
<div class="code-comment">// Sort and render the fragments.  <br />
// ２．保存してあるフラグメントデータをピクセルごとにソートして描画</div>
SortAndRenderFragments( pD3DContext, pDevice, pRTV );<br />
</code></div></div>
<p>
パス２はスクリーンの各ピクセルごとにシェーダを走らせるのでピクセルシェーダでの実装となります。つまり、Linked List OITではCompute Shaderを使用しません。<br />
<br />
<br />
<br />
<br />
<br />
[<a href="http://www4.atword.jp/cathy39/2010/05/07/linked-list-oit-japanese-3/">つづく</a>]<br />
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/06/linked-list-oit-japanese-2/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/06/linked-list-oit-japanese-2/" />
	</item>
		<item>
		<title>Linked Listを利用したOIT</title>
		<link>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-japanese-1/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-japanese-1/#comments</comments>
		<pubDate>Tue, 04 May 2010 06:31:04 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT(Japanese)]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=83</guid>
		<description><![CDATA[
GDC　2010にてLinked List を利用したOrder Independent Transparency の紹介がありました。

スライドはこちら。
GDC 2010: OIT and GI using DX [...]]]></description>
			<content:encoded><![CDATA[<p>
GDC　2010にてLinked List を利用したOrder Independent Transparency の紹介がありました。<br />
<br />
スライドはこちら。<br />
GDC 2010: OIT and GI using DX11 linked lists (Nick Thibieroz &amp; Holger Grün)<br />
http://developer.amd.com/documentation/presentations/Pages/default.aspx<br />
<br />
Order Independent Transparency (以後OIT)というのは、半透明の描画順ソートを行う技術です。通常のZテストとアルファブレンディングで描画順のソートを完全に正しく行うのには限界があり、実質不可能です。たとえばポリゴンが他のポリゴンに突き抜けている場合などはかなり無理です。しかし、OITを利用すればそのような状態でも正しく半透明ポリゴンを重ねて描画することができます。<br />
<br />
DirectX SDKサンプルにもOIT11というサンプルがあり、ポリゴンが突き抜けているような状態でも正しくブレンドすることができています。しかし残念ながら非常に重くて使い物になりません。一方、同じOITを行うATI のRadeon™ HD 5000 シリーズの「Mecha」デモはOIT11に比べてはるかに複雑なシーンなのにわりとさくさく動いています。GDCで紹介されたOITの技術はMechaデモで使用しているものと同じ、とういことで、OIT11サンプルを改造してLinked Listを実装し、速度を比較してみることにしました。<br />
<br />
<br />
<strong>実装結果</strong><br />
<br />
オリジナルのOIT11サンプルはRADEON HD5800上で11.3fpsで動いています。<br />
<br />
<img class="aligncenter size-medium wp-image-23" title="Original OIT11" src="http://www4.atword.jp/cathy39/files/2010/05/oit11_original.jpg" alt="" width="300" height="248" />
<br />
Linked List　OITを実装後、fpsは1800まであがりました。<br />
実に約160倍です。DirectXのサンプルはあまり参考にしないほうがいいですね…<br />
<br />
<img class="aligncenter size-medium wp-image-23" title="linked list OIT" src="http://www4.atword.jp/cathy39/files/2010/05/oit_linkedlist.jpg" alt="" width="300" height="248" />
<br />
実装方法はおいおい投稿していきます。<br />
<br />
[つづく]</p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-japanese-1/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-japanese-1/" />
	</item>
		<item>
		<title>OIT using Linked Lists - 4</title>
		<link>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-4/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-4/#comments</comments>
		<pubDate>Tue, 04 May 2010 04:30:25 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=71</guid>
		<description><![CDATA[
[Previous post]


3. Implement Sorting and rendering pass

In the second pass, all fragments in the linked list at each pixel are sorted by depth value, then the color is blended in order of depth.

3-a. Implement shaders.

Create new hlsl files for the sorting and rendering pass. In the pixel shader, copy all fragments in the list to [...]]]></description>
			<content:encoded><![CDATA[<p>
[<a href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-3/">Previous post</a>]<br />
<br />
<br />
<b>3. Implement Sorting and rendering pass</b><br />
<br />
In the second pass, all fragments in the linked list at each pixel are sorted by depth value, then the color is blended in order of depth.<br />
<br />
<b>3-a. Implement shaders.</b><br />
<br />
Create new hlsl files for the sorting and rendering pass. In the pixel shader, copy all fragments in the list to a temporary array first, and then sort them. You need a vertex shader as well to render a screen quad.<br />
<br />
<div class="code-surround"><div class="code-main">
<code><br />
StructuredBuffer&lt;SFragmentLink&gt; FragmentLinkSRV : register(t0);<br />
Buffer StartOffsetSRV : register(t1);<br />
<br />
struct QuadVS_Output<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;float4 pos   : SV_POSITION;<br />
};<br />
<br />
<br />
float4 SortFragmentsPS( QuadVS_Output _input ) : SV_Target0<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uIndex = (uint)_input.pos.y * g_nFrameWidth + (uint)_input.pos.x;<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Read and store linked list data to the tempolary buffer.</div>
&nbsp;&nbsp;&nbsp;&nbsp;SFragment aData[32];<br />
&nbsp;&nbsp;&nbsp;&nbsp;int anIndex[32];<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uNumFragment = 0;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uNext = StartOffsetSRV[uIndex];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;while ( uNext != 0xFFFFFFFF ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SFragmentLink element = FragmentLinkSRV[uNext];<br />
		<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aData[uNumFragment] = element.fragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[uNumFragment] = uNumFragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++uNumFragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uNext = element.uNext;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint N2 = 1 &lt;&lt; (int)(ceil(log2(uNumFragment)));<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// fill initial data</div>
&nbsp;&nbsp;&nbsp;&nbsp;for(int i = uNumFragment; i &lt; N2; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[i] = i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aData[i].fDepth = 1.1f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Bitonic sort. copied from OIT_CS.hlsl</div>
&nbsp;&nbsp;&nbsp;&nbsp;for( int k = 2; k &gt;1; j &gt; 0 ; j = j&gt;&gt;1 ) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for( int i = 0; i  i )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float dixj = aData[ anIndex[ ixj ] ].fDepth;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( ( i&amp;k ) == 0 &amp;&amp; di &gt; dixj )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp = anIndex[ i ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ i ] = anIndex[ ixj ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ ixj ] = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( ( i&amp;k ) != 0 &amp;&amp; di &lt; dixj )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp = anIndex[ i ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ i ] = anIndex[ ixj ];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anIndex[ ixj ] = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Output the final result to the frame buffer<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Accumulate fragments into final result</div>
&nbsp;&nbsp;&nbsp;&nbsp;float4 result = 0.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;for( int x = uNumFragment-1; x &gt;= 0; x-- )<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint uColor = aData[ anIndex[ x ] ].uColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float4 color;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.r = ( (uColor &gt;&gt; 0)  &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.g = ( (uColor &gt;&gt; 8)  &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.b = ( (uColor &gt;&gt; 16) &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color.a = ( (uColor &gt;&gt; 24) &amp; 0xFF ) / 255.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = lerp( result, color, color.a );<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;result.a = 1.0f;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;return result;<br />
}<br />
<br />
</code></div></div>
<br />
<p>
The start offset buffer is referred as a uint buffer.<br />
Since OIT11 is not taking opaque primitives into account,  the initial value of blending is a clear color, black. To make it practical, read a back color texture as the initial value of blending. As you can see this code, there is a limit number of fragments per pixel (i.e. 32 fragments per pixel). It is necessary to insert safety code in the pixel shader to avoid array overrun.<br />
<br />
<br />
<b>3-b. Add Shader Resource Views</b><br />
<br />
In the second pass, the two buffers are referred as Shader Resource Views. Add following code in <em>OIT::OnD3D11ResizedSwapChain</em>.<br />
<br />
</p>
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Create Shader Resource Views</div>
D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;<br />
descSRV.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;<br />
descSRV.Buffer.FirstElement = 0;<br />
<br />
descSRV.Format = DXGI_FORMAT_UNKNOWN;<br />
descSRV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * 8;<br />
V_RETURN( pDevice-&gt;CreateShaderResourceView( m_pFragmentLinkBuffer, &amp;descSRV, &amp;m_pFragmentLinkSRV ) );<br />
<br />
descSRV.Format = DXGI_FORMAT_R32_UINT;<br />
descSRV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height;<br />
V_RETURN( pDevice-&gt;CreateShaderResourceView( m_pStartOffsetBuffer, &amp;descSRV, &amp;m_pStartOffsetSRV ) );<br />
</code></div></div>
<p>
<br />
In addition, create a vertex buffer and input layout for rendering screen quad in <em>OIT::OnD3D11CreateDevice</em>.<br />
<br />
<br />
<b>3-c. Implement Sorting and rendering function.</b><br />
<br />
Set the vertex buffer, input layout and shader resource views and render the screen quad in <em>OIT::SortAndRender</em>.<br />
</p>
<br />
<div class="code-surround"><div class="code-main">
<code><br />
ID3D11ShaderResourceView* ppSRVs[] = {<br />
&nbsp;&nbsp;&nbsp;&nbsp;m_pFragmentLinkSRV,<br />
&nbsp;&nbsp;&nbsp;&nbsp;m_pStartOffsetSRV,<br />
};<br />
pD3DContext-&gt;PSSetShaderResources( 0, sizeof(ppSRVs)/sizeof(ppSRVs[0]), ppSRVs );<br />
<br />
pD3DContext-&gt;VSSetShader( m_pSortAndRenderVS, NULL, 0 );<br />
pD3DContext-&gt;PSSetShader( m_pSortAndRenderPS, NULL, 0 );<br />
<br />
<br />
<div class="code-comment">// Draw a screen quad by a large triangle.</div>
pD3DContext-&gt;IASetInputLayout( m_pIL );<br />
UINT uStrides = sizeof( SQuadVertex );<br />
UINT uOffsets = 0;<br />
pD3DContext-&gt;IASetVertexBuffers( 0, 1, &amp;m_pVB, &amp;uStrides, &amp;uOffsets );<br />
pD3DContext-&gt;IASetIndexBuffer( NULL, DXGI_FORMAT_R32_UINT, 0 );<br />
pD3DContext-&gt;IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );<br />
<br />
pD3DContext-&gt;Draw( 3, 0 );<br />
<br />
<div class="code-comment">// Unbind SRVs</div>
ID3D11ShaderResourceView* ppSRVNULL[] = {<br />
&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br />
};<br />
pD3DContext-&gt;PSSetShaderResources( 0, sizeof(ppSRVs)/sizeof(ppSRVs[0]), ppSRVNULL );<br />
<br />
</code></div></div>
<p>
<br />
<br />
<b>4. Source code</b><br />
<br />
Here is the source code.<br />
[<a href="http://www4.atword.jp/cathy39/files/2010/05/oit.zip">download zip</a>]<br />
You can compile and run the Linked List version of the OIT11 sample by overwriting all of the source code to the OIT11 directory.<br />
<br />
<br />
<b>5. Conclusion</b><br />
<br />
Linked List OIT is a fast technique and very easy to implement. However, there are several points to improve in my implementation. For example, it supports only one blending mode and no anti aliasing. I will try to make it more practical for video games in the future.<br />
<br />
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-4/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-4/" />
	</item>
		<item>
		<title>OIT using Linked Lists - 3</title>
		<link>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-3/</link>
		<comments>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-3/#comments</comments>
		<pubDate>Tue, 04 May 2010 03:40:16 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=58</guid>
		<description><![CDATA[
[Previous post]


2. Implement Linked List Creation


The OIT11 uses one 2D Texture and three buffers. Linked List OIT requires two buffers, one is a structured buffer which is called "Fragment Link Buffer". The other is a uint buffer which is called "Start Offset Buffer".

- Fragment Link Buffer
contains all fragments. Each fragment has a color, depth value [...]]]></description>
			<content:encoded><![CDATA[<p>
[<a href="http://www4.atword.jp/cathy39/2010/04/29/linked-list-oit-2/">Previous post</a>]<br />
<br />
<br />
<b>2. Implement Linked List Creation</b><br />
<br />
<br />
The OIT11 uses one 2D Texture and three buffers. Linked List OIT requires two buffers, one is a structured buffer which is called "Fragment Link Buffer". The other is a uint buffer which is called "Start Offset Buffer".<br />
<br />
- Fragment Link Buffer<br />
contains all fragments. Each fragment has a color, depth value and the index of the next fragment in a linked list. If there is no next fragment, the index will be a magic value, 0xffffffff in this case.<br />
The declaration of a framgent in the pixel shader is written as follows. Color is packed to a uint value.<br />
</p>
<div class="code-surround"><div class="code-main"><code><br />
struct SFragment {<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint  uColor;<br />
&nbsp;&nbsp;&nbsp;&nbsp;float fDepth;<br />
};<br />
<br />
struct SFragmentLink {<br />
&nbsp;&nbsp;&nbsp;&nbsp;SFragment fragment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint      uNext;<br />
};<br />
</code></div></div>
<p>
  <br />
- Start Offset Buffer<br />
contains the index of the first fragment of a linked list at each pixel. It is initialized by a magic value before rendering at every frame.<br />
<br />
<br />
<b>2-a. Implement shader</b><br />
<br />
Modify OIT_PS.hlsl and implement fragment link buffer creation.<br />
Declare the buffers as follows.<br />
<div class="code-surround">
<div class="code-main"><code><br />
<div class="code-comment">// Fragment And Link Buffer</div>
RWStructuredBuffer FLBuffer&lt;SFragmentLink&gt; : register( u0 );<br />
<div class="code-comment">// Start Offset Buffer</div>
RWByteAddressBuffer StartOffsetBuffer : register( u1 );<br />
</code></div>
</div>
<p>
Then implement the entry point function. It can be almost same as the code in the slide.<br />
</p>
<div class="code-surround">
<div class="code-main"><code>[earlydepthstencil]<br />
void StoreFragments( SceneVS_Output input )<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint x = input.pos.x;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint y = input.pos.y;<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Create fragment data.</div>
&nbsp;&nbsp;&nbsp;&nbsp;uint4 ucolor = saturate( input.color ) * 255;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SFragmentLink element;<br />
&nbsp;&nbsp;&nbsp;&nbsp;element.fragment.uColor = (ucolor.x) | (ucolor.y &lt;&lt; 8) | (ucolor.z &lt;&lt; 16) | (ucolor.a &lt;&lt; 24);<br />
&nbsp;&nbsp;&nbsp;&nbsp;element.fragment.fDepth = input.pos.z;<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Increment and get current pixel count.</div>
&nbsp;&nbsp;&nbsp;&nbsp;uint uPixelCount = FLBuffer.IncrementCounter();<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Read and update Start Offset Buffer.</div>
&nbsp;&nbsp;&nbsp;&nbsp;uint uIndex = y * g_nFrameWidth + x;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uStartOffsetAddress = 4 * uIndex;<br />
&nbsp;&nbsp;&nbsp;&nbsp;uint uOldStartOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;StartOffsetBuffer.InterlockedExchange( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uStartOffsetAddress, uPixelCount, uOldStartOffset );<br />
<br />
<div class="code-comment">&nbsp;&nbsp;&nbsp;&nbsp;// Store fragment link.</div>
&nbsp;&nbsp;&nbsp;&nbsp;element.uNext = uOldStartOffset;<br />
&nbsp;&nbsp;&nbsp;&nbsp;FLBuffer[uPixelCount] = element;<br />
}<br />
</code></div>
</div>
<p>
Note that the byte address buffer must be accessed by byte size.<br />
<br />
<br />
<b>2-b. Add Buffers and UAVs</b><br />
<br />
Add two buffers and their UAVs. The following code is implemented in <em>OIT::OnD3D11ResizedSwapChain</em> function.<br />
</p>
<div class="code-surround" style="height:500px"><div class="code-main">
<code><div class="code-comment">// Create Fragment and Link buffer.</div>
descBuf.StructureByteStride = sizeof(float) + sizeof(BYTE) * 4 * 2;<br />
descBuf.ByteWidth = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * 8 * descBuf.StructureByteStride;<br />
descBuf.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;<br />
V_RETURN( pDevice-&gt;CreateBuffer( &amp;descBuf, NULL, &amp;m_pFragmentLinkBuffer ));<br />
<br />
<div class="code-comment">// Create Start Offset buffer</div>
descBuf.StructureByteStride = 4 * sizeof(BYTE);<br />
descBuf.ByteWidth = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * descBuf.StructureByteStride;<br />
descBuf.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;<br />
V_RETURN( pDevice-&gt;CreateBuffer( &amp;descBuf, NULL, &amp;m_pStartOffsetBuffer ));<br />
<br />
<div class="code-comment">// Create Unordered Access Views</div>
D3D11_UNORDERED_ACCESS_VIEW_DESC descUAV;<br />
descUAV.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;<br />
descUAV.Buffer.FirstElement = 0;<br />
<br />
descUAV.Format = DXGI_FORMAT_UNKNOWN;<br />
descUAV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height * 8;<br />
descUAV.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER;<br />
V_RETURN( pDevice-&gt;CreateUnorderedAccessView( m_pFragmentLinkBuffer, &amp;descUAV, &amp;m_pFragmentLinkUAV ) );<br />
<br />
descUAV.Format = DXGI_FORMAT_R32_TYPELESS;<br />
descUAV.Buffer.NumElements = pBackBufferSurfaceDesc-&gt;Width * pBackBufferSurfaceDesc-&gt;Height;<br />
descUAV.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;<br />
V_RETURN( pDevice-&gt;CreateUnorderedAccessView( m_pStartOffsetBuffer, &amp;descUAV, &amp;m_pStartOffsetUAV ) );<br />
<br />
</code></div></div>
<p>
Note that <em>descBuf.BindFlags</em> contains <em>D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE</em> as the original code.<br />
<br />
The fragment link buffer must contain all fragments. I specified the same size as the deep frame buffer in OIT11 sample (i.e. 8x screen size). Structured buffers must be created with <em>D3D11_RESOURCE_MISC_BUFFER_STRUCTURED</em>.<br />
<br />
The start offset buffer is a screen-sized buffer and the UAV is used as a Byte address buffer. Specify <em>D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS</em> when create.<br />
<br />
Specify <em>D3D11_BUFFER_UAV_FLAG_COUNTER</em> so that the UAV of the fragment link buffer has counter support. UAVs for structured buffers must be created with DXGI_FORMAT_UNKNOWN format. <br />
<br />
<br />
<b>2-c. Implement function</b><br />
<br />
Implement <em>OIT::CreateFragmentAndLink</em> function. It is easy to do it by modifying <em>OIT::FillDeepBuffer</em> because you can use the same constant buffer as the original code.<br />
Clear the start offset buffer by a magic value before rendering.<br />
<br />
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Clear the start offset buffer by magic value.</div>
static const UINT clearValueUINT[1] = { 0xffffffff };<br />
pD3DContext-&gt;ClearUnorderedAccessViewUint( m_pStartOffsetUAV, clearValueUINT );<br />
<br />
<div class="code-comment">// Bind UAVs.<br />
// No render target is required.</div>
ID3D11UnorderedAccessView* pUAVs[] = {<br />
	m_pFragmentLinkUAV,<br />
	m_pStartOffsetUAV,<br />
};<br />
<div class="code-comment">// Initialize the counter value.</div>
UINT anInitIndices[] = { 0, 0 };<br />
pD3DContext-&gt;OMSetRenderTargetsAndUnorderedAccessViews( 0, NULL, pDSV, 0, sizeof(pUAVs)/sizeof(pUAVs[0]), pUAVs, anInitIndices );<br />
<br />
<div class="code-comment">// Set Pixel Shader and shader constants.</div>
pD3DContext-&gt;PSSetShader( m_pCreateFragmentLinkPS, NULL, 0 );<br />
<br />
HRESULT hr;<br />
D3D11_MAPPED_SUBRESOURCE MappedResource;<br />
V( pD3DContext-&gt;Map( m_pPS_CB, 0, D3D11_MAP_WRITE_DISCARD, 0, &amp;MappedResource ) );<br />
PS_CB* pPS_CB = ( PS_CB* )MappedResource.pData;  <br />
pPS_CB-&gt;nFrameWidth = m_nFrameWidth;<br />
pPS_CB-&gt;nFrameHeight = m_nFrameHeight;<br />
pD3DContext-&gt;Unmap( m_pPS_CB, 0 );<br />
pD3DContext-&gt;PSSetConstantBuffers( 0, 1, &amp;m_pPS_CB );<br />
<br />
pScene-&gt;D3D11Render( mWorldViewProjection, pD3DContext );<br />
<br />
<div class="code-comment">// Unbind UAVs.</div>
ID3D11UnorderedAccessView* pUAVsNULL[] = { NULL, NULL, NULL, NULL };<br />
pD3DContext-&gt;OMSetRenderTargetsAndUnorderedAccessViews( 0, NULL, pDSV, 0, sizeof(pUAVs)/sizeof(pUAVs[0]), pUAVsNULL, NULL );<br />
<br />
</code></div></div>
<p>
Don't forget to initialize the counter value when setting the UAVs.<br />
If you specify [earlydepthstencil] to the shader, you have to disable deth write before rendering. Otherwise some fragments will be rejected by depth test.<br />
<br />
[ <a href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-4/">To be continued... </a>]<br />
</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-3/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-3/" />
	</item>
		<item>
		<title>OIT using Linked Lists - 2</title>
		<link>http://www4.atword.jp/cathy39/2010/04/29/linked-list-oit-2/</link>
		<comments>http://www4.atword.jp/cathy39/2010/04/29/linked-list-oit-2/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 12:33:09 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=10</guid>
		<description><![CDATA[
[Previous post]

I show my implementation here. Refer to the slide and OIT11 sample code for details of each technique.　The slide is very useful to understand how linked lists works and it also contains code. You can implement easily after you read the slide.


1. Modify Rendering Flow

In usual rendering, pixels which pass depth test are drawn [...]]]></description>
			<content:encoded><![CDATA[<p>
[<a href="http://www4.atword.jp/cathy39/2010/04/21/linkedlistoit1/">Previous post</a>]<br />
<br />
I show my implementation here. Refer to the slide and OIT11 sample code for details of each technique.　The slide is very useful to understand how linked lists works and it also contains code. You can implement easily after you read the slide.<br />
<br />
<br />
<b>1. Modify Rendering Flow</b><br />
<br />
In usual rendering, pixels which pass depth test are drawn to a frame buffer directly. In OIT, transparent primitives are not rendered to the frame buffer directly. Instead, all fragments are stored to a large buffer. Each fragment has a color and depth value and belongs to a pixel in the screen. There are multiple fragments per pixel where multiple transparent polygons overlaps. After rendering all transparent primitives, all fragments at a pixel are sorted by its depth and then the blended color is drawn to the frame buffer.<br />
<br />
<br />
The OIT11 sample stores the fragments to a large buffer in order of pixel address. <br />
For instance, the fragments are stored as follows.<br />
Fragment 1, 2, 3, .... of the pixel[0]<br />
Fragment 1, 2, ... of the pixel[1]<br />
<br />
To store fragments like this, before storing fragments, it is necessary to know how many fragments each pixel has and where the fragment should be stored in the large buffer.<br />
The OIT11 sample has 4 phases. You can see the entire phases in <em>OIT::Render</em>.<br />
<br />
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Create a count of the number of fragments at each pixel location</div>
CreateFragmentCount( pD3DContext, pScene, mWorldViewProjection, pRTV, pDSV );<br />
<br />
<div class="code-comment">// Create a prefix sum of the fragment counts.  Each pixel location will hold<br />
// a count of the total number of fragments of every preceding pixel location.</div>
CreatePrefixSum( pD3DContext );<br />
<br />
<div class="code-comment">// Fill in the deep frame buffer with depth and color values.  Use the prefix<br />
// sum to determine where in the deep buffer to place the current fragment.</div>
FillDeepBuffer( pD3DContext, pRTV, pDSV, pScene, mWorldViewProjection );<br />
<br />
<div class="code-comment">// Sort and render the fragments.  Use the prefix sum to determine where the <br />
// fragments for each pixel reside.</div>
SortAndRenderFragments( pD3DContext, pDevice, pRTV );<br />
</code></div></div>
<p>
The first and third phases are implemented by pixel shaders and the others by compute shaders.<br />
<br />
On the other hand, Linked List OIT stores fragments in order of being drawn. So it requires only 2 passes. Instead of count the number of fragments, it stores fragments as linked lists. All fragments which belong to a certain pixel are in a linked list.<br />
<em>OIT::Render</em> can be rewritten as follows:<br />
</p>
<div class="code-surround"><div class="code-main">
<code><div class="code-comment">// Linked List creation.</div>
CreateFragmentLink( pD3DContext, pRTV, pDSV, pScene, mWorldViewProjection );<br />
<br />
<div class="code-comment">// Sort and render the fragments.  </div>
SortAndRenderFragments( pD3DContext, pDevice, pRTV );<br />
</code></div></div>
<br />
<p>
Both passes are implemented by a pixel shader. The primitives are drawn in the first pass and the second pass is performed by rendering a screen quad. <br />
Linked List OIT does not use Compute shader.<br />
<br />
<br />
[<a href="http://www4.atword.jp/cathy39/2010/05/04/linked-list-oit-3/">To be continued...</a>]<br />
</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/04/29/linked-list-oit-2/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/04/29/linked-list-oit-2/" />
	</item>
		<item>
		<title>OIT using Linked Lists</title>
		<link>http://www4.atword.jp/cathy39/2010/04/21/linkedlistoit1/</link>
		<comments>http://www4.atword.jp/cathy39/2010/04/21/linkedlistoit1/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 16:15:09 +0000</pubDate>
		<dc:creator>Kaori</dc:creator>
		
		<category><![CDATA[OIT]]></category>

		<guid isPermaLink="false">http://www4.atword.jp/cathy39/?p=7</guid>
		<description><![CDATA[
There was a presentation about Order Independent Transparency using Linked Lists at GDC2010.

GDC 2010: OIT and GI using DX11 linked lists (Nick Thibieroz &#38; Holger Grün)
You can download the slide here.
http://developer.amd.com/documentation/presentations/Pages/default.aspx


I noticed the DirectX OIT11 sample was too slow but Mecha Demo for ATI Radeon™ HD 5000 Series seemed to be fast. 
So I tried [...]]]></description>
			<content:encoded><![CDATA[<p>
There was a presentation about Order Independent Transparency using Linked Lists at GDC2010.<br />
<br />
GDC 2010: OIT and GI using DX11 linked lists (Nick Thibieroz &amp; Holger Grün)<br />
You can download the slide here.<br />
<a href="http://developer.amd.com/documentation/presentations/Pages/default.aspx">http://developer.amd.com/documentation/presentations/Pages/default.aspx</a><br />
<br />
<br />
I noticed the DirectX OIT11 sample was too slow but Mecha Demo for ATI Radeon™ HD 5000 Series seemed to be fast. <br />
So I tried to modify the DirectX sample and implement linked lists instead.<br />
<br />
<br />
<b>Result</b><br />
<br />
The original OIT11 runs at 11.3 fps on RADEON HD 5800. <br />
<img src="http://www4.atword.jp/cathy39/files/2010/05/oit11_original.jpg" alt="" title="Original OIT11" width="300" height="248" class="aligncenter size-medium wp-image-23" />
<br />
<br />
After modification, it increase to around 1800 fps.<br />
Linked list OIT is 160x faster!<br />
<br />
<img src="http://www4.atword.jp/cathy39/files/2010/05/oit_linkedlist.jpg" alt="" title="linked list OIT" width="300" height="248" class="aligncenter size-medium wp-image-23" />
<br />
<br />
<br />
I will post my implementation soon.<br />
<br />
<br />
<br />
<br />
[<a href="http://www4.atword.jp/cathy39/2010/04/29/linked-list-oit-2/">To be continued...</a>]</p>
]]></content:encoded>
			<wfw:commentRss>http://www4.atword.jp/cathy39/2010/04/21/linkedlistoit1/feed/</wfw:commentRss>
		<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://www4.atword.jp/cathy39/2010/04/21/linkedlistoit1/" />
	</item>
	</channel>
</rss>

