在这一课里,我们将添加光照和键盘控制,它让程序的效果看起来更丰富。这些新增的代码是我自己编的,SharpGL的例程里面是没有的,我并不是个经验丰富的程序员,所以代码如果有问题请联系我。wanglei_wan@yahoo.com.cn
    由于在上一节中我采用的纹理是白色的自制图片,对光照的反映不是非常明显,这一节采用的纹理填充立方体为第5课所用的纹理。
 
    这节所增加的内容如下:

1.  初始化光源

         1> 增加三个变量来存储光源位置和正方体位置        

InBlock.gif //六面体位置
InBlock.gif float x = 0f;
InBlock.gif float y = 0f;
InBlock.gif float z = -0.6f;
InBlock.gif //光源位置
InBlock.gif float lx = 0f;
InBlock.gif float ly = 0f;
InBlock.gif float lz = -4f;

         2>  增加三个变量来存贮光源信息

                 
InBlock.gif float[] fLightPosition = new float[4]; // 光源位置
InBlock.gif float[] fLightAmbient = new float[4] { 1f, 1f, 1f, 1.0f }; // 环境光参数
InBlock.gif float[] fLightDiffuse = new float[4] { 1f, 1f, 1f, 1f }; // 漫射光参数
         
 

             3>  在Form窗的构造函数中完成光源的初始化信息

InBlock.giffLightPosition = new float[4] { lx, ly, lz, 1f };
InBlock.gifgl.Light(OpenGL.LIGHT0, OpenGL.AMBIENT, fLightAmbient); //环境光源
InBlock.gifgl.Light(OpenGL.LIGHT0, OpenGL.DIFFUSE, fLightDiffuse); //漫射光源
InBlock.gifgl.Light(OpenGL.LIGHT0, OpenGL.POSITION, fLightPosition); //光源位置
InBlock.gifgl.Enable(OpenGL.LIGHTING); //开启光照
InBlock.gifgl.Enable(OpenGL.LIGHT0);
 
             具体意义参考Nehe的教程就可以了,很好懂。这里需要注意的是上面有这样一跳语句:
InBlock.gifgl.Enable(OpenGL.LIGHTING); //开启光照
这在Nehe的OpenGL教程中是没有提到的,也困扰了我一些时间,后来读了些SharpGL的源代码,这条语句应该是开启关照效果的初始化选项。如果不掉用此条语句,关照效果是没有显示的。

           4>  在OpenGLDraw中添加了以下几条语句

InBlock.gif        fLightPosition = new float[4] { lx, ly, lz, 1f };
InBlock.gif        gl.Light(OpenGL.LIGHT0, OpenGL.POSITION, fLightPosition); //光源位置
InBlock.gif         //坐标系移动至(0,0,-6);
InBlock.gif        gl.Translate(0f, 0f, -6.0f);
InBlock.gif         //以(0,0,-6)为原点的三维坐标系进行相对位置移动
InBlock.gif        gl.Translate(x, y, z);
                 主要用于光源位置获取,立方体位置获取及他们的定位,相信我注释的应该很明白。添加后的事件响应函数有如下的形式:
InBlock.gif private void openGLControl1_OpenGLDraw( object sender, PaintEventArgs e)
InBlock.gif{        
InBlock.gif         //    将纹理绑定在要绘制的图像表面
InBlock.gif        SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
InBlock.gif
InBlock.gif        gl.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT);
InBlock.gif         //坐标重置,定位到系统原点
InBlock.gif        gl.LoadIdentity();
InBlock.gif         //设置光源位置坐标
InBlock.gif        fLightPosition = new float[4] { lx, ly, lz, 1f };
InBlock.gif        gl.Light(OpenGL.LIGHT0, OpenGL.POSITION, fLightPosition); //光源位置
InBlock.gif         //坐标系移动至(0,0,-6);
InBlock.gif        gl.Translate(0f, 0f, -6.0f);
InBlock.gif         //以(0,0,-6)为原点的三维坐标系进行相对位置移动
InBlock.gif        gl.Translate(x, y, z);
InBlock.gif         //绑定纹理
InBlock.gif        texture1.Bind(gl);
InBlock.gif         //开始六面体
InBlock.gif        gl.Begin(OpenGL.QUADS);
InBlock.gif
InBlock.gif         // Front Face
InBlock.gif        gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
InBlock.gif        gl.End();
InBlock.gif        texture2.Bind(gl);
InBlock.gif        gl.Begin(OpenGL.QUADS);
InBlock.gif         // Back Face
InBlock.gif        gl.TexCoord(1.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, -1.0f);   // Bottom Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 1.0f); gl.Vertex(1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 0.0f); gl.Vertex(1.0f, -1.0f, -1.0f);   // Bottom Left Of The Texture and Quad
InBlock.gif        gl.End();
InBlock.gif        texture3.Bind(gl);
InBlock.gif        gl.Begin(OpenGL.QUADS);
InBlock.gif         // Top Face
InBlock.gif        gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, 1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, 1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
InBlock.gif        gl.End();
InBlock.gif        texture4.Bind(gl);
InBlock.gif        gl.Begin(OpenGL.QUADS);
InBlock.gif         // Bottom Face
InBlock.gif        gl.TexCoord(1.0f, 1.0f); gl.Vertex(-1.0f, -1.0f, -1.0f);   // Top Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 1.0f); gl.Vertex(1.0f, -1.0f, -1.0f);   // Top Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
InBlock.gif        gl.End();
InBlock.gif        texture5.Bind(gl);
InBlock.gif        gl.Begin(OpenGL.QUADS);
InBlock.gif         // Right face
InBlock.gif        gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, -1.0f);   // Bottom Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
InBlock.gif        gl.End();
InBlock.gif        texture6.Bind(gl);
InBlock.gif        gl.Begin(OpenGL.QUADS);
InBlock.gif         // Left Face
InBlock.gif        gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, -1.0f);   // Bottom Left Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(1.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
InBlock.gif        gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
InBlock.gif        gl.End();
InBlock.gif        gl.Flush();
InBlock.gif}
                   
 

2  键盘按键的响应

               重新回到Form设计器中,单击OpenGLControl1控件将其激活,在事件中找到KeyDown事件,双击即可定位到按键响应函数。
加入按键处理代码(这不用我解释了吧,不懂的随便找本C#的书上面都有),主要功能:WSADQE键分别控制立方体的“上下左右前后”,KI键控制光源的前后移动,JL控制光源的左右移动,空格键控制光源是否点亮。这样在光源移动到立方体后面时,我们就看不到立方体了,光源在左右移动时就可以看到半亮半暗的立方体,光源关闭时看到的是全黑的情景。增加的Bool变量light用来存储光源是否点亮。
InBlock.gif bool light = true;
InBlock.gif private void openGLControl1_KeyDown( object sender, KeyEventArgs e)
InBlock.gif{
InBlock.gif         switch (e.KeyCode)
InBlock.gif        {
InBlock.gif                 case Keys.W:
InBlock.gif                        y = y + 0.1f;
InBlock.gif                         break;
InBlock.gif                 case Keys.S:
InBlock.gif                        y = y - 0.1f;
InBlock.gif                         break;
InBlock.gif                 case Keys.A:
InBlock.gif                        x = x - 0.1f;
InBlock.gif                         break;
InBlock.gif                 case Keys.D:
InBlock.gif                        x = x + 0.1f;
InBlock.gif                         break;
InBlock.gif                 case Keys.Q:
InBlock.gif                        z = z + 0.1f;
InBlock.gif                         break;
InBlock.gif                 case Keys.E:
InBlock.gif                        z = z - 0.1f;
InBlock.gif                         break;
InBlock.gif                 case Keys.J:
InBlock.gif                        lx = lx - 0.2f;
InBlock.gif                         break;
InBlock.gif                 case Keys.L:
InBlock.gif                        lx = lx + 0.2f;
InBlock.gif                         break;
InBlock.gif                 case Keys.I:
InBlock.gif                        lz = lz - 0.2f;
InBlock.gif                         break;
InBlock.gif                 case Keys.K:
InBlock.gif                        lz = lz + 0.2f;
InBlock.gif                         break;
InBlock.gif                 case Keys.Space:
InBlock.gif                                 if (light)
InBlock.gif                                {
InBlock.gif                                         this.openGLControl1.OpenGL.Disable(OpenGL.LIGHT0);
InBlock.gif                                }
InBlock.gif                                 else
InBlock.gif                                {
InBlock.gif                                         this.openGLControl1.OpenGL.Enable(OpenGL.LIGHT0);
InBlock.gif                                }
InBlock.gif                                light = !light;
InBlock.gif                                 break;
InBlock.gif                 default:
InBlock.gif                         break;
InBlock.gif
InBlock.gif        }
InBlock.gif
InBlock.gif}
 

3 最终实现效果

        1> ASDWQE实现六面体的三维移动

        2> JLKI实现光源的三维移动(不包括上下移动,我没有做)

        3> 光源开关

        4>六面体移动加上光源移动

 
工程文件源代码见附件: