Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (553)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  FBO for drawing / modify an image  (Read 3332 times)
0 Members and 1 Guest are viewing this topic.
Offline divxdede

Junior Member





« Posted 2012-05-01 14:48:46 »

Hello all,

For simplify, i have an Image with
 - A java ByteBuffer containing pixels
 - A render context giving an OpenGL Texture ID (if this image was already used by an OpenGL process)

So, now i want to be able to render on it and get back pixels buffer.

I would do a things like it (on general idea)
 - Bind a  texture from this image if it's not already done
 - Generate an FBO
 - Bind the FBO to the texture (or draw the texture on the FBO)
 - Bind the FBO
 - *** draw ***
 - delete the FBO (i assume that the result is directly on the texture Huh)

So after all, i want to mark the image as "Dirty" that mean the ByteBuffer is not up to date.
If in java i try a getBuffer(), i want to be able:
 - Get Back pixels buffer from the texture

So, i'm newbie in OpenGL, and i'm not sure that this procedure can be done as is.
Is a good way ?  i don't sure that FBO can be used like it ?
So if you can advise me on how to achieve this, it will be really usefull.

For more explanation, I would be able to do an API for drawing on an image in the same way if i draw on the screen.

Thanks in advance.
Sébastien.


Online theagentd
« Reply #1 - Posted 2012-05-01 15:24:59 »

Yes, it´s possible.
Something like this (untested code):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
int fbo = glGenFramebuffers();
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);

glViewport(0, 0, texWidth, texHeight);

//Draw to texture

glBindFramebuffer(GL_FRAMEBUFFER, 0); //Unbind FBO
glDeleteFramebuffers(fbo);

glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTES, byteBuffer);

//byteBuffer now contains the image data of the texture


This is slow as hell though. You could use it to generate static images at load time, but doing this every frame is a very bad idea since glGetTexImage() forces the GPU to finish rendering to the texture before it returns which stalls the CPU while waiting for it and then the GPU after it finishes since it has no more work.

Myomyomyo.
Offline divxdede

Junior Member





« Reply #2 - Posted 2012-05-01 16:46:53 »

Thanks a lot, i will test if it's work.
But yes, it's intended to create image and reuse it as is but not intended to modify image each frame rendering.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline divxdede

Junior Member





« Reply #3 - Posted 2012-05-02 19:43:39 »

Based on you example, i try this:

Initialisation of the FBO:
1  
2  
3  
4  
5  
   frameBufferId = GL30.glGenFramebuffers();
     
    GL30.glBindFramebuffer( GL30.GL_FRAMEBUFFER, frameBufferId);
    GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, imageContext.getTextureId() , 0);
    GL11.glViewport(0 , 0 , image.getWidth(), image.getHeight() );


When a drawing operation occurs on my image context, if it's underlying FBO is not the current frame buffer, i do this:
1  
2  
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId);
    GL11.glViewport(0 , 0 , image.getWidth(), image.getHeight() );


When drawaing operations are done on the image context, i close the underlyng FBO
1  
2  
3  
4  
5  
6  
        // returns on windows-system FBO
     GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
     
   // delete the FBO
  GL30.glDeleteFramebuffers(this.frameBufferId);
   this.frameBufferId = -1;


So after this sequence, i draw the texture on a 2D QUAD (i use an ortho projection since i work only in 2D)
but the texture remains unmodified... i don't find what is wrong...
Offline divxdede

Junior Member





« Reply #4 - Posted 2012-05-02 20:04:24 »

it need a call of GL11().glBindTexture(GL.GL_TEXTURE_2D, 0) before to bind the texture to the FBO

Offline davedes
« Reply #5 - Posted 2012-05-02 20:05:45 »

Ideally you should just initialize a single FBO that covers all sizes and reuse it as needed, rather than creating/deleting many FBOs throughout your game.

You should also do a glCheckFramebufferStatus to be safe, and probably unbind the frame buffer after creating it (unless you plan on using it immediately after creation). Don't forget to reset your viewport to your game's size after unbinding the FBO.

Rendering to a texture looks like this (pseduo-code):
1  
2  
3  
4  
5  
6  
7  
fbo.bind(); 
//now we are rendering to the FBO's color texture
//draw our stuff here...
fbo.unbind();

//now we are rendering to the screen... so we need to draw the FBO's color texture
drawTex( fbo.getTexture() );


Another thing... You might need to reset your glOrtho/modelview/etc. when entering the FBO, i.e. via a matrix push/pop.

Offline divxdede

Junior Member





« Reply #6 - Posted 2012-05-02 20:39:16 »

Thanks, i try to go in this way.

when i init my app, i do this

1  
2  
3  
4  
5  
6  
7  
  
   GL11.glMatrixMode(GL.GL_PROJECTION);
   GL11.glLoadIdentity();
   GL11.glOrtho(0, appWidth ,  appHeight , 0, 1, -1);
   GL11.glMatrixMode(GL.GL_MODELVIEW);
   GL11.glEnable( GL.GL_TEXTURE_2D );
   GL11.glViewport(0 , 0 , getWidth() , getHeight() );


when i bind the fbo, i can do this:

1  
2  
3  
4  
  
   GL11.glPushMatrix();
   GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId);
   GL11.glViewport(0 , 0 , image.getWidth() , image.getHeight() );


When i unbind the fbo, i do this

1  
2  
3  
4  
   
   GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
   GL11.glPopMatrix();
   GL11.glViewport(0 , 0 , appWidth,  appHeight);


I have with this strange result (coordinate and scale issue that let means that i have problems with view context)
What can i miss ?
Offline davedes
« Reply #7 - Posted 2012-05-02 21:00:23 »

Try re-entering ortho mode. Also push some attributes like GL_VIEWPORT_BIT and GL_TRANSFORM_BIT via glPushAttrib.

Here's my little FBO wrapper if you're interested. It uses GL_EXT_framebuffer_object since OpenGL 3.0 is still a bit new (and my Mac only supports GL 2.1).

http://www.java-gaming.org/?action=pastebin&id=79

Offline divxdede

Junior Member





« Reply #8 - Posted 2012-05-03 06:41:50 »

Finally this works for me :

FBO init:

 
1  
2  
3  
4  
5  
6  
   
   // we muse ensure that before that, the textureId is not bind
  frameBufferId = GL30.glGenFramebuffers();
   GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId);
   GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, textureId , 0);
   GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);


Graphics Context bind (for drawing on the image):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
  
  originalViewport.clear();                                             // direct IntBuffer in native bytes order
 GL11.glGetInteger( GL.GL_VIEWPORT , originalViewport ); // backup the current viewport
     
  GL11.glMatrixMode( GL.GL_PROJECTION );
  GL11.glPushMatrix();
       
  GL11.glLoadIdentity();
  GL11.glOrtho(0, image.getWidth() , 0, image.getHeight() , 1, -1);
  GL11.glMatrixMode( GL.GL_MODELVIEW );
  GL11.glPushMatrix();
       
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId);
  GL11.glViewport(0, 0, imageWidth , imageHeight );


And when i need to push back into the window context :
1  
2  
3  
4  
5  
6  
7  
8  
   
   GL11().glMatrixMode( GL.GL_MODELVIEW );
   GL11().glPopMatrix();
   GL11().glMatrixMode( GL.GL_PROJECTION );
   GL11().glPopMatrix();
       
   GL30.glBindFramebuffer( GL30.GL_FRAMEBUFFER, 0);
   GL11.glViewport( originalViewport.get(0) , originalViewport.get(1) , originalViewport.get(2) , originalViewport.get(3) );


And the destroy part:
1  
2  
3  
   
   GL30.glDeleteFramebuffers(frameBufferId);
   frameBufferId = -1;


I'm not really happy with this current design, in my opinion, it's to my "window" class to restore it's original viewport, but i will see after how i can enhance this.
Thank's for all, your wrapper helps me to write mine.

Online theagentd
« Reply #9 - Posted 2012-05-03 06:56:25 »

You can push the viewport attribute (glPushAttrib(GL_VIEWsomething) and then glPopAttrib(GL_VIEWsomething)) to save the current viewport.

Myomyomyo.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline divxdede

Junior Member





« Reply #10 - Posted 2012-05-03 07:28:43 »

You can push the viewport attribute (glPushAttrib(GL_VIEWsomething) and then glPopAttrib(GL_VIEWsomething)) to save the current viewport.

Thanks, i don't know this, i will try this evening
Online theagentd
« Reply #11 - Posted 2012-05-03 08:05:05 »

1  
2  
3  
glPushAttrib(GL_VIEWPORT_BIT);

glPopAttrib(GL_VIEWPORT_BIT);


Myomyomyo.
Offline divxdede

Junior Member





« Reply #12 - Posted 2012-05-05 07:51:27 »

It works fine for now.

FOr add deeper in my tools, in can draw on a specific region on a texture.
it becomes when we create a "subimage" from another one at the API level.
i must in this case let it drawing only in the texture that corresponds to it's subimage.
For now, i used a translatef + scissor like it:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
    
     public void bind(GLContext ctx) {
      // set rendering destination to FBO
      ImageContext imageContext = (ImageContext)image.getContext();
     
       ctx.getGL11().glMatrixMode( GL.GL_PROJECTION );
       ctx.getGL11().glPushMatrix();
       
       ctx.getGL11().glLoadIdentity();
       ctx.getGL11().glOrtho( 0 , imageContext.getTextureWidth() , 0 , imageContext.getTextureHeight() , 1, -1);
       ctx.getGL11().glMatrixMode( GL.GL_MODELVIEW );
       ctx.getGL11().glPushMatrix();
       
       GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId);
       super.bind(ctx); // push all attrib-bits + all client-attrib-bits
      ctx.getGL11().glViewport( 0 , 0 , imageContext.getTextureWidth() , imageContext.getTextureHeight() );
       
       ctx.getGL11().glTranslatef( imageContext.getX() , imageContext.getY() , 0f );
       ctx.getGL11().glEnable( GL.GL_SCISSOR_TEST );
       ctx.getGL11().glScissor( imageContext.getX() , imageContext.getY() , imageContext.getWidth() , imageContext.getHeight() );
    }


I would know if the viewport reset before translate call ? because here i explain a translate from my viewport coordonate reardless previous translatef that may be done before.
It seems to work well, bu i want to be sure.
Thanks in advance.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

TehJavaDev (13 views)
2014-08-28 18:26:30

CopyableCougar4 (25 views)
2014-08-22 19:31:30

atombrot (38 views)
2014-08-19 09:29:53

Tekkerue (31 views)
2014-08-16 06:45:27

Tekkerue (31 views)
2014-08-16 06:22:17

Tekkerue (19 views)
2014-08-16 06:20:21

Tekkerue (29 views)
2014-08-16 06:12:11

Rayexar (66 views)
2014-08-11 02:49:23

BurntPizza (42 views)
2014-08-09 21:09:32

BurntPizza (34 views)
2014-08-08 02:01:56
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!