OpenGL学习笔记(七)

龙云尧个人博客,转载请注明出处。

CSDN地址:http://blog.csdn.net/michael753951/article/details/71511785

个人blog地址:http://yaoyl.cn/nehexue-xi-bi-ji-qi-2017-05-09-20-59/


我们在前六个部分已经尝试了nehe教程中1-8可得所有内容,接下来第七部分将实现一个简单的实验,这个实验将涵盖前面所有的内容,以作为一个前期总结。

前期准备

在实验之前,我们需要知道一个OpenGL中的基本概念。OpenGL中glEnable方法的使用。关于这个功能函数的使用以及参数设定,你可以点击【gl.glenable()介绍】以及【glEnable(GL_DEPTH_TEST) 有什么用?】进行查看。以下关于glenable的内容转载自上述第二篇博客。


在InitGL() 或者类似的初始化OpenGL的地方,会有glEnable(GL_DEPTH_TEST);

启用了之后,OpenGL在绘制的时候就会检查,当前像素前面是否有别的像素,如果别的像素挡道了它,那它就不会绘制,也就是说,OpenGL就只绘制最前面的一层。

当我们需要绘制透明图片时,就需要关闭它 glDisable(GL_DEPTH_TEST); 并且打开混合 glEnable(GL_BLEND);

而且还需要设置使用的透明度 glColor4f(1.0f,1.0f,1.0f,0.5f); 这样就是一半的显示了,设置为1就是不透明

glBlendFunc(GL_SRC_ALPHA,GL_ONE); 基于源像素Alpha通道值的半透明混合函数


在实验一以及后续的几个实验中,我们Enable的都是传入GL_DEPTH_TEST作为参数启用深度测试。并立刻在glEnable方法后面调用glDepthFunc(GL_LEQUAL);方法进行前景像素的显示设置。

这个概念在之前的实验中有所涉及,但是我们当时没有关注,这里我们将将其单独拿出来进行分析。**本部分以下部分均为转载。**转载来源为【glDepthFunc】

函数原型:

void glDepthFunc(GLenum func);

函数功能:

指定“目标像素与当前像素在z方向上值大小比较”的函数,符合该函数关系的目标像素才进行绘制,否则对目标像素不予绘制。

参数说明:

func指定深度比较函数,GL_NEVER,GL_LESS,GL_EQUAL,GL_LEQUAL,GL_GREATER,GL_NOTE_QUAL,GL_GEQUAL,GL_ALWAYS,缺省值GL_LESS,

GL_NEVER,不通过(输入的深度值不取代参考值)

GL_LESS,如果输入的深度值小于参考值,则通过

GL_EQUAL,如果输入的深度值等于参考值,则通过

GL_LEQUAL,如果输入的深度值小于或等于参考值,则通过

GL_GREATER,如果输入的深度值大于参考值,则通过

GL_NOTE_QUAL,如果输入的深度值不等于参考值,则通过

GL_GEQUAL,如果输入的深度值大于或等于参考值,则通过

GL_ALWAYS,总是通过(输入的深度值取代参考值)

描述:

   通过目标像素与当前像素在z方向上值大小的比较是否满足参数指定的条件,来决定在深度(z方向)上是否绘制该目标像素。该函数只有启用“深度测试”时才有效,参考glEnable(GL_DEPTH_TEST)和glDisable(GL_DEPTH_TEST)

代码分析

前期准备能够帮助我们更好的理解作者在代码中的方法调用,,也能帮助我们更加深入的了解OpenGL的运行机制。我们接下来探讨本次实验中的实现方式。

根据Lesson1课程给我们大基建好的框架结构以及我们整理出来的那张结构图,我们可以快速理解本次实验代码。

首先定义了一个stars结构体,用来存放每一个星星的RGB值,与中心点的距离以及选装角度。

1typedef struct              // Create A Structure For Star
2{
3    int r, g, b;            // Stars Color
4    GLfloat dist,           // Stars Distance From Center
5        angle;          // Stars Current Angle
6}
7stars;
8stars star[num];            // Need To Keep Track Of 'num' Stars

接着是LoadBMP和LoadGLTextures,这个和以前的实验代码无异,只需要改一下读入的文件名即可。ReSizeGLScene函数同样不需要修改。

接下来的InitGL开始,将会和第一节课开始出现不一样。

首先我们在前期准备中已经知道了glEnable的意义,并且我们也已经知道,深度测试和透明两种功能不能同时开启。而我们在上一次实验中在设置透明的时候,也曾经写过如下代码:

1    glEnable(GL_BLEND);         // Turn Blending On
2    glDisable(GL_DEPTH_TEST);   // Turn Depth Testing Off

又因为本次实验需要直接使用透明,所以我们在InitGL中将不再glDisable(GL_BLEND),而是直接glEnable(GL_BLEND)。

接着就是很重要的一个方法了——DrawGLScene,这个地方,作者将星星的旋转以及着色代码在这里进行实现。

 1int DrawGLScene(GLvoid)                                 // Here's Where We Do All The Drawing
 2{
 3    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
 4    glBindTexture(GL_TEXTURE_2D, texture[0]);           // Select Our Texture
 5
 6    for (loop=0; loop<num; loop++)                      // Loop Through All The Stars
 7    {
 8        glLoadIdentity();                               // Reset The View Before We Draw Each Star
 9        glTranslatef(0.0f,0.0f,zoom);                   // Zoom Into The Screen (Using The Value In 'zoom')
10        glRotatef(tilt,1.0f,0.0f,0.0f);                 // Tilt The View (Using The Value In 'tilt')
11        glRotatef(star[loop].angle,0.0f,1.0f,0.0f);     // Rotate To The Current Stars Angle
12        glTranslatef(star[loop].dist,0.0f,0.0f);        // Move Forward On The X Plane
13        glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);    // Cancel The Current Stars Angle
14        glRotatef(-tilt,1.0f,0.0f,0.0f);                // Cancel The Screen Tilt
15        
16        if (twinkle)
17        {
18            glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
19            glBegin(GL_QUADS);
20                glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
21                glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
22                glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
23                glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
24            glEnd();
25        }
26
27        glRotatef(spin,0.0f,0.0f,1.0f);
28        glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
29        glBegin(GL_QUADS);
30            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
31            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
32            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
33            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
34        glEnd();
35
36        spin+=0.01f;
37        star[loop].angle+=float(loop)/num;
38        star[loop].dist-=0.01f;
39        if (star[loop].dist<0.0f)
40        {
41            star[loop].dist+=5.0f;
42            star[loop].r=rand()%256;
43            star[loop].g=rand()%256;
44            star[loop].b=rand()%256;
45        }
46    }
47    return TRUE;                                        // Everything Went OK
48}

如果我们在之前的课程中已经很深入的了解了的话,这一次的DrawScene就比较容易理解啦,我也就不在这里重复赘述了。

对winMain稍作修改。

 1int WINAPI WinMain( HINSTANCE   hInstance,          // Instance
 2                    HINSTANCE   hPrevInstance,      // Previous Instance
 3                    LPSTR       lpCmdLine,          // Command Line Parameters
 4                    int         nCmdShow)           // Window Show State
 5{
 6    MSG     msg;                                    // Windows Message Structure
 7    BOOL    done=FALSE;                             // Bool Variable To Exit Loop
 8
 9    // Ask The User Which Screen Mode They Prefer
10    if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
11    {
12        fullscreen=FALSE;                           // Windowed Mode
13    }
14
15    // Create Our OpenGL Window
16    if (!CreateGLWindow("NeHe's Animated Blended Textures Tutorial",640,480,16,fullscreen))
17    {
18        return 0;                                   // Quit If Window Was Not Created
19    }
20
21    while(!done)                                    // Loop That Runs While done=FALSE
22    {
23        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))   // Is There A Message Waiting?
24        {
25            if (msg.message==WM_QUIT)               // Have We Received A Quit Message?
26            {
27                done=TRUE;                          // If So done=TRUE
28            }
29            else                                    // If Not, Deal With Window Messages
30            {
31                TranslateMessage(&msg);             // Translate The Message
32                DispatchMessage(&msg);              // Dispatch The Message
33            }
34        }
35        else                                        // If There Are No Messages
36        {
37            // Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
38            if ((active && !DrawGLScene()) || keys[VK_ESCAPE])  // Active?  Was There A Quit Received?
39            {
40                done=TRUE;                          // ESC or DrawGLScene Signalled A Quit
41            }
42            else                                    // Not Time To Quit, Update Screen
43            {
44                SwapBuffers(hDC);                   // Swap Buffers (Double Buffering)
45                if (keys['T'] && !tp)
46                {
47                    tp=TRUE;
48                    twinkle=!twinkle;
49                }
50                if (!keys['T'])
51                {
52                    tp=FALSE;
53                }
54
55                if (keys[VK_UP])
56                {
57                    tilt-=0.5f;
58                }
59
60                if (keys[VK_DOWN])
61                {
62                    tilt+=0.5f;
63                }
64
65                if (keys[VK_PRIOR])
66                {
67                    zoom-=0.2f;
68                }
69
70                if (keys[VK_NEXT])
71                {
72                    zoom+=0.2f;
73                }
74
75                if (keys[VK_F1])                        // Is F1 Being Pressed?
76                {
77                    keys[VK_F1]=FALSE;                  // If So Make Key FALSE
78                    KillGLWindow();                     // Kill Our Current Window
79                    fullscreen=!fullscreen;             // Toggle Fullscreen / Windowed Mode
80                    // Recreate Our OpenGL Window
81                    if (!CreateGLWindow("NeHe's Animated Blended Textures Tutorial",640,480,16,fullscreen))
82                    {
83                        return 0;                       // Quit If Window Was Not Created
84                    }
85                }
86            }
87        }
88    }
89
90    // Shutdown
91    KillGLWindow();                                 // Kill The Window
92    return (msg.wParam);                            // Exit The Program
93}

同样,很好理解的代码我就不重复解释了。最终运行的结果如图所示。

这里写图片描述