我如何创建一个更动态的统一着色器

本文关键字:动态 何创建 创建 一个 | 更新日期: 2023-09-27 18:05:29

我试图创建一个统一的缓冲区对象(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。根据需要创建结构的反射。当我做片段和顶点着色器时,我可以使用字符串,然后是GL.CreateShader()和GL.ShaderSource。我唯一能想到的是ShaderType。GeometryShader实际上是统一着色器,它的标签不同。

任何方法都是值得赞赏的,即使这意味着做完全不同的事情。如果我遗漏了任何信息,我深表歉意,并会根据需要补充。

我如何创建一个更动态的统一着色器

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

不存在"统一对象"这回事。只有缓冲区对象,可以用来存储统一的数据。它们还可以用来存储顶点数据、像素数据和其他各种东西。但它们都是相同的对象类型:缓冲对象。你用同样的方法创建它们

向缓冲区对象提供数据的方法相当简单。glBuffer(Sub)Data和glMapBuffer(Range)。你的问题不在于接口,而在于c#,它不是原生API。所以你上传你的数据得经过重重关卡。

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