本文基础:
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 来关闭相应灯查看灯光颜色叠加效果。
版权声明:本文为luozhuang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。