SlimDX: Direct3D9 Lightning Problem

Started by
4 comments, last by Nik02 14 years ago
I am creating a simple application to get familiar with SlimDX library. I found some code written in MDX and I'm trying to convert it to run on SlimDX. I am having some problems with the light because everything is being shown as black. The code is:

	public partial class DirectTest : Form
	{
		private Device device= null;
		private float angle = 0.0f;
		Light light = new Light();

		public DirectTest()
		{
			InitializeComponent();

			this.Size = new Size(800, 600);
			this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
		}
		/// <summary>
		/// We will initialize our graphics device here
		/// </summary>
		public void InitializeGraphics()
		{
			PresentParameters pres_params = new PresentParameters()
			{
				Windowed = true,
				SwapEffect = SwapEffect.Discard
			};
			device = new Device(new Direct3D(), 0, DeviceType.Hardware, this.Handle, 
						CreateFlags.SoftwareVertexProcessing, pres_params);
		}

		private void SetupCamera()
		{
			device.SetRenderState(RenderState.CullMode, Cull.None);
			device.SetTransform(TransformState.World, Matrix.RotationAxis(new Vector3(angle / ((float)Math.PI * 2.0f),
							 angle / ((float)Math.PI * 4.0f), angle / ((float)Math.PI * 6.0f)),
							angle / (float)Math.PI));
			angle += 0.1f;
			device.SetTransform(TransformState.Projection, Matrix.PerspectiveFovLH((float)Math.PI /
				4, this.Width / this.Height, 1.0f, 100.0f));
			device.SetTransform(TransformState.View, Matrix.LookAtLH(new Vector3(0, 0, 5.0f),
				new Vector3(), new Vector3(0, 1, 0)));
			device.SetRenderState(RenderState.Lighting, false);
		}

		protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
		{
			device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.CornflowerBlue, 1.0f, 0);
			SetupCamera();

			CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];
			verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f);
			verts[0].Normal = new Vector3(0.0f, 0.0f, -1.0f);
			verts[0].Color = System.Drawing.Color.White.ToArgb();
			verts[1].Position = new Vector3(-1.0f, -1.0f, 1.0f);
			verts[1].Normal = new Vector3(0.0f, 0.0f, -1.0f);
			verts[1].Color = System.Drawing.Color.White.ToArgb();
			verts[2].Position = new Vector3(1.0f, -1.0f, 1.0f);
			verts[2].Normal = new Vector3(0.0f, 0.0f, -1.0f);
			verts[2].Color = System.Drawing.Color.White.ToArgb();

			light.Type = LightType.Point;
			light.Position = new Vector3();
			light.Diffuse = System.Drawing.Color.White;
			light.Attenuation0 = 0.2f;
			light.Range = 10000.0f;

			device.SetLight(0, light);
			device.EnableLight(0, true);

			device.BeginScene();

			device.VertexFormat = CustomVertex.PositionColored.format;
			device.DrawUserPrimitives<CustomVertex.PositionColored>(PrimitiveType.TriangleList, 1, verts);
			device.EndScene();

			device.Present();
			this.Invalidate();
		}
	}
}


The Vertex Format that I am using is the following

    	[StructLayout(LayoutKind.Sequential)]
		public struct PositionNormalColored
		{
			public Vector3 Position;
			public int Color;
			public Vector3 Normal;
			public static readonly VertexFormat format = VertexFormat.Diffuse | VertexFormat.Position | VertexFormat.Normal;
		}


Any suggestions on what the problem might be? Thanks in Advance
Advertisement
In the code I pasted I had a mistake, because I was changing the code to see what's going wrong, and I didn't revert it back. Instead of
CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];			verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f);			verts[0].Normal = new Vector3(0.0f, 0.0f, -1.0f);			verts[0].Color = System.Drawing.Color.White.ToArgb();			verts[1].Position = new Vector3(-1.0f, -1.0f, 1.0f);			verts[1].Normal = new Vector3(0.0f, 0.0f, -1.0f);			verts[1].Color = System.Drawing.Color.White.ToArgb();			verts[2].Position = new Vector3(1.0f, -1.0f, 1.0f);			verts[2].Normal = new Vector3(0.0f, 0.0f, -1.0f);			verts[2].Color = System.Drawing.Color.White.ToArgb();


it should be:
CustomVertex.PositionNormalColored[] verts = new CustomVertex.PositionNormalColored[3];			verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f);			verts[0].Normal = new Vector3(0.0f, 0.0f, -1.0f);			verts[0].Color = System.Drawing.Color.White.ToArgb();			verts[1].Position = new Vector3(-1.0f, -1.0f, 1.0f);			verts[1].Normal = new Vector3(0.0f, 0.0f, -1.0f);			verts[1].Color = System.Drawing.Color.White.ToArgb();			verts[2].Position = new Vector3(1.0f, -1.0f, 1.0f);			verts[2].Normal = new Vector3(0.0f, 0.0f, -1.0f);			verts[2].Color = System.Drawing.Color.White.ToArgb();
Not an expert on raw vertices, but how about adding a material?
I'm not an expert in SlimDX specifically, but:

-Raw D3D9 has a render state that enables the fixed-function lighting engine globally. I don't see a call that would be equivalent to that in your code. Raw RS code is D3DRS_LIGHTING.

-There is also a render state that determines where the lighting engine gets its material diffuse color source. You cannot use both vertex colors and color calculated by light*material at the same time (while using fixed function lighting), but you can switch between the sources at will. See D3DRS_DIFFUSEMATERIALSOURCE and equivalent in SlimDX.

-As "Narf the Mouse" said, you need to set a material to the device if you want to use the built-in lighting engine.

Do consider using vertex shaders for new code. It is an infinitely more flexible approach than fixed-function T/L. You do have to write a little bit more code because you have to define the concepts of "light" and "material" yourself, but this stuff has well-defined and public formulas all around the net.

Niko Suni

So I still need to specify a material, and change the way colors are specified.
Thanks a lot for the reply I will try to use vertex shaders and get to know a bit more about materials in SlimDX
Note that when you use shaders, you define the concept of "material" and "light" yourself. You can't use the D3D fixed function lighting at the same time.

It is very easy to emulate the fixed-function lighting in the vertex shader, though - diffuse lighting is simple n dot l formula, and specular uses the Phong half-angle formula. Ambient lighting is a simple constant factor added to diffuse and specular, as is emissive lighting.

The DX SDK supplies the formulas for the lighting engine in the topic "Mathematics of Lighting (Direct3D 9)" from which it is relatively simple to derive corresponding vertex shader code.

Niko Suni

This topic is closed to new replies.

Advertisement