opengl学习 nehe lesson 8

opengl学习 nehe lesson 8

趁着在安装东西的时候,想起来好久没把这些东西总结出来.于是凑合着写着吧..在循序渐进的学习过程中.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.0f0.0f); glVertex3f(-1.0f-1.0f,  1.0f);
        glTexCoord2f(
1.0f0.0f); glVertex3f( 1.0f-1.0f,  1.0f);
        glTexCoord2f(
1.0f1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
        glTexCoord2f(
0.0f1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
        
// Back Face
        glTexCoord2f(1.0f0.0f); glVertex3f(-1.0f-1.0f-1.0f);
        glTexCoord2f(
1.0f1.0f); glVertex3f(-1.0f,  1.0f-1.0f);
        glTexCoord2f(
0.0f1.0f); glVertex3f( 1.0f,  1.0f-1.0f);
        glTexCoord2f(
0.0f0.0f); glVertex3f( 1.0f-1.0f-1.0f);
        
// Top Face
        glTexCoord2f(0.0f1.0f); glVertex3f(-1.0f,  1.0f-1.0f);
        glTexCoord2f(
0.0f0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
        glTexCoord2f(
1.0f0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
        glTexCoord2f(
1.0f1.0f); glVertex3f( 1.0f,  1.0f-1.0f);
        
// Bottom Face
        glTexCoord2f(1.0f1.0f); glVertex3f(-1.0f-1.0f-1.0f);
        glTexCoord2f(
0.0f1.0f); glVertex3f( 1.0f-1.0f-1.0f);
        glTexCoord2f(
0.0f0.0f); glVertex3f( 1.0f-1.0f,  1.0f);
        glTexCoord2f(
1.0f0.0f); glVertex3f(-1.0f-1.0f,  1.0f);
        
// Right face
        glTexCoord2f(1.0f0.0f); glVertex3f( 1.0f-1.0f-1.0f);
        glTexCoord2f(
1.0f1.0f); glVertex3f( 1.0f,  1.0f-1.0f);
        glTexCoord2f(
0.0f1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
        glTexCoord2f(
0.0f0.0f); glVertex3f( 1.0f-1.0f,  1.0f);
        
// Left Face
        glTexCoord2f(0.0f0.0f); glVertex3f(-1.0f-1.0f-1.0f);
        glTexCoord2f(
1.0f0.0f); glVertex3f(-1.0f-1.0f,  1.0f);
        glTexCoord2f(
1.0f1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
        glTexCoord2f(
0.0f1.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;
    }

}


效果如下:

opengl学习 nehe lesson 8_第1张图片

你可能感兴趣的:(opengl学习 nehe lesson 8)