2011-08-15 93 views
1

我试图创建一个统一的缓冲区对象(UBO),并且我需要用制服填充阵列。我目前的做法是采用硬编码结构。我将如何创建更动态的统一着色器?

[Serializable,StructLayout(LayoutKind.Sequential, Pack = 1)] 
     public struct MaterialBlock 
     { 
      private Vector4 uniform; 
     }; 

然后我用编组得到从结构字节数组,我填补我与阵列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 shader,它的标签是不同的。

任何方法将不胜感激,即使这意味着完全不同。如果我遗漏了任何信息,我表示歉意,并会根据请求添加它。

+0

我很困惑这个问题很多事情。我不明白如何在用glBindBuffer绑定缓冲区对象之前调用glBufferData。代码讲述着色器创建之后的文本,但与统一块无关。最终,OpenGL是为C和C++设计的,而不是托管C#。这是一个非常低级的API,它的很多部分都需要与C#不太一样的交互。 –

+0

glBindBuffer/BufferData混淆是我的一个小错误。我想一个更好的问题是,“创建统一对象的所有方法是什么?”。因为我不想拥有这种硬编码结构。 (在提供的代码中进行更改以反映缓冲区/绑定混音)。 – Zaneo

+0

“ShaderType.GeometryShader实际上是统一着色器”,是吧?那是什么意思?不,几何着色器不是统一着色器的另一个术语,无论如何,什么是统一着色器? –

回答

0

什么是创建统一对象的所有方法?

没有这样的东西作为“统一对象”。只有缓冲区对象可以用来存储统一的数据。它们也可以用来存储顶点数据,像素数据和其他各种东西。但它们都是相同的对象类型:缓冲对象。而且你以同样的方式创建它们。

将数据提供给缓冲区对象的方法非常简单。 glBuffer(Sub)Data和glMapBuffer(Range)。你的问题不在C#中,而是C#,它不是一个本地API。所以你必须跳过上传你的数据。

老实说,我会建议使用一点C++/CLI作为处理缓冲区对象数据上传的接口。在本地对象中处理数据比在托管对象中处理数据更轻松,更简洁。