Как обработать и вернуть массив с JOGL - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь использовать JOGL для взаимодействия между Java и GLSL для параллельной обработки массивов. Мне не интересно рисовать что-либо на экране. Я хотел бы иметь возможность взять пару массивов с плавающей точкой, передать их в шейдерную программу, обработать их с помощью графического процессора и вернуть значения обратно в код Java.

Например, у меня есть плавающие массивы

float[] array1 = {...};
float[] array2 = {...};

Тогда у меня есть шейдерная программа, которая содержит строку

float resultArray = sin(array2)*array1; // Just a random function of the two arrays

Затем верните 'resultArray' в виде массива с плавающей точкой обратно в мою Java-программу для использования в других целях.

Мой текущий код

int v = gl.glCreateShader(GL.GL_VERTEX_SHADER);
int f = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);

String vertShader =
    "
    void main()
    {
        gl_Position    = gl_ModelViewProjectionMatrix * gl_Vertex;
        gl_TexCoord[0] = gl_MultiTexCoord0;
    }
    ";
gl.glShaderSource(v, 1, vertShader, (int[])null);
gl.glCompileShader(v);

String fragShader =
    "
    out float resultArray;
    varying float array1;
    varying float array2;

    void main( void )
    {
        // Assuming this code should go in the fragment shader
        float resultArray = sin(array2)*array1;
    }
    ";
gl.glShaderSource(f, 1, fragShader, (int[])null);
gl.glCompileShader(f);

int shaderprogram = gl.glCreateProgram();
gl.glAttachShader(shaderprogram, v);
gl.glAttachShader(shaderprogram, f);
gl.glLinkProgram(shaderprogram);
gl.glValidateProgram(shaderprogram);

gl.glUseProgram(shaderprogram);

float[] resultArray = gl.callSomeMethodThatDoesntExist(shaderprogram, array1, array2);

Но я не уверен, как передавать массивы с плавающей точкой в ​​шейдеры и как получить результат после его обработки.

Кто-нибудь может указать мне правильное направление?

1 Ответ

0 голосов
/ 16 ноября 2018

Эй @ Дэниел, вы можете передавать массивы в шейдеры, используя униформу. Мне нравится думать об униформе как о аргументах или входных данных для шейдера.

С https://www.khronos.org/opengl/wiki/Uniform_(GLSL):

Эти [униформы] действуют как параметры, которые пользователь шейдерной программы может передать этой программе.

struct Thingy
{
  vec4 an_array[3];
  int foo;
};

layout(location = 2) uniform Thingy some_thingies[6];

Некоторые люди предпочитают передавать массивы в виде текстур, где значения r, g, b представляют некоторые значения, которые вам нужны в вашем шейдере.

uniform sampler2D myTexture;

Для получения результата; как правило, ваш шейдер будет выводить в кадровый буфер по умолчанию.

По умолчанию Framebuffer - это Framebuffer, с помощью которого создается OpenGL. Он создается вместе с контекстом OpenGL. Как и объекты Framebuffer, кадровый буфер по умолчанию представляет собой серию изображений. В отличие от FBO, одно из этих изображений обычно представляет то, что вы на самом деле видите на некоторой части экрана. Стандартный кадровый буфер создается во время создания контекста OpenGL.

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

Определяемые пользователем выходные данные фрагментного шейдера представляют собой серию "цвета". Эти значения цвета направлены в конкретные буферы на основе в состоянии glDrawBuffers. Они называются «фрагментными цветами», хотя Вы можете обращаться с ними как с любыми произвольными данными.

Вы также можете выводить в более чем один буфер в зависимости от того, как вы настроили свой кадровый буфер, см.

Отображение между цветами фрагмента и фактическими буферами в Framebuffer определяется glDrawBuffers, который является частью состояния framebuffer. Например, если мы настроим наши буферы рисования следующим образом:

const GLenum buffers [] = {GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT2, GL_NONE, GL_COLOR_ATTACHMENT0}; glDrawBuffers (4, буферы);

К сожалению, хотя фрагментные шейдеры работают только с доступными им данными по каждому пикселю, и вы не можете контролировать, какой это пиксель. Чтобы справиться с этим, люди часто используют технику, называемую отложенным затенением, когда необходимая информация о пикселях передается в качестве входных данных текстуры фрагментного шейдера (обычно используется для постобработки).

Надеюсь, этот ответ не слишком длинный и сложный для понимания, к сожалению, вернуть массив с помощью шейдера немного сложнее, чем вы ожидаете.

В качестве альтернативы, OpenCL может быть более подходящим для того, что вы пытаетесь сделать, хотя у меня нет опыта в этом.

...