My previous article demonstrated useful texture handling techology by calling name of image file for texture mapping without many stages with conditions implementation required. The follow-up is an image masking application provided.
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) {
CImage img;
HRESULT hResult = img.Load(fName); 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 (img.GetBPP() != 24) {
CImage tmg;
tmg.Create(img.GetWidth(), img.GetHeight(), 24); img.BitBlt(tmg.GetDC(), CPoint(0, 0)); }
CImage * pSmg = new CImage;
CDC * tDC = CDC::FromHandle(img.GetDC()); MakeBWMask(pSmg, tDC, img.GetWidth(), img.GetHeight(), tDC->GetPixel(0, 0),
img.GetBPP());
CBitmap * pBmw = GetImgBitmap(pSmg); if (pBmw == NULL)
return FALSE;
BITMAP BMPw;
pBmw->GetBitmap(&BMPw);
GLuint nBw = LoadGLTexture(&BMPw);
CDC * pDC = new CDC; pDC->CreateCompatibleDC(CDC::FromHandle(img.GetDC()));
CBitmap bmt;
bmt.CreateCompatibleBitmap(CDC::FromHandle(img.GetDC()),
img.GetWidth(), img.GetHeight());
CBitmap * pBm = pDC->SelectObject(&bmt);
pDC->BitBlt(0, 0, img.GetWidth(), img.GetHeight(),
CDC::FromHandle(pSmg->GetDC()), 0, 0, SRCCOPY);
pDC->BitBlt(0, 0, img.GetWidth(),
img.GetHeight(), NULL, 0, 0, DSTINVERT);
CDC::FromHandle(img.GetDC())->BitBlt(0, 0, img.GetWidth(),
img.GetHeight(), pDC, 0, 0, SRCAND);
pDC->SelectObject(pBm);
bmt.DeleteObject();
pDC->DeleteDC();
delete pDC;
CBitmap * pBmi = GetImgBitmap(&img);
BITMAP BMPi;
pBmi->GetBitmap(&BMPi);
delete pBmw; delete pSmg;
pSmg = NULL;
GLuint nImg = LoadGLTexture(&BMPi); delete pBmi;
return MAKELONG(nImg, nBw); }
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); if (rgb == eColor)
tDC->SetPixel(i, j, RGB(255, 255, 255)); else
tDC->SetPixel(i, j, RGB(0, 0, 0)); }
}
The variables inserted:
int m_texNum; int m_maskNum; CWordArray m_globTexture; CDWordArray m_globMask; enum VIEW_TYPE
{
VIEW_DEFAULT, VIEW_TEXTURE, VIEW MASK, };
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(); m_globTexture.Add((WORD)LoadImgTexture(_T("Data/MSUN.jpg"))); m_globTexture.Add((WORD)LoadImgTexture(_T("Data/famrt.jpg")));
m_globMask.Add(LoadMaskTexture(_T("Data/vldv.bmp"))); m_globMask.Add(LoadMaskTexture(_T("Data/ussr.bmp"))); m_globMask.Add(LoadMaskTexture(_T("Data/rsfsr.bmp")));
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:
{
GLdouble model[16]; glGetDoublev(GL_MODELVIEW_MATRIX, model);
GLdouble proj[16]; glGetDoublev(GL_PROJECTION_MATRIX, proj);
GLint vw[4]; glGetIntegerv(GL_VIEWPORT, vw);
GLdouble xt0, yt0, zt0; gluProject(0.0, 0.0, 0.0, model,
proj, vw, &xt0, &yt0, &zt0);
GLdouble xt, yt, zt;
gluProject(0.0, 0.0, a, model, proj, vw, &xt, &yt, &zt); if (zt < zt0) {
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();
glBindTexture(GL_TEXTURE_2D, HIWORD(m_globMask[m_maskNum]));
glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); glBlendFunc(GL_DST_COLOR, GL_ZERO);
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();
glBindTexture(GL_TEXTURE_2D, LOWORD(m_globMask[m_maskNum]));
glBlendFunc(GL_ONE, GL_ONE); 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); glDisable(GL_BLEND); }
gluProject(0.0, 0.0, -a, model, proj, vw, &xt, &yt, &zt); if (zt < zt0) {
..............................................................................
..............................................................................
gluProject(-a, 0.0, 0.0,
model, proj, vw, &xt, &yt, &zt); if (zt < zt0) {
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();
glBindTexture
(GL_TEXTURE_2D, HIWORD(m_globMask[m_maskNum]));
glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); glBlendFunc(GL_DST_COLOR, GL_ZERO);
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();
glBindTexture
(GL_TEXTURE_2D, LOWORD(m_globMask[m_maskNum]));
glBlendFunc(GL_ONE, GL_ONE); 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); glDisable(GL_BLEND); }
roll += 0.05f; if (roll>1.0f) {
roll -= 1.0f; }
}
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:
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