初學圖形編程,開始記錄
工作內容:通過學習某知名商業引擎,構建新遊戲引擎,對新引擎進行簡單測試。
札記:
1、移植代碼大部分時間都是很枯燥的,不用想只需要重複的做,重複的做。。。。, 最多要改的地方就是編碼規範,然後是在許多模塊沒有建立的基礎上對把移植好的模塊編譯連接,最重要的技巧就是註釋,許多設計沒有建立的模塊太多,只能留下空實現的函數,以後用到的時候再實現吧。
2、這次做完了Texture模塊,雖然還沒有做任何渲染相關的代碼,但是測試還是需要的,不然以後累加起來可能就忘記了。
2.1。測試流程:載入一個圖片到緩存,操作緩存(即像素),做出特定的模糊效果,再另保存爲文件,進行查看。(注:文件操作和DDS圖像文件讀取已經做完)
2.2。製作高斯模糊(累加像素求平均值):
輸入:像素數據指針,高斯模糊半徑(X和Y分量上各一個)
算法流程:1、遍歷每一個像素點
2、以這個像素點爲中心,根據高斯模糊半徑創建一個區域,此區域內的像素用來計算中心點像素的高斯模糊值。
3、遍歷這個區域的每一個像素,累加RGBA的各個分量值(我測試的圖片是32位的DDS文件)。
4、用各個分量除以累加的數量組合成一個像素(即高斯模糊後的像素點)。
注:
1、使用unsigned char儲存一個像素的分量,但累加的時候要使用更大存儲空間的類型比如unsigned int,否則會溢出。
2、這次操作的圖像是讀DDS文件,保存格式爲BMP,發現兩種格式文件的RGBA的通道存儲順序是不一致的,所以操作的時候要改爲正確的才能進行存儲。
3、BMP格式解析文件是從下到上進行倒置存儲的。
4、進行多次遍歷像素點的時候要保持遍歷的順序,否則容易出現貼圖倒置或翻轉的效果。
事例代碼:
//---------------------------------------------------------------------------
void FillPerPixelGaussBlur(yqg_IPixelData * pDest, DWORD originX, DWORD originY, BYTE * pSrc, DWORD radiusX, DWORD radiusY)
{
// 記錄共受多少個像素的影響
DWORD t_Num = 0;
// 獲得高斯模糊半徑內的像素區域
DWORD t_pixelLeft = originX > radiusX ? originX-radiusX : 0;
DWORD t_pixelTop = originY > radiusY ? originY-radiusY : 0;
DWORD t_pixelRight = (originX+radiusX) < pDest->GetWidth() ? originX+radiusX : pDest->GetWidth();
DWORD t_pixelBottom= (originY+radiusY) < pDest->GetHeight() ? originY+radiusY : pDest->GetHeight();
DWORD t_pPixels[4];
for(int t_d = 0; t_d < 4; ++t_d)
{
t_pPixels[t_d] = 0;
}
// 遍歷區域內的每個元素
for(DWORD t_dX = t_pixelLeft; t_dX < t_pixelRight; ++t_dX)
{
for(DWORD t_dY = t_pixelTop; t_dY < t_pixelBottom; ++t_dY)
{
// 計數
++t_Num;
// 將影響像素分值添加到高斯模糊像素上
BYTE * t_pOrigin = (BYTE*)&(((DWORD*)pSrc)[t_dX + t_dY * pDest->GetWidth()]);
t_pPixels[0] = t_pPixels[0] + *(t_pOrigin+0); //Red
t_pPixels[1] = t_pPixels[1] + *(t_pOrigin+1); //Green
t_pPixels[2] = t_pPixels[2] + *(t_pOrigin+2); //Blue
t_pPixels[3] = t_pPixels[3] + *(t_pOrigin+3); //Alpha
}
}
// 取累加後的像素平均值,即高斯模糊
if(t_Num != 0)
{
BYTE * t_pDestPixel = pDest->operator()(originX, originY);
*(t_pDestPixel+0) = (BYTE)(t_pPixels[0] / t_Num);//Blue
*(t_pDestPixel+1) = (BYTE)(t_pPixels[1] / t_Num);//Green
*(t_pDestPixel+2) = (BYTE)(t_pPixels[2] / t_Num);//Red
*(t_pDestPixel+3) = (BYTE)(t_pPixels[3] / t_Num);
}
}
//---------------------------------------------------------------------------
2.3。製作徑向縮放模糊(針對任意一點,循環數量,根據數量值求出單位縮放,確定當前數量下的像素點,進行累加,然後求平均值):
輸入:像素數據指針,徑向縮放中心點(指定的像素位置),數量
算法流程:1、遍歷每一個像素點
2、循環數量,根據每個數量下的單位縮放值和中心點累加像素值。
3、求平均值,即該像素點的徑向縮放模糊值。
注:做縮放值和像素點的計算時要確定類型,如unsigned int相減是不會的得到負數的,細節很重要。
事例代碼:
//---------------------------------------------------------------------------
void FillPerPixelRadialBlur(yqg_IPixelData * pDest, BYTE * pSrc, DWORD dCenterX, DWORD dCenterY, DWORD dNum, DWORD dCurrentPosX, DWORD dCurrentPosY)
{
// 縮放值
float t_fScale;
// 根據縮放值和中心點計算後用來累加像素點的位置
DWORD t_caluPixelPosX;
DWORD t_caluPixelPosY;
// 臨時存儲累加的計算結果,並初始化
DWORD t_pPixels[4];
for(int t_d = 0; t_d < 4; ++t_d)
{
t_pPixels[t_d] = 0;
}
// 遍歷數量
for(DWORD t_dIndex = 0; t_dIndex < dNum; ++t_dIndex)
{
// 計算縮放值
t_fScale = 1.0f + (-(dNum*1.0f/pDest->GetWidth()) * t_dIndex) / (dNum - 1);
// 計算累加像素點的位置
t_caluPixelPosX = (DWORD)(((int)dCurrentPosX - (int)dCenterX) * t_fScale + dCenterX);
t_caluPixelPosY = (DWORD)(((int)dCurrentPosY - (int)dCenterY) * t_fScale + dCenterY);
t_caluPixelPosX = (t_caluPixelPosX > (pDest->GetWidth() - 1)) ? (pDest->GetWidth() - 1) : t_caluPixelPosX;
t_caluPixelPosY = (t_caluPixelPosY > (pDest->GetHeight() - 1)) ? (pDest->GetHeight() - 1) : t_caluPixelPosY;
// 將影響像素分值添加到徑向縮放模糊像素上
BYTE * t_pOrigin = (BYTE*)&(((DWORD*)pSrc)[t_caluPixelPosX + t_caluPixelPosY * pDest->GetWidth()]);
t_pPixels[0] = t_pPixels[0] + *(t_pOrigin+0); //Red
t_pPixels[1] = t_pPixels[1] + *(t_pOrigin+1); //Green
t_pPixels[2] = t_pPixels[2] + *(t_pOrigin+2); //Blue
t_pPixels[3] = t_pPixels[3] + *(t_pOrigin+3); //Alpha
}
// 取累加後的像素平均值,即高斯模糊
BYTE * t_pDestPixel = pDest->operator()(dCurrentPosX, dCurrentPosY);
*(t_pDestPixel+0) = (BYTE)(t_pPixels[0] / dNum);//Blue
*(t_pDestPixel+1) = (BYTE)(t_pPixels[1] / dNum);//Green
*(t_pDestPixel+2) = (BYTE)(t_pPixels[2] / dNum);//Red
*(t_pDestPixel+3) = (BYTE)(t_pPixels[3] / dNum);
}
//---------------------------------------------------------------------------
以下是原圖和效果圖