Archives

November 2007 の記事

メモリの価格が急激に下がっているそうです。
そんな話をしていたら、タイミングよく PC Watch に記事が掲載されて
いました。
元麻布春男の週刊PCホットライン 1GB=2,000円時代のメモリ増設を考える(上)

バルクであれば 2GB のメモリが 4980円程度!
この間買ったばかりの 1GB メモリは 2枚で7000円くらいでした。

つい先日まで 1GB ×4 で喜んでいたのに、今なら 2GB×4 の 8GB RAM
だって十分現実的です。


まだ Quad では試せていませんが、最近試していた Multi Core による
build 時間の短縮も効果がありました。PC の性能向上は速くていつも
驚かされます。
Multi Core CPU や 64bit OS に大容量メモリなど、プログラミング環境
としてより速い PC を求めることに説得力が出てきました。
使い方次第ではありますが速さは作業効率の向上につながります。


ところがプログラマ用 PC の性能向上を妨げるものは、会社の予算でも、
上司の許可でもなく、プログラマ自身であることがあります。


せっかく PC をもっと良いものに交換しようと持ちかけても、
環境構築が面倒だからいらない、という人は思ったよりたくさんいます。

もちろんプロジェクトの終盤とか大事な時期とか、変えてはいけない時も
あります。だけどそうでなくても、環境再構築や OS の入れ替え、
PC の引越しをかなり面倒だと考える人は多いようです。
よほど困っている場合を除いて、意外にも現状で満足してしまうようです。


私は仕事柄ビデオカードテスト用にマシンを用意したり、各種 OS を
入れたり、またはスタッフ用に PC を準備したりと、
何度も何度も PC のセットアップすることが多いです。
そのため自然に再セットアップの最小手段を準備しておくようになりました。

コピーすべきデータを常に分けておいたり、最低限必要なアプリケーション
や設定など、自分の PC にするための手順を把握しています。

エデイタやシェルなど基本的な設定ファイルや環境は Subversion に全部
入れてしまっています。新しい PC 上でも checkout すればすぐ使え、
設定を変えても複数の PC 間で同期を取ることも容易です。

最初に書き換えるレジストリなども reg ファイルにして、同じように
svn に入れてしまっています。


環境の再構築で時間をとられるのはほんの一時的ですが、build 時間など
作業効率はその後長く影響し続けます。
これはチーム全体の効率にかかわってきます。

より速い環境へと PC を自在に渡り歩くスキルも、これから
必要になってくるのかもしれません。



連休明けて、引き続き VS2008 です。
今度は IDE 上での MP Build を試しています。
ソース単位で並列にコンパイルできます。

Project の Property から下記の設定をしています。

C/C++ → Code Generation
  Enable Minimal Rebuild が「Yes (/Gm)」になっていたら「No」へ
  (他にも /MP 非互換オプションがあればはずす必要あり)

C/C++ → Command Line
  Additional options: に「/MP4」を追加


・Pentium4 3.6GHz×2×HT (=4) での比較
  (MP無し) 52秒→28秒 (/MP4)

・Core2 Duo 2.4GHz での比較
  (MP無し) 30秒→18秒 (/MP2)

厳密な条件ではないですが、VS IDE 上でも簡単に試すことができました。
Makefile で依存関係を記述すると 1ファイル単位のコンパイルになって
しまうので、/MP 指定もあまり有効に活用されません。
こちらの方が簡単に結果を出せるようです。

ソースファイル 12本ほどのプロジェクトです。Vista x64 使用。
やはり何度も build を繰り返していて、ほぼファイルが全部キャッシュ
された状態で比較しています。
よって条件によってはここまで差が出ないと思われます。
Core2 Duo でも /MP4 の方がさらに1~2秒よい結果となりました。

Visual Studio 2008 MP オプション実験
Visual Studio 2008



先日のエントリで書いた Visual Studio 2008 の MP オプションを
かるく(いいかげんに)試してみました。
Visual Studio 2008
取りあえずコマンドラインから。

使用した環境
・Visual Studio 2008 Professional (VC9.0)
・Vista x64、x64(amd64) 版コンパイラ cl
・Pentium4 3.6GHz ×2CPU × HT = 4thread RAM2G
・41本の cpp ソースコンパイル

コマンドラインオプション
 -W3 -WX -O2 -Oi -Ot -Oy -Ob2 -GA -GF -Gy -DWIN32
 -D_WINDOWS -D_MBCS -EHsc -fp:except-
 -fp:fast -Zi -TP -c

-c なので obj 生成のみ。
何度も試したのでファイルはほぼキャッシュされている状態。

結果 (コンパイル時間の比較)

VC9 /MP1   47sec    (28%)  (/MP無指定と同じ)
VC9 /MP2   30sec    (55%)
VC9 /MP4   21sec    (100%)

後ろの括弧の中はパフォーマンスモニタの CPU 使用率(目安) です。
かなり効果ありました。

でももっと驚いたのは

VC8 /MP1   42sec
VC8 /MP4   19sec

あれ、VC8 (VS2005) でも /MP が使えている。
テストしててエラーが出ないからおかしいなとは思ったのですが。
マニュアルに無いけど隠し機能でしょうか。知らなかっただけかも。

同条件で Core2 Duo の場合
・Visual Studio 2008 Professional (VC9.0)
・Vista x64、x64(amd64) 版コンパイラ cl
・Core2 Duo E6600 2.4GHz RAM4G

VC9 /MP1   29sec
VC9 /MP2   17sec



以前下記エントリで書いた ctrlswapmini についてです。
WindowsMobile touchkeysip / ctrlswapmini

Advanced W-ZERO3[es] WS011SH での ctrlswapmini 動作に関して、
拡張かな時に [→] キーの判定が効かなくなるのは他のソフトとの
相性が原因だったと報告をいただきました。
ただ同条件にしても W-ZERO3[es] WS007SH では問題が発生しないため、
本当の原因は特定できていません。

また別件で、Advanced W-ZERO3[es] WS011SH では ctrlswapmini の
回転時キーマップが有効にならないとの報告をいただきました。
こちらも W-ZERO3[es] WS007SH では動作しているので、
機種依存の問題の可能性があります。
やはり実機がないとわからないですが、何か追加情報等ありましたら
ご連絡ください。

ctrlswapmini



2007/11/21
Visual Studio 2008

VisualStudio2008 がリリースされたのでインストールしてみました。
とりあえず Express Edition で。インストールフォルダは 9.0。
とりあえずCコンパイラのバージョン比較

・VisualStudio2008 Express Edition cl
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86

・VisualStudio2005 Professional cl
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

追加されたコンパイルオプションは次の3つでした。

/Qfast_transcendentals  generate inline FP intrinsics even with /fp:except
/Qimprecise_fwaits      generate FWAITs only on "try" boundaries, not inside "try"
/MP[n]                  use up to 'n' processes for compilation

どれくらい効果があるのか、MP オプションがかなり気になります。
Multi Processor 対応で build してくれるそうです。
MP オプションの詳細や使い方は下記のとおり。
/MP (Build with Multiple Processes)

その他増えた機能などはこちら。

What's New in Visual C++ 2008

Intrinsics も SSE4 に対応したようですね。
intrin.h も更新されています。
新しい SSE 関連の Intrinsics 命令の説明は下記のページです。

Supplemental Streaming SIMD Extensions 3 Instructions
Streaming SIMD Extensions 4 Instructions
SSE4A and Advanced Bit Manipulation Intrinsics

動作環境がないので試せないけど、
かなり面白そうな命令が多数並んでいます。

関連エントリ
SSE についてのメモ(2) SSE4など



以前「続 キーボードの作り方 / WindowsMobile (SIP)
で書いたように、指で直接操作できる新しい SIP を作ってみました。

touchkeysip
WindowsMobile5/6 で動作します。

スクリプトにより各キーの機能やレイアウトなどもすべて再構築
できます。
キーボードの画像は文字を並べてるわけではなくて bmp の一枚絵です。
こちらも簡単に作成&入れ替え可能です。

最近は外付けキーボードしか使ってなかったので、
bluetooth か USB ホストがあればこれで十分な気がしてきました。

さまざまな機種での動作報告とか、キーボードのデータ絵とか、
カスタマイズデータとかできましたら、
ぜひご連絡いただけたらなと思っております。


また ctrlswapmini の方ですが、拡張かな時に Advanced W-ZERO3[es]
WS011SH の場合、カーソルキー右でトグル操作を区切れないとの報告が
入っています。

たとえば 「かか」と入力する場合、[2か][→][2か]と操作しても
右カーソルキーが実際に機能してしまうそうです。

W-ZERO3[es] WS007SH ではきちんと動作しているので、機種依存の問題の
可能性があります。実機がないため確認及び調査できませんが、
より詳しい情報をお持ちの方がいましたらご連絡お願いいたします。



oga at 15:40
Vista x64 環境に移行して、以前よりも安定して運用できています。
今のところ自分の使う範囲では、ソフトもハードも特に困ったことはなく
メリットが大きいので気に入っています。
といっても必ずしも RAM 増えたわけでもなく、仕事で使ってる PC は
x86 時代と同じ 2GB のまま。
具体的にどこが違うのかといえば、ウィンドウを大量に開いても動作が
不安定にならなくなりました。

x86 で Console x5、VisualStudio 2005、Maya、IE7 等を起動した
状態でさらに Vim を 14 枚ほど開くと、ウィンドウの UI パーツが
ところどころ表示されなくなっていました。
ツールによっては保存等のダイアログが表示されなくなったり、いろいろ
挙動があやしくなります。

調べてみると、これはデスクトップアプリケーション用ヒープが足りない
状態に相当するようです。デスクトップアプリケーションヒープはこの辺に
多少説明があります。

Microsoft [PRB] User32.dll または Kernel32.dll の初期化に失敗する
MS デスクトップ アプリケーションのヒープを増やす

メインメモリの容量に関係なく、このヒープは一律 3MB 割り当てられて
いるようです。レジストリの設定で増やせますが、大幅な追加は推奨し
ていないようです。目いっぱい RAM を搭載できる現在、これがどの程度
システムに影響を与えるのか、その根拠についてはわかりません。

Vista x64 で同レジストリエントリを調べると、32bit OS のおよそ
6.6倍に相当する 20MB 割り当てられていました。

%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows
SharedSection=1024,20480,768 
Windows=On SubSystemType=Windows ServerDll=basesrv,1
ServerDll=winsrv:UserServerDllInitialization,3 
ServerDll=winsrv:ConServerDllInitialization,2
ProfileControl=Off MaxRequestThreads=16

安定の原因は、単にこのデスクトップヒープが増えたおかげでしょうか。
そもそもヒープが足りなくなる原因はメモリリークらしいので、
もしそうだとしたら根本的な解決ではなく、先送りにしているだけ
かもしれません。

原因不明のメモリ不足エラーに対処する方法(デスクトップ・アプリケーション・ヒープ不足エラーに対処する方法)



DBZ でもペンタッチは可能でしたが、あくまで手書きメモ専用と割り切った
ものでした。PV-F1 はこれを一気にメインの入力手段へと変えてしまいます。

あまりに高価だった PV-F1 を普及帯へ押し上げたのが PI-ZAURUS です。
初代 PI-3000 はまだ電源スイッチが付いていたものの、PI-6000 など
次々登場する後継機種ではついに電源スイッチすら廃止されます。

液晶画面のタップだけで電源が入るので、本体にはタッチパネル兼液晶画面
しかない、ある意味究極の形となりました。

そんな中ハードボタンが注目を浴びるようになった、Palm 等ほかの
PDA の人気によるものです。

・スクロールキー+アプリキーなどハードウエアボタン搭載
・縦型(縦長)のスタイル

どちらも Zaurus が築いてきたスタイルとは正反対であったものの、
MI-P1 以降、代を重ねるごとにその影響は強くなります。

これ以後 PDA の進化の方向は、
ペンオペレーションへ一気に傾倒しすぎた反動か
それとも使いづらく神経を使う操作性からの反動か、
QWERTY キーまで搭載して完全にハードウエアキー全盛となります。
手書き文字認識もほとんど忘れられた存在となってしまいました。

そして手本は Palm から携帯電話へと代わります。

PocketPC は世代ごとに、ハードウエアキー等の標準が変化しています。
・ゲームパッドのような CASSIOPEIA スタイル
・センターカーソルキー+左右にアプリケーションボタンの iPAQ スタイル

そして WindowsMobile では、左右のソフトキーが追加されました。
モードや画面、アプリケーションごとに自由に機能を割り当てられる
ソフトキーの存在は携帯電話と同じものです。

カーソルキー+ソフトキーだけでほぼ全部の操作が可能で、旧 PocketPC
用に作られたアプリ以外はほぼペン操作無しに扱えるようになりました。


PDA の操作が徐々に携帯電話化していく中、突如再びタッチパネルの
時代が訪れました。

その第一段階は DS の登場です。PDA では使い古されたはずのペン
オペレーションが、ゲームでは斬新なものとして大きく脚光を浴びました。

そして iPhone & iPod touch の登場が大きな事件であったことは
いうまでもありません。


WindowsMobile にもソフトウエア入力パネル (SIP) があります。
QWERTY キーボードやら、携帯電話風のテンキーやら備えた端末が多数
出ていてすっかり邪魔者扱いされがちな SIP ですが、
ここであらためて注目してみました。

かつて SIP を作ったときの記録は下記の通りです。
キーボードの作り方(1)
キーボードの作り方(2)
キーボードの作り方(3)


● WindowsMobile の SIP

WindowsMobile でも SIP の基本構造は全く代わっていないようです。
Dvoraksip のサンプルもほとんど同じものでした。
基本的には新しい SDK で Build するだけでよく、修正点はそれほど
多くありません。

唯一違う点があるとすれば、画面解像度のバリエーションが大幅に
増えたことです。
PocketPC2002/2003 の時代は QVGA 240x320 解像度しかなく、
画面の縦横切り替えすらありませんでした。

QVGA 用に作った SIP をそのまま VGA 機種に組み込むと、RealVGA 化
していなくても等倍の解像度で表示されます。
非常に小さく、針の先でつつくようなこじんまりとしたパネルになって
しまいます。

ハイレゾに対応した座標系の補正や、表示するリソースの拡大は SIP 側の
プログラム側で対応しておく必要があるようです。


デバイスの画面解像度は下記の API で取得できます。

int width= GetSystemMetrics( SM_SXSCREEN );
int height= GetSystemMetrics( SM_SYSCREEN );

画面を回転させたときも、きちんと移転後の縦横サイズを受け取る
ことができます。この値から縦横の判断もできるようです。

この画面解像度を元に、表示リソースの拡大縮小変換、ペンタッチ座標の
スケール変換を行えば、きちんと意図した座標で表示可能となります。


● ハイレゾ対応方法

VGA 機種で SIP を表示してもパネルのサイズが 240x80 のまま表示
されます。ウィンドウ領域や描画サイズを拡大しても変わりません。
これはパネルエリアの親ウィンドウのサイズが固定されているからです。

この辺もいろいろ試しましたが、やはり自分でリサイズする必要がある
ようです。パネル選択時に呼ばれる IInputMethod2::Select() には
親ウィンドウが渡されます。

IInputMethod2::Select( HWND hwndSip )

このハンドルを元にパネル領域のサイズ変更が可能です。
例えば VGA に対応した 480x160dot 等に拡大することができます。
また

IInputMethod2::GetInfo( IMINFO* info )

でも正しいパネルサイズを返す必要があります。

IInputMethod2::ReceiveSipInfo( SIPINFO* psi )

こちらの ReceiveSipInfo() は特に変更する必要はありません。

画面回転時は画面の幅が広くなりますが、このときは指定したサイズを
元に勝手にセンタリングされるようです。
縦横に応じてサイズを可変にすれば、横画面でも左右端まで使った
大きなキーボードを作ることができます。

iPod touch のように、本格的に指で使いやすい SIP を作ることも
可能だと思います。


ちなみに WindowsMobile5.0 の SDK で作成しておけば、そのまま
WindowsMobile6.0 でも動作します。


● IME の制御

キーボードの作り方(1) でも書いていますが、日本語入力モードの
切り替えは基本的にキーストロークのシミュレートでできます。
[ALT]+[漢字] や [全/半] など。
より安全に切り替えたり、現在の状態を参照する場合は Imm 系 API
を使います。

下記のコードは em1key 等で使用しているものの抜粋で WindowsCE
専用です。未確定バッファがあるときは IME を CLOSE できないように
なっています。em1key ではフック内では使わずに、一旦 Window に
ポストして代わりに呼び出してもらっています。

enum {
    IMECTRL_OPEN  = (1<<0),
    IMECTRL_CLOSE = (1<<1),
};

// 0= QUERY, 1= OPEN, 2= CLOSE, 3= 切り替え
int ControlEngine::ImeControl( int mode )
{
    HIMC    himc= NULL;
    int     openstat= ImmGetOpenStatus( himc );
    if( openstat ){
        if( mode & IMECTRL_CLOSE ){
            int	size= ImmGetCompositionString( himc, GCS_COMPSTR, NULL, 0 );
            if( !size ){
                ImmSetOpenStatus( himc, FALSE );
            }
        }
    }else{
        if( mode & IMECTRL_OPEN ){
            ImmSetOpenStatus( himc, TRUE );
        }
    }
    return  openstat;
}



参考
歴代ザウルス
歴代ポケットPC
※ DBZ は SHARP の電子手帳 PA-9500 シリーズ



とうとう Direct3D10.1 / ShaderModel 4.1 対応 GPU が出てしまいました。
スペック詳細はこちら

AMD ATI Radeon HD 3800 Series - GPU Specifications

またあわせて、Direct3D 10.1 の詳細も明らかになっています。
こちらは以前コメント欄で情報いただいたものと同じで、おそらくその
最終版と思われます。

AMD the ATI Radeon HD 3800 Series and MicrosoftR DirectX 10.1 whitepaper (PDF)

実際に動く GPU は出てきました。あと必要なのは、WindowsVista SP1 と
10.1 に対応したドライバです。この 2つさえそろえば Direct3D 10.1 対応
アプリも実際に動作するようになります。

HYPERでんち の GPU 年表や GPU リストも更新しました。
年表によると GeForce8800GTX の登場はちょうど一年前、2006年11月だった
ようです。その後実際に WindowsVista が発売されたのは 2007年 1月で、
さらにドライバの完成は 3月までまでかかっています。

10.1 が実際に使えるようになるのも、ちょうど 10.0 から 1年後の時期に
なりそうです。



というわけで、さまざまな技術革新によりハードの性能はどんどん上がって
います。できることも可能性も飛躍的に向上しています。
毎日のようにアナウンスされるいくつもの製品や技術によって、かつて夢
だったことが次々と、ものすごいスピードで現実になっています。

できることも広がって技術者として純粋に嬉しいし、どれもこれも興味深いし
楽しいものです。このような可能性をいろいろと追求しながら、
ものを作っていけたらと思っています。

そのためには こんな未熟者 ではぜんぜんだめなので、、、
代わりに、どんどん新しいこと吸収したり、
ほんとにすごいことやいろんなことやったり、
調べたり勉強したり考えたり悩んだりしつつ
ものを作っていくプログラマを募集致します。

当初は実際のライン立ち上げではなく、比較的少人数による技術面の準備や
研究が中心となる予定です。
すでにある作業をただこなすだけのスタッフというよりも、
技術的なこととか、内容や実装面とか、いろいろ相談して進めていく
仲間が欲しいと考えています。
私もいろいろ教わることが多いと思いますので、
だめなら「小笠原だめだ」と言ってやってください。

ご興味ある方がいましたら下記ページをご覧ください。
<>

上の html のページは非常にシンプルですが、TOP の方からフラッシュ版を
開けます。気になった方はそちらの方もどうぞ。

話を聞いてみたい程度でも構いませんので、
まずは気軽に、ご連絡をお待ちしております。



ここしばらく半透明描画などの方法についていくつか考えたことを紹介して
きました。
Direct3D 10 ShaderModel4.0 ピクセル単位の半透明ソートを行う
Direct3D 10 ShaderModel 4.0 半透明ソート補足

浮動少数への畳み込みは、丸め込みの桁上がりの解決が必要なこと、仮数部の
情報量が限られていて格納時の効率が悪いこと、レイヤー数に上限があること
演算に Blend 機能を使うためRead 帯域をかなり消費するなどろいろと制限が
あります。
ところがドキュメントを調べていて非常良い方法があることがわかりました。

NVIDIA SIGGRAPH 2007 Stencil Routed A-Buffer

Multisample のハードウエアの機能を、非常に効率よく使った手法です。

最初説明でも書いたとおり、フレームバッファに値を蓄積するためには
直前の出力を受け取る必要があります。現状これが可能なのは

・RenderTarget Blend
・DepthStencil

の2つだけです。Blend の場合は値の演算ができるものの、Depth や Stencil
はテストと更新だけに限られます。またテストの結果は描画するしないの
bool 判定であり、MRT 等で複数の出力を持っていても同じ結果が反映されます。
MRT すべて書くか、すべて書かないかの二通りしかできません。

もし MRT 毎にそれぞれ異なる Stencil Test や Stencil Operation が設定
できれば、かなりできることが広がるでしょう。無理やり浮動少数の演算に
押し込めていた履歴による値の選択と切り捨てが、もっときれいに実装できる
ようになるはずです。

Stencil Routed A-Bufferはまさにこの、複数の出力に対する異なる
Stencil Test を実現可能にします。

Multisample anti-aliasing は数倍の解像度のフレームバッファにレンダ
リングします。このとき Shader 自体の pixel 出力は同一の値が用いられる
点が Supersample と異なります。
これを利用すると、同じ値を一度に複数書き込む手段として活用することが
できるわけです。

Multisample で8倍などの高解像度 RenderTarget を実現するには、
同じように Zバッファも必要です。付随して Stencil も同じ分だけ持っている
ことになります。
Stencil Test や Stencil Operation は全 pixel 同じ操作となりますが、
Stencil の初期値をずらすことで各ピクセル個別に操作することができる
ようになります。
これでピクセルごとに描画回数の保存と、回数に依存した書き込むピクセルの
選択が可能となりました。

あとは書き込まれた値に個別にアクセスする手段があれば十分です。
アクセス手法は後ほどもう少し調べます。

この辺の機能もやはり Direct3D 10.1 では Multisample 周りの機能が拡張
されていくようです。Programmable AA sample Pattern にしても、この辺を
踏まえての機能拡張だったのかもしれません。

とにかく GPU のハードウエア機能を活用するだけで、ほぼ要求を満たして
いることになるので非常にすばらしいです。まだ試していませんが、
かなり使える手法です。いろいろ実験してみたいと思ってます。


というか今更ですが、全くこれらのメジャーな文献を読んでいなかったことが
本当に信じられないくらい恥ずかしい限りです。

全くの無知のまま、いろいろ書いていた説明の数々、一応読んでくださった方
親切に無視してくださった方、
そしてこれら Realtime Graphics の研究に携わっている先人の方々に深く
お詫び申し上げます。

ごめんなさい。


前回ピクセル単位で、半透明のソートを行うシェーダーを作成しました。
Direct3D 10 ShaderModel4.0 ピクセル単位の半透明ソートを行う
Direct3D 10 ShaderModel 4.0 半透明ソート補足

レンダリング時にはカラー値をためておくだけにして、最後にシェーダーで
一気に Z ソートして合成をかけます。

そのため常に順番が正しく描画されることと、ピクセル単位なので交差
しようが自分自身と重なろうが、描画が矛盾しないという特徴があります。

他にも、最後の Blend をシェーダーで求めているため、通常のハードウエア
Blend だけでは表現できない複雑かつ高度な半透明合成ができるという利点も
あります。

今回はその点に着目して偏光板を作ってみました。

polarization shader

単純な板なので、実際に走らせて動いているところを見ないと少々わかり
にくいかもしれません。ダウンロードは下記からどうぞ。

wheelhandle_ss11t.zip

[SPACE]    pauge 一時停止
[U]        + Plane 追加
[D]        - Plane 削除
[Up]       camera up
[Down]     camera down
[Left]     rotate
[Right]    rotate

今回シミュレートしているのはあくまで偏光板同士の透過率の変化です。
背景画像など、一般の映像をカメラなどの偏光フィルターを通した場合の
表現ではない点にご注意ください。


この偏光板シェーダーは、透明度として Alpha の代わりに Tangent Vector を
用います。
ソートのあと、順番に Blend 合成するときに 2枚の偏光板同士の位相に応じて
透明度が変化します。

  TV  = Tangent Vector
  Tr  = Transparency

  blendf= saturate( 1.0f - abs( dot( TV[i-1], TV[i] ) ) * Tr )

透過度の最大値を Tr で与えています。0 または 180度で透過度が最大と
なり、90度ずれると 0% になります。

上記のように、2ピクセル間の関連性でのみ透過度を求めます。そのため、
2枚重なったエリアよりも 3枚以上重なったエリアの方が透過度が上がる
(明るくなる)ことがあります。

例えば A と C が 90度ずれている場合透明度は 0% で真っ黒になります。
ところが間に 45度ずれた B を挿入すると透過度が上がります。

A --------90--------- C   0%

A ---45--- B ---45--- C   50%

A と C の間は真っ黒なのに、B など斜めの板が重なってるエリアは
明るくなっているのがわかるでしょうか。(Aが手前、Cが奥です)

polarization shader

これは現実の偏光板でも起こる正しい現象のようです。

パラメターが増えたために、MRT は 6 枚使っています。
フレームバッファ 1pixel 96byte もあります。

データがただの板でわかりにくいですが、ソートされているのでカーソルキー
左右で回転などしても大丈夫です。ちなみに板の裏面は色つきです。