黃爸爸狗園

本園只有sanitizer,沒有狗籠

0%

GBA圖形處理邏輯模擬 - Affine background

cover

GBA除了能夠依照Map memory的排列,由左至右、由上到下的產生畫面外,還能夠使用矩陣運算,產生縮放&旋轉過後的背景圖案,本文將會描述其原理,並且這部分的知識將與Affine object共通

仿射矩陣

  • 根據維基百科的對仿射變換的定義: ::: success 仿射轉換(Affine transformation),又稱仿射映射,是指在幾何中,對一個向量空間進行一次線性轉換並接上一個平移,轉換為另一個向量空間。 ::: 言下之意,對於GBA的2D顯示來說,我們會需要一個矩陣來幫我們做這個轉換,這個矩陣會長得像是這樣,讓我們假設我們要逆時鐘旋轉然後X軸縮放倍,Y軸縮放倍,最後平移(x, y),讓我們先來討論線性轉換的部分(旋轉與縮放)

    這個矩陣其實就是由一個旋轉矩陣跟一個縮放矩陣組合而成

忘記怎麼計算矩陣了嗎? 請參考Matrix calculation rules

逆矩陣

  • 酷,所以GBA的圖形硬體就是用上面的方式來實現旋轉縮放的囉?
    • 很遺憾並不是,正確來說是完全相反
      • 字面上意思的相反
    • 我們剛剛所提及的方式,是將VRAM中的tile旋轉並縮放後,投射到螢幕上,但你仔細想想就會發現不太可行
      • 我們可以思考一個問題,你放大之後,8*8的tile變成16*16,中間的插值是不是需要另外處理?
    • 所以GBA的作法是將螢幕座標乘上仿射矩陣的逆矩陣,反著映射回VRAM,這下就保證每一個pixel都會有屬於它的data了
      • 可想而知的,只要一轉下去,品質一定糟糕到受不了,不過GBA嘛......你也不能要求太多
  • 因為上面的矩陣沒有平移(平移不是線性轉換),所以可逆

實際上的渲染流程

  • 我們的渲染流程並不難,先讓我們來看一下幾個重要的register
    • 由於能支援仿射功能的圖層有兩個(BG2、BG3),所以以下的register都會是兩組 1.BGX_L, BGX_H, BGY_L, BGY_H
      • 用來定義texture space的起始點(Starting point),因為格式不是integer而是fixed-point,因此長度會比較長,需要分兩塊來存 2.BGX_PA, BGX_PD, BGX_PC, BGX_PD
      • 用來描述我們的仿設反矩陣

Starting point是Q8格式的fixed-point,即[0:7]是小數部分,[8:26]是整數部分,[27]是sign bit

PA、PB、PC、PD是Q8格式的fixed-point,即[0:7]是小數部分,[8:14]是整數部分,[15]是sign bit

  • 基本上運算規則如下
    • BG_X與BG_Y就是仿射矩陣的平移部份了
    • 就是這麼的樸實無華 且枯燥,用圖來看會像是這樣
    • 我們之前有提到過在Affine BG下,map data都是1 byte,在這個狀態下只要把 除8,就可以得到map data的address了
    • 順帶附上fixed-point乘法的程式碼
      1
      2
      3
      4
      5
      6
      7
      8
      int q_mul(int32_t a, int16_t b) {
      int32_t temp;

      temp = (int32_t)a * (int32_t)b; // result type is operand's type
      // Rounding; mid values are rounded up
      temp += (temp >> 7) & 1;
      return temp >> 8;
      }