Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ActualGavin Williams

Posted 09 December 2012 - 09:52 PM

Hi,

I have always used the effects framework to manage my shaders, but I decided to introduce constant buffers, as I'm about to implement geometry instancing and I figured it would give me greater control. And also it was about time I get to know how they work. But I don't think I'm doing it right as my wall sections are just disappearing. So can anyone see what I'm doing wrong ..

So here's all the relevant code :

The CBufferStruct ...

/// <summary>
		/// CBufferStruct
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		public struct CBufferStruct
		{
			public Matrix mWorld;
			public Matrix mView;
			public Matrix mProj;
			public static readonly int SizeInBytes = Marshal.SizeOf(typeof(CBufferStruct));
		}

Then in the Walls constructor ...

// create cBuffer
			BufferDescription bufferDescription = new BufferDescription()
			{
				BindFlags = BindFlags.ConstantBuffer,
				CpuAccessFlags = CpuAccessFlags.None,
				OptionFlags = ResourceOptionFlags.None,
				SizeInBytes = CBufferStruct.SizeInBytes,
				Usage = ResourceUsage.Default,
			};
			cBuffer = new Buffer(SlimDXGraphics.Device11,  bufferDescription);
			cBufferStruct = new CBufferStruct()
			{
				mProj = new Matrix(),
				mView = new Matrix(),
				mWorld = Matrix.Translation(new Vector3()),
				//padding = new Matrix()
			};

Then in Walls.RenderToGBuffer() ...

foreach (Chunk chunk in map.VisibleChunks)
			{
				//if (!(chunk.Coords.X == 1 && chunk.Coords.Y == 1)) // debug code to selectively render a single terrain chunk
				foreach (KeyValuePair<int, List<Point>> kVPair in chunk.wallInstanceCollectionsDictionary)
				{
					foreach (Point p in kVPair.Value)
					{
						context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(map.wall000.VertexBuffer, VertexPCNT.SizeInBytes, 0));
						cBufferStruct.mProj = camera.ProjMatrix;
						cBufferStruct.mView = camera.ViewMatrix;
						cBufferStruct.mWorld = Matrix.Translation(new Vector3(p.X, p.Y, 0));
					  
						using (DataStream data = new DataStream(CBufferStruct.SizeInBytes, true, true))
						{
							data.Position = 0;
							data.Write(cBufferStruct);
							context.UpdateSubresource(new DataBox(0, 0, data), cBuffer, 0);
							data.Dispose();
						}
						// now bind the constant buffer to the pipeline
						context.VertexShader.SetConstantBuffer(cBuffer, 0); // not sure about this, some examples don't have it
					  
						// configure vertex shader ------------------------------------------------------------
						//effect_Walls.GetVariableByName("gWorld").AsMatrix().SetMatrix(Matrix.Translation(new Vector3(p.X, p.Y, 0)));
						//effect_Walls.GetVariableByName("gView").AsMatrix().SetMatrix(camera.ViewMatrix);
						//effect_Walls.GetVariableByName("gProj").AsMatrix().SetMatrix(camera.ProjMatrix);
						effect_Walls.GetVariableByName("gTexture").AsResource().SetResource(map.SRVWallTexture);
						// draw -------------------------------------------------------------------------------
						for (int pass = 0; pass < effectTech_Walls.Description.PassCount; ++pass)
						{
							EffectPass Pass = effectTech_Walls.GetPassByIndex(pass);
							System.Diagnostics.Debug.Assert(Pass.IsValid, "Invalid EffectPass");
							Pass.Apply(context);
							if (map.wall000.IndexCount == 0)
								context.Draw(map.wall000.VertexCount, 0);
							else
								context.DrawIndexed(map.wall000.IndexCount, 0, 0);
						};
					}
				}
			}

Edit : And here's the shader vars ...

// constant buffers need to be a multiple of 16 byte in size
cbuffer gConstantBuffer : register (b0)
{
// spacial transforms
float4x4 gWorld;
float4x4 gView;
float4x4 gProj;
// padding
//float4x4 padding;
}
Texture2D<float4> gTexture : register (t0);


Thanks for any help or comments.

#1Gavin Williams

Posted 09 December 2012 - 09:38 PM

Hi,

I have always used the effects framework to manage my shaders, but I decided to introduce constant buffers, as I'm about to implement geometry instancing and I figured it would give me greater control. And also it was about time I get to know how they work. But I don't think I'm doing it right as my wall sections are just disappearing. So can anyone see what I'm doing wrong ..

So here's all the relevant code :

The CBufferStruct ...

/// <summary>
		/// CBufferStruct
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		public struct CBufferStruct
		{
			public Matrix mWorld;
			public Matrix mView;
			public Matrix mProj;
			public static readonly int SizeInBytes = Marshal.SizeOf(typeof(CBufferStruct));
		}

Then in the Walls constructor ...

// create cBuffer
			BufferDescription bufferDescription = new BufferDescription()
			{
				BindFlags = BindFlags.ConstantBuffer,
				CpuAccessFlags = CpuAccessFlags.None,
				OptionFlags = ResourceOptionFlags.None,
				SizeInBytes = CBufferStruct.SizeInBytes,
				Usage = ResourceUsage.Default,
			};
			cBuffer = new Buffer(SlimDXGraphics.Device11,  bufferDescription);
			cBufferStruct = new CBufferStruct()
			{
				mProj = new Matrix(),
				mView = new Matrix(),
				mWorld = Matrix.Translation(new Vector3()),
				//padding = new Matrix()
			};

Then in Walls.RenderToGBuffer() ...

foreach (Chunk chunk in map.VisibleChunks)
			{
				//if (!(chunk.Coords.X == 1 && chunk.Coords.Y == 1)) // debug code to selectively render a single terrain chunk
				foreach (KeyValuePair<int, List<Point>> kVPair in chunk.wallInstanceCollectionsDictionary)
				{
					foreach (Point p in kVPair.Value)
					{
						context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(map.wall000.VertexBuffer, VertexPCNT.SizeInBytes, 0));
						cBufferStruct.mProj = camera.ProjMatrix;
						cBufferStruct.mView = camera.ViewMatrix;
						cBufferStruct.mWorld = Matrix.Translation(new Vector3(p.X, p.Y, 0));
					  
						using (DataStream data = new DataStream(CBufferStruct.SizeInBytes, true, true))
						{
							data.Position = 0;
							data.Write(cBufferStruct);
							context.UpdateSubresource(new DataBox(0, 0, data), cBuffer, 0);
							data.Dispose();
						}
						// now bind the constant buffer to the pipeline
						context.VertexShader.SetConstantBuffer(cBuffer, 0); // not sure about this, some examples don't have it
					  
						// configure vertex shader ------------------------------------------------------------
						//effect_Walls.GetVariableByName("gWorld").AsMatrix().SetMatrix(Matrix.Translation(new Vector3(p.X, p.Y, 0)));
						//effect_Walls.GetVariableByName("gView").AsMatrix().SetMatrix(camera.ViewMatrix);
						//effect_Walls.GetVariableByName("gProj").AsMatrix().SetMatrix(camera.ProjMatrix);
						effect_Walls.GetVariableByName("gTexture").AsResource().SetResource(map.SRVWallTexture);
						// draw -------------------------------------------------------------------------------
						for (int pass = 0; pass < effectTech_Walls.Description.PassCount; ++pass)
						{
							EffectPass Pass = effectTech_Walls.GetPassByIndex(pass);
							System.Diagnostics.Debug.Assert(Pass.IsValid, "Invalid EffectPass");
							Pass.Apply(context);
							if (map.wall000.IndexCount == 0)
								context.Draw(map.wall000.VertexCount, 0);
							else
								context.DrawIndexed(map.wall000.IndexCount, 0, 0);
						};
					}
				}
			}

Thanks for any help or comments.

PARTNERS