混合即透明显示(透明的实现是将前面物体的颜色与后面物体的颜色混合),这里需要用到Alpha值,Alpha值为0为全透明,1为全不透明
关键点:混合公式(R,G,B,Alpha) = (Rs * Sr + Rd * Dr, Gs * Sg + Gd * Dg, Bs * Sb + Bd * Db, As * Sa + Ad * Da
通常,S+D = 1,故混色公式同时可写成
(R,G,B,Alpha) = (Rs * As + Rd * (1 - As), Gs * As + Gd * (1 - As), Bs * As + Bs * (1 - As), As * As + Ad * (1 - As))
注意点:正确的混色过程应该是先绘制全部的场景之后再绘制透明的图形。并且要按照与深度缓存相反的次序来绘制(先画最远的物体)。
开始声明全局变量:
BOOL blend;//是否混合
BOOL bp;
OpenGL初始化函数中需要使用glColor4f()函数(使用了Alpha值)
int InitGL(GLvoid)
{
if (!LoadGLTextures())//调用纹理载入
{
return FALSE;
}
glEnable(GL_TEXTURE_2D);//启用纹理映射
glShadeModel(GL_SMOOTH); //设置深度缓存
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST); //启用深度测试
glDepthFunc(GL_LEQUAL); //所作深度测试的类型
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);//设置环境光
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);//设置漫反射
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);//设置光源位置
glEnable(GL_LIGHT1);//启用一号光源
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//反锯齿
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);//全亮度,50%Alph混合
glBlendFunc(GL_SRC_ALPHA, GL_ONE);//基于源像素alpha通道值的半透明混合函数
return TRUE;
}
WinMain()函数中定义了B键对混合开启和关闭的操作
代码如下:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
BOOL done = FALSE;
if (MessageBox(NULL, L"你想在全屏模式下运行吗", L"设置全屏模式", MB_YESNO | MB_ICONQUESTION) == IDNO)
{
fullscreen = FALSE;
}
if (!CreateGLWindow(L"OpenGL程序框架", 640, 480, 16, fullscreen))
{
return 0;
}
while (!done)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))//有消息在等待吗
{
if (msg.message == WM_QUIT)
{
done = TRUE;
}
else
{
TranslateMessage(&msg);//翻译消息
DispatchMessage(&msg);//发送消息
}
}
else
{
if (active)
{
if (keys[VK_ESCAPE])//ESC按下
{
done = TRUE;
}
else
{
DrawGLScene();
SwapBuffers(hDC);
}
if (keys['L'] && !lp)//L键按下并且未松开
{
lp = TRUE;
light = !light;
if (!light)//如果没有光源
{
glDisable(GL_LIGHTING);//禁用光源
}
else
{
glEnable(GL_LIGHTING);//启用光源
}
}
if (!keys['L'])//L键松开了
{
lp = FALSE;
}
if (keys['F'] && !fp)//F键按下并且未松开
{
fp = TURE;
filter += 1;
if (filter > 2)
{
filter = 0;
}
}
if (!keys['F'])
{
fp = FALSE;
}
if (keys[VK_PRIOR])//PageDown按下了
{
z -= 0.02f;//若按下,木箱远离观察者
}
if (keys[VK_UP])//PageUp按下
{
z += 0.02f;//若按下,木箱靠近观察者
}
if (keys[VK_UP])//Up方向键按下
{
yspeed += 0.01f;
}
if (keys[VK_DOWN])//Down方向键按下
{
yspeed -= 0.01f;
}
if (keys[VK_RIGHT])//Right方向键按下
{
xspeed += 0.01f;
}
if (keys[VK_LEFT])//Left方向键按下
{
xspeed -= 0.01f;
}
if (keys['B'] && !bp)//B键按下
{
bp = TRUE;
blend = !blend;
if (blend)//混合打开
{
glEnable(GL_BLEND);//打开混合
glDisable(GL_DEPTH_TEST)//关闭深度测试
}
else
{
glDisable(GL_BLEND);//关闭混合
glEnable(GL_DEPTH_TEST);//打开深度测试
}
}
if (!keys['B'])
{
bp = FALSE;
}
if (keys[VK_F1])//F1按下
{
keys[VK_F1] = FALSE;
KillGLWindow();
fullscreen = !fullscreen;
if (!CreateGLWindow(L"OpenGL程序框架", 640, 480, 16, fullscreen))//重建OpenGL窗口
{
return 0;
}
}
}
}
}
KillGLWindow();
return(msg.wParam);
}