在这一课里,我们将添加光照和键盘控制,它让程序的效果看起来更丰富。这些新增的代码是我自己编的,SharpGL的例程里面是没有的,我并不是个经验丰富的程序员,所以代码如果有问题请联系我。wanglei_wan@yahoo.com.cn
由于在上一节中我采用的纹理是白色的自制图片,对光照的反映不是非常明显,这一节采用的纹理填充立方体为第5课所用的纹理。
这节所增加的内容如下:
1. 初始化光源
1> 增加三个变量来存储光源位置和正方体位置
//六面体位置
float x = 0f;
float y = 0f;
float z = -0.6f;
//光源位置
float lx = 0f;
float ly = 0f;
float lz = -4f;
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 }; // 漫射光参数
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);
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);
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();
}
{
// 将纹理绑定在要绘制的图像表面
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;
}
}
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>六面体移动加上光源移动
工程文件源代码见附件:
转载于:https://blog.51cto.com/crazylove/174239