我正在尝试创建一个统一缓冲对象(UBO),我需要用制服填充数组。我目前的做法是使用硬编码结构。
[Serializable,StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MaterialBlock
{
private Vector4 uniform;
};
然后我使用Marshaling从该结构中获取字节数组,并用我的UBO填充该数组。
public void SetUniformShader(MaterialBlock block, int count) {
int maxSizeMaterialUniformBuffer;
int sizeMaterialBlock = Marshal.SizeOf(typeof (MaterialBlock));
int sizeUniformInstance = sizeMaterialBlock*count;
int uniformInstancesPerBlock;
int numberOfBlocks;
int activeUniformBlocks;
byte[] mtlBuffer;
int uniformBlockIndex;
GL.GetActiveUniformBlock(ProgramId, 0, ActiveUniformBlockParameter.UniformBlockBinding,
out uniformBlockIndex);
GL.GetProgram(ProgramId, ProgramParameter.ActiveUniformBlocks, out activeUniformBlocks);
GL.GetInteger(GetPName.MaxUniformBlockSize, out maxSizeMaterialUniformBuffer);
uniformInstancesPerBlock = maxSizeMaterialUniformBuffer/sizeMaterialBlock;
numberOfBlocks =
(int) Math.Ceiling(((double) sizeUniformInstance/uniformInstancesPerBlock*sizeMaterialBlock));
mtlBuffer = new byte[maxSizeMaterialUniformBuffer];
IntPtr buffer = Marshal.AllocHGlobal(sizeMaterialBlock);
Marshal.StructureToPtr(block, buffer, false);
for (int i = 0; i < uniformInstancesPerBlock; i++) {
Marshal.Copy(buffer, mtlBuffer, i*sizeMaterialBlock, sizeMaterialBlock);
}
Marshal.FreeHGlobal(buffer);
GL.GenBuffers(1, out _iUniform);
GL.BindBuffer(BufferTarget.UniformBuffer, _iUniform);
GL.BufferData(BufferTarget.UniformBuffer, new IntPtr(sizeMaterialBlock), mtlBuffer,
BufferUsageHint.DynamicDraw);
}
我想知道是否有更动态的方式来保存统一信息,而不必使用System.Reflection来按需创建结构。当我做片段和顶点着色器时,我能够使用一个字符串,然后是GL.CreateShader()和GL.ShaderSource。我唯一能想到的就是ShaderType.GeometryShader实际上是Uniform着色器,它的标签也不同。
任何方法都会受到赞赏,即使它意味着完全不同。如果我遗漏了任何信息,我会道歉,并会根据要求尝试添加。
答案 0 :(得分:0)
创建统一对象的所有方法是什么?
没有“统一对象”这样的东西。只有缓冲区对象,可用于存储统一数据。它们还可用于存储顶点数据,像素数据和各种其他内容。但它们都是相同的对象类型:缓冲对象。而且你以同样的方式创建它们。
向缓冲区对象提供数据的方法非常简单。 glBuffer(Sub)Data和glMapBuffer(Range)。您的问题不在于界面,而在于C#,它不是本机API。所以你必须通过箍来上传你的数据。
老实说,我建议使用一点C ++ / CLI作为处理缓冲区对象数据上传的接口。处理本机对象中的数据比管理数据更容易,更简洁。