如何使用JOGL处理和返回数组

时间:2018-11-15 22:44:23

标签: java jogl

我正在尝试使用JOGL在Java和GLSL之间进行接口以并行处理数组。我对在屏幕上绘制任何内容都不感兴趣。我希望能够使用一对float数组,将它们传递给着色器程序,使用GPU处理它们,然后将值返回给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);

但是我不确定如何将float数组传递到着色器中,也不确定如何处理后的结果。

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:2)

嘿@Daniel,您可以使用制服将数组传递到着色器中。我喜欢将制服看作是着色器的参数或输入。

来自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;

用于恢复您的输出;通常,您的着色器将输出到默认的帧缓冲区。

  

默认帧缓冲区是用于创建OpenGL的帧缓冲区。它与OpenGL上下文一起创建。像帧缓冲对象一样,默认的帧缓冲是一系列图像。与FBO不同,这些图像之一通常代表您实际在屏幕的某个部分看到的图像。   默认的帧缓冲区是在构造OpenGL上下文时创建的。

据我所知,片段着色器只能输出到帧缓冲区,因此,如果您需要取回某种数组,则需要输出到帧缓冲区,然后从帧缓冲区中提取数据

  

片段着色器的用户定义输出表示一系列   “颜色”。这些颜色值被定向到基于   在glDrawBuffers状态上。不过,这些被称为“片段颜色”   您可以将它们视为任意数据。

您还可以根据设置帧缓冲区的方式输出到多个缓冲区,请参见:https://www.khronos.org/opengl/wiki/Fragment_Shader#Output_buffers

  

片段颜色和帧缓冲区中的实际缓冲区之间的映射由glDrawBuffers定义,它是帧缓冲区状态的一部分。   例如,如果我们这样设置绘制缓冲区:

     

const GLenum缓冲区[] = {GL_COLOR_ATTACHMENT4,GL_COLOR_ATTACHMENT2,   GL_NONE,GL_COLOR_ATTACHMENT0}; glDrawBuffers(4,buffers);

不幸的是,虽然片段着色器仅在每个像素可用的数据上操作,并且您无法控制哪个像素。为了解决这个问题,人们经常使用一种称为延迟着色的技术,该技术将有关像素所需的信息作为片段着色器的纹理输入(通常用于后期处理)传递。

希望这个答案不会太冗长和复杂,不幸的是,使用着色器返回数组比您预期的要复杂一些。

或者,OpenCL可能更适合您尝试做的事情,尽管我对此没有经验。