OpenTK: передача массива unifrorm и vec2d во фрагментный шейдер

#c# #opengl #glsl #fragment-shader #opentk

#c# #opengl #glsl #фрагментный шейдер #opentk

Вопрос:

Я следовал этому руководству до завершения и создал этот проект на основе этого кода, который включает отправку массива vec2 в фрагментный шейдер. Однако я изо всех сил пытаюсь реализовать это эффективно, поскольку все мои попытки передать массив в шейдер завершились неудачей (прошел бы только первый элемент, остальные были бы равны нулю). В настоящее время я обхожу эту проблему, создавая индивидуальные формы для каждого элемента, но это совсем не идеально (существует 4 массива, каждый из которых содержит 76 элементов). Кроме того, я бы в конечном итоге хотел заменить эти массивы на dvec2 (Vector2d в OpenTK), но мне не удается даже передать один, и я не уверен, почему… Я пробовал использовать все соответствующие перегрузки GL.Uniform2, но, похоже, ни один из них не работает. Вот соответствующие фрагменты моего кода (полный код можно просмотреть по приведенным выше ссылкам):

     // These two functions successfully get the values to the shader
    public void SetVector2(string name, Vector2 data)
    {
        GL.UseProgram(Handle);
        GL.Uniform2(uniformLocations[name], data);
    }
    // But this one does so very undesirably, passing to independent variables rather than directly to a uniform array
    public void SetVector2Array(string name, Vector2[] data)
    {/*
        // This fails
        var floats = new float[data.Length * 2];

        for (int i = 0; i < data.Length * 2; i  = 2)
        {
            floats[i] = data[i / 2].X;
            floats[i   1] = data[i / 2].Y;
        }

        GL.UseProgram(Handle);
        //GL.Uniform2(uniformLocations[name], data.Length, floats);
        GL.Uniform2(uniformLocations[name   "[0]"], data.Length, floats);*/

        GL.UseProgram(Handle);

        for (int i = 0; i < data.Length; i  )
        {
            GL.Uniform2(uniformLocations[name   i], data[i]);
        }
    }


    // This fails altogether... not really sure what value this sends, but it's not the right one
    public void SetVector2d(string name, Vector2d data)
    {
        double[] d = new double[]
        {
            data.X,
            data.Y,
        };

        GL.UseProgram(Handle);
        GL.Uniform2(uniformLocations[name], 2, d);
    }
  

Мой фрагментный шейдер выглядит следующим образом (я бы хотел заменить каждый из 4 массивов простым «uniform vec2 array_name»):

 #define MAX_MATING_ITER 76

uniform vec2 ma0;
uniform vec2 ma1;
uniform vec2 ma2;
uniform vec2 ma3;
uniform vec2 ma4;
uniform vec2 ma5;
uniform vec2 ma6;
uniform vec2 ma7;
uniform vec2 ma8;
uniform vec2 ma9;
...
uniform vec2 md67;
uniform vec2 md68;
uniform vec2 md69;
uniform vec2 md70;
uniform vec2 md71;
uniform vec2 md72;
uniform vec2 md73;
uniform vec2 md74;
uniform vec2 md75;

// The 4 arrays I use
vec2 ma[MAX_MATING_ITER];
vec2 mb[MAX_MATING_ITER];
vec2 mc[MAX_MATING_ITER];
vec2 md[MAX_MATING_ITER];

void main()
{
    ma[0] = ma0;
    ma[1] = ma1;
    ma[2] = ma2;
    ma[3] = ma3;
    ma[4] = ma4;
    ma[5] = ma5;
    ma[6] = ma6;
    ma[7] = ma7;
    ma[8] = ma8;
    ma[9] = ma9;
    ...
    md[66] = md66;
    md[67] = md67;
    md[68] = md68;
    md[69] = md69;
    md[70] = md70;
    md[71] = md71;
    md[72] = md72;
    md[73] = md73;
    md[74] = md74;
    md[75] = md75;

    // Rest of the code
}
  

Комментарии:

1. Я не могу найти Uniform2(int, double[]) перегрузки в OpenTK. Откуда это берется? В принципе, шейдеры не поддерживают double s.

2. @donggas90 Uniform2(int, int, double[]) , Uniform2(int, int, double*) и Uniform2(int, int, ref double) допустимы.

3. @Rabbid76 Я ошибся. Я подумал о мобильных GL ES , потому что в настоящее время Vulkan намного популярнее, чем GL для настольных компьютеров.