9.3D空间中移动图像

 
你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画。这一课将教会你所有的一切。前面的课程涵盖了基础的OpenGL,每一课都是在前一课的基础上创建的。这一课是前面几课知识的综合,当你学习这课时,请确保你已经掌握了前面几课的知识。
 
 
我在此将所有的代码重新写一遍,算是做了个总结

首先我们先实现一下Nehe中星星的纹理贴图,并且用随机颜色覆盖它。

1.   OpenGL初始化设置(这些代码是在Form的构造函数中实现的,很常规)

//此句只是为了引用方便
SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
////初始化光源
gl.LoadIdentity();
texture1.Create(gl, "star.bmp");
//    启用纹理映射
gl.Enable(OpenGL.TEXTURE_2D);
//启用阴影平滑
gl.ShadeModel(OpenGL.SMOOTH);
//黑色背景
gl.ClearColor(0f, 0f, 0f, 0.5f);
//设置深度缓存
gl.ClearDepth(1.0f);
// 真正精细的透视修正
gl.Hint(OpenGL.PERSPECTIVE_CORRECTION_HINT, OpenGL.NICEST);
// 基于源象素alpha通道值的半透明混合函数
gl.BlendFunc(OpenGL.SRC_ALPHA, OpenGL.ONE);
//启用混色
gl.Enable(OpenGL.BLEND);

2.   建立星星的结构体,保存星星的颜色,星星位置深度,星星旋转坐标角度,并建立结构对象。

//星星结构体
struct stars
{
     public float r, g, b; //星星颜色
     public float dist; //星星与原点的距离
     public float angle; //星星的旋转角度
}
static stars star = new stars();

3.    建立随机类的类对象,用以随机产生星星的颜色值

Random rand = new Random();
 

4.   在构造函数中初始化星星的颜色参数

//初始化星星值
byte[] starcolor = new byte[3];
rand.NextBytes(starcolor);
star.r = ( float)starcolor[0]/255;
star.g = ( float)starcolor[1]/255;
star.b = ( float)starcolor[2]/255;        

5.   设计OpenGLDraw的事件响应函数

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();
    gl.Translate(0.0f, 0.0f, -6.0f);
    texture1.Bind(gl);
    gl.Color(star.r, star.g, star.b, 1f); //着色
    gl.Begin(OpenGL.QUADS);
    gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 0.0f);   // Bottom Left Of The Texture and Quad
    gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 0.0f);   // Bottom Right Of The Texture and Quad
    gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 0.0f);   // Top Right Of The Texture and Quad
    gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 0.0f);   // Top Left Of The Texture and Quad
    gl.End();
    gl.Flush();
}

6 做键盘事件响应,T键随机改变星星的颜色

private void openGLControl1_KeyDown( object sender, KeyEventArgs e)
{
    SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
     switch (e.KeyCode)
    {
             case Keys.T:
                     byte[] starcolor = new byte[3];
                    rand.NextBytes(starcolor);
                    star.r = ( float)starcolor[0] / 255;
                    star.g = ( float)starcolor[1] / 255;
                    star.b = ( float)starcolor[2] / 255;    
                     //star.b++;
                     break;
             default:
                     break;
    }

7 此部分注意事项:

在Nehe的教程中采用的是Byte型的颜色值,用的是glColor4ub这个函数,在SharpGL中的gl.Color函数虽然重载了Byte型参数,但是执行效果很不对劲,例如用下面的语句代替上文中的相应代码,星星应该显示红色,但是意外的事情发生了,星星不见了,根本观察不到,我不知道为什么,可能是SharpGL的一个Bug也可能是我没用明白,所以在本试验中着色全部采用float
gl.Color(( byte)0xff, ( byte)0, ( byte)0, ( byte)0xff); //着红色

8 下面是此部分的执行效果, 此部分代码下载 源代码1

 
 

以上一部分的代码为基础

进行移动图像

1. 将星星对象改为对象数组,去五十个星星对象,并定义一些变量来监测星星的属性

/************************************************************************/
/*                                关于星星的变量及其定义设置                                                                                */
/************************************************************************/
Random rand = new Random();
//星星结构体
struct stars
{
public float r, g, b;
public float dist;
public float angle;
}
//星星数量
const int starnumber=50;
//星星对象结构体
stars[] star = new stars[starnumber];
//星星是否闪烁
bool twinkle = false;
//星星的自转
float spin; //星星的自转
float zoom = -15.0f; //星星离观察者的距离
float tilt = 90.0f; //星星的倾角
 

2 OpenGLDraw事件响应

其中用到了前面所叙述的很多OpenGL函数
 
private void openGLControl1_OpenGLDraw( object sender, PaintEventArgs e)
{
//    将纹理绑定在要绘制的图像表面
SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
//清除屏幕及深度缓存
gl.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT);
//选择纹理
texture1.Bind(gl);

for ( int loop = 0; loop < starnumber; loop++)
{
gl.LoadIdentity();
gl.Translate(0f, 0f, zoom);
gl.Rotate(tilt, 1f, 0f, 0f);
gl.Rotate(star[loop].angle, 0f, 1f, 0f);
gl.Translate(star[loop].dist, 0f, 0f);

gl.Rotate(-star[loop].angle, 0f, 1f, 0f);
gl.Rotate(-tilt, 1f, 0f, 0f);

if (twinkle)
{
gl.Color(star[starnumber - loop - 1].r, star[starnumber - loop - 1].g, star[starnumber - loop - 1].b, 1f);
gl.Begin(OpenGL.QUADS);
gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 0.0f);   // Bottom Left Of The Texture and Quad
gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 0.0f);   // Bottom Right Of The Texture and Quad
gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 0.0f);   // Top Right Of The Texture and Quad
gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 0.0f);   // Top Left Of The Texture and Quad
gl.End();
//gl.Flush();
}

gl.Rotate(spin, 0f, 0f, 1f);
gl.Color(star[loop].r, star[loop].g, star[loop].b, 1f);
gl.Begin(OpenGL.QUADS);
gl.TexCoord(0.0f, 0.0f); gl.Vertex(-1.0f, -1.0f, 0.0f);   // Bottom Left Of The Texture and Quad
gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, -1.0f, 0.0f);   // Bottom Right Of The Texture and Quad
gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 1.0f, 0.0f);   // Top Right Of The Texture and Quad
gl.TexCoord(0.0f, 1.0f); gl.Vertex(-1.0f, 1.0f, 0.0f);   // Top Left Of The Texture and Quad
gl.End();
spin += 0.01f;
star[loop].angle += ( float)loop / starnumber;
star[loop].dist -= 0.01f;
if (star[loop].dist < 0.0f)
{
star[loop].dist += 5f;
byte[] starcolor = new byte[3];
rand.NextBytes(starcolor);
star[loop].r = ( float)starcolor[0] / 255;
star[loop].g = ( float)starcolor[1] / 255;
star[loop].b = ( float)starcolor[2] / 255;
}
}


}

3 按键处理

用T键关闭或打开闪烁事件
SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
switch (e.KeyCode)
{
case Keys.T:
twinkle = !twinkle;
break;
default:
break;
}
 
此部分源代码: 下载
 

4 执行效果

 

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