趁着在安装东西的时候,想起来好久没把这些东西总结出来.于是凑合着写着吧..在循序渐进的学习过程中.NEHE的教程我已经看到20课多了 而我发上来的却才是第7课.也不知道自己在忙些什么.总想着能快速的学完.然后学完之后却忘了很多了. 今天趁着这个空闲时候看看能写出多少吧..
nehe lesson_8的内容是有关于颜色混合 Apha混合.我们曾在使用glClearColor(1.0,1.0,1.0,1.0)使用过颜色值的4个分量.前三个则是RGB 那么第4个呢? 就是现在所说的Apha分量.它将会在混合当中用到.
Apha混合 原理是一个数学公式.:
(当前绘制颜色RGB分量)*当前Apha分量+.:(背景颜色RGB分量)*(1-当前Apha分量)
其次它文中提到了一点:
绘制混色时候,需要关闭深度测试.虽然这是不正确的方法.因为我们需要在半透明的图形背后绘制对象.但这往往会工作的很好,所以这课当中我们用到正是这种方法
而对于混合的正确绘制过程应当如下所示:
正确的混色过程应该是先绘制全部的场景之后再绘制透明的图形。并且要按照与深度缓存相反的次序来绘制(先画最远的物体)。考虑对两个多边形(1和2)进行alpha混合,不同的绘制次序会得到不同的结果。(这里假定多边形1离观察者最近,那么正确的过程应该先画多边形2,再画多边形1。正如您再现实中所见到的那样,从这两个<透明的>多边形背后照射来的光线总是先穿过多边形2,再穿过多边形1,最后才到达观察者的眼睛。)在深度缓存启用时,您应该将透明图形按照深度进行排序,并在全部场景绘制完毕之后
再绘制这些透明物体。否则您将得到不正确的结果。我知道某些时候这样做是很令人痛
苦的,但这是正确的方法。
对于混色操作:我们应当使用的步骤则是:
glEnable(GL_BLEND);//开启混色功能
glBlendFunc(GL_SRC_ALPHA,GL_ONE);//启用源Apha混色
对于本课当中:在启用混色之后应当关闭深度测试 glDisable(GL_DEPTH_TEST);
这次源码是基于lesson_7修改而来.并没有多大的变化.而且对于读取bmp并没有修改为我之前我所写的bmpLoader的方式
源代码如下:
lesson_8
#include "openglglut.h"
/**//**
** NEHE lesson_8
** Apha混色学习
*/
GLfloat xRot=0; /**//** 正方体绕x轴旋转角度*/
GLfloat yRot=0; /**//** 正方体绕y轴旋转角度*/
GLfloat z=-6.0;
static GLuint texnum[3]; /**//** 定义存储纹理*/
bool light=false;
bool blend=false;
int filter=2; /**//** 定义选择的滤波方式*/
GLfloat light_ambient[]={0.5,0.5,0.5,1.0};
GLfloat light_diffuse[]={1.0,1.0,1.0,1.0};
GLfloat light_position[]={0.0,0.0,2.0,1.0};
/**//** 这是一个通过WIN API 载入一张bmp格式图片的方法*/
bool LoadBmpTexture(LPTSTR filename)
{
HBITMAP bBmp; /**//** 位图文件的句柄*/
BITMAP bmp; /**//** 位图的结构*/
/**//** 通过API LoadImage 读入bmp文件,获得句柄*/
bBmp=(HBITMAP)LoadImage(GetModuleHandle(NULL),filename,IMAGE_BITMAP,0,0,
LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if(!bBmp)
return false;
/**//** 获得图像数据对象*/
GetObject(bBmp,sizeof(bmp),&bmp);
glPixelStorei(GL_UNPACK_ALIGNMENT,1); /**//** ? */
glGenTextures(3,&texnum[0]); /**//** 创建三个纹理 分别存储于texnum[0],texnum[1],texnum[2]*/
/**//** Nearest滤波*/
glBindTexture(GL_TEXTURE_2D,texnum[0]); /**//** 为它指定第一个纹理 设置纹理滤波方式*/
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); /**//** 线性滤波 */
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); /**//** 线性滤波 */
gluBuild2DMipmaps(GL_TEXTURE_2D, 3,bmp.bmWidth,bmp.bmHeight
,GL_BGR_EXT,GL_UNSIGNED_BYTE,bmp.bmBits);
/**//** 线性滤波*/
glBindTexture(GL_TEXTURE_2D,texnum[1]); /**//** 为它指定第一个纹理 设置纹理滤波方式*/
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3,bmp.bmWidth,bmp.bmHeight
,GL_BGR_EXT,GL_UNSIGNED_BYTE,bmp.bmBits);
/**//** MipMapped 滤波*/
glBindTexture(GL_TEXTURE_2D,texnum[2]); /**//** 为它指定第一个纹理 设置纹理滤波方式*/
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3,bmp.bmWidth,bmp.bmHeight
,GL_BGR_EXT,GL_UNSIGNED_BYTE,bmp.bmBits);
DeleteObject(bBmp); /**//** 删除对象,释放内存*/
return true;
}
int main(int argc,char** argv)
{
createWindow("opengl lesson_8",&argc,argv); /**//** 初始化并创建窗口*/
glutDisplayFunc(glutDisplay); /**//** 注册重绘函数*/
glutIdleFunc(glutIdle); /**//** 注册空闲回调函数*/
glutReshapeFunc(glutResize); /**//** 注册窗口调整函数*/
glutSpecialFunc(glutSpecial); /**//** 注册特殊按键窗口*/
glutKeyboardFunc(glutKeyboard); /**//** 注册键盘处理函数*/
InitOpenGL(); /**//** 初始化opengl*/
InitDepthTest(); /**//** 启用深度测试*/
InitTexture(); /**//** 初始化启用纹理映射并加载纹理*/
InitLight(); /**//** 初始化启用光照*/
InitBlend(); /**//** 初始化alpha混色*/
glutMainLoop(); /**//** 仿真循环*/
return 0;
}
void InitTexture(void)
{
/**//** 读入工程目录下data文件中的bmp文件*/
if(!LoadBmpTexture(L"..\\Data\\Glass.bmp"))
{
printf("load texture error!\n");
exit(0);
}
/**//** 若载入纹理成功 则启用纹理映射*/
glEnable(GL_TEXTURE_2D);
}
void InitLight(void)
{
glLightfv(GL_LIGHT1,GL_AMBIENT,light_ambient); /**//** 初始化环境光*/
glLightfv(GL_LIGHT1,GL_DIFFUSE,light_diffuse); /**//** 初始化散射光*/
glLightfv(GL_LIGHT1,GL_POSITION,light_position); /**//** 初始化光源位置*/
/**//** liggt_position 包含(x,y,z,w) w为0 表示方向性光源,w非0表示位置性光源*/
glEnable(GL_LIGHT1);
//glEnable(GL_LIGHTING); /** 这句才是关键 才真正启用光照*/
}
void InitBlend(void)
{
glColor4f(1.0f,1.0f,1.0f,0.5f); // 全亮度, 50% Alpha 混合
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 基于源象素alpha通道值的半透明混合函数
}
void glutIdle(void)
{
glutPostRedisplay();
}
void glutDisplay(void) /**//** 重绘函数*/
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);/**//** 清除颜色缓存和深度缓存*/
glLoadIdentity(); /**//** 初始化当前矩阵为单位矩阵*/
glTranslatef(0.0,0.0,z); /**//** 往左移动和往屏幕内部移动,绘制正方体*/
glRotatef(xRot,1.0,0.0,0.0); /**//** 正方体绕x轴旋转xRot角度*/
glRotatef(yRot,0.0,1.0,0.0); /**//** 正方体绕y轴旋转yRot角度*/
glBindTexture(GL_TEXTURE_2D,texnum[filter]); /**//** 选择一个纹理*/
glBegin(GL_QUADS); /**//** 通过绘制六个正方形组成正方体,并为每一面都贴上纹理*/
// Front Face
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);
// Back Face
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);
// Top Face
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);
// Bottom Face
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);
// Right face
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);
// Left Face
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();
glutSwapBuffers();
}
void glutKeyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 27: /**//** Esc按键按下后退出程序 */
exit(0);
break;
case 'l':
light=!light;
light?glEnable(GL_LIGHTING):glDisable(GL_LIGHTING);
break;
case 'f':
filter+=1;
filter%=2;/**//** 选择哪种滤波方式*/
break;
case 'a':
yRot-=1.0;
break;
case 'd':
yRot+=1.0;
break;
case 's':
xRot+=1.0;
break;
case 'w':
xRot-=1.0;
break;
case 'z':
z-=0.02;
break;
case 'x':
z+=0.02;
break;
case 'b':
blend=!blend;
if(blend)
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}
else
{
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
break;
default:
break;
}
}
void glutSpecial(int value, int x, int y)
{
switch (value)
{
case GLUT_KEY_F1: // 按F1键时切换窗口/全屏模式
if(isFullScreen)
{
glutReshapeWindow(GL_WIN_WIDTH, GL_WIN_HEIGHT);
glutPositionWindow(GL_WIN_INITIAL_X, GL_WIN_INITIAL_Y);
isFullScreen = false;
}
else
{
glutFullScreen();
isFullScreen = true;
}
return;
default:
return;
}
}
效果如下:
posted on 2009-08-08 17:14
米游 阅读(569)
评论(0) 编辑 收藏 引用 所属分类:
OpenGL/OSG