How can you change a GL_RG32F ofTexture to GL_RGB32F ofTexture?

Is there a simple way to change a GL_RG32F type ofTexture object to a GL_RGB32F type ofTexture? I want to copy the texture data to a ofPixels object using readToPixels() but for a reason that I don’t know, does not work when the texture type is GL_RG32F.

When I try to use readToPixels() with a GL_RG32F ofTexture object, the following error occurs.

[ error ] ofPixels: image type not supported

[ error ] ofPixels: format doesn't support channels

[ error ] ofGLUtils: ofGetGLFormatFromPixelFormat(): unknown OF pixel format OF_PIXELS_UNKNOWN, returning GL_RED

I think I found a work around, but it doesn’t feel ideal and would be thankful for a new way to approach this.

For me, making a ofFbo object that has GL_RGB32F format and drawing the GL_RG32F ofTexture into the framebuffer and using the texture from the updated framebuffer as the texture to be copied into the ofPixels object worked without errors.

So my question is, is there a more direct way to copy the GL_RG32F texture data to an ofPixels object using readToPixels()?

Hey there!

I suggest using a pixel buffer object to copy the GL_RG32F to ofFloatPixels directly like this:

// setup

ofFbo fbo;
fbo.allocate(256, 256, GL_RG32F); // 

ofBufferObject pixBuf;
pixBuf.allocate(fbo.getWidth() * fbo.getHeight() * 2 * sizeof(float), GL_DYNAMIC_READ); // width * height * 2 channels * 4 bytes
	
ofFloatPixels pixels; // store float-precision pixels

// anywhere else

fbo.copyTo(pixBuf);
float* p = pixBuf.map<float>(GL_READ_ONLY);

pixels.setFromExternalPixels(p, fbo.getWidth(), fbo.getHeight(), 2);

pixBuf.unmap();
pixBuf.unbind(GL_PIXEL_UNPACK_BUFFER);

Thank you for your reply! Is it possible to do the same with ofPixels? I’m actually using an addon that requires an ofPixels object. (ofxSquashBuddies)

Yes! A fast way in which you could do this is by drawing the contents of the GL_RG32F FBO into another GL_RG8 FBO of the same size. This should automatically perform the conversion from high to low-precision. Then, you can perform the copy to an ofPixels object using unsigned char instead of float.

Thank you for your suggestions!

I tried like below
at setup :
Here I tried using sizeof( unsigned char ) instead of sizeof( float ), but it did not make a difference in the visual output or the error logs.

    send_pixBuf.allocate(flow_w * flow_h * 2 *sizeof ( float ), GL_DYNAMIC_READ);
    send_fbo.allocate(flow_w, flow_h, GL_RG8);

at draw :

    send_fbo.begin();
    ofClear(255);
    fluid_flow.getVelocity().draw(0,0,flow_w,flow_h);
    send_fbo.end();
    
    send_fbo.copyTo(send_pixBuf);
    unsigned char *p = send_pixBuf.map<unsigned char>(GL_READ_ONLY);

    ofPixels send_pixels;
    send_pixels.setFromExternalPixels(p, flow_w, flow_h, 2);

So the fluid_flow is an object that was derived from the ofxFlowTools addon. When you use getVelocity(), It returns a ofTexture that has GL_RG32F type.

I tried to draw that texture into the additional GL_RG8 fbo like you said, and then copy it into a ofPixel object with unsigned char instead of float. But although the program seems to run, it still prints the error below.

[ error ] ofPixels: image type not supported

And also, when the ofPixels object is sent and received through local network(I don’t know exactly what I mean by this. I’m using the IP address 127.0.0.1), it somehow renders like a grayscale image, unlike the GL_RG8 type, which renders in green and red.

So either when the data is copied to an ofPixels object or when it is sent with the ofxSquashBuddies could be causing the problem. But even if I set aside the problems shown in the rendered visuals above, I still can’t seem to get rid of the error message shared above.

On closer inspection, I discovered ofPixels does not support two-channel RG pixels. My bad! This means you can simply change send_fbo to type GL_RGBA and then do readPixels() like you did before instead of the pixel buffer method–although I would recommend it to speed up the copy.

Thanks again! I thought if I could send the image in GL_RG32F format, I would be able to send large images in comparison via network while showing reasonable latency. (Because presumably the GL_RG32F is smaller than GL_RGB32F)

So even if I speed up the copying process (from ofFbo to ofPixels) on the client side, I don’t think it will have huge improvements on the performance of streaming images.

One thing I might try in the future though, on a side note, would be to write a shader program that takes the GL_RG32F texture as uniform and writes to an fbo that has type GL_RGBA32F and some how pack information in the BA channels as well so that the image size maybe reduced?