VC+opengl 帮忙看看这段贴纹理的代码为什么就是显示不出来

richiexieqing 2015-12-11 12:54:43
最近刚刚开始接触opengl,想自绘一套3d效果的控件。现在遇到一个问题就是-控件背景透明。试了一转最后还是觉得把背景抠出来当做纹理贴上去比较可行。图现在是抠出来了,可是就是贴不上啊。
相关代码如下:

void CGLEdit::DrawEdit()
{
glColor3f(0, 0, 0);
static BITMAP bmp = GetBmp(L"B.bmp");
static GLuint texid;

glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, 3, bmp.bmWidth, bmp.bmHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp.bmBits);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);//这个注释了或者改成GL_REPLACE也没用

glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glBindTexture(GL_TEXTURE_2D, texid);
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
glNormal3d(0.0,0.0,1.0);
glTexCoord2d(0.0, 0.0); glVertex3d(-HalfPanelWidth,-HalfPanelWidth, 0.0);
glTexCoord2d(1.0, 0.0); glVertex3d( HalfPanelWidth,-HalfPanelWidth, 0.0);
glTexCoord2d(1.0, 1.0); glVertex3d( HalfPanelWidth, HalfPanelWidth, 0.0);
glTexCoord2d(0.0, 1.0); glVertex3d(-HalfPanelWidth, HalfPanelWidth, 0.0);
glEnd();

glDisable(GL_TEXTURE_2D);


glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glColor4f(0, 0, 1, 1);

glBegin(GL_QUADS);//为了测试环境,画了一个蓝色的方块
glNormal3d(0.0,0.0,1.0);
glVertex3d(-HalfPanelWidth/2.0,-HalfPanelWidth/2.0, 0.1); //HalfPanelWidth和HalfPanelWidth是绘图区的半长和半宽
glVertex3d( HalfPanelWidth/2.0,-HalfPanelWidth/2.0, 0.1);
glVertex3d( HalfPanelWidth/2.0, HalfPanelWidth/2.0, 0.1);
glVertex3d(-HalfPanelWidth/2.0, HalfPanelWidth/2.0, 0.1);
glEnd();
}
BITMAP CGLEdit::GetBmp(LPCTSTR title)
{
static HBITMAP hbmp = 0;
hbmp = (HBITMAP)::LoadImage(GetModuleHandle(0), title, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
static BITMAP bmp = { 0 };
GetObject(hbmp, sizeof(BITMAP), &bmp);
return bmp;
}


这段代码是照搬 http://bbs.csdn.net/topics/390870410改了一下尺寸,HalfPanelWidth和HalfPanelWidth控件的半长和半宽
运行结果却如下:

我想达到的效果是背景上的红线应该是要在蓝色方块哪儿才被遮住。
现在看opengl环境肯定没问题,蓝色块儿也显示出来了,可纹理没有。
麻烦大家教教我,这段怎么改。抠出来的图肯定是没问题的,保存在B.bmp中
...全文
249 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
richiexieqing 2015-12-14
  • 打赏
  • 举报
回复
好吧,之前总是不出来的问题找到了,我又试了一下,用glTexImage2D也是可以的。
之前颜色成分那一项填的是 3,改成4就可以了,出来效果和gluBuild2DMipmaps是一样的。楼主菜鸟,搞不懂bmp怎么会有alpha通道。
网上看到很多人都在问opengl怎么弄成透明背景,菜鸟斗胆把自己的代码贴出来。
图中有两个重绘的CStatic和一个CButton。
原本是想用通常的过程,直接将opengl绘的图swap到控件的dc上,结果试来试去,在子控件上就是无法获得父控件dc上的像素。
所以每个控件加了一个公开变量CDC* m_MemDC,其上绑定了一个DIB。我让opengl先在m_MemDC上作图,然后再BitBlt到控件DC。
子控件是从父控件的m_MemDC上BitBlt过来的背景图像。在设置纹理时要把过滤设置成GL_NEAREST色差会减弱一点。但像素会有一点错位。
控件建立DIB代码,在头文件中要声明三个全局变量:
	
BITMAPINFOHEADER BIH;
HDC pdcDIB;
HBITMAP hbmpDIB;

尤其pdcDIB需要让子控件访问,所以要声明为public。
建立DIB:

void CGLStatic::CreateDIB()
{

CRect rect;
GetClientRect(&rect);

int iSize = sizeof(BITMAPINFOHEADER);
memset(&BIH, 0, iSize);

BIH.biSize = iSize;
BIH.biWidth = (LONG)(rect.Width());
BIH.biHeight = (LONG)(rect.Height());
BIH.biPlanes = 1;
BIH.biBitCount = 24;
BIH.biCompression = BI_RGB;

pdcDIB = CreateCompatibleDC(NULL);

assert(pdcDIB);

hbmpDIB = CreateDIBSection(
pdcDIB,
(BITMAPINFO*)&BIH,
DIB_RGB_COLORS,
&bmp_cnt,
NULL,
0);

assert(hbmpDIB);
assert(bmp_cnt);

if(hbmpDIB)
SelectObject(pdcDIB, hbmpDIB);
}

建立了DIB,再绘制opengl时就绑定pdcDIB和HRC然后再bitblt到控件dc

wglMakeCurrent(pdcDIB, m_hGLContext);
////////.......................
BitBlt(hDC, 0, 0,rect.width(),rect.height,pdcDIB, 0, 0, SRCCOPY);

以上是父控件中绘图,以下是在子控件中获取父控件的pdcDIB,再转为opengl纹理而后贴图

void CGLEdit::DrawBck()
{
////////////////////////将背景传到内存dc上
CGLPanel* ParentPanel=(CGLPanel*)this->GetParent();
HDC ParentHDC=ParentPanel->pdcDIB;

CRect rect1;
GetWindowRect(rect1);
GetParent()->ScreenToClient(rect1);

HDC hDCMem = ::CreateCompatibleDC(ParentHDC);

int DIBDim=NearestPowerOfTwo((int)(2.0*HalfPanelWidth), (int)(2.0*HalfPanelHeight));
//这里要解释一下,因为我发现即使我的opengl版本很高了,可纹理尺寸依然要为2的幂次方才能正常显示
//所以这里就先检测子控件的尺寸,HalfPanelWidth和HalfPanelHeight分别为子控件的半宽和半高,
//然后返回一个比子控件尺寸大的,最小的一个2的幂次方作为抠图的尺寸DIBDim,作为纹理尺寸
HBITMAP hBitMap = ::CreateCompatibleBitmap(ParentHDC, DIBDim,DIBDim);
HBITMAP hOldMap = (HBITMAP)::SelectObject(hDCMem, hBitMap);

BitBlt(hDCMem, 0, 0, DIBDim, DIBDim, ParentHDC,
rect1.CenterPoint().x-DIBDim/2, rect1.CenterPoint().y-DIBDim/2, SRCCOPY);
//这里将扩大的尺寸换到子控件坐标下
BITMAP bmp;
GetObject(hBitMap,sizeof(bmp),&bmp);
//通过内存bitmap句柄获取位图信息
//////////////////////////////////////////////////开始opengl作图,和普通读取bmp文件做纹理一样
// Create one OpenGL texture
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture (GL_TEXTURE_2D,textureID);
gluBuild2DMipmaps(GL_TEXTURE_2D,4, bmp.bmWidth,
bmp.bmHeight,GL_BGR_EXT, GL_UNSIGNED_BYTE,bmp.bmBits);

//glTexImage2D(GL_TEXTURE_2D, 0, 4, bmp.bmWidth, bmp.bmHeight,
// 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, bmp.bmBits);

glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//一定要为GL_NEAREST,否则像素颜色会和背景有差别
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

::SelectObject(hDCMem, hOldMap); //释放临时资源
::DeleteObject(hBitMap);
::DeleteObject(hOldMap);
::DeleteDC(hDCMem);

glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColor4f(1, 1, 1, 1);

GLdouble BckWH=(GLdouble)DIBDim*0.5;//贴纹理
glBegin(GL_QUADS);
glTexCoord2d(0.0, 0.0); glVertex3d(-BckWH,-BckWH, 0.0);
glTexCoord2d(1.0, 0.0); glVertex3d( BckWH,-BckWH, 0.0);
glTexCoord2d(1.0, 1.0); glVertex3d( BckWH, BckWH, 0.0);
glTexCoord2d(0.0, 1.0); glVertex3d(-BckWH, BckWH, 0.0);
glEnd();

glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHT0);
}


下图是运行效果

子控件上画了一个半透明的蓝色小方框,效果还可以,就是在子控件上边界上红线有一点点对不齐。应该是贴图时尺寸变量精度问题造成的。
赵4老师 2015-12-14
  • 打赏
  • 举报
回复
建议楼主闲暇时间通览一下3DS Max中文版联机帮助。
shiter 2015-12-11
  • 打赏
  • 举报
回复
引用 4 楼 赵4老师的回复:
增加光源的亮度? 设置自发光双面材质? 提高贴图的分辨率? 设置VideoPost处理?
还是赵老师会的多,
赵4老师 2015-12-11
  • 打赏
  • 举报
回复
增加光源的亮度? 设置自发光双面材质? 提高贴图的分辨率? 设置VideoPost处理?
richiexieqing 2015-12-11
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
搜网络教程“学OpenGL编3D游戏”。
(对OpenGL相关问题,我只会粘贴上面这一句蹭分。


谢谢你的蹭分回复,下下来之后照着源码改了一下生成纹理的代码为
gluBuild2DMipmaps(GL_TEXTURE_2D,4, bmp.bmWidth,  bmp.bmHeight,GL_BGR_EXT, GL_UNSIGNED_BYTE,bmp.bmBits);

果然出来了,只是效果差了那么一点点,如下

就是颜色会差那么一点点,还有办法改进么?
richiexieqing 2015-12-11
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
搜网络教程“学OpenGL编3D游戏”。 (对OpenGL相关问题,我只会粘贴上面这一句蹭分。
你的这个回复我确实在一些帖子里看见过了
赵4老师 2015-12-11
  • 打赏
  • 举报
回复
搜网络教程“学OpenGL编3D游戏”。 (对OpenGL相关问题,我只会粘贴上面这一句蹭分。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧