Как бы я создал более динамичный равномерный шейдер? - PullRequest
1 голос
/ 15 августа 2011

Я пытаюсь создать единый буферный объект (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 Ответ

0 голосов
/ 15 августа 2011

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

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

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

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

...