Trying to pass struct with Vector4 array to cbuffer
I'm playing around with SlimDX (with DX10/11) a bit and I got some nice results so far, but I'm stuck on passing an array of Vector4s to the shaders.
If I try the following struct:
[StructLayout(LayoutKind.Sequential)]
public struct PerFrameBuffer
{
public Vector4 Position;
public Matrix World;
public Matrix View;
public Matrix Projection;
[MarshalAs( UnmanagedType.ByValArray, SizeConst=2)]
public Vector4[] Lights;
}
and try to store it in the following cbuffer:
cbuffer cPerFrame : register( b0 )
{
float4 xPosition;
matrix xWorld;
matrix xView;
matrix xProjection;
float4 pointLights[2];
}
I don't get any errors, but the values in the matrices are broken.
However when I declare my struct in c# as follows:
[StructLayout(LayoutKind.Sequential)]
public struct PerFrameBuffer
{
public Vector4 Position;
public Matrix World;
public Matrix View;
public Matrix Projection;
public Vector4 Light1;
public Vector4 Light2;
}
Then everything works fine as ex开发者_StackOverflow中文版pected.
I don't really want to make 64 fields in the struct and fill them up like that (I could with reflection but still). How can I use an array to pass the Vector4's to my constantbuffer?
If by any means this is a dumb idea and should be done in another way, please let me know. It's my first time programming directx and shader related stuff.
To be complete:
Declaration of the buffer in C#
cPerFrameBuffer = new SlimDX.Direct3D11.Buffer(device, new BufferDescription
{
Usage = ResourceUsage.Default,
SizeInBytes = Marshal.SizeOf(typeof(PerFrameBuffer)),
BindFlags = BindFlags.ConstantBuffer
});
context.VertexShader.SetConstantBuffer(cPerFrameBuffer, 0);
How I'm updating the buffer:
var cb = new AbstractDXManager.PerFrameBuffer()
{
Position = new Vector4(camera.Position, 1.0f),
Projection = Matrix.Transpose(camera.ProjectionMatrix),
View = Matrix.Transpose(camera.ViewMatrix),
World = Matrix.Transpose(Matrix.Identity),
};
cb.Lights = new Vector4[2];
cb.Lights[0] = cb.Position;
cb.Lights[1] = new Vector4(20, 20, 20, 1);
var context = device.ImmediateContext;
using (DataStream data = new DataStream(Marshal.SizeOf(typeof(PerFrameBuffer)), true, true))
{
data.Write(cb);
data.Position = 0;
context.UpdateSubresource(new DataBox(0, 0, data), cPerFrameBuffer, 0);
}
Thanks in advance
I had the same problem. I changed buffer writing. Now it works
This is my struct
[StructLayout(LayoutKind.Sequential,Pack=1)]
public struct WorldConstants
{
public Matrix View;
public Matrix Projection;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public Color4 [] DiffuseColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public Color4[] AmbientColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public Vector4[] LightDirection;
public Vector4 ViewPosition;
}
I used StructToPtr to get the alligned data.
using (DataStream stream = new DataStream(streamSize, true, true))
{
int rawsize = Marshal.SizeOf(typeof(ElementT));
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
foreach (var element in elements)
{
Marshal.StructureToPtr(element, buffer, false);
stream.WriteRange(buffer,rawsize);
}
Marshal.FreeHGlobal(buffer);
Unfortunately this causes an additional copy of the data. In my case I didn't notice any performance problems.
精彩评论