プログラミング演習3 李 亜民クラス 第2回 ラスタライズ
今回の内容 概念説明 ラスタライズ scan/span 作業 クラスの穴埋め 課題について
概念説明 ラスタライズ scan/span
3Dグラフィックスパイプライン 本日は⑥について解説 3Dモデル構築 :第3回 モデル変換 :第1回 バーテックス処理 :第4回 モデル変換 :第1回 バーテックス処理 :第4回 ビューポート変換 :第1回 バックフェースカリング :第3回 ラスタライズ :第2回 ピクセルシェーディング :第4回 Zバッファ の適用 :第3回
ラスタライズ ポリゴン(ベクトル集合)→ピクセル集合の変換を行う 各ピクセルに座標、色、材質等のパラメータを割り当て、ピク セルシェーダに渡す この講義では、ポリゴンは3つの頂点で構成されるものとする ラスタライズは、各ポリゴンについて処理を行う
ラスタライズの流れ(1)データ取得 ラスタライザに頂点データが渡される
ラスタライズの流れ(2)バッファ初期化 右/左端バッファを用意し、それぞれを大きい/小さい値で初期化 左をInteger.MAX_VALUE、右をMIN等(∞である必要は無い)
ラスタライズの流れ(3)Scan(1辺目) y方向に補間してバッファに格納 右端はバッファ値より大きいこと、左端は小さいことを条件に上書き
ラスタライズの流れ(4)Scan( 2辺目) 書き込み条件を考慮しつつ同様に繰り返し
ラスタライズの流れ(5)Scan( 3辺目) 直線の描画と異なり、単純にy軸について補間すれば良い x座標は飛び飛びになりうる
ラスタライズの流れ(5)Span LBuffからRBuffまでx軸方向に補間 補間されて得られたピクセルをピクセルシェーダに送信 本日は、ここで得られた座標をそのまま単色で塗りつぶす
Scan:エッジ方向補間 指定された辺について保管し、左右バッファに格納 擬似コード通りである必要はない。各自工夫を! Scan(v1, v2, LBuff[], RBuff[]) // 繰り返し方向確認 if (v1.y > v2.y) swap(v1, v2) // 水平なら描画しない if (v1.y == v2.y) return // 補間 for y = v1.y to v2.y Pixel p = lerp(…) if (…) LBuff[p.y] = p if (…) RBuff[p.y] = p
Span:x軸方向補間 左右にバッファを用意し、各エッジ(辺)ごとに補間 Span(LBuff[], RBuff[]) // 補間 for y = 0 to Screen Height // 面が存在するか確認し、無ければスキップ if RBuff[y].x <= LBuff[y].x continue for x = Lbuff[y].x to Rbuff[y].x Pixel p = lerp(…); pを塗りつぶし
ラスタライズに関する注意 左右バッファは面ごとに初期化し直す必要がある 上書きの条件や初期化する値など、左右のバッファで処 理が異なる部分をよく確認すること for each face バッファ初期化 Scan(A, B) Scan(B, C) Scan(C, A) Span(LBuff, RBuff)
作業 クラスの穴埋め
Vertexクラス(未完成) メンバ変数 コンストラクタ メソッド Vector v : 変換後座標 Vector ov : 変換前座標 変換前x,y,z指定 (任意に追加して下さい) メソッド Pixel lerp(…) 線形補間(未完成) Vector.lerp(…)同様、x,y,zそれぞれについて補間すれば良い 補間して以後、変換前座標は不要なので、返り値はPixelに
Faceクラス メンバ変数 Vertex A,B,C (頂点) コンストラクタ Vertex3つで指定 メソッド 特になし(追加は任意で)
Pixelクラス(未完成) メンバ変数 コンストラクタ メソッド int x, y, z : 座標 double型x, y, z指定(Math.roundでint型に) メソッド Pixel lerp(…) 線形補間(未完成) Vertex.lerp(…)同様
第2回課題 1. 任意の三角形を作成し、単色で塗りつぶして下さい 2. [発展] ダブルバッファリングを実装して下さい。 クラス:lec02に記述 initに初期化処理を記述 render(), drawFace(),scan(),span()の穴埋め その他、任意にメソッドを追加(setTriangle()等) 2. [発展] ダブルバッファリングを実装して下さい。 Canvasクラスを改変 バッファを用意し、drawPointではバッファに書き込み 書き込み完了後、drawImage(…)でバッファを表示 詳しい方法については、各自で調べる等してください
ダブルバッファリング(Canvasを改変) // インスタンス変数宣言 Image buf; Graphics bufG; public void init (){ … // バッファの初期化処理を追加 buf = createImage(700,700); bufG = buf.getGraphics(); } public void paint (Graphics g){ // バッファをクリア bufG.clearRect(0,0,700,700); // レンダリング render(); // バッファから一気に描画 g.drawImage(buf,0,0, this); } public void drawPoint (…){ // バッファに描画するように変更 bufG.setColor(c); bufG.drawLine(x,y,x,y)
課題の実行例