本文基础:​​C#+OpenGL编程之环境搭建​​

  现在是第四章 OpenGL 光照,这章开始,我遇到麻烦了,因为原书的auxSolidSphere这个函数,C# 没有封装,我就把例程修改为:

  3个光源,一个正方形。

  

using System;
using System.Collections.Generic;
using System.Text;
using Tao.OpenGl;
using Tao.Glfw;

namespace OpenGL
{
class light : Examplefirst
{
/** 定义三个光源(红色 绿色和蓝色)的位置 */
static float[] lightPositionR = new float[] { 0.0f, 0.0f, 5.0f, 1.0f };
static float[] lightPositionG = new float[] { 0.0f, 0.0f, 5.0f, 1.0f };
static float[] lightPositionB = new float[] { 0.0f, 0.0f, 5.0f, 1.0f };

/** 定义三个光源的漫射光 */
static float[] diffuseLightR = new float[] { 1.0f, 0.0f, 0.0f, 1.0f };
static float[] diffuseLightG = new float[] { 0.0f, 1.0f, 0.0f, 1.0f };
static float[] diffuseLightB = new float[] { 0.0f, 0.0f, 1.0f, 1.0f };

/** 定义三个光源的镜面光 */
static float[] specularLightR = new float[] { 1.0f, 0.0f, 0.0f, 1.0f };
static float[] specularLightG = new float[] { 0.0f, 1.0f, 0.0f, 1.0f };
static float[] specularLightB = new float[] { 0.0f, 0.0f, 1.0f, 1.0f };

/** 再定义一个默认的光源 */
static float[] diffuseLight = new float[] { 0.8f, 0.8f, 0.8f, 1.0f };
static float[] specularLight = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
static float[] lightPosition = new float[] { 0.0f, 0.0f, 10.0f, 1.0f };

float m_Angle = 0.0f; /**< 设置初始角度为0 */

public light()
: base()
{

base.title = "第四章 OpenGL 光照";
}





/// <summary>
/// 初始化视口投影,恢复原书的视口
/// </summary>
public override void iniView(int windowWidth, int windowHeight)
{


Glu.gluPerspective(45.0f, windowWidth / windowHeight, 1.0f, 100.0f);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();

/** 设置0号光源 */
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, diffuseLight);
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_SPECULAR, specularLight);
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, lightPosition);

/** 设置1号红色光源 */
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, diffuseLightR);
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_SPECULAR, specularLightR);
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, lightPositionR);

/** 设置2号绿色光源 */
Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_DIFFUSE, diffuseLightG);
Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_SPECULAR, specularLightG);
Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_POSITION, lightPositionG);

/** 设置3号蓝色光源 */
Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_DIFFUSE, diffuseLightB);
Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_SPECULAR, specularLightB);
Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_POSITION, lightPositionB);

Gl.glEnable(Gl.GL_LIGHT0); /**< 启用0号灰色光源,让物体可见 */
Gl.glEnable(Gl.GL_LIGHTING);
//虽然我们没有用到纹理,不过如果你没有执行NORMALIZE,立方体将是个灰色的(不正确的)。
Gl.glEnable(Gl.GL_NORMALIZE);
}

/// <summary>
/// 重载,使用Draw方法绘图
/// </summary>
/// <param name="mouseX"></param>
/// <param name="currentTime"></param>
public override void DrawGLScene(int mouseX, double currentTime)
{
Draw();
}

/// <summary>
/// 重载
/// </summary>
/// <param name="mouseX"></param>
/// <param name="currentTime"></param>
public override void Update(float milliseconds)
{
//按下ESC结束
isRunning = ((Glfw.glfwGetKey(Glfw.GLFW_KEY_ESC) == Glfw.GLFW_RELEASE) &&
Glfw.glfwGetWindowParam(Glfw.GLFW_OPENED) == Gl.GL_TRUE);

/** 更新红色光源 */
if (Glfw.glfwGetKey(Glfw.GLFW_KEY_F1) == Glfw.GLFW_RELEASE) /**< 当数字'1'键没有被按下时 */
{
Gl.glEnable(Gl.GL_LIGHT1); /**< 启用1号红色光源*/

}
else
{
Gl.glDisable(Gl.GL_LIGHT1);
/**< 当被按下时,禁用该光源 */
}


/** 更新绿色光源 */
if (Glfw.glfwGetKey(Glfw.GLFW_KEY_F2) == Glfw.GLFW_RELEASE) /**< 当数字'2'键没有被按下时 */
{
Gl.glEnable(Gl.GL_LIGHT2); /**< 启用2号绿色光源 */
}
else
{

Gl.glDisable(Gl.GL_LIGHT2); /**< 当被按下时,禁用该光源 */
}


/** 更新蓝色光源 */
if (Glfw.glfwGetKey(Glfw.GLFW_KEY_F3) == Glfw.GLFW_RELEASE) /**< 当数字'3'键没有被按下时 */
{
Gl.glEnable(Gl.GL_LIGHT3); /**< 启用3号蓝色光源*/

}
else
{
Gl.glDisable(Gl.GL_LIGHT3); /**< 当被按下时,禁用该光源 */
}
m_Angle = m_Angle + milliseconds * 10;

}

/** 绘制函数 */
void Draw()
{
/** 用户自定义的绘制过程 */

Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glLoadIdentity();




/** 设置红色光源位置 */
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, lightPositionR);


/** 设置绿色光源位置 */
Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_POSITION, lightPositionG);



/** 设置蓝色光源位置 */
Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_POSITION, lightPositionB);



/** 绘制一个球体 */
Gl.glPushMatrix();
/**< 设置旋转 */
Gl.glTranslatef(0.0f, 0.0f, -30.0f); /**< 移入屏幕 */
Gl.glRotatef(m_Angle, 1.0f, 0.0f, 0.0f);
Gl.glRotatef(m_Angle, 0.0f, 1.0f, 0.0f);
Gl.glRotatef(m_Angle, 0.0f, 0.0f, 1.0f);
auxSolidSphere(2.5f);
Gl.glPopMatrix();

Gl.glFlush(); /**< 强制执行所有的OpenGl.GL命令 */
}

/// <summary>
/// 由于没有auxSolidSphere这个辅助函数,我做了修改,改为正方形
/// </summary>
/// <param name="p"></param>
private void auxSolidSphere(float p)
{
Gl.glPushMatrix();

Gl.glColor3f(1.0f, 0.0f, 0.0f); /**< 红色 */
Gl.glScalef(p, p, p);
DrawCube();
Gl.glPopMatrix();

}

public void DrawCube()
{
Gl.glBegin(Gl.GL_QUADS);

Gl.glColor3f(1, 0, 0);
Gl.glVertex3f(-1.0f, -1.0f, -1.0f);
Gl.glVertex3f(-1.0f, 1.0f, -1.0f);
Gl.glVertex3f(1.0f, 1.0f, -1.0f);
Gl.glVertex3f(1.0f, -1.0f, -1.0f);

Gl.glColor3f(1, 1, 0);
Gl.glVertex3f(-1.0f, -1.0f, -1.0f);
Gl.glVertex3f(1.0f, -1.0f, -1.0f);
Gl.glVertex3f(1.0f, -1.0f, 1.0f);
Gl.glVertex3f(-1.0f, -1.0f, 1.0f);

Gl.glColor3f(1, 0, 1);
Gl.glVertex3f(-1.0f, -1.0f, -1.0f);
Gl.glVertex3f(-1.0f, -1.0f, 1.0f);
Gl.glVertex3f(-1.0f, 1.0f, 1.0f);
Gl.glVertex3f(-1.0f, 1.0f, -1.0f);

Gl.glColor3f(0, 1, 0);
Gl.glVertex3f(-1.0f, -1.0f, 1.0f);
Gl.glVertex3f(1.0f, -1.0f, 1.0f);
Gl.glVertex3f(1.0f, 1.0f, 1.0f);
Gl.glVertex3f(-1.0f, 1.0f, 1.0f);

Gl.glColor3f(0, 0, 1);
Gl.glVertex3f(-1.0f, 1.0f, -1.0f);
Gl.glVertex3f(-1.0f, 1.0f, 1.0f);
Gl.glVertex3f(1.0f, 1.0f, 1.0f);
Gl.glVertex3f(1.0f, 1.0f, -1.0f);

Gl.glColor3f(0, 1, 1);
Gl.glVertex3f(1.0f, -1.0f, -1.0f);
Gl.glVertex3f(1.0f, 1.0f, -1.0f);
Gl.glVertex3f(1.0f, 1.0f, 1.0f);
Gl.glVertex3f(1.0f, -1.0f, 1.0f);

Gl.glEnd();
}

}
}

  程序我们用到了Update重载来计算动画变量,在我的机器上只用时间差值太慢,我

时间差值X10作为动画时间,大家可以根据自己机器修改。

  程序运行结果与原书不同,一个白色的正方形,因为三个颜色红 绿 蓝叠加就是白色,大家可以通过按住键盘F1 F2 F3 来关闭相应灯查看灯光颜色叠加效果。