Jump to content

  • Log In with Google      Sign In   
  • Create Account


#ActualMegafont

Posted 11 November 2012 - 06:22 PM

Hi and thank you very much. I did a little research into how to setup my structure properly. It no longer is drawing nonsense on the screen, but the problem is that now it draws absolutely nothing on the screen after it clears it each frame. I'm not sure what's going on but obviously something somewhere is still screwed up unfortunately.

Here is what my code looks like now with the structure updated, and I also now copy the structure into the constant buffer using Marshal.StructureToPtr().
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SlimDX;
using SlimDX.D3DCompiler;
using SlimDX.Direct3D11;
using Buffer = SlimDX.Direct3D11.Buffer;		// I added this line to fix ambiguity between SlimDX.Direct3D11.Buffer and System.Buffer.  This tells it to use the SlimDX Buffer class rather than the one in the System namespace when I reference the type Buffer.
using SlimDX.DXGI;
using SlimDX.Windows;
using Device = SlimDX.Direct3D11.Device;
using Resource = SlimDX.Direct3D11.Resource;

//--------------------------------------------------------------------------------------
// NOTE:
//--------------------------------------------------------------------------------------
// I modified this program and its shaders.fx file to help with debugging a bug that
// I was having a hell of a time solving. See the note at the top of the shaders.fx
// file for info on changes I made to that file.
//--------------------------------------------------------------------------------------
namespace Test_1
{
	struct SimpleVertex
	{
		Vector3 Position;
		Vector3 Normal;
		Vector4 Color;
		public SimpleVertex(Vector3 position, Vector3 normal, Vector4 color)
		{
			Position = position;
			Normal = normal;
			Color = color;
		}
	};

	[StructLayout(LayoutKind.Sequential, Pack=1)]
	struct ConstantBufferStruct
	{
		public Matrix mWorld;
		public Matrix mView;
		public Matrix mProjection;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
		public Vector4[] vLightDir;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
		public Vector4[] vLightColor;
	  
		public Vector4 vOutputColor;
	};

	static class Program
	{
		static float rotationY = 0.785f;	 // Y Rotation in radians per second   (0.785 radians = 45 degrees)

		static int startTime;
		static int curTime;
		static RenderForm form;
		static Buffer constantBuffer;
		static Buffer indexBuffer;
		static Buffer vertexBuffer;
		static DataStream constants;
		static DataStream indices;
		static DataStream vertices;
		static DepthStencilView depthStencilView;
		static Device device;
		static DeviceContext context;
		static InputLayout layout;
		static PixelShader pixelShader;
		static PixelShader pixelShaderSolid;
		static PixelShader pixelShaderColor;
		static RenderTargetView renderTarget;
		static ShaderSignature inputSignature;
		static SwapChain swapChain;
		static Texture2D depthStencil;
		static VertexShader vertexShader;
		static Viewport viewport;
		static Matrix matrix_World;
		static Matrix matrix_View;
		static Matrix matrix_Projection;
		static ConstantBufferStruct cbStruct = new ConstantBufferStruct();

		static void Main()
		{
			form = new RenderForm("OMG a Window!!");
			var description = new SwapChainDescription()
			{
				BufferCount = 2,
				Usage = Usage.RenderTargetOutput,
				OutputHandle = form.Handle,
				IsWindowed = true,
				ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
				SampleDescription = new SampleDescription(1, 0),
				Flags = SwapChainFlags.AllowModeSwitch,
				SwapEffect = SwapEffect.Discard
			};

			Device.CreateWithSwapChain(DriverType.Hardware,
									   DeviceCreationFlags.Debug,
									   description,
									   out device,
									   out swapChain);

			// create a view of our render target, which is the backbuffer of the swap chain we just created
			using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
			{
				renderTarget = new RenderTargetView(device, resource);
			};

			// Create the depth stencil texture
			Texture2DDescription depthStencilDesc = new Texture2DDescription();
			depthStencilDesc.Width = form.ClientSize.Width;
			depthStencilDesc.Height = form.ClientSize.Height;
			depthStencilDesc.MipLevels = 1;
			depthStencilDesc.ArraySize = 1;
			depthStencilDesc.Format = Format.D24_UNorm_S8_UInt;
			depthStencilDesc.SampleDescription = new SampleDescription(1, 0);
			depthStencilDesc.Usage = ResourceUsage.Default;
			depthStencilDesc.BindFlags = BindFlags.DepthStencil;
			depthStencilDesc.CpuAccessFlags = CpuAccessFlags.None;
			depthStencilDesc.OptionFlags = ResourceOptionFlags.None;
			depthStencil = new Texture2D(device, depthStencilDesc);

			// Create the Depth Stencil View
			DepthStencilViewDescription depthStencilViewDesc = new DepthStencilViewDescription();
			depthStencilViewDesc.Format = depthStencilDesc.Format;
			depthStencilViewDesc.Dimension = DepthStencilViewDimension.Texture2D;
			depthStencilViewDesc.MipSlice = 0;
			depthStencilView = new DepthStencilView(device, depthStencil, depthStencilViewDesc);
			// setting a viewport is required if you want to actually see anything
			context = device.ImmediateContext;
			viewport = new Viewport(0.0f,
									0.0f,
									form.ClientSize.Width,
									form.ClientSize.Height,
									0.0f,
									1.0f);
			context.OutputMerger.SetTargets(depthStencilView, renderTarget);
			context.Rasterizer.SetViewports(viewport);

			// Setup our shaders
			InitShaders();

			// Setup our vertex data
			InitVertexData();

			// Setup our matrices
			InitMatrices();

			// Set the shaders
			context.VertexShader.Set(vertexShader);
			context.PixelShader.Set(pixelShader);

			// Prevent DXGI handling of Alt+Enter, which doesn't work properly with Winforms
			using (var factory = swapChain.GetParent<Factory>())
			{
				factory.SetWindowAssociation(form.Handle,
											 WindowAssociationFlags.IgnoreAltEnter);
			};

			// Handle Alt+Enter ourselves
			form.KeyDown += (o, e) =>
			{
				if (e.Alt && e.KeyCode == Keys.Enter)
				{
					swapChain.IsFullScreen = !swapChain.IsFullScreen;
				}
			};

			// Handle form size changes
			form.UserResized += (o, e) =>
			{
				renderTarget.Dispose();
				depthStencil.Dispose();
				depthStencilView.Dispose();

				swapChain.ResizeBuffers(2,
										0,
										0,
										Format.R8G8B8A8_UNorm,
										SwapChainFlags.AllowModeSwitch);

				using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
				{
					renderTarget = new RenderTargetView(device, resource);
				}

				depthStencilDesc.Width = form.ClientSize.Width;
				depthStencilDesc.Height = form.ClientSize.Height;
				depthStencil = new Texture2D(device, depthStencilDesc);
				depthStencilView = new DepthStencilView(device, depthStencil, depthStencilViewDesc);

				context.OutputMerger.SetTargets(depthStencilView, renderTarget);
				context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
			};
			startTime = Environment.TickCount;
			MessagePump.Run(form, RenderFrame);


			// Clean up all resources
			// anything we missed will show up in the IDE's debug output
			vertices.Close();
			vertexBuffer.Dispose();
			layout.Dispose();
			inputSignature.Dispose();
			vertexShader.Dispose();
			pixelShader.Dispose();
			renderTarget.Dispose();
			swapChain.Dispose();
			device.Dispose();
			indexBuffer.Dispose();
			indices.Dispose();
			constantBuffer.Dispose();
			constants.Dispose();
			depthStencil.Dispose();
			depthStencilView.Dispose();
			pixelShaderSolid.Dispose();
			pixelShaderColor.Dispose();
		}

		static void InitShaders()
		{
			// load and compile the vertex shader
			string vsCompileError = "Vertex Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "VS", "vs_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out vsCompileError))
			{
				inputSignature = ShaderSignature.GetInputSignature(bytecode);
				vertexShader = new VertexShader(device, bytecode);
			}

			// load and compile the pixel shader
			string psCompileError = "Pixel Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PS", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
			{
				pixelShader = new PixelShader(device, bytecode);
			}
			// load and compile the solid pixel shader
			psCompileError = "Solid Pixel Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PSSolid", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
			{
				pixelShaderSolid = new PixelShader(device, bytecode);
			}
			// load and compile the color pixel shader
			psCompileError = "Color Pixel Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PSColor", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
			{
				pixelShaderColor = new PixelShader(device, bytecode);
			}
		}
		static void InitMatrices()
		{
			// world matrix	  
			matrix_World = Matrix.Identity;
			// view matrix
			Vector3 vEye = new Vector3(0.0f, 4.0f, -10.0f);
			Vector3 vLookAt = new Vector3(0.0f, 1.0f, 0.0f);
			Vector3 vUp = new Vector3(0.0f, 1.0f, 0.0f);
			matrix_View = Matrix.LookAtLH(vEye,
										  vLookAt,
										  vUp);

			// projection matrix
			matrix_Projection = Matrix.PerspectiveFovLH((float)Math.PI / 2,  // Vertical Field of View
														(float)form.ClientSize.Width / (float)form.ClientSize.Height,  // Aspect Ratio
														0.01f,  // Near Z
														100.0f);  // Far Z

			// Write the matrices we just generated into the DataStream
			cbStruct.mWorld = Matrix.Transpose(matrix_World);
			cbStruct.mView = Matrix.Transpose(matrix_View);
			cbStruct.mProjection = Matrix.Transpose(matrix_Projection);
			cbStruct.vLightColor = new Vector4[2];
			cbStruct.vLightDir = new Vector4[2];
		  
			constants = new DataStream(Marshal.SizeOf(typeof(ConstantBufferStruct)), true, true);

			// If no specific marshalling is needed, can use
			// dataStream.Write(value) for better performance.		  
			Marshal.StructureToPtr(cbStruct, constants.DataPointer, false);
			ConstantBufferStruct temp = new ConstantBufferStruct();
			temp.vLightColor = new Vector4[2];
			temp.vLightColor = new Vector4[2];
			temp.vOutputColor = new Vector4(1.0f, 0.5f, 0.5f, 1.0f);
			temp = (ConstantBufferStruct) Marshal.PtrToStructure(constants.DataPointer, typeof(ConstantBufferStruct));
			if (temp.mWorld.Equals(cbStruct.mWorld) &&
				temp.mView.Equals(cbStruct.mView) &&
				temp.mProjection.Equals(cbStruct.mProjection))
			{
				System.Diagnostics.Debug.WriteLine("MATRICES ARE CORRECT!");
			}
			else
			{
				System.Diagnostics.Debug.WriteLine("MATRICES ARE NOT CORRECT!");
			}
			if (temp.vOutputColor.Equals(cbStruct.vOutputColor))
			{
				System.Diagnostics.Debug.WriteLine("OUTPUT COLOR IS CORRECT!");
			}
			else
			{
				System.Diagnostics.Debug.WriteLine("OUTPUT COLOR IS NOT CORRECT!");
			}
			// Create the constant buffer
			constantBuffer = new Buffer(device,
										constants,
										(int)constants.Length,
										ResourceUsage.Default,
										BindFlags.ConstantBuffer,
										CpuAccessFlags.None,
										ResourceOptionFlags.None,
										0);
			context.UpdateSubresource(new DataBox(0, 0, constants),
									  constantBuffer,
									  0);
			context.VertexShader.SetConstantBuffer(constantBuffer, 0);
		}
		static void InitVertexData()
		{
			// Create test vertex data, making sure to rewind the stream afterward.
			vertices = new DataStream(Marshal.SizeOf(new SimpleVertex(Vector3.Zero, Vector3.Zero, Vector4.Zero)) * 24, true, true);
			SimpleVertex[] tempVertexArray =
			{
				new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
			};

			foreach (SimpleVertex vertex in tempVertexArray)
			{
				vertices.Write(vertex);
			}
			vertices.Position = 0;

			// create the vertex layout and vertex buffer
			var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0),
								   new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0),
								   new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 24, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0)};
			layout = new InputLayout(device,
									 inputSignature,
									 elements);
			vertexBuffer = new Buffer(device,
									  vertices,
									  (int)vertices.Length,
									  ResourceUsage.Default,
									  BindFlags.VertexBuffer,
									  CpuAccessFlags.None,
									  ResourceOptionFlags.None,
									  0);

			// Setup the test index data, making sure to rewind the stream afterward.
			UInt16[] indicesList = { 3, 1, 0,
									 2, 1, 3,
									 6, 4, 5,
									 7, 4, 6,
									 11, 9, 8,
									 10, 9, 11,
									 14, 12, 13,
									 15, 12, 14,
									 19, 17, 16,
									 18, 17, 19,
									 22, 20, 21,
									 23, 20, 22
								   };
			// As you can see in the indices list above, we have 36 values total, each of which
			// is a UInt16 value (or 2-byte short integer)
			indices = new DataStream(36 * 2, true, true);
			foreach (UInt16 index in indicesList)
			{
				indices.Write(index);
			}
			indices.Position = 0;

			// Now create the index buffer.
			indexBuffer = new Buffer(device,
									 indices,
									 (int)indices.Length,
									 ResourceUsage.Default,
									 BindFlags.IndexBuffer,
									 CpuAccessFlags.None,
									 ResourceOptionFlags.None,
									 0);


			// Configure the Input Assembler portion of the graphics pipeline with the vertex data.
			context.InputAssembler.InputLayout = layout;
			context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
			context.InputAssembler.SetVertexBuffers(0,
													new VertexBufferBinding(vertexBuffer, 40, 0));
			context.InputAssembler.SetIndexBuffer(indexBuffer,
												  Format.R16_UInt,
												  0);
		}

		static void RenderFrame()
		{
			curTime = Environment.TickCount;
			float t = (curTime - startTime) / 1000.0f;   // Calculate elapsed time since start in seconds

			// 1st Cube: Rotate around the origin.
			matrix_World = Matrix.RotationY(t * rotationY);

			// Setup our lighting parameters
			Vector4[] vLightDirs =
			{
				new Vector4(-0.577f, 0.577f, -0.577f, 1.0f),
				new Vector4(0.0f, 0.0f, -1.0f, 1.0f)
			};
			Vector4[] vLightColors =
			{
				new Vector4(0.5f, 0.5f, 0.5f, 1.0f),
				new Vector4(0.5f, 0.0f, 0.0f, 1.0f)
			};

			// Rotate the second light around the origin
			Matrix mRotate = Matrix.RotationY(-2.0f * t);
			Vector4 vLightDir = vLightDirs[1];
			vLightDir = Vector4.Transform(vLightDir, mRotate);
			vLightDirs[1] = vLightDir;

			// Clear the render target to a soothing blue
			context.ClearRenderTargetView(renderTarget,
										  new Color4(0.0f, 0.125f, 0.3f, 1.0f));
			// Clear the Depth buffer to 1.0 (max depth)
			context.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);

			// Update the constant buffer variables
			cbStruct.mWorld = Matrix.Transpose(matrix_World);
			cbStruct.mView = Matrix.Transpose(matrix_View);
			cbStruct.mProjection = Matrix.Transpose(matrix_Projection);
			cbStruct.vLightDir[0] = vLightDirs[0];
			cbStruct.vLightDir[1] = vLightDirs[1];
			cbStruct.vLightColor[0] = vLightColors[0];
			cbStruct.vLightColor[1] = vLightColors[1];
			cbStruct.vOutputColor = new Vector4(0, 0, 0, 0);
			// If no specific marshalling is needed, can use
			// dataStream.Write(value) for better performance.		  
			Marshal.StructureToPtr(cbStruct, constants.DataPointer, false);
		  
			// Give GPU updated matrices data.
			context.UpdateSubresource(new DataBox(0, 0, constants),
									  constantBuffer,
									  0);

			// Render the cube
			context.VertexShader.Set(vertexShader);
			context.VertexShader.SetConstantBuffer(constantBuffer, 0);
			context.PixelShader.Set(pixelShaderSolid);
			context.PixelShader.SetConstantBuffer(constantBuffer, 0);
			context.DrawIndexed(36,
								0,
								0);

		  
			// Render each light
			for (int m = 0; m < 2; m++)
			{
				Matrix mLight = Matrix.Translation(5.0f * new Vector3(vLightDirs[m].X, vLightDirs[m].Y, vLightDirs[m].Z));
				Matrix mLightScale = Matrix.Scaling(0.2f, 0.2f, 0.2f);
				mLight = mLightScale * mLight;
				// Update the world variable to reflect the current light
				cbStruct.mWorld = Matrix.Transpose(mLight);
				cbStruct.vOutputColor = vLightColors[m];
				// If no specific marshalling is needed, can use
				// dataStream.Write(value) for better performance.		  
				Marshal.StructureToPtr((object)cbStruct, constants.DataPointer, false);
				context.UpdateSubresource(new DataBox(0, 0, constants),
										 constantBuffer,
										 0);
				context.PixelShader.Set(pixelShaderSolid);

				context.DrawIndexed(36,
									0,
									0);
			}
		  
			// Present the frame we just rendered.
			swapChain.Present(0,
							  PresentFlags.None);
		}
	}
}

Thanks again for you're help and hopefully someone can help me solve this second issue. I'm just not sure whether the problem is still with the packing of the data in the constant buffer, or if the problem lies elsewhere. I don't know how to check to make sure that the data is getting into the constant buffer correctly. If its not, the arrays are where the problem lies, like you said, because the struct works fine in previous tutorials with the Matrices stored the same way, but there are no arrays in the struct in those tutorials.



UPDATE:
I got the demo to work by making a small function that writes all the data from the structure one item at a time into the DataStream using the DataStream.Write() method. The program is now working properly. It would seem that when I used Marshal.StructToPtr() it was doing something wrong. The two spots in the render code that update the Constant Buffer seemed to be fighting each other in some way. If I had one update using Marshal.StructToPtr() and the other using constants.Write(cbStruct), then half of the draw code would work. Which half works was determined by which way I set up the two updates. So if I flipped it so the first update used constants.Write(cbStruct) and the second update of the constant buffer used Marshal.StructToPtr(), then the other half of the render code worked but the half that worked before stopped working. If both updates use constants.Write(cbStruct) or if both updates use Marshal.StructToPtr(), then I get an empty screen with nothing but the background color. Very strange indeed.

When I change the Render code so that both of the updates to the Constant Buffer use my little util function that writes the data to the DataStream one item at a time using the DataStream.Write() method, the program works exactly as it should. Both halves of the render code function correctly with this setup and I see 3 cubes on the screen with lighting on the center cube as expected.

So in short, the problem obviously has to do with the way the struct was getting written to the Constant Buffer when I used Marshal.StructToPtr(). So apparently there is still something not quite right about how my struct is set up. Here's what the struct looks like now. Let me know if I'm doing something wrong. Thanks.
	[StructLayout(LayoutKind.Sequential, Pack=1)]
	public struct ConstantBufferStruct
	{
		public Matrix mWorld;
		public Matrix mView;
		public Matrix mProjection;
	  
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
		public Vector4[] vLightDir;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
		public Vector4[] vLightColor;

		public Vector4 vOutputColor;
	};

#2Megafont

Posted 11 November 2012 - 06:18 PM

Hi and thank you very much. I did a little research into how to setup my structure properly. It no longer is drawing nonsense on the screen, but the problem is that now it draws absolutely nothing on the screen after it clears it each frame. I'm not sure what's going on but obviously something somewhere is still screwed up unfortunately.

Here is what my code looks like now with the structure updated, and I also now copy the structure into the constant buffer using Marshal.StructureToPtr().
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SlimDX;
using SlimDX.D3DCompiler;
using SlimDX.Direct3D11;
using Buffer = SlimDX.Direct3D11.Buffer;		// I added this line to fix ambiguity between SlimDX.Direct3D11.Buffer and System.Buffer.  This tells it to use the SlimDX Buffer class rather than the one in the System namespace when I reference the type Buffer.
using SlimDX.DXGI;
using SlimDX.Windows;
using Device = SlimDX.Direct3D11.Device;
using Resource = SlimDX.Direct3D11.Resource;

//--------------------------------------------------------------------------------------
// NOTE:
//--------------------------------------------------------------------------------------
// I modified this program and its shaders.fx file to help with debugging a bug that
// I was having a hell of a time solving. See the note at the top of the shaders.fx
// file for info on changes I made to that file.
//--------------------------------------------------------------------------------------
namespace Test_1
{
	struct SimpleVertex
	{
		Vector3 Position;
		Vector3 Normal;
		Vector4 Color;
		public SimpleVertex(Vector3 position, Vector3 normal, Vector4 color)
		{
			Position = position;
			Normal = normal;
			Color = color;
		}
	};

	[StructLayout(LayoutKind.Sequential, Pack=1)]
	struct ConstantBufferStruct
	{
		public Matrix mWorld;
		public Matrix mView;
		public Matrix mProjection;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
		public Vector4[] vLightDir;
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
		public Vector4[] vLightColor;
	  
		public Vector4 vOutputColor;
	};

	static class Program
	{
		static float rotationY = 0.785f;	 // Y Rotation in radians per second   (0.785 radians = 45 degrees)

		static int startTime;
		static int curTime;
		static RenderForm form;
		static Buffer constantBuffer;
		static Buffer indexBuffer;
		static Buffer vertexBuffer;
		static DataStream constants;
		static DataStream indices;
		static DataStream vertices;
		static DepthStencilView depthStencilView;
		static Device device;
		static DeviceContext context;
		static InputLayout layout;
		static PixelShader pixelShader;
		static PixelShader pixelShaderSolid;
		static PixelShader pixelShaderColor;
		static RenderTargetView renderTarget;
		static ShaderSignature inputSignature;
		static SwapChain swapChain;
		static Texture2D depthStencil;
		static VertexShader vertexShader;
		static Viewport viewport;
		static Matrix matrix_World;
		static Matrix matrix_View;
		static Matrix matrix_Projection;
		static ConstantBufferStruct cbStruct = new ConstantBufferStruct();

		static void Main()
		{
			form = new RenderForm("OMG a Window!!");
			var description = new SwapChainDescription()
			{
				BufferCount = 2,
				Usage = Usage.RenderTargetOutput,
				OutputHandle = form.Handle,
				IsWindowed = true,
				ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
				SampleDescription = new SampleDescription(1, 0),
				Flags = SwapChainFlags.AllowModeSwitch,
				SwapEffect = SwapEffect.Discard
			};

			Device.CreateWithSwapChain(DriverType.Hardware,
									   DeviceCreationFlags.Debug,
									   description,
									   out device,
									   out swapChain);

			// create a view of our render target, which is the backbuffer of the swap chain we just created
			using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
			{
				renderTarget = new RenderTargetView(device, resource);
			};

			// Create the depth stencil texture
			Texture2DDescription depthStencilDesc = new Texture2DDescription();
			depthStencilDesc.Width = form.ClientSize.Width;
			depthStencilDesc.Height = form.ClientSize.Height;
			depthStencilDesc.MipLevels = 1;
			depthStencilDesc.ArraySize = 1;
			depthStencilDesc.Format = Format.D24_UNorm_S8_UInt;
			depthStencilDesc.SampleDescription = new SampleDescription(1, 0);
			depthStencilDesc.Usage = ResourceUsage.Default;
			depthStencilDesc.BindFlags = BindFlags.DepthStencil;
			depthStencilDesc.CpuAccessFlags = CpuAccessFlags.None;
			depthStencilDesc.OptionFlags = ResourceOptionFlags.None;
			depthStencil = new Texture2D(device, depthStencilDesc);

			// Create the Depth Stencil View
			DepthStencilViewDescription depthStencilViewDesc = new DepthStencilViewDescription();
			depthStencilViewDesc.Format = depthStencilDesc.Format;
			depthStencilViewDesc.Dimension = DepthStencilViewDimension.Texture2D;
			depthStencilViewDesc.MipSlice = 0;
			depthStencilView = new DepthStencilView(device, depthStencil, depthStencilViewDesc);
			// setting a viewport is required if you want to actually see anything
			context = device.ImmediateContext;
			viewport = new Viewport(0.0f,
									0.0f,
									form.ClientSize.Width,
									form.ClientSize.Height,
									0.0f,
									1.0f);
			context.OutputMerger.SetTargets(depthStencilView, renderTarget);
			context.Rasterizer.SetViewports(viewport);

			// Setup our shaders
			InitShaders();

			// Setup our vertex data
			InitVertexData();

			// Setup our matrices
			InitMatrices();

			// Set the shaders
			context.VertexShader.Set(vertexShader);
			context.PixelShader.Set(pixelShader);

			// Prevent DXGI handling of Alt+Enter, which doesn't work properly with Winforms
			using (var factory = swapChain.GetParent<Factory>())
			{
				factory.SetWindowAssociation(form.Handle,
											 WindowAssociationFlags.IgnoreAltEnter);
			};

			// Handle Alt+Enter ourselves
			form.KeyDown += (o, e) =>
			{
				if (e.Alt && e.KeyCode == Keys.Enter)
				{
					swapChain.IsFullScreen = !swapChain.IsFullScreen;
				}
			};

			// Handle form size changes
			form.UserResized += (o, e) =>
			{
				renderTarget.Dispose();
				depthStencil.Dispose();
				depthStencilView.Dispose();

				swapChain.ResizeBuffers(2,
										0,
										0,
										Format.R8G8B8A8_UNorm,
										SwapChainFlags.AllowModeSwitch);

				using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
				{
					renderTarget = new RenderTargetView(device, resource);
				}

				depthStencilDesc.Width = form.ClientSize.Width;
				depthStencilDesc.Height = form.ClientSize.Height;
				depthStencil = new Texture2D(device, depthStencilDesc);
				depthStencilView = new DepthStencilView(device, depthStencil, depthStencilViewDesc);

				context.OutputMerger.SetTargets(depthStencilView, renderTarget);
				context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
			};
			startTime = Environment.TickCount;
			MessagePump.Run(form, RenderFrame);


			// Clean up all resources
			// anything we missed will show up in the IDE's debug output
			vertices.Close();
			vertexBuffer.Dispose();
			layout.Dispose();
			inputSignature.Dispose();
			vertexShader.Dispose();
			pixelShader.Dispose();
			renderTarget.Dispose();
			swapChain.Dispose();
			device.Dispose();
			indexBuffer.Dispose();
			indices.Dispose();
			constantBuffer.Dispose();
			constants.Dispose();
			depthStencil.Dispose();
			depthStencilView.Dispose();
			pixelShaderSolid.Dispose();
			pixelShaderColor.Dispose();
		}

		static void InitShaders()
		{
			// load and compile the vertex shader
			string vsCompileError = "Vertex Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "VS", "vs_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out vsCompileError))
			{
				inputSignature = ShaderSignature.GetInputSignature(bytecode);
				vertexShader = new VertexShader(device, bytecode);
			}

			// load and compile the pixel shader
			string psCompileError = "Pixel Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PS", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
			{
				pixelShader = new PixelShader(device, bytecode);
			}
			// load and compile the solid pixel shader
			psCompileError = "Solid Pixel Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PSSolid", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
			{
				pixelShaderSolid = new PixelShader(device, bytecode);
			}
			// load and compile the color pixel shader
			psCompileError = "Color Pixel Shader Compile Error!!!";
			using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PSColor", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
			{
				pixelShaderColor = new PixelShader(device, bytecode);
			}
		}
		static void InitMatrices()
		{
			// world matrix	  
			matrix_World = Matrix.Identity;
			// view matrix
			Vector3 vEye = new Vector3(0.0f, 4.0f, -10.0f);
			Vector3 vLookAt = new Vector3(0.0f, 1.0f, 0.0f);
			Vector3 vUp = new Vector3(0.0f, 1.0f, 0.0f);
			matrix_View = Matrix.LookAtLH(vEye,
										  vLookAt,
										  vUp);

			// projection matrix
			matrix_Projection = Matrix.PerspectiveFovLH((float)Math.PI / 2,  // Vertical Field of View
														(float)form.ClientSize.Width / (float)form.ClientSize.Height,  // Aspect Ratio
														0.01f,  // Near Z
														100.0f);  // Far Z

			// Write the matrices we just generated into the DataStream
			cbStruct.mWorld = Matrix.Transpose(matrix_World);
			cbStruct.mView = Matrix.Transpose(matrix_View);
			cbStruct.mProjection = Matrix.Transpose(matrix_Projection);
			cbStruct.vLightColor = new Vector4[2];
			cbStruct.vLightDir = new Vector4[2];
		  
			constants = new DataStream(Marshal.SizeOf(typeof(ConstantBufferStruct)), true, true);

			// If no specific marshalling is needed, can use
			// dataStream.Write(value) for better performance.		  
			Marshal.StructureToPtr(cbStruct, constants.DataPointer, false);
			ConstantBufferStruct temp = new ConstantBufferStruct();
			temp.vLightColor = new Vector4[2];
			temp.vLightColor = new Vector4[2];
			temp.vOutputColor = new Vector4(1.0f, 0.5f, 0.5f, 1.0f);
			temp = (ConstantBufferStruct) Marshal.PtrToStructure(constants.DataPointer, typeof(ConstantBufferStruct));
			if (temp.mWorld.Equals(cbStruct.mWorld) &&
				temp.mView.Equals(cbStruct.mView) &&
				temp.mProjection.Equals(cbStruct.mProjection))
			{
				System.Diagnostics.Debug.WriteLine("MATRICES ARE CORRECT!");
			}
			else
			{
				System.Diagnostics.Debug.WriteLine("MATRICES ARE NOT CORRECT!");
			}
			if (temp.vOutputColor.Equals(cbStruct.vOutputColor))
			{
				System.Diagnostics.Debug.WriteLine("OUTPUT COLOR IS CORRECT!");
			}
			else
			{
				System.Diagnostics.Debug.WriteLine("OUTPUT COLOR IS NOT CORRECT!");
			}
			// Create the constant buffer
			constantBuffer = new Buffer(device,
										constants,
										(int)constants.Length,
										ResourceUsage.Default,
										BindFlags.ConstantBuffer,
										CpuAccessFlags.None,
										ResourceOptionFlags.None,
										0);
			context.UpdateSubresource(new DataBox(0, 0, constants),
									  constantBuffer,
									  0);
			context.VertexShader.SetConstantBuffer(constantBuffer, 0);
		}
		static void InitVertexData()
		{
			// Create test vertex data, making sure to rewind the stream afterward.
			vertices = new DataStream(Marshal.SizeOf(new SimpleVertex(Vector3.Zero, Vector3.Zero, Vector4.Zero)) * 24, true, true);
			SimpleVertex[] tempVertexArray =
			{
				new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
				new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
			};

			foreach (SimpleVertex vertex in tempVertexArray)
			{
				vertices.Write(vertex);
			}
			vertices.Position = 0;

			// create the vertex layout and vertex buffer
			var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0),
								   new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0),
								   new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 24, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0)};
			layout = new InputLayout(device,
									 inputSignature,
									 elements);
			vertexBuffer = new Buffer(device,
									  vertices,
									  (int)vertices.Length,
									  ResourceUsage.Default,
									  BindFlags.VertexBuffer,
									  CpuAccessFlags.None,
									  ResourceOptionFlags.None,
									  0);

			// Setup the test index data, making sure to rewind the stream afterward.
			UInt16[] indicesList = { 3, 1, 0,
									 2, 1, 3,
									 6, 4, 5,
									 7, 4, 6,
									 11, 9, 8,
									 10, 9, 11,
									 14, 12, 13,
									 15, 12, 14,
									 19, 17, 16,
									 18, 17, 19,
									 22, 20, 21,
									 23, 20, 22
								   };
			// As you can see in the indices list above, we have 36 values total, each of which
			// is a UInt16 value (or 2-byte short integer)
			indices = new DataStream(36 * 2, true, true);
			foreach (UInt16 index in indicesList)
			{
				indices.Write(index);
			}
			indices.Position = 0;

			// Now create the index buffer.
			indexBuffer = new Buffer(device,
									 indices,
									 (int)indices.Length,
									 ResourceUsage.Default,
									 BindFlags.IndexBuffer,
									 CpuAccessFlags.None,
									 ResourceOptionFlags.None,
									 0);


			// Configure the Input Assembler portion of the graphics pipeline with the vertex data.
			context.InputAssembler.InputLayout = layout;
			context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
			context.InputAssembler.SetVertexBuffers(0,
													new VertexBufferBinding(vertexBuffer, 40, 0));
			context.InputAssembler.SetIndexBuffer(indexBuffer,
												  Format.R16_UInt,
												  0);
		}

		static void RenderFrame()
		{
			curTime = Environment.TickCount;
			float t = (curTime - startTime) / 1000.0f;   // Calculate elapsed time since start in seconds

			// 1st Cube: Rotate around the origin.
			matrix_World = Matrix.RotationY(t * rotationY);

			// Setup our lighting parameters
			Vector4[] vLightDirs =
			{
				new Vector4(-0.577f, 0.577f, -0.577f, 1.0f),
				new Vector4(0.0f, 0.0f, -1.0f, 1.0f)
			};
			Vector4[] vLightColors =
			{
				new Vector4(0.5f, 0.5f, 0.5f, 1.0f),
				new Vector4(0.5f, 0.0f, 0.0f, 1.0f)
			};

			// Rotate the second light around the origin
			Matrix mRotate = Matrix.RotationY(-2.0f * t);
			Vector4 vLightDir = vLightDirs[1];
			vLightDir = Vector4.Transform(vLightDir, mRotate);
			vLightDirs[1] = vLightDir;

			// Clear the render target to a soothing blue
			context.ClearRenderTargetView(renderTarget,
										  new Color4(0.0f, 0.125f, 0.3f, 1.0f));
			// Clear the Depth buffer to 1.0 (max depth)
			context.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);

			// Update the constant buffer variables
			cbStruct.mWorld = Matrix.Transpose(matrix_World);
			cbStruct.mView = Matrix.Transpose(matrix_View);
			cbStruct.mProjection = Matrix.Transpose(matrix_Projection);
			cbStruct.vLightDir[0] = vLightDirs[0];
			cbStruct.vLightDir[1] = vLightDirs[1];
			cbStruct.vLightColor[0] = vLightColors[0];
			cbStruct.vLightColor[1] = vLightColors[1];
			cbStruct.vOutputColor = new Vector4(0, 0, 0, 0);
			// If no specific marshalling is needed, can use
			// dataStream.Write(value) for better performance.		  
			Marshal.StructureToPtr(cbStruct, constants.DataPointer, false);
		  
			// Give GPU updated matrices data.
			context.UpdateSubresource(new DataBox(0, 0, constants),
									  constantBuffer,
									  0);

			// Render the cube
			context.VertexShader.Set(vertexShader);
			context.VertexShader.SetConstantBuffer(constantBuffer, 0);
			context.PixelShader.Set(pixelShaderSolid);
			context.PixelShader.SetConstantBuffer(constantBuffer, 0);
			context.DrawIndexed(36,
								0,
								0);

		  
			// Render each light
			for (int m = 0; m < 2; m++)
			{
				Matrix mLight = Matrix.Translation(5.0f * new Vector3(vLightDirs[m].X, vLightDirs[m].Y, vLightDirs[m].Z));
				Matrix mLightScale = Matrix.Scaling(0.2f, 0.2f, 0.2f);
				mLight = mLightScale * mLight;
				// Update the world variable to reflect the current light
				cbStruct.mWorld = Matrix.Transpose(mLight);
				cbStruct.vOutputColor = vLightColors[m];
				// If no specific marshalling is needed, can use
				// dataStream.Write(value) for better performance.		  
				Marshal.StructureToPtr((object)cbStruct, constants.DataPointer, false);
				context.UpdateSubresource(new DataBox(0, 0, constants),
										 constantBuffer,
										 0);
				context.PixelShader.Set(pixelShaderSolid);

				context.DrawIndexed(36,
									0,
									0);
			}
		  
			// Present the frame we just rendered.
			swapChain.Present(0,
							  PresentFlags.None);
		}
	}
}

Thanks again for you're help and hopefully someone can help me solve this second issue. I'm just not sure whether the problem is still with the packing of the data in the constant buffer, or if the problem lies elsewhere. I don't know how to check to make sure that the data is getting into the constant buffer correctly. If its not, the arrays are where the problem lies, like you said, because the struct works fine in previous tutorials with the Matrices stored the same way, but there are no arrays in the struct in those tutorials.



UPDATE:
I got the demo to work by making a small function that writes all the data from the structure one item at a time into the DataStream using the DataStream.Write() method. The program is now working properly. It would seem that when I used Marshal.StructToPtr() it was doing something wrong. The two spots in the render code that update the Constant Buffer seemed to be fighting each other in some way. If I had one update using Marshal.StructToPtr() and the other using constants.Write(cbStruct), then half of the draw code would work. Which half works was determined by which way I set up the two updates. So if I flipped it so the first update used constants.Write(cbStruct) and the second update of the constant buffer used Marshal.StructToPtr(), then the other half of the render code worked but the half that worked before stopped working.

When I change the Render code so that both of the updates to the Constant Buffer use my little util function that writes the data to the DataStream one item at a time using the DataStream.Write() method, the program works exactly as it should. Both halves of the render code function correctly with this setup and I see 3 cubes on the screen with lighting on the center cube as expected.

So in short, the problem obviously has to do with the way the struct was getting written to the Constant Buffer when I used Marshal.StructToPtr(). So apparently there is still something not quite right about how my struct is set up. Here's what the struct looks like now. Let me know if I'm doing something wrong. Thanks.
    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct ConstantBufferStruct
    {
	    public Matrix mWorld;
	    public Matrix mView;
	    public Matrix mProjection;
	   
	    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
	    public Vector4[] vLightDir;
	    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
	    public Vector4[] vLightColor;
	    public Vector4 vOutputColor;
    };

#1Megafont

Posted 10 November 2012 - 07:29 PM

Hi and thank you very much. I did a little research into how to setup my structure properly. It no longer is drawing nonsense on the screen, but the problem is that now it draws absolutely nothing on the screen after it clears it each frame. I'm not sure what's going on but obviously something somewhere is still screwed up unfortunately.

Here is what my code looks like now with the structure updated, and I also now copy the structure into the constant buffer using Marshal.StructureToPtr().
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SlimDX;
using SlimDX.D3DCompiler;
using SlimDX.Direct3D11;
using Buffer = SlimDX.Direct3D11.Buffer;	    // I added this line to fix ambiguity between SlimDX.Direct3D11.Buffer and System.Buffer.  This tells it to use the SlimDX Buffer class rather than the one in the System namespace when I reference the type Buffer.
using SlimDX.DXGI;
using SlimDX.Windows;
using Device = SlimDX.Direct3D11.Device;
using Resource = SlimDX.Direct3D11.Resource;

//--------------------------------------------------------------------------------------
// NOTE:
//--------------------------------------------------------------------------------------
// I modified this program and its shaders.fx file to help with debugging a bug that
// I was having a hell of a time solving. See the note at the top of the shaders.fx
// file for info on changes I made to that file.
//--------------------------------------------------------------------------------------
namespace Test_1
{
    struct SimpleVertex
    {
	    Vector3 Position;
	    Vector3 Normal;
	    Vector4 Color;
	    public SimpleVertex(Vector3 position, Vector3 normal, Vector4 color)
	    {
		    Position = position;
		    Normal = normal;
		    Color = color;
	    }
    };

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    struct ConstantBufferStruct
    {
	    public Matrix mWorld;
	    public Matrix mView;
	    public Matrix mProjection;
	    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
	    public Vector4[] vLightDir;
	    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
	    public Vector4[] vLightColor;
	   
	    public Vector4 vOutputColor;
    };

    static class Program
    {
	    static float rotationY = 0.785f;	 // Y Rotation in radians per second   (0.785 radians = 45 degrees)

	    static int startTime;
	    static int curTime;
	    static RenderForm form;
	    static Buffer constantBuffer;
	    static Buffer indexBuffer;
	    static Buffer vertexBuffer;
	    static DataStream constants;
	    static DataStream indices;
	    static DataStream vertices;
	    static DepthStencilView depthStencilView;
	    static Device device;
	    static DeviceContext context;
	    static InputLayout layout;
	    static PixelShader pixelShader;
	    static PixelShader pixelShaderSolid;
	    static PixelShader pixelShaderColor;
	    static RenderTargetView renderTarget;
	    static ShaderSignature inputSignature;
	    static SwapChain swapChain;
	    static Texture2D depthStencil;
	    static VertexShader vertexShader;
	    static Viewport viewport;
	    static Matrix matrix_World;
	    static Matrix matrix_View;
	    static Matrix matrix_Projection;
	    static ConstantBufferStruct cbStruct = new ConstantBufferStruct();

	    static void Main()
	    {
		    form = new RenderForm("OMG a Window!!");
		    var description = new SwapChainDescription()
		    {
			    BufferCount = 2,
			    Usage = Usage.RenderTargetOutput,
			    OutputHandle = form.Handle,
			    IsWindowed = true,
			    ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
			    SampleDescription = new SampleDescription(1, 0),
			    Flags = SwapChainFlags.AllowModeSwitch,
			    SwapEffect = SwapEffect.Discard
		    };

		    Device.CreateWithSwapChain(DriverType.Hardware,
									   DeviceCreationFlags.Debug,
									   description,
									   out device,
									   out swapChain);

		    // create a view of our render target, which is the backbuffer of the swap chain we just created
		    using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
		    {
			    renderTarget = new RenderTargetView(device, resource);
		    };

		    // Create the depth stencil texture
		    Texture2DDescription depthStencilDesc = new Texture2DDescription();
		    depthStencilDesc.Width = form.ClientSize.Width;
		    depthStencilDesc.Height = form.ClientSize.Height;
		    depthStencilDesc.MipLevels = 1;
		    depthStencilDesc.ArraySize = 1;
		    depthStencilDesc.Format = Format.D24_UNorm_S8_UInt;
		    depthStencilDesc.SampleDescription = new SampleDescription(1, 0);
		    depthStencilDesc.Usage = ResourceUsage.Default;
		    depthStencilDesc.BindFlags = BindFlags.DepthStencil;
		    depthStencilDesc.CpuAccessFlags = CpuAccessFlags.None;
		    depthStencilDesc.OptionFlags = ResourceOptionFlags.None;
		    depthStencil = new Texture2D(device, depthStencilDesc);

		    // Create the Depth Stencil View
		    DepthStencilViewDescription depthStencilViewDesc = new DepthStencilViewDescription();
		    depthStencilViewDesc.Format = depthStencilDesc.Format;
		    depthStencilViewDesc.Dimension = DepthStencilViewDimension.Texture2D;
		    depthStencilViewDesc.MipSlice = 0;
		    depthStencilView = new DepthStencilView(device, depthStencil, depthStencilViewDesc);
		    // setting a viewport is required if you want to actually see anything
		    context = device.ImmediateContext;
		    viewport = new Viewport(0.0f,
								    0.0f,
								    form.ClientSize.Width,
								    form.ClientSize.Height,
								    0.0f,
								    1.0f);
		    context.OutputMerger.SetTargets(depthStencilView, renderTarget);
		    context.Rasterizer.SetViewports(viewport);

		    // Setup our shaders
		    InitShaders();

		    // Setup our vertex data
		    InitVertexData();

		    // Setup our matrices
		    InitMatrices();

		    // Set the shaders
		    context.VertexShader.Set(vertexShader);
		    context.PixelShader.Set(pixelShader);

		    // Prevent DXGI handling of Alt+Enter, which doesn't work properly with Winforms
		    using (var factory = swapChain.GetParent<Factory>())
		    {
			    factory.SetWindowAssociation(form.Handle,
											 WindowAssociationFlags.IgnoreAltEnter);
		    };

		    // Handle Alt+Enter ourselves
		    form.KeyDown += (o, e) =>
		    {
			    if (e.Alt && e.KeyCode == Keys.Enter)
			    {
				    swapChain.IsFullScreen = !swapChain.IsFullScreen;
			    }
		    };

		    // Handle form size changes
		    form.UserResized += (o, e) =>
		    {
			    renderTarget.Dispose();
			    depthStencil.Dispose();
			    depthStencilView.Dispose();

			    swapChain.ResizeBuffers(2,
									    0,
									    0,
									    Format.R8G8B8A8_UNorm,
									    SwapChainFlags.AllowModeSwitch);

			    using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
			    {
				    renderTarget = new RenderTargetView(device, resource);
			    }

			    depthStencilDesc.Width = form.ClientSize.Width;
			    depthStencilDesc.Height = form.ClientSize.Height;
			    depthStencil = new Texture2D(device, depthStencilDesc);
			    depthStencilView = new DepthStencilView(device, depthStencil, depthStencilViewDesc);

			    context.OutputMerger.SetTargets(depthStencilView, renderTarget);
			    context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
		    };
		    startTime = Environment.TickCount;
		    MessagePump.Run(form, RenderFrame);


		    // Clean up all resources
		    // anything we missed will show up in the IDE's debug output
		    vertices.Close();
		    vertexBuffer.Dispose();
		    layout.Dispose();
		    inputSignature.Dispose();
		    vertexShader.Dispose();
		    pixelShader.Dispose();
		    renderTarget.Dispose();
		    swapChain.Dispose();
		    device.Dispose();
		    indexBuffer.Dispose();
		    indices.Dispose();
		    constantBuffer.Dispose();
		    constants.Dispose();
		    depthStencil.Dispose();
		    depthStencilView.Dispose();
		    pixelShaderSolid.Dispose();
		    pixelShaderColor.Dispose();
	    }

	    static void InitShaders()
	    {
		    // load and compile the vertex shader
		    string vsCompileError = "Vertex Shader Compile Error!!!";
		    using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "VS", "vs_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out vsCompileError))
		    {
			    inputSignature = ShaderSignature.GetInputSignature(bytecode);
			    vertexShader = new VertexShader(device, bytecode);
		    }

		    // load and compile the pixel shader
		    string psCompileError = "Pixel Shader Compile Error!!!";
		    using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PS", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
		    {
			    pixelShader = new PixelShader(device, bytecode);
		    }
		    // load and compile the solid pixel shader
		    psCompileError = "Solid Pixel Shader Compile Error!!!";
		    using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PSSolid", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
		    {
			    pixelShaderSolid = new PixelShader(device, bytecode);
		    }
		    // load and compile the color pixel shader
		    psCompileError = "Color Pixel Shader Compile Error!!!";
		    using (var bytecode = ShaderBytecode.CompileFromFile("shaders.fx", "PSColor", "ps_4_0", ShaderFlags.EnableStrictness | ShaderFlags.Debug, EffectFlags.None, null, null, out psCompileError))
		    {
			    pixelShaderColor = new PixelShader(device, bytecode);
		    }
	    }
	    static void InitMatrices()
	    {
		    // world matrix	   
		    matrix_World = Matrix.Identity;
		    // view matrix
		    Vector3 vEye = new Vector3(0.0f, 4.0f, -10.0f);
		    Vector3 vLookAt = new Vector3(0.0f, 1.0f, 0.0f);
		    Vector3 vUp = new Vector3(0.0f, 1.0f, 0.0f);
		    matrix_View = Matrix.LookAtLH(vEye,
										  vLookAt,
										  vUp);

		    // projection matrix
		    matrix_Projection = Matrix.PerspectiveFovLH((float)Math.PI / 2,  // Vertical Field of View
													    (float)form.ClientSize.Width / (float)form.ClientSize.Height,  // Aspect Ratio
													    0.01f,  // Near Z
													    100.0f);  // Far Z

		    // Write the matrices we just generated into the DataStream
		    cbStruct.mWorld = Matrix.Transpose(matrix_World);
		    cbStruct.mView = Matrix.Transpose(matrix_View);
		    cbStruct.mProjection = Matrix.Transpose(matrix_Projection);
		    cbStruct.vLightColor = new Vector4[2];
		    cbStruct.vLightDir = new Vector4[2];
		   
		    constants = new DataStream(Marshal.SizeOf(typeof(ConstantBufferStruct)), true, true);

		    // If no specific marshalling is needed, can use
		    // dataStream.Write(value) for better performance.		   
		    Marshal.StructureToPtr(cbStruct, constants.DataPointer, false);
		    ConstantBufferStruct temp = new ConstantBufferStruct();
		    temp.vLightColor = new Vector4[2];
		    temp.vLightColor = new Vector4[2];
		    temp.vOutputColor = new Vector4(1.0f, 0.5f, 0.5f, 1.0f);
		    temp = (ConstantBufferStruct) Marshal.PtrToStructure(constants.DataPointer, typeof(ConstantBufferStruct));
		    if (temp.mWorld.Equals(cbStruct.mWorld) &&
			    temp.mView.Equals(cbStruct.mView) &&
			    temp.mProjection.Equals(cbStruct.mProjection))
		    {
			    System.Diagnostics.Debug.WriteLine("MATRICES ARE CORRECT!");
		    }
		    else
		    {
			    System.Diagnostics.Debug.WriteLine("MATRICES ARE NOT CORRECT!");
		    }
		    if (temp.vOutputColor.Equals(cbStruct.vOutputColor))
		    {
			    System.Diagnostics.Debug.WriteLine("OUTPUT COLOR IS CORRECT!");
		    }
		    else
		    {
			    System.Diagnostics.Debug.WriteLine("OUTPUT COLOR IS NOT CORRECT!");
		    }
		    // Create the constant buffer
		    constantBuffer = new Buffer(device,
									    constants,
									    (int)constants.Length,
									    ResourceUsage.Default,
									    BindFlags.ConstantBuffer,
									    CpuAccessFlags.None,
									    ResourceOptionFlags.None,
									    0);
		    context.UpdateSubresource(new DataBox(0, 0, constants),
									  constantBuffer,
									  0);
		    context.VertexShader.SetConstantBuffer(constantBuffer, 0);
	    }
	    static void InitVertexData()
	    {
		    // Create test vertex data, making sure to rewind the stream afterward.
		    vertices = new DataStream(Marshal.SizeOf(new SimpleVertex(Vector3.Zero, Vector3.Zero, Vector4.Zero)) * 24, true, true);
		    SimpleVertex[] tempVertexArray =
		    {
			    new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  1.0f,  0.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3( 0.0f, -1.0f,  0.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3(-1.0f,  0.0f,  0.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 1.0f,  0.0f,  0.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f, -1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f, -1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f,  1.0f, -1.0f), new Vector3( 0.0f,  0.0f, -1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f, -1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(0.0f, 0.0f, 0.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f, -1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(1.0f, 1.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3( 1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f)),
			    new SimpleVertex(new Vector3(-1.0f,  1.0f,  1.0f), new Vector3( 0.0f,  0.0f,  1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f)),
		    };

		    foreach (SimpleVertex vertex in tempVertexArray)
		    {
			    vertices.Write(vertex);
		    }
		    vertices.Position = 0;

		    // create the vertex layout and vertex buffer
		    var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0),
								   new InputElement("NORMAL", 0, Format.R32G32B32_Float, 12, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0),
								   new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 24, 0, SlimDX.Direct3D11.InputClassification.PerVertexData, 0)};
		    layout = new InputLayout(device,
									 inputSignature,
									 elements);
		    vertexBuffer = new Buffer(device,
									  vertices,
									  (int)vertices.Length,
									  ResourceUsage.Default,
									  BindFlags.VertexBuffer,
									  CpuAccessFlags.None,
									  ResourceOptionFlags.None,
									  0);

		    // Setup the test index data, making sure to rewind the stream afterward.
		    UInt16[] indicesList = { 3, 1, 0,
									 2, 1, 3,
									 6, 4, 5,
									 7, 4, 6,
									 11, 9, 8,
									 10, 9, 11,
									 14, 12, 13,
									 15, 12, 14,
									 19, 17, 16,
									 18, 17, 19,
									 22, 20, 21,
									 23, 20, 22
								   };
		    // As you can see in the indices list above, we have 36 values total, each of which
		    // is a UInt16 value (or 2-byte short integer)
		    indices = new DataStream(36 * 2, true, true);
		    foreach (UInt16 index in indicesList)
		    {
			    indices.Write(index);
		    }
		    indices.Position = 0;

		    // Now create the index buffer.
		    indexBuffer = new Buffer(device,
									 indices,
									 (int)indices.Length,
									 ResourceUsage.Default,
									 BindFlags.IndexBuffer,
									 CpuAccessFlags.None,
									 ResourceOptionFlags.None,
									 0);


		    // Configure the Input Assembler portion of the graphics pipeline with the vertex data.
		    context.InputAssembler.InputLayout = layout;
		    context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
		    context.InputAssembler.SetVertexBuffers(0,
												    new VertexBufferBinding(vertexBuffer, 40, 0));
		    context.InputAssembler.SetIndexBuffer(indexBuffer,
												  Format.R16_UInt,
												  0);
	    }

	    static void RenderFrame()
	    {
		    curTime = Environment.TickCount;
		    float t = (curTime - startTime) / 1000.0f;   // Calculate elapsed time since start in seconds

		    // 1st Cube: Rotate around the origin.
		    matrix_World = Matrix.RotationY(t * rotationY);

		    // Setup our lighting parameters
		    Vector4[] vLightDirs =
		    {
			    new Vector4(-0.577f, 0.577f, -0.577f, 1.0f),
			    new Vector4(0.0f, 0.0f, -1.0f, 1.0f)
		    };
		    Vector4[] vLightColors =
		    {
			    new Vector4(0.5f, 0.5f, 0.5f, 1.0f),
			    new Vector4(0.5f, 0.0f, 0.0f, 1.0f)
		    };

		    // Rotate the second light around the origin
		    Matrix mRotate = Matrix.RotationY(-2.0f * t);
		    Vector4 vLightDir = vLightDirs[1];
		    vLightDir = Vector4.Transform(vLightDir, mRotate);
		    vLightDirs[1] = vLightDir;

		    // Clear the render target to a soothing blue
		    context.ClearRenderTargetView(renderTarget,
										  new Color4(0.0f, 0.125f, 0.3f, 1.0f));
		    // Clear the Depth buffer to 1.0 (max depth)
		    context.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);

		    // Update the constant buffer variables
		    cbStruct.mWorld = Matrix.Transpose(matrix_World);
		    cbStruct.mView = Matrix.Transpose(matrix_View);
		    cbStruct.mProjection = Matrix.Transpose(matrix_Projection);
		    cbStruct.vLightDir[0] = vLightDirs[0];
		    cbStruct.vLightDir[1] = vLightDirs[1];
		    cbStruct.vLightColor[0] = vLightColors[0];
		    cbStruct.vLightColor[1] = vLightColors[1];
		    cbStruct.vOutputColor = new Vector4(0, 0, 0, 0);
		    // If no specific marshalling is needed, can use
		    // dataStream.Write(value) for better performance.		   
		    Marshal.StructureToPtr(cbStruct, constants.DataPointer, false);
		   
		    // Give GPU updated matrices data.
		    context.UpdateSubresource(new DataBox(0, 0, constants),
									  constantBuffer,
									  0);

		    // Render the cube
		    context.VertexShader.Set(vertexShader);
		    context.VertexShader.SetConstantBuffer(constantBuffer, 0);
		    context.PixelShader.Set(pixelShaderSolid);
		    context.PixelShader.SetConstantBuffer(constantBuffer, 0);
		    context.DrawIndexed(36,
							    0,
							    0);

		   
		    // Render each light
		    for (int m = 0; m < 2; m++)
		    {
			    Matrix mLight = Matrix.Translation(5.0f * new Vector3(vLightDirs[m].X, vLightDirs[m].Y, vLightDirs[m].Z));
			    Matrix mLightScale = Matrix.Scaling(0.2f, 0.2f, 0.2f);
			    mLight = mLightScale * mLight;
			    // Update the world variable to reflect the current light
			    cbStruct.mWorld = Matrix.Transpose(mLight);
			    cbStruct.vOutputColor = vLightColors[m];
			    // If no specific marshalling is needed, can use
			    // dataStream.Write(value) for better performance.		   
			    Marshal.StructureToPtr((object)cbStruct, constants.DataPointer, false);
			    context.UpdateSubresource(new DataBox(0, 0, constants),
										 constantBuffer,
										 0);
			    context.PixelShader.Set(pixelShaderSolid);

			    context.DrawIndexed(36,
								    0,
								    0);
		    }
		   
		    // Present the frame we just rendered.
		    swapChain.Present(0,
							  PresentFlags.None);
	    }
    }
}

Thanks again for you're help and hopefully someone can help me solve this second issue. I'm just not sure whether the problem is still with the packing of the data in the constant buffer, or if the problem lies elsewhere. I don't know how to check to make sure that the data is getting into the constant buffer correctly. If its not, the arrays are where the problem lies, like you said, because the struct works fine in previous tutorials with the Matrices stored the same way, but there are no arrays in the struct in those tutorials.

PARTNERS