2020年2月24日 星期一

關於 C++ 的遞增( ++ )與遞減( -- )運算

關於 C++ 的遞增( ++ )與遞減( -- )運算

前言

  C++ 的遞增( ++ )與遞減( -- )運算很常會在面試的考題裡,雖然我一直覺得實務上很難碰到類似的問題,但就是很容易會考,重要的是我答錯了,所以把學習的過程做個紀錄。

內容

  遞增( ++ )與遞減( -- )有個讓人容易疑惑的用法如下
int a=0;
int b=0;
printf("%d\n",++a);//1
printf("%d\n",b++);//0
printf("%d\n",a);//1
printf("%d\n",b);//1

疑惑的地方是把運算寫在前方與後方的差異,可以看到 ++a 的結果是 1 ,但 b++ 卻是 0 ,a 與 b 在運算後都是 1 ,寫在前方可以理解為"先遞增再給值",而寫在後方可以理解為"先給值再遞增",觀念其實就是這麼簡單,但我在實務上沒碰過有人會利用這個語言特性來寫程式,但這個語言特性很容易成為面試的考題,而且我還答錯,馬上就被人質疑對 C++ 不熟,真是慘痛的教訓。這個業界非常奇怪,實務不常用的拿來考,並且把當它當重要的標準,也只能無奈地記起來了。

2020年2月17日 星期一

DepthMap 的編碼

DepthMap 的編碼

前言

  最近要實現 DepthMap ,但在手機平台實現發生了問題,在 GLES2 可能會不支援 Depth texture ,如果不支援就直接放棄嗎?有個方法可以解決,就是將深度值"編碼"後解到 RGBA8 的 Texture ,這個方法的實作又些麻煩,在此做個紀錄。

內容

  在 DepthMap 的實現裡需要把深度值寫到 Texture 或 DepthBuffer 裡,但不幸的是 GLES2 並不保證支援 Depth texture ,更別說是 R32 格式的 Texture,有替代方案嗎?可以參考 WebGL Tutorial: Directional Shadow Mapping without extensions 裡的作法,將深度值"編碼"寫到 RGBA8 的 Texture ,在取值的時候要"解碼"後取得深度值。

  該如何從 Float 的深度值"編碼"到 RGBA8 的數值,請看以下
vec4 encodeFloat (float depth) {
  const vec4 bitShift = vec4(
    256 * 256 * 256,
    256 * 256,
    256,
    1.0
  );
  const vec4 bitMask = vec4(
    0,
    1.0 / 256.0,
    1.0 / 256.0,
    1.0 / 256.0
  );
  vec4 comp = fract(depth * bitShift);
  comp -= comp.xxyz * bitMask;
  return comp;
}

這是將深度值編碼成4個 Float 的 Function ,編碼後透過 Fragment shader 直接輸出到 RGBA8 的 Texture 上,接著在取得 DepthMap 的數值時要經過解碼,請看以下
float decodeFloat (vec4 color) {
  const vec4 bitShift = vec4(
    1.0 / (256.0 * 256.0 * 256.0),
    1.0 / (256.0 * 256.0),
    1.0 / 256.0,
    1
  );
  return dot(color, bitShift);
}

解碼後就可以取得原先的深度值。

參考資料

WebGL Tutorial: Directional Shadow Mapping without extensions

2020年2月10日 星期一

把螢幕畫面錄成 GIF 檔的軟體

把螢幕畫面錄成 GIF 檔的軟體

前言

  Windows 的截圖功能很好用,但有的時候需要能動的圖像,而表達能動的圖片看來就只有 GIF 檔能勝認了,於是上網找到 [ www.screentogif.com ] ScreenToGif  這個軟體,用起來相當簡單,在此把學習的過程做個紀錄。

內容

  先到 [ www.screentogif.com ] ScreenToGif  下載軟體,如下圖
下載 ScreenToGif

下載完後解壓,再開啟軟體,可以看到下圖
開啟 ScreenToGif

開啟後按下螢幕錄影,可以看到以下
錄影視窗

錄影視窗的中間是透明的,可以在下方調整錄影視窗的大小,再按下錄影後開始錄影,錄到想要的時間按下停止,可以得到以下
編輯畫面

到了編輯畫面後在左上按下"檔案"的按鍵後,再按下"另存新檔"後,可以得到以下
存檔介面

在存檔介面設定存檔路徑與檔明後按下"儲存"就可以取得結果。

參考資料

[ www.screentogif.com ] ScreenToGif

2020年2月9日 星期日

RX570 驅動程式 Bug

RX570 驅動程式 Bug
內容
  在 Ubuntu 安裝 RX570 驅動程式後,晶片名稱會顯示成 RX470,如下圖
顯示錯誤的晶片名稱


這應該就只是單純的名稱錯誤。

2020年2月3日 星期一

關於逆矩陣的運算

關於逆矩陣的運算

前言

  逆矩陣的計算相當繁瑣,很難記在腦中或用推導的方式取得,所以每次需要時都要重新 google 一次,這篇做個紀錄,方便以後查詢。

內容

  詳細的計算式可以在 [ stackoverflow.com ] inverting a 4x4 matrix 裡找到,這裡複製一下結果如下
bool gluInvertMatrix(const double m[16], double invOut[16])
{
    double inv[16], det;
    int i;

    inv[0] = m[5]  * m[10] * m[15] - 
             m[5]  * m[11] * m[14] - 
             m[9]  * m[6]  * m[15] + 
             m[9]  * m[7]  * m[14] +
             m[13] * m[6]  * m[11] - 
             m[13] * m[7]  * m[10];

    inv[4] = -m[4]  * m[10] * m[15] + 
              m[4]  * m[11] * m[14] + 
              m[8]  * m[6]  * m[15] - 
              m[8]  * m[7]  * m[14] - 
              m[12] * m[6]  * m[11] + 
              m[12] * m[7]  * m[10];

    inv[8] = m[4]  * m[9] * m[15] - 
             m[4]  * m[11] * m[13] - 
             m[8]  * m[5] * m[15] + 
             m[8]  * m[7] * m[13] + 
             m[12] * m[5] * m[11] - 
             m[12] * m[7] * m[9];

    inv[12] = -m[4]  * m[9] * m[14] + 
               m[4]  * m[10] * m[13] +
               m[8]  * m[5] * m[14] - 
               m[8]  * m[6] * m[13] - 
               m[12] * m[5] * m[10] + 
               m[12] * m[6] * m[9];

    inv[1] = -m[1]  * m[10] * m[15] + 
              m[1]  * m[11] * m[14] + 
              m[9]  * m[2] * m[15] - 
              m[9]  * m[3] * m[14] - 
              m[13] * m[2] * m[11] + 
              m[13] * m[3] * m[10];

    inv[5] = m[0]  * m[10] * m[15] - 
             m[0]  * m[11] * m[14] - 
             m[8]  * m[2] * m[15] + 
             m[8]  * m[3] * m[14] + 
             m[12] * m[2] * m[11] - 
             m[12] * m[3] * m[10];

    inv[9] = -m[0]  * m[9] * m[15] + 
              m[0]  * m[11] * m[13] + 
              m[8]  * m[1] * m[15] - 
              m[8]  * m[3] * m[13] - 
              m[12] * m[1] * m[11] + 
              m[12] * m[3] * m[9];

    inv[13] = m[0]  * m[9] * m[14] - 
              m[0]  * m[10] * m[13] - 
              m[8]  * m[1] * m[14] + 
              m[8]  * m[2] * m[13] + 
              m[12] * m[1] * m[10] - 
              m[12] * m[2] * m[9];

    inv[2] = m[1]  * m[6] * m[15] - 
             m[1]  * m[7] * m[14] - 
             m[5]  * m[2] * m[15] + 
             m[5]  * m[3] * m[14] + 
             m[13] * m[2] * m[7] - 
             m[13] * m[3] * m[6];

    inv[6] = -m[0]  * m[6] * m[15] + 
              m[0]  * m[7] * m[14] + 
              m[4]  * m[2] * m[15] - 
              m[4]  * m[3] * m[14] - 
              m[12] * m[2] * m[7] + 
              m[12] * m[3] * m[6];

    inv[10] = m[0]  * m[5] * m[15] - 
              m[0]  * m[7] * m[13] - 
              m[4]  * m[1] * m[15] + 
              m[4]  * m[3] * m[13] + 
              m[12] * m[1] * m[7] - 
              m[12] * m[3] * m[5];

    inv[14] = -m[0]  * m[5] * m[14] + 
               m[0]  * m[6] * m[13] + 
               m[4]  * m[1] * m[14] - 
               m[4]  * m[2] * m[13] - 
               m[12] * m[1] * m[6] + 
               m[12] * m[2] * m[5];

    inv[3] = -m[1] * m[6] * m[11] + 
              m[1] * m[7] * m[10] + 
              m[5] * m[2] * m[11] - 
              m[5] * m[3] * m[10] - 
              m[9] * m[2] * m[7] + 
              m[9] * m[3] * m[6];

    inv[7] = m[0] * m[6] * m[11] - 
             m[0] * m[7] * m[10] - 
             m[4] * m[2] * m[11] + 
             m[4] * m[3] * m[10] + 
             m[8] * m[2] * m[7] - 
             m[8] * m[3] * m[6];

    inv[11] = -m[0] * m[5] * m[11] + 
               m[0] * m[7] * m[9] + 
               m[4] * m[1] * m[11] - 
               m[4] * m[3] * m[9] - 
               m[8] * m[1] * m[7] + 
               m[8] * m[3] * m[5];

    inv[15] = m[0] * m[5] * m[10] - 
              m[0] * m[6] * m[9] - 
              m[4] * m[1] * m[10] + 
              m[4] * m[2] * m[9] + 
              m[8] * m[1] * m[6] - 
              m[8] * m[2] * m[5];

    det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];

    if (det == 0)
        return false;

    det = 1.0 / det;

    for (i = 0; i < 16; i++)
        invOut[i] = inv[i] * det;

    return true;
}

如果需要推導的過程與驗算的話,可以在 [ ncalculators.com ] nxn Inverse Matrix Calculator 。

參考資料

[ stackoverflow.com ] inverting a 4x4 matrix
[ ncalculators.com ] nxn Inverse Matrix Calculator