計算機圖形學-紋理對映
阿新 • • 發佈:2019-01-26
先放個圖
利用MFC框架實現紋理對映
紋理對映主要包括紋理定義、紋理控制、紋理對映方式、紋理座標和紋理物件等
1 首先建立點陣圖類
class CBMPLoader { public: CBMPLoader(); ~CBMPLoader(); bool LoadBitmap(char *filename); //裝載一個bmp檔案 void FreeImage(); //釋放影象資料 unsigned int ID; //生成紋理的ID號 int imageWidth; //影象寬度 int imageHeight; //影象高度 unsigned char *image; //指向影象資料的指標 };
2 點陣圖類的實現
CBMPLoader::CBMPLoader() { /** 初始化成員值為0 */ image = 0; imageWidth = 0; imageHeight = 0; } CBMPLoader::~CBMPLoader() { FreeImage(); /**< 釋放影象資料佔據的記憶體 */ } /** 裝載一個位圖檔案 */ bool CBMPLoader::LoadBitmap(char *file) { FILE *pFile = 0; //檔案指標; /*建立點陣圖檔案資訊和點陣圖檔案頭結構*/ BITMAPINFOHEADER bitmapInfoHeader; BITMAPFILEHEADER header; unsigned char textureColors = 0;/**< 用於將影象顏色從BGR變換到RGB */ /** 開啟檔案,並檢查錯誤 */ pFile = fopen(file, "rb"); if (pFile == 0) return false; /** 讀入點陣圖檔案頭資訊 */ fread(&header, sizeof(BITMAPFILEHEADER), 1, pFile); /** 檢查該檔案是否為點陣圖檔案 */ if (header.bfType != BITMAP_ID) { fclose(pFile); /**< 若不是點陣圖檔案,則關閉檔案並返回 */ return false; } /** 讀入點陣圖檔案資訊 */ fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); /** 儲存影象的寬度和高度 */ imageWidth = bitmapInfoHeader.biWidth; imageHeight = bitmapInfoHeader.biHeight; /** 確保讀取資料的大小 */ if (bitmapInfoHeader.biSizeImage == 0) bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth * bitmapInfoHeader.biHeight * 3; /** 將指標移到資料開始位置 */ fseek(pFile, header.bfOffBits, SEEK_SET); /** 分配記憶體 */ image = new unsigned char[bitmapInfoHeader.biSizeImage]; /** 檢查記憶體分配是否成功 */ if (!image) /**< 若分配記憶體失敗則返回 */ { delete[] image; fclose(pFile); return false; } /** 讀取影象資料 */ fread(image, 1, bitmapInfoHeader.biSizeImage, pFile); /** 將影象顏色資料格式進行交換,由BGR轉換為RGB */ for (int index = 0; index < (int)bitmapInfoHeader.biSizeImage; index += 3) { textureColors = image[index]; image[index] = image[index + 2]; image[index + 2] = textureColors; } fclose(pFile); /**< 關閉檔案 */ return true; /**< 成功返回 */ } /** 釋放記憶體 */ void CBMPLoader::FreeImage() { /** 釋放分配的記憶體 */ if (image) { delete[] image; image = 0; } }
3 編寫測試類
extern GLfloat LightAmbient[]; extern GLfloat LightDiffuse[]; extern GLfloat LightSpecular[]; /**< 鏡面光引數 */ extern GLfloat LightPosition[]; /**< 光源位置 */ class Example{ public: bool Init(int cx ,int cy){ /** 使用者自定義的初始化過程 */ glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //ResizeDraw(true); /**< 改變OpenGL視窗大小,直接呼叫子類的函式 */ glViewport(0, 0, cx, cy); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)cx / (GLfloat)cy, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_TEXTURE_2D); /**< 啟用紋理對映 */ if (!Texture.LoadBitmap("image.bmp")) /**< 載入點陣圖檔案 */ { MessageBox(NULL, TEXT("裝載點陣圖檔案失敗!"), TEXT("錯誤"), MB_OK); /**< 如果載入失敗則彈出對話方塊 */ return false; } glGenTextures(1, &Texture.ID); /**< 生成一個紋理物件名稱 */ glBindTexture(GL_TEXTURE_2D, Texture.ID); /**< 建立紋理物件 */ /** 控制濾波 */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); /** 建立紋理 */ gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, Texture.imageWidth, Texture.imageHeight, GL_RGB, GL_UNSIGNED_BYTE, Texture.image); /** 設定光源的屬性值 */ glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); /**< 設定環境光 */ glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); /**< 設定漫射光 */ glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular); /**< 設定漫射光 */ glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); /**< 設定光源位置 */ /** 啟用光照和光源 */ glEnable(GL_LIGHTING); glEnable(GL_LIGHT1); return true; /**< 成功返回 */ } /**< 執行所有的初始化工作,如果成功函式返回true */ void Uninit(){ Texture.FreeImage(); /** 釋放紋理影象佔用的記憶體 */ glDeleteTextures(1, &Texture.ID); /**< 刪除紋理物件 */ } /**< 執行所有的解除安裝工作 */ void Draw(){ /** 使用者自定義的繪製過程 */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /**< 清楚快取 */ glLoadIdentity(); /** 繪製過程 */ glTranslatef(0.0f, 0.0f, -7.0f); glRotatef(rot, 1.0f, 1.0f, 0.0f); /** 選擇紋理 */ glBindTexture(GL_TEXTURE_2D, Texture.ID); /** 開始繪製四邊形 */ glBegin(GL_QUADS); /// 前側面 glNormal3f(0.0f, 0.0f, 1.0f); /**< 指定法線指向觀察者 */ glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); /// 後側面 glNormal3f(0.0f, 0.0f, -1.0f); /**< 指定法線背向觀察者 */ glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); /// 頂面 glNormal3f(0.0f, 1.0f, 0.0f); /**< 指定法線向上 */ glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); /// 底面 glNormal3f(0.0f, -1.0f, 0.0f); /**< 指定法線朝下 */ glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); /// 右側面 glNormal3f(1.0f, 0.0f, 0.0f); /**< 指定法線朝右 */ glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); /// 左側面 glNormal3f(-1.0f, 0.0f, 0.0f); /**< 指定法線朝左 */ glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); /**< 四邊形繪製結束 */ glFlush(); /**< 強制執行所有的OpenGL命令 */ } /** 使用者自定義的程式變數 */ CBMPLoader Texture; /**< 點陣圖載入類的物件 */ float rot = 1; /**< 用於旋轉物體 */ };
4.
實現繪圖
Example test;
GLfloat LightAmbient[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; /**< 環境光引數 */
GLfloat LightDiffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /**< 漫射光引數 */
GLfloat LightSpecular[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /**< 鏡面光引數 */
GLfloat LightPosition[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; /**< 光源位置 */
void CTextureView::OnDraw(CDC* /*pDC*/)
{
CTextureDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處為本機資料新增繪製程式碼
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 繪製場景
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
DrawPicture();
glPopMatrix();
// 交換緩衝區
SwapBuffers(wglGetCurrentDC());
}
void CTextureView::DrawPicture()
{
CRect rc; GetWindowRect(&rc);
int cx = rc.Width(); int cy = rc.Height();
test.Init(cx,cy);
test.Draw();
SetTimer(1, 1, NULL);
}
void CTextureView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
if (nIDEvent == 1){
test.rot += 1;
InvalidateRect(NULL, FALSE);
SetTimer(1, 1, NULL);
}
CView::OnTimer(nIDEvent);
}