Convolution filters and lack of FloatBuffer support

Started by Ciardhubh, July 17, 2008, 11:26:02

Previous topic - Next topic

Ciardhubh

Hi,

I'm currently trying to get convolution filters to work using LWJGL. Does anybody have a working example they would share?

I tried to implement the Redbook example in LWGJL but failed. Partially because for some reason LWJGL lacks the support of FloatBuffers for ARBImaging.glConvolutionFilter2D(...). Is this lack intentional or was it an oversight?

The example in the book explicitely uses float arrays and I've seen the same example for JOGL (http://www.java-tips.org/other-api-tips/jogl/how-to-use-various-2d-convolutions-filters-to-find-edges-in-an.html) and it does exactly what I'm trying to do.

The example is supposed to draw an image with the given filter.

Original C code (only the convolution filter specific part):
GLfloat  horizontal[3][3] = {
    { 0, -1, 0 },
    { 0,  1, 0 },
    { 0,  0, 0 }
};

...

glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE,
			 3, 3, GL_LUMINANCE, GL_FLOAT, horizontal);
glEnable(GL_CONVOLUTION_2D);


My attempt in LWJGL (had to change to int/IntBuffer due to lack of FloatBuffer support in glConvolutionFilter2D):
private int[] horizontal = {
     0, -1, 0,
     0, 1, 0,
     0, 0, 0
};
private IntBuffer horizontalBuffer = (IntBuffer) BufferUtils.createIntBuffer(horizontal.length).put(horizontal).flip();

...

ARBImaging.glConvolutionFilter2D(ARBImaging.GL_CONVOLUTION_2D, GL11.GL_LUMINANCE,
  3, 3, GL11.GL_LUMINANCE, GL11.GL_INT, horizontalBuffer);
GL11.glEnable(ARBImaging.GL_CONVOLUTION_2D);


That is exactly like the JOGL example I've seen (except that I had to use int instead of float) and all I get is a black screen.  Without the filter the image draws normally. Any ideas?

bitsNbytes

hi,

i think integer-colors are between 0 to 255, so 1 is very dark.

what happens when you try

private int[] horizontal = {
     0, -255, 0,
     0, 255, 0,
     0, 0, 0
};


?

alternatively you could try using shaders

hope that helps

Ciardhubh

Quote from: bitsNbytes on July 28, 2008, 18:01:33
hi,

i think integer-colors are between 0 to 255, so 1 is very dark.

what happens when you try

private int[] horizontal = {
     0, -255, 0,
     0, 255, 0,
     0, 0, 0
};


?

alternatively you could try using shaders

hope that helps

The way I understand it, convolution filters use these values as a weight for colours in the image. So a 1 is not near black but 1*orginalColour. I've tried it with 255, though. The result was the same black image.

A huge part of the examples I've seen, use floating point values for their convolution matrices. So I think it may be a bug/oversight in LWJGL as you cannot pass a FloatBuffer to glConvolutionFilter2D().

I have occassionally encountered methods that do not accept FloatBuffers and thus cannot handle drawing to GL_LUMINANCE even though this seems to be supported by OpenGL. Another example would be glDrawPixels().

Shaders are something I'll take a look at some time in the future ;)

Ciardhubh

Yay, it works. I've read somewhere that OpenGL internally converts data types, depending on what the target format requires. This and the idea to use 255 instead of 1 led to a solution. Since GL_LUMINANCE is a value between 0 and 1 as float, I use values between 0 and Integer.MAX_VALUE (and Integer.MIN_VALUE and 0 for negative values).

    private int[] horizontal = {
        0, Integer.MIN_VALUE, 0,
        0, Integer.MAX_VALUE, 0,
        0, 0, 0
    };
    private IntBuffer horizontalBuffer =
            (IntBuffer) BufferUtils.createIntBuffer(horizontal.length).put(horizontal).flip();
...
    ARBImaging.glConvolutionFilter2D(ARBImaging.GL_CONVOLUTION_2D, GL11.GL_LUMINANCE,
            3, 3, GL11.GL_LUMINANCE, GL11.GL_INT, horizontalBuffer);


Feels like a bit of a hack though and it probably is less efficient than directly passing floats ;)