Pheet 6 - Prince Sultan University

advertisement
Prince Sultan University
College of Computer & Information Science
Department of Computer Science
CS360: Computer Graphics
Practice Sheet 6 : Lighting a Sphere (GameWin class Application)
Objective:
The main purpose of this practice sheet is to illustrate how lighting sources and light effects are
simulated in openGL. OpenGL supports up to 8 light sources that may be used to light a model:
Light0, Light1, Light3, …., Light7.
The light coming out of a light source is usually directional consisting of two major components:
Diffuse and Specular. We add to this the global Ambient component, which is supposed to be
directionless. Another major attribute of a light source is its position in 3D space.
The example used in this sheet uses a sphere to illustrate the effect of light and shading on a
given object. The light source and its light components are specified at initialization stage.
1
Creating a an OpenTK GameWin Application:
1- Create a normal Console Application, name it SphereLighting.
2- Add references to the following libraries:
a. OpenTK, GLControl, OpenTKCompatibiliy
b. System.Windows.Forms
c. System.Drawing
Enabling the Lighting Model and Specifying the Light Source:
The Light source and its attributes are defined in the method initLight() below. The method also
enables a number of capabilities including the Lighting model:
private void initLight()
{
float[]
float[]
float[]
float[]
float[]
mat_specular = { 1.0f, 0.0f, 0.0f, 1.0f };
mat_shininess = { 97.0f };
light_position = { 10.0f, 0.0f, 0.0f, 0.0f };
light_ambient = { 1.0f, 0.5f, 0.0f, 1.0f };
light_diffuse = { 0.8f, 0.8f, 0.8f, 1.0f };
GL.ClearColor(Color.CornflowerBlue);
GL.ShadeModel(ShadingModel.Smooth);
GL.Material(MaterialFace.Front, MaterialParameter.Specular,
mat_specular);
GL.Material(MaterialFace.Front, MaterialParameter.Shininess,
mat_shininess);
GL.Light(LightName.Light0, LightParameter.Position, light_position);
GL.Light(LightName.Light0, LightParameter.Ambient, light_ambient);
GL.Light(LightName.Light0, LightParameter.Diffuse, light_diffuse);
GL.Light(LightName.Light0, LightParameter.Specular, mat_specular);
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.ColorMaterial);
// GL.Enable(EnableCap.CullFace);
}
Note the Ambient, Diffuse and Specular Components.
2
The Full Applications:
Replace the dummy code in the Console Application you created with this code:
using
using
using
using
using
System;
System.Windows.Forms;
System.Drawing;
OpenTK;
OpenTK.Graphics;
namespace OpenTKCircle
{
class Program : GameWindow
{
Matrix4 matrixProjection, matrixModelview;
float cameraRotation = 0f;
private void initLight()
{
float[] mat_specular = { 1.0f, 0.0f, 0.0f, 1.0f };
float[] mat_shininess = { 97.0f };
float[] light_position = { 10.0f, 0.0f, 0.0f, 0.0f };
float[] light_ambient = { 1.0f, 0.5f, 0.0f, 1.0f };
float[] light_diffuse = { 0.8f, 0.8f, 0.8f, 1.0f };
GL.ClearColor(Color.CornflowerBlue);
GL.ShadeModel(ShadingModel.Smooth);
GL.Material(MaterialFace.Front, MaterialParameter.Specular,
mat_specular);
GL.Material(MaterialFace.Front, MaterialParameter.Shininess,
mat_shininess);
GL.Light(LightName.Light0, LightParameter.Position, light_position);
GL.Light(LightName.Light0, LightParameter.Ambient, light_ambient);
GL.Light(LightName.Light0, LightParameter.Diffuse, light_diffuse);
GL.Light(LightName.Light0, LightParameter.Specular, mat_specular);
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.ColorMaterial);
// GL.Enable(EnableCap.CullFace);
}
protected override void OnLoad(EventArgs e)
{
//GL.ClearColor(Color)
GL.ClearColor(Color.CornflowerBlue);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace);
GL.EnableClientState(EnableCap.VertexArray);
GL.EnableClientState(EnableCap.ColorArray);
initLight();
}
protected override void OnResize(EventArgs e)
{
GL.Viewport(0, 0, Width, Height);
3
matrixProjection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI
/ 4, Width / (float)Height, 1f, 100f);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref matrixProjection);
}
public static Vertex[] CalculateVertices2(float radius, float height, byte
segments, byte rings)
{
var data = new Vertex[segments * rings];
int i = 0;
for (double y = 0; y < rings; y++)
{
double phi = (y / (rings - 1)) * Math.PI;
for (double x = 0; x < segments; x++)
{
double theta = (x / (segments - 1)) * 2 * Math.PI;
Vector3 v = new Vector3()
{
X = (float)(radius * Math.Sin(phi) * Math.Cos(theta)),
Y = (float)(height * Math.Cos(phi)),
Z = (float)(radius * Math.Sin(phi) * Math.Sin(theta)),
};
Vector3 n = Vector3.Normalize(v);
Vector2 uv = new Vector2()
{
X = (float)(x / (segments - 1)),
Y = (float)(y / (rings - 1))
};
data[i] = new Vertex() { Position = v, Normal = n, TexCoord = uv };
i++;
}
}
return data;
}
public static ushort[] CalculateElements(float radius, float height, byte
segments, byte rings)
{
var num_vertices = segments * rings;
var data = new ushort[num_vertices * 6];
ushort i = 0;
for (byte y = 0; y < rings - 1; y++)
{
for (byte x = 0; x < segments - 1; x++)
{
data[i++] = (ushort)((y + 0) * segments + x);
data[i++] = (ushort)((y + 1) * segments + x);
4
data[i++] = (ushort)((y + 1) * segments + x + 1);
data[i++] = (ushort)((y + 1) * segments + x + 1);
data[i++] = (ushort)((y + 0) * segments + x + 1);
data[i++] = (ushort)((y + 0) * segments + x);
}
}
// Verify that we don't access any vertices out of bounds:
foreach (int index in data)
if (index >= segments * rings)
throw new IndexOutOfRangeException();
return data;
}
public struct Vertex
{
public Vector2 TexCoord;
public Vector3 Normal;
public Vector3 Position;
}
//Draw the Sphere
protected override void OnRenderFrame(OpenTK.FrameEventArgs e)
{
base.OnRenderFrame(e);
initLight();
cameraRotation = (cameraRotation < 360f) ? (cameraRotation + 1f *
(float)e.Time) : 0f;
// MessageBox.Show(e.Time.ToString());
Matrix4.CreateRotationY(cameraRotation, out matrixModelview);
matrixModelview *= Matrix4.LookAt(0f, 0f, -5f, 0f, 0f, 0f, 0f, 1f,
0f);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref matrixModelview);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
Vertex[] SphereVertices = CalculateVertices2(0.5f, 0.5f, 100, 100);
ushort[] SphereElements = CalculateElements(0.5f, 0.5f, 100, 100);
GL.Clear(ClearBufferMask.ColorBufferBit |
ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref matrixModelview);
GL.Begin(BeginMode.Triangles);
foreach (var element in SphereElements)
{
var vertex = SphereVertices[element];
GL.TexCoord2(vertex.TexCoord);
GL.Normal3(vertex.Normal);
GL.Vertex3(vertex.Position);
}
5
GL.End();
SwapBuffers();
}
[STAThread]
private static void Main(string[] args)
{
using (Program p = new Program())
{
p.Run(60d);
}
}
}
}
Answer the Following Questions:
1- Explain how the sphere vertices and indices are computed. Try to deduce the equations
used.
2- What are the rings and segments used in computing the sphere elements? Use a
diagram to explain. How many segments and rings have been used?
3- What is the significance of computing and using normals in drawing the model?
4- What are the transformations used in rendering this model and in what order have they
been applied.
6
Download