Как бы я создал более динамичный равномерный шейдер?

Я пытаюсь создать единый буферный объект (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 на самом деле является единообразным шейдером, и его метка отличается.

Любые методы будут оценены по достоинству, даже если это будет означать, что они будут совершенно другими Если я пропустил какую-либо информацию, я извиняюсь и постараюсь добавить ее по запросу.

1 ответ

Каковы все способы создания единого объекта?

Не существует такого понятия, как "единый объект". Есть только буферные объекты, которые можно использовать для хранения единых данных. Они также могут быть использованы для хранения данных вершин, данных пикселей и различных других вещей. Но это все один и тот же тип объекта: буферный объект. И вы создаете их все одинаково.

Способы предоставления данных в буферный объект довольно просты. glBuffer(Sub)Data и glMapBuffer(Range). Ваша проблема не столько в интерфейсе, сколько в C#, который не является нативным API. Таким образом, вы должны прыгать через обручи, чтобы загрузить свои данные.

Честно говоря, я бы предложил использовать немного C++/CLI в качестве интерфейса для обработки загрузки данных вашего объекта буфера. Проще и менее многословно работать с данными в нативных объектах, чем в управляемых.

Другие вопросы по тегам