Masking Texture in OpenGL using Class CImage
source link: https://www.codeproject.com/Articles/1157044/Masking-Texture-in-OpenGL-using-Class-CImage
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Introduction
In my previous article, Image Mapping in OpenGL Using Class CImage, I demonstrated some useful texture handling techology by just calling the name of the image file for texture mapping without a lot of stages with the conditions implementation required. The straight follow-up should be the image masking application provided also arranged as just calling the name of the image bitmap file.
Background
The procedure of masking texture implementation in OpenGL just calling the name of the image bitmap file has been developed with the application of the class CImage
. The demo project MaskTexture
has been derived from my previous article project ImgTexture
derived from the standard MFC Cube Sample project renamed with the CodeProject ProjRename program.
Using the Code
The global procedure LoadMaskTexture(LPCTSTR fName)
and related procedure MakeBWMask(CImage * pImg, CDC *pDC, int w, int h, COLORREF eColor, int BPP)
have been added to the GlobGLTexture.cpp file from the previous article project ImgTexture
. For using the technology provided, you may insert the GlobGLTexture.cpp file into your own project with the menu PROJECT->Add Existing Item... command.
The procedure for masking texture loading:
DWORD LoadMaskTexture(LPCTSTR fName) //Load Mask texture from Bitmap Image file { CImage img; HRESULT hResult = img.Load(fName); //Standard procedure of CImage loading if (FAILED(hResult)) { _TCHAR fmt[1028]; _stprintf_s((_TCHAR *)fmt, hResult, _T("Error %d\n%s\nin file:\n%s"), _com_error(hResult).ErrorMessage(), fName); MessageBox(NULL, fmt, _T("Error:"), MB_OK | MB_ICONERROR); return FALSE; }//if(FAILED(hResult)) if (img.GetBPP() != 24) //if Bitmap format not compatible with //GL_BGR_EXT { CImage tmg; tmg.Create(img.GetWidth(), img.GetHeight(), 24); //Create CImage compatible //with GL_BGR_EXT img.BitBlt(tmg.GetDC(), CPoint(0, 0)); //Copy Original Image to //the environment created } CImage * pSmg = new CImage; CDC * tDC = CDC::FromHandle(img.GetDC()); //Temporarily graphic context //Create Black & White mask from original image: MakeBWMask(pSmg, tDC, img.GetWidth(), img.GetHeight(), tDC->GetPixel(0, 0), img.GetBPP()); CBitmap * pBmw = GetImgBitmap(pSmg); //Bitmap of the //Black & White mask if (pBmw == NULL) return FALSE; BITMAP BMPw; pBmw->GetBitmap(&BMPw); GLuint nBw = LoadGLTexture(&BMPw); //Create texture of the //Black & White mask CDC * pDC = new CDC; //Temporarily graphic context pDC->CreateCompatibleDC(CDC::FromHandle(img.GetDC())); CBitmap bmt; bmt.CreateCompatibleBitmap(CDC::FromHandle(img.GetDC()), img.GetWidth(), img.GetHeight()); CBitmap * pBm = pDC->SelectObject(&bmt); //Copy Black & White mask into Temporarily graphic context: pDC->BitBlt(0, 0, img.GetWidth(), img.GetHeight(), CDC::FromHandle(pSmg->GetDC()), 0, 0, SRCCOPY); //Invert colours in Copy Temporarily graphic context mask int //Temporarily graphic context: pDC->BitBlt(0, 0, img.GetWidth(), img.GetHeight(), NULL, 0, 0, DSTINVERT); //Copy Temporarily graphic context into original image into //making background color Black: CDC::FromHandle(img.GetDC())->BitBlt(0, 0, img.GetWidth(), img.GetHeight(), pDC, 0, 0, SRCAND); pDC->SelectObject(pBm); bmt.DeleteObject(); pDC->DeleteDC(); delete pDC; //Remove Temporarily graphic context CBitmap * pBmi = GetImgBitmap(&img); BITMAP BMPi; pBmi->GetBitmap(&BMPi); delete pBmw; //Clear all Temoparily delete pSmg; pSmg = NULL; GLuint nImg = LoadGLTexture(&BMPi); //Create texture of the mask //with Black background delete pBmi; return MAKELONG(nImg, nBw); //return HIWORD with color texture name //and LOWORD with Black & White texture name }
The scheme masking texture has been provided in the table below:
Original masking image Bitmap format and one-ton background color; Top Left pixel GetPixel(0,0) must be of background color | Original Background Image; may be of any format | |||
Black-white masking image provided with MakeBWMask procedure | Clear to black the masking space 1 1! 1! in the Original Bakground Image | |||
Change background to black with the Black-white masking image inverted: | Final Masked Image is a result of composition colour mask with the black background to the original background texture with the black space for masking |
The left column of the table above demonstrates the LoadMaskTexture
steps of creation two masking textures:
- Black-white masking image provided with MakeBWMask procedure
- Colour masking image with the black background with the Black-white masking the image inverted
The procedure for Black-white masking image creating (change all the background pixels to white, others to black):
void MakeBWMask(CImage * pImg, CDC *pDC, int w, int h, COLORREF eColor, int BPP) { pImg->Create(w, h, BPP); CDC * tDC = CDC::FromHandle(pImg->GetDC()); for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) { COLORREF rgb = pDC->GetPixel(i, j); //get pixel colour if (rgb == eColor) tDC->SetPixel(i, j, RGB(255, 255, 255)); //if the colour is a //background colour //set pixel white; else tDC->SetPixel(i, j, RGB(0, 0, 0)); //if the colour is not //a background //colour, set pixel black; } }
The variables inserted:
int m_texNum; //Current order number of the name of the texture int m_maskNum; //Current order number of the name of the mask texture CWordArray m_globTexture; //Array of the textures' names available CDWordArray m_globMask; //Array of the bitmap mask textures' names available enum VIEW_TYPE { VIEW_DEFAULT, //Original Cube Sample View VIEW_TEXTURE, //Texture View VIEW MASK, //Masking View };
The original CImgTextureView::Init()
procedure with the procedures related remains unchanged; in CImgTextureView::OnCreate
procedure in demo purposes, the two lines of the texture implementation and three lines of masking implementation from the image files in the Data folder of the root directory located:
int CImgTextureView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; Init(); // initialize OpenGL m_globTexture.Add((WORD)LoadImgTexture(_T("Data/MSUN.jpg"))); //you may insert //here any image file //in any pathway m_globTexture.Add((WORD)LoadImgTexture(_T("Data/famrt.jpg")));//and as much as //you like m_globMask.Add(LoadMaskTexture(_T("Data/vldv.bmp"))); //you may insert here any //bitmap image file in //any pathway m_globMask.Add(LoadMaskTexture(_T("Data/ussr.bmp"))); //and as much as you like; //just keep in mind that //the color m_globMask.Add(LoadMaskTexture(_T("Data/rsfsr.bmp"))); //of the left top pixel //(GetPixel(0,0)) assumed as //a background color return 0; } ;
You may insert here any image files and any masking bitmap image files from any pathway valid and as much as you like. In the original CMaskTextureView::DrawScene
procedure, the block of masking texture handling inserted:
case VIEW_MASK: { //Every face visibility checking required(depth test) GLdouble model[16]; //MODELVIEW_MATRIX glGetDoublev(GL_MODELVIEW_MATRIX, model); GLdouble proj[16]; //PROJECTION_MATRIX glGetDoublev(GL_PROJECTION_MATRIX, proj); GLint vw[4]; //VIEWPORT MATRIX glGetIntegerv(GL_VIEWPORT, vw); GLdouble xt0, yt0, zt0; //true coord of the cube center gluProject(0.0, 0.0, 0.0, model, proj, vw, &xt0, &yt0, &zt0); //calc true coord of the //cube center //////////////Front Face // Front Face Bkg GLdouble xt, yt, zt; gluProject(0.0, 0.0, a, model, proj, vw, &xt, &yt, &zt); //calc true coord //of the face center if (zt < zt0) //if face is visible { glBindTexture(GL_TEXTURE_2D, m_globTexture[m_texNum]); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-a, -a, a); glTexCoord2f(2.0f, 0.0f); glVertex3f(a, -a, a); glTexCoord2f(2.0f, 2.0f); glVertex3f(a, a, a); glTexCoord2f(0.0f, 2.0f); glVertex3f(-a, a, a); glEnd(); // Front Face BW glBindTexture(GL_TEXTURE_2D, HIWORD(m_globMask[m_maskNum])); glEnable(GL_BLEND); // Enable Blending glDisable(GL_DEPTH_TEST); // Disable Depth Testing glBlendFunc(GL_DST_COLOR, GL_ZERO); // Blend Screen Color With // Zero (Black) glBegin(GL_QUADS); glTexCoord2f(roll + 0.0f, 0.0f); glVertex3f(-a, -a, a); glTexCoord2f(roll + 2.0f, 0.0f); glVertex3f(a, -a, a); glTexCoord2f(roll + 2.0f, 2.0f); glVertex3f(a, a, a); glTexCoord2f(roll + 0.0f, 2.0f); glVertex3f(-a, a, a); glEnd(); // Front Face Mask glBindTexture(GL_TEXTURE_2D, LOWORD(m_globMask[m_maskNum])); glBlendFunc(GL_ONE, GL_ONE); // Copy Image 2 Color to // the screen glBegin(GL_QUADS); glTexCoord2f(roll + 0.0f, 0.0f); glVertex3f(-a, -a, a); glTexCoord2f(roll + 2.0f, 0.0f); glVertex3f(a, -a, a); glTexCoord2f(roll + 2.0f, 2.0f); glVertex3f(a, a, a); glTexCoord2f(roll + 0.0f, 2.0f); glVertex3f(-a, a, a); glEnd(); glEnable(GL_DEPTH_TEST); // Enable Depth Testing glDisable(GL_BLEND); // Disable Blending } //////////////Back Face gluProject(0.0, 0.0, -a, model, proj, vw, &xt, &yt, &zt); //calc true coord //of the face center if (zt < zt0) //if face is visible { .............................................................................. .............................................................................. ///////////////////////////////////////////// Left face // Left Face bkg gluProject(-a, 0.0, 0.0, model, proj, vw, &xt, &yt, &zt); //calc true coord of //the face center if (zt < zt0) //if face is visible { glBindTexture(GL_TEXTURE_2D, m_globTexture[m_texNum]); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-a, -a, -a); glTexCoord2f(1.0f, 0.0f); glVertex3f(-a, -a, a); glTexCoord2f(1.0f, 1.0f); glVertex3f(-a, a, a); glTexCoord2f(0.0f, 1.0f); glVertex3f(-a, a, -a); glEnd(); // Left Face BW glBindTexture (GL_TEXTURE_2D, HIWORD(m_globMask[m_maskNum])); glEnable(GL_BLEND); // Enable Blending glDisable(GL_DEPTH_TEST); // Disable Depth Testing glBlendFunc(GL_DST_COLOR, GL_ZERO); // Blend Screen Color // With Zero (Black) glBegin(GL_QUADS); glTexCoord2f(0.0f, roll + 0.0f); glVertex3f(-a, -a, -a); glTexCoord2f(1.0f, roll + 0.0f); glVertex3f(-a, -a, a); glTexCoord2f(1.0f, roll + 1.0f); glVertex3f(-a, a, a); glTexCoord2f(0.0f, roll + 1.0f); glVertex3f(-a, a, -a); glEnd(); // Left Face Mask glBindTexture (GL_TEXTURE_2D, LOWORD(m_globMask[m_maskNum])); glBlendFunc(GL_ONE, GL_ONE); // Copy Image 2 Color To The Screen glBegin(GL_QUADS); glTexCoord2f(0.0f, roll + 0.0f); glVertex3f(-a, -a, -a); glTexCoord2f(1.0f, roll + 0.0f); glVertex3f(-a, -a, a); glTexCoord2f(1.0f, roll + 1.0f); glVertex3f(-a, a, a); glTexCoord2f(0.0f, roll + 1.0f); glVertex3f(-a, a, -a); glEnd(); glEnable(GL_DEPTH_TEST); // Enable Depth Testing glDisable(GL_BLEND); // Disable Blending } roll += 0.05f; // Increase Our Texture Roll Variable if (roll>1.0f) // Is Roll Greater Than One { roll -= 1.0f; // Subtract 1 From Roll } } break;
In this block, we need to arrange a depth test before every face handling because GL_DEPTH_TEST
is set to disabled for blending. Before every scene drawing, we call standard gluProject
procedure to calc the true coord of the cube center. Before every face drawing, we call standard gluProject
procedure to calc the true coord of the face center. The face is visible if the center of the face is shorter to observe than the center of the cube.
The right column of the table demonstrates the DrawScene
steps of masking texture:
- Original Image Texture mapping performed the same as usual texture mapping procedure
- Clear to black the masking space in the Original Background Image
- Final Masked Image is a result of composition colour mask with the black background to the original background texture with the black space for masking
After masking performance, the scroll factor increased.
All the following Menu and Accelerator Commands have been done with standard AppWizard
technologies.
Application Demo Menu and Keyboard Commands
Some menu and some special Accelerator keys arranged in order to demonstrate the ImgTexture
project implementation:
- Menu File->Open - selecting the file with the image for texture mapping
- Menu File->Open Mask *.bmp - selecting the file with the bitmap image for texture masking
- Menu View->Default - original Cube performance
- Menu View->Texture - current texture performance
- Menu View->Next Texture - next texture performance (also Right Arrow click)
- Menu View->Prev Texture - previous texture performance (also Left Arrow click)
- Menu View->Next Mask - next masking performance (also Page Up click)
- Menu View->Prev Mask - previous masking performance (also Page Down click)
Points of Interest
The technology provided above is an attempt to demonstrate one of the simple masking texture implementation possibilities. You may use the foregoing procedures in your own applications inserting the GlobGLTexture.cpp file into your own project with the menu PROJECT->Add Existing Item... command.
The project has been developed in MFC platform. Nevertheless, the GlobGLTexture.cpp procedures are also valid in Win32 and are acceptable for use in Mobile applications.
History
- 21st November, 2016: Initial version
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK