简体   繁体   中英

How to process and return an array with JOGL

I am trying to use JOGL to interface between Java and GLSL for processing arrays in parallel. I'm not interested in drawing anything to the screen. I would like to be able to take a pair of float arrays, pass them to a shader program, process them with the GPU, and return the values back to the Java code.

For example, I have float arrays

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

Then I have a shader program that contains the line

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

Then return the 'resultArray' as a float array back to my Java program to use for other purposes.

My current code is

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);

But I'm not sure how to pass the float arrays into the shaders, nor how to get the result after it is processed.

Can anyone point me in the right direction?

Hey @Daniel you can pass arrays in to a shader using uniforms. I like to think of uniforms sort of as arguments or inputs to a shader.

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

These [uniforms] act as parameters that the user of a shader program can pass to that program.

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

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

Some people prefer to pass arrays in as textures, where the r,g,b values represent some values you need in your shader.

uniform sampler2D myTexture;

For getting back your output; generally your shader will output to the default framebuffer.

The Default Framebuffer is the Framebuffer that OpenGL is created with. It is created along with the OpenGL Context. Like Framebuffer Objects, the default framebuffer is a series of images. Unlike FBOs, one of these images usually represents what you actually see on some part of your screen. The default framebuffer is created at the time the OpenGL context is constructed.

As far as I know fragment shaders are only capable of outputting to a frame buffer and so if you need to get back an array of some sort you will need to output to a frame buffer and then extract your data from the frame buffer.

User-defined outputs from a fragment shader represent a series of "colors". These color values are directed into specific buffers based on the glDrawBuffers state. These are called "fragment colors", though you can treat them like any arbitrary data.

You can also output to more than one buffer depending on how you have set up your framebuffer see: https://www.khronos.org/opengl/wiki/Fragment_Shader#Output_buffers

The mapping between fragment colors and actual buffers within a Framebuffer is defined by glDrawBuffers, which is part of the framebuffer's state. For example, if we set our draw buffers up like this:

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

Unfortunately though fragment shaders only operate on the data available to them on a per pixel basis, and you don't have control over which pixel that is. To deal with this people often use a technique called deferred shading where information required about pixels is passed in as texture inputs of the fragment shader (commonly used to do post processing).

Hopefully this answer is not to long and complicated to follow, unfortunately getting back an array using a shader is a bit more complicated than you would expect.

Alternatively, OpenCL might be more appropriate for what you are trying to do, though I have no experience with that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM