■遂にPSPで3Dが動き始めたつ。(2006-05/08、17:00)
(ダサいが、テクスチャードポリゴン。Geコマンドのみで書いてる。つまりはGU。PSPSDKはインストールして無い)
ええと、このブログでは、2Dは初心者。3Dはちゅーきゅー者と、(何も知らない)始めのほうで、
「決め付けて」しまったので、私は今まで「勿論初心者」でしたが、晴れてこれで中級者?なんちて。
でね。SEGADRIVEA27-A28の「縦画面モード」の実装は「あまりにタコ」(おっとそんな事いったらMAMEに叱られちゃう)
なんで、ちと3Dでもしよつ。って言って、キョーの午前ちゅーから始めた訳ですが(2時間グライ)
出来ちゃった。ですう。
これは「PSPSDK」の「cube」ってサンプルの「移植」なんですう。初心者だから(おっとこの語句は使えないのか?)
「PSPSDKのインストール」は未だに「やってない」。
ああ、やっぱ「初心者」っぽい...。
つまり、「必要な関数ぶっこ抜いて、コピペで貼り付けただけ」
明日グライに別館に挙げとくわ。(今日は、画面見るのやんなった)
じゃね。(2006-05/06、17:14)
■さて、今日の、おっと昨日のか。今はねえ。2006年05月10日01:02分(PSP氏、談)。
05/09の確か16時半グライに上のをさらにテキトーに弄った奴。別館にあげた。それはいいんだが、
とにかくまず3Dをやりたいんじゃなくてだ。まず2Dをやりたい。でも、2Dで、「回転スプライト」。つまり3Dって事。
まだ3Dはやりたくねーんだよ。これは本心だから仕方ねえ。3Dやるのに重要なのは1も2もなくて、「データーの管理」
これが最重要。きちんと管理する仕組み(プログラム)を作れりゃ「大きな物」が出来る。「急ぐがば回れ」。
「大きな仕事」をするプログラムは大抵「小さい」。「PSPSDK」の「GU」は「ユーザーがDirectXのRM風に指定した奴」を
単に「PSPの実行形式(DirectXで言えばExecutes-buffer)に変換するだけ」の「とても小さなプログラム」だが、
「大きな仕事」をするじゃろ。「あの辺」までは「自作」出来ないとちとマズイ。(ちゃんとした資料があればの話)
だって、「あの先」が難しいんだぜ。本当はな。「ポリゴン分割」グライ出来ないと話にならんじゃろ。スピードを
落とさずリアルタイムでって話。VRAMが余らんくらいまでイカないと。まあずーーーーーーと先の話だ。
で、とにかく目的は「SEGADRIVE」の「たて画面モード」。その為にGUをチョイトどんなもんか触っただけの話。
なんか「PSPSDK」の「GU」はVERによって差があるのか「混乱してる模様」安定してからでも遅くないと判断。
一生安定しない可能性も高いが...。
だから目的だってば、えっとね。プログラムを理解する為には「壊す」のが手っ取りバヤイ。もちろん「戦略を
持って壊す」んだぞ。「無計画」なのは「壊した」とは言わない。そいつは「意味のない時間を空費した」だけだ。
で、計画的に壊した第一弾が、「別館の3Dサンプル」別に3Dを勉強するのが目的ではない。そんなのもう知ってる。
あ、そうそう。別館の弄ってた時には気が付かなかったから意味ワカンナカッタんだけど、
「sceGumLoadIdentity();」って単に「GU」の「内蔵行列」を「単位行列に初期化するだけ」だお。つまり
XYZW
1000X
0100Y
0010Z
0001W
って事。Wって何?なんてきかない事。2000年を超えたら「知ってないとダメ」すでにNG。
要は計算が楽になるから存在する。
で、あれをもっと壊してみた。まず2Dの回転スプライト。なんだから、「2つの三角形ポリゴン」で十分。つまり、
//[RGB1] 0+_ 明るい
// /:~=_
// / : ~=_
//[RGB2] 4+_3+ ~+1 普通
// |~='`, /|
// |,'~=_'/ |
//[RGB3] 7+_ ~+5'+2 暗い
// ~=_ | /
// ~=_|/
//[RGB1] ~+6 明るい
struct Vertex vertices[2*3] __attribute__((aligned(16))) =
{//face#1(up)
//{U, V, 色, x, y, z},色は今回関係ない(と思う)
{0, 0, RGB1(0x7f,0x00,0x00),-1,-1, 1}, // 頂点0
{1, 0, RGB2(0x7f,0x00,0x00),-1, 1, 1}, // 頂点4
{1, 1, RGB3(0x7f,0x00,0x00), 1, 1, 1}, // 頂点5
{0, 0, RGB1(0x7f,0x00,0x00),-1,-1, 1}, // 頂点0
{1, 1, RGB3(0x7f,0x00,0x00), 1, 1, 1}, // 頂点5
{0, 1, RGB2(0x7f,0x00,0x00), 1,-1, 1}, // 頂点1
};
これ以上イラネ。これがGeコマンドになると、Geに投げるVertex(頂点)の数が6個だな。だって6行だもん。
(Geには「頂点リスト」で投げる。RUKAさんはVRAMにメモリ割り当てしてるど、今度まねしよ。)
(注記:頂点0と頂点5は二度同じ物がある。まったく同じ行だろ。だが、頂点4つで済ますコマンドはPSPに存在しないか、解析されてない。)
(注記:上の「絵」は、PSPが右回りか、左回りかワカラン頃に描いたから間違ってる可能性もあるが、
(仮に間違えても、頂点位置は正しくなる)。このデーター(三角形の2ポリゴン)で実験して、PSPでちゃんと
表示されるから、あってるらしい。つまり左周り(反時計周り)。ちなみに「PSPSDKのCubeサンプルのコメント」は、
「コメントの頂点」が間違ってるから要注意。別館の奴は「コメントが正しい」。頂点なんだから、データーが
同じ行は、コメントまで含めて「まったく同じ」になる筈。「コメント軽視」してる。つまり「PSPDSKのサンプルは
急いで出した」っちゅー事。みーんな「急ぐ」んだよなあ。別に急ぐ「必要」何処にもないのに...)
で、説明が面倒なので<以下、中略>
ああ疲れた。ちゅー訳で、PSPが吐いたリストがこれ、おしまい。
CMD:0x000000e2=0x00001d0c
CMD:0x000000e3=0x0000f3e2
CMD:0x000000e4=0x00000c1d
CMD:0x000000e5=0x0000e2f3
CMD:0x00000036=0x00001010
CMD:0x00000053=0x00000007
CMD:0x0000005b=0x003f8000
CMD:0x00000048=0x003f8000
CMD:0x00000049=0x003f8000
CMD:0x000000d2=0x00000001
CMD:0x0000009c=0x00000000
CMD:0x0000009d=0x00000200
CMD:0x0000009e=0x00088000
CMD:0x0000009f=0x00000200
CMD:0x00000015=0x00000000
CMD:0x00000016=0x00043ddf
CMD:0x0000009e=0x00088000
CMD:0x0000009f=0x00000200
CMD:0x0000004c=0x00007100
CMD:0x0000004d=0x00007780
CMD:0x00000042=0x00437000
CMD:0x00000043=0x00c30900
CMD:0x00000045=0x00450000
CMD:0x00000046=0x00450000
CMD:0x00000044=0x00c70000
CMD:0x00000047=0x0046fffe
CMD:0x000000d6=0x00000000
CMD:0x000000d7=0x0000ffff
CMD:0x000000d4=0x00000000
CMD:0x000000d5=0x00043ddf
CMD:0x000000de=0x00000007
CMD:0x00000023=0x00000001
CMD:0x0000009b=0x00000001
CMD:0x00000050=0x00000001
CMD:0x0000001d=0x00000001
CMD:0x0000001e=0x00000001
CMD:0x0000001c=0x00000001
CMD:0x0000000f=0x00000000
CMD:0x0000000c=0x00000000
CMD:0x0000009c=0x00000000
CMD:0x0000009d=0x00000200
CMD:0x000000d3=0x00000501
CMD:0x00000012=0x0080011c
CMD:0x00000010=0x00080000
CMD:0x00000001=0x0094f7a0
CMD:0x00000004=0x00060002 //何でここに4番があるの?不要の可能性(つまり単なる初期化)が高い。イマイチわからん。テクスチャ転送?
テクスチャはVRAMに無いとダメちゅー事かな?
CMD:0x000000d3=0x00000000
CMD:0x000000c2=0x00000000
CMD:0x000000c3=0x00000002
CMD:0x000000cb=0x00000000
CMD:0x000000a0=0x00905f80
CMD:0x000000a8=0x00080040
CMD:0x000000b8=0x00000606
CMD:0x000000cb=0x00000000
CMD:0x000000c9=0x00000004
CMD:0x000000ca=0x00ffff00
CMD:0x000000c6=0x00000101
CMD:0x00000048=0x003f8000
CMD:0x00000049=0x003f8000
CMD:0x0000004a=0x00000000
CMD:0x0000004b=0x00000000
CMD:0x00000055=0x00ffffff
CMD:0x00000058=0x000000ff
CMD:0x0000003e=0x00000000
CMD:0x0000003f=0x003edcfd
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x003f446f
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00bf8020
CMD:0x0000003f=0x00bf8000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00000000
CMD:0x0000003f=0x00bf8010
CMD:0x0000003f=0x00000000
CMD:0x0000003c=0x00000000
CMD:0x0000003d=0x003f8000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x003f8000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x003f8000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x00000000
CMD:0x0000003d=0x00000000
CMD:0x0000003a=0x00000000
CMD:0x0000003b=0x003f441b
CMD:0x0000003b=0x003f248d
CMD:0x0000003b=0x00000000
CMD:0x0000003b=0x00bf248d
CMD:0x0000003b=0x003f441b
CMD:0x0000003b=0x00000000
CMD:0x0000003b=0x00000000
CMD:0x0000003b=0x00000000
CMD:0x0000003b=0x003f8000
CMD:0x0000003b=0x00000000
CMD:0x0000003b=0x00000000
CMD:0x0000003b=0x00c00000
CMD:0x00000012=0x00000197
CMD:0x00000010=0x00080000
CMD:0x00000001=0x0094f000
CMD:0x00000004=0x00030006 //←注目!!ちゃんと「Geコマンドの4番」だし、上で解説したとおり「6個!」
CMD:0x0000000f=0x00000000
CMD:0x0000000c=0x00000000
これを何も考えず、SEGADRIVEに突っ込んだら、(もちろんパッチはあてる)「2Dの回転スプライト」が出来る筈だよな理屈上。
(ちなみにこのデーターは暫定的に50度傾いてる。)
でも、きょーはねむいからおしまい。
ええと、「PSPSDK」は「単なる変換プログラム==ツール」として使用した。PSP実機で(別館のあれを簡略化した奴)実行させ。
「Geコマンドのログ」を吐かせた。それが上の奴。Geコマンドだから、8ビット+24ビットになってる。
あとは想像するとおり。
おやすみ(2006-05/10、01:48)
■で、ちとGeコマンドの解析。(上の奴)
ちなみにバッファが512になってるのはそういう風にバッファを別館のサンプルで取ったから。
-------- // Dither 4x4行列
,0xe2001d0c // 1,13, 0,12
,0xe300f3e2 // 15, 3,14, 2
,0xe4000c1d // 0,12, 1,13
,0xe500e2f3 // 14, 2,15, 3
,0x36001010 // Patch Subdivision// 0-7: S Subdivision==16 // 8-15: T Subdivision==16
,0x53000007 // 色 Material // (すべて有効)
001: Ambient
010: Diffuse
100: Specular
(注記:0x003f8000は、Ge-floatで1)
,0x5b3f8000 // Specular Power
,0x483f8000 // テクスチャー U Scale
,0x493f8000 // テクスチャー V Scale
,0xd2000001 // Frame バッファー ピクセル Storage モード//01: 16-ビット ABGR 5551
---------
,0x9c000000 // Frame バッファー Pointer
,0x9d000200 // Frame バッファー 幅// 0-15: バッファー 0x200==width 512ピクセル.
,0x9e088000 // 深度 バッファー Pointer
,0x9f000200 // 深度 バッファー 幅// 0-15: バッファー 0x200==width 512ピクセル.
,0x15000000 // Draw 領域 開始位置(0,0)
,0x16043ddf // Draw 領域 終了位置
0-9: X 終了位置 ((X + 幅)-1)
10-19: Y 終了位置 ((Y+高さ)-1)
,0x9e088000 // 深度 バッファー Pointer
,0x9f000200 // 深度 バッファー 幅// 0-15: バッファー 0x200==width 512ピクセル.
----------
,0x4c007100 // Viewport X Offset (つまり7.1かな?)
0-23: X Offset (12.4 固定少数点形式)
,0x4d007780 // Viewport Y Offset(つまり7.7かな?)
0-23: Y Offset (12.4 固定少数点形式)
,0x42437000 // Viewport 幅 X Scale 値 (GE 不動少数点形式)
,0x43c30900 // Viewport 高さ Scale 値 (GE 不動少数点形式)
,0x45450000 // Viewport X 位置 Offset 値 (GE 不動少数点形式)
,0x46450000 // Viewport Y 位置 Offset 値 (GE 不動少数点形式)
,0x44c70000 // 深度 Scale 値 (GE 不動少数点形式)
,0x4746fffe // 深度 位置 Offset 値 (GE 不動少数点形式)
,0xd6000000 // Near 深度 範囲 //0-15: 深度 値
,0xd700ffff // Far 深度 範囲 //0-15: 深度 値
,0xd4000000 // Scissor 領域 開始位置// 開始位置(X,Y)==(0,0);
,0xd5043ddf // Scissor 領域 終了位置// 0- 9: X 終了位置//10-19: Y 終了位置
,0xde000007 // 深度 Test Function //111: Pass ピクセル when depth is 多い or 等しい
,0x23000001 // 深度 Test 有効
,0x9b000001 // Front Face Culling Order //1: カウンター-clockwise primitives are visible
,0x50000001 // Shade モードl// 1: Smooth
,0x1d000001 // Backface Culling 有効
,0x1e000001 // テクスチャー Mapping 有効
,0x1c000001 // Clip Plane 有効
//□ sceGuFinish();
,0x0f000000 // レンダー完了
,0x0c000000 // 実行停止
-----------
ここからメインループ
for(;;)
{
-----------
,0x9c000000 // Frame バッファー Pointer
,0x9d000200 // Frame バッファー 幅// 0-15: バッファー 0x200==width 512ピクセル.
,0xd3000501
,0x1280011c// VTYPE: p--vvv-www-ffWWL LNNC CCTT
// 1 0001 1100
LL:10: 16-ビット 固定
CCC:111: 32-ビット ABGR-8888
TT:00: Not present in 頂点
,0x10080000 // BASE ベースアドレス レジスター
,0x0194f7a0 // VADDR 頂点 アドレス (BASE)
---------------
,0x04060002 // Ge04 Sprites 2Vertex(??)(ココはテクスチャ転送??)
,0xd3000000 // Clear Flags(すべて無効??)
0: Clear 有効
8-11: Clear フラグ (OR together)
001: Clear 色 バッファー
010: Clear ステンシル/アルファ バッファー
100: Clear 深度 バッファー
----------------
//□ この辺はGUの内部変数の(主に行列)計算なので、
GEコマンドにはならない。
----------------
//□ sceGuTexMode(GU_PSM_4444,0,0,0);
,0xc2000000 // テクスチャー モード
0: Swizzle 有効
8-15: ???<現在不明>
16-20: 最大 mipmap level
,0xc3000002 // テクスチャー ピクセル Storage モード
// 2: 16-ビット ABGR 4444
//ここは、 1: 16-ビット ABGR 5551に変えないとまずいかもしんない。(別館の奴は)バグ?正しいの?ワカラン。
,0xcb000000 // テクスチャー Flush
Invalidate テクスチャー キャッシュ on テクスチャー change
//さっぱりワカラン。このタイミングで転送???キャッシュのフラッシングかな?
//□ sceGuTexImage(0,64,64,64,texture);
,0xa0905f80 // [TBP0] テクスチャー バッファー Pointer 0// 0-23: 24 least significant ビットs of ポインター (see [TBW0])
,0xa8080040 // [TBW0] テクスチャー バッファー 幅 0
//64ピクセル 0-15: バッファー width in ピクセルs
//8ビット(char型?) 16-20: 4 most significant ビットs of ポインター (see [TBP0])
,0xb8000606// テクスチャー サイズ レベル 0(この「レベル」はミップマップレベル?)
0-7: 幅 = 2^TW
8-15: 高さ = 2^TH
// つまり64x64テクスチャ(そおいや別館のは64x64テクスチャ。320x240なら、512x256にしないとダメ?つまり9,8若しくは分割)
,0xcb000000 // テクスチャー Flush
Invalidate テクスチャー キャッシュ on テクスチャー change
//さっぱりワカラン。このタイミングで転送???キャッシュのフラッシングかな?
//□ sceGuTexFunc(GU_TFX_ADD,GU_TCC_RGB);
,0xc9000004 // TFUNC テクスチャー Function
0-2: テクスチャー Effect
000: Modulate
001: Decal
010: ブレンド
011: Replace
100: 加算(そういや別館のは加算だったな)
8: テクスチャー 色 の要素
0: テクスチャー アルファー is ignored(つまりなし)
1: テクスチャー アルファー is read
16: Fragment Double 有効
0: Fragment 色 is untouched(つまり無効)
1: Fragment 色 is doubled
//□ sceGuTexEnvColor(0xffff00);
,0xcaffff00 // テクスチャー 環境 色BGR(0xff,0xff,0x00)つまり水色。きっと別館のサンプルはそおなってる。知らんが。
//□ sceGuTexFilter(GU_LINEAR,GU_LINEAR);
,0xc6000101 // テクスチャー Filter
0- 2: Minifying filter(1?)
8-10: Magnifying filter
000: Nearest
001: 直線状(これだって?)
100: Nearest; ミップマップ Nearest
101: 直線状; ミップマップ Nearest
110: Nearest; ミップマップ 直線状
111: 直線状; ミップマップ 直線状
//□ sceGuTexScale(1.0f,1.0f);
(注記:0x003f8000は、Ge-floatで1)
,0x483f8000 // テクスチャー U Scale値 (GE 不動少数点形式)1==拡大しない。
,0x493f8000 // テクスチャー V Scale値 (GE 不動少数点形式)1==拡大しない。
//□ sceGuTexOffset(0.0f,0.0f);
,0x4a000000 // テクスチャー U Offset値 (GE 不動少数点形式)0==なし。
,0x4b000000 // テクスチャー V Offset値 (GE 不動少数点形式)0==なし。
//□ sceGuAmbientColor(0xffffffff);
,0x55ffffff // Ambient モードl 色BGR(0xff,0xff,0xff)つまり白色。きっと別館のサンプルはそおなってる。知らんが。
,0x580000ff // Ambient モードl アルファ// 0-7: アルファ の要素
// // draw cube
//□ sceGumDrawArray( // GUの内蔵バッファ(アレイ)に溜まってる奴を描画。
// GU_TRIANGLES,
// GU_TEXTURE_32BITF|/*32*/
// GU_COLOR_5551|/*8888*/
// GU_VERTEX_32BITF|
// GU_TRANSFORM_3D,
// 2*3,0,vertices);
,0x3e000000//Projection行列(選択)転送コマンド
で、4x4行列
,0x3f3edcfd,0x3f000000,0x3f000000,0x3f000000 // X,0,0,0
,0x3f000000,0x3f3f446f,0x3f000000,0x3f000000 // 0,X,0,0
,0x3f000000,0x3f000000,0x3fbf8020,0x3fbf8000 // 0,0,X,X
,0x3f000000,0x3f000000,0x3fbf8010,0x3f000000 // 0,0,X,0
,0x3c000000//View行列(選択)転送コマンド
で、3x4行列(ここは3x4行列)
,0x3d3f8000,0x3d000000,0x3d000000 // 1,0,0
,0x3d000000,0x3d3f8000,0x3d000000 // 0,1,0
,0x3d000000,0x3d000000,0x3d3f8000 // 0,0,1
,0x3d000000,0x3d000000,0x3d000000 // 0,0,0
(注記:0x003f8000は、Ge-floatで1)
,0x3a000000//World 行列 (選択)転送コマンド
で、3x4行列(ここは3x4行列)
,0x3b3f441b,0x3b3f248d,0x3b000000 // X,X,0
,0x3bbf248d,0x3b3f441b,0x3b000000 // X,X,0
,0x3b000000,0x3b000000,0x3b3f8000 // 0,0,1
,0x3b000000,0x3b000000,0x3bc00000 // 0,0,X
,0x12000197// VTYPE: p--vvv-www-ffWWL LNNC CCTT
// 1 1001 0111
TT:11: 32-ビット 不動少数点形式
CCC:101: 16-ビット ABGR-5551
LL:ge-float, 11: 32-ビット 不動少数点形式
,0x10080000 // BASE ベースアドレス レジスター
,0x0194f000 // VADDR 頂点 アドレス (BASE)
,0x04030006 // Ge04 Triangles 6Vertex
//□ sceGuFinish();
,0x0f000000 // FINISH レンダー完了
,0x0c000000 // END 実行停止
じゃおやすみ(2006-05/10、05:18)
更新(2006-05/10、13:33)
と、つらつら、Geコマンドを眺めて、なんか凄い無駄なよーな気がしてきた。
だって、「Zバッファ」はまずイランでしょ?初代プレステと同じ「Zソート」でいいよ。
(そもそも「ソート」する気もないんだから...)
もっと簡単なサンプル探して、部分的にやり直したほーがいいかも?