7.光照和键盘控制

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

1.  初始化光源

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

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

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

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

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

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

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

        fLightPosition = new float[4] { lx, ly, lz, 1f };
        gl.Light(OpenGL.LIGHT0, OpenGL.POSITION, fLightPosition); //光源位置
         //坐标系移动至(0,0,-6);
        gl.Translate(0f, 0f, -6.0f);
         //以(0,0,-6)为原点的三维坐标系进行相对位置移动
        gl.Translate(x, y, z);
                 主要用于光源位置获取,立方体位置获取及他们的定位,相信我注释的应该很明白。添加后的事件响应函数有如下的形式:
private void openGLControl1_OpenGLDraw( object sender, PaintEventArgs e)
{        
         //    将纹理绑定在要绘制的图像表面
        SharpGL.OpenGL gl = this.openGLControl1.OpenGL;

        gl.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT);
         //坐标重置,定位到系统原点
        gl.LoadIdentity();
         //设置光源位置坐标
        fLightPosition = new float[4] { lx, ly, lz, 1f };
        gl.Light(OpenGL.LIGHT0, OpenGL.POSITION, fLightPosition); //光源位置
         //坐标系移动至(0,0,-6);
        gl.Translate(0f, 0f, -6.0f);
         //以(0,0,-6)为原点的三维坐标系进行相对位置移动
        gl.Translate(x, y, z);
         //绑定纹理
        texture1.Bind(gl);
         //开始六面体
        gl.Begin(OpenGL.QUADS);

         // Front Face
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
        gl.End();
        texture2.Bind(gl);
        gl.Begin(OpenGL.QUADS);
         // Back Face
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, -1.0f);   // Bottom Right Of The Texture and Quad
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(1.0f, -1.0f, -1.0f);   // Bottom Left Of The Texture and Quad
        gl.End();
        texture3.Bind(gl);
        gl.Begin(OpenGL.QUADS);
         // Top Face
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, 1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, 1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
        gl.End();
        texture4.Bind(gl);
        gl.Begin(OpenGL.QUADS);
         // Bottom Face
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(-1.0f, -1.0f, -1.0f);   // Top Right Of The Texture and Quad
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(1.0f, -1.0f, -1.0f);   // Top Left Of The Texture and Quad
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
        gl.End();
        texture5.Bind(gl);
        gl.Begin(OpenGL.QUADS);
         // Right face
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, -1.0f);   // Bottom Right Of The Texture and Quad
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
        gl.End();
        texture6.Bind(gl);
        gl.Begin(OpenGL.QUADS);
         // Left Face
        gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, -1.0f);   // Bottom Left Of The Texture and Quad
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
        gl.End();
        gl.Flush();
}
                   
 

2  键盘按键的响应

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

        }

}
 

3 最终实现效果

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

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

        3> 光源开关

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

 
工程文件源代码见附件:

你可能感兴趣的:(职场,C#,OpenGL,休闲,SharpGL)