Can someone walk me through setting up render to texture?

Started by hyphz, April 08, 2005, 11:32:05

Previous topic - Next topic

hyphz

Ok, I'm very new to OpenGL and LWJGL and I want to try and set up a render-to-texture.  Here's what I've got so far with my comments (which I'm afraid may be more amusing than useful...)

IntBuffer stupidpointlessbuffer = BufferUtils.createIntBuffer(1);
GL11.glGenTextures(stupidpointlessbuffer);
int texid = stupidpointlessbuffer.get(0);


Get a new texture ID, which requires us to set up a buffer even though we only want one and we want it right now, hence the variable name.

GL11.glBindTexture(GL11.GL_TEXTURE_2D, texid);


I have no idea what this does.  It's here because every other OpenGL program I've ever seen does it.  Even the OpenGL documentation I saw wouldn't explain what GL_TEXTURE_2D is other than saying it's "reserved for future development".

GL11.glTexImage2D(GL11.GL_TEXTURE_2D,0,4,128,128,0,GL11.GL_RGBA,GL11.GL_UNSIGNED_BYTE,space);


Create the actual texture.

RenderTexture mgTex = new RenderTexture(false, true, false, false, RenderTexture.RENDER_TEXTURE_2D, 1);


Create a render texture that points to it.

microBuffer = new Pbuffer(128, 128, new PixelFormat(), mgTex, null);


Create the Pbuffer, whatever that is, that will render to the texture.

 microBuffer.makeCurrent();


Start rendering to that texture instead of the Display.

GL11.glBegin(GL11.GL_QUADS);
  GL11.glVertex2f(0, 0);
 GL11.glVertex2f(0, 1);
  GL11.glVertex2f(1, 1);
  GL11.glVertex2f(1, 0);
 GL11.glEnd();
 GL11.glFlush();


Draw some random stuff on the texture.

Quote
Display.makeCurrent();

Go back to the display again.

Quote
GL11.glEnable(GL11.GL_TEXTURE_2D);

From what I'm given to understand, as of now everything that I draw is textured with the texture currently bound to GL_TEXTURE_2D..

Quote
       GL11.glBegin(GL11.GL_QUADS);
       GL11.glTexCoord2f(0,0); GL11.glVertex2f(0, 0);
       GL11.glTexCoord2f(0,1); GL11.glVertex2f(0, 1);
       GL11.glTexCoord2f(1,1); GL11.glVertex2f(1, 1);
       GL11.glTexCoord2f(1,0); GL11.glVertex2f(1, 0);
       GL11.glEnd();
       GL11.glFlush();

Draw a big quad with the texture direct mapped to it.

Sadly, the result is a whole big heap'o'nothing.  Can anyone tell me what I'm doing wrong, other than trying this in the first place while knowing as little as I do ;)
[/code]

Orangy Tang

glBindTexture sets the current texture. All textuing operations take place on the bound texture. Use it with a null (0) texture id to clear the bound texture (although usually better to disable texturing). GL_TEXTURE_2D specifies that you're binding a 2d texture (as opposed to a 1d or 3d texture).

You don't actually set a colour when you render to your texture, so you might just be getting blackness.

Equally, the default view setup is in 1:1 with gl units and pixels. Your quads may just be one pixel large (unless you've changed this).

Unfortunatly I've not used render to texture, so I can't help you any with that. I'd suggest you just do some regular texturing stuff first so you can be confident that isn't the problem.

hyphz

Quote from: "Orangy Tang"glBindTexture sets the current texture. All textuing operations take place on the bound texture.

Ok, you're going to have to go slow with me here... isn't that what makeCurrent does?

hyphz

Ah, ok.. after I fixed up the coords and added colour, I got a white box.  But now I'm trying to go advanced and have a white box with a red bit in the middle (gasp)

And I don't get the red bit.  For some reason.

IntBuffer stupidpointlessbuffer = BufferUtils.createIntBuffer(1);
GL11.glGenTextures(stupidpointlessbuffer);
int texid = stupidpointlessbuffer.get(0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texid);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D,0,4,128,128,0,GL11.GL_RGBA,GL11.GL_UNSIGNED_BYTE,space);
RenderTexture mgTex = new RenderTexture(false, true, false, false, RenderTexture.RENDER_TEXTURE_2D, 1);
microBuffer = new Pbuffer(128, 128, new PixelFormat(), mgTex, null);

microBuffer.makeCurrent();
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor3b((byte)255, (byte)255, (byte)255);
GL11.glVertex2f(0, 0);
GL11.glVertex2f(0, 100);
GL11.glVertex2f(100, 100);
GL11.glVertex2f(100, 0);
GL11.glEnd();
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor3b((byte)255, (byte)0, (byte)0);
GL11.glVertex2f(50, 50);
GL11.glVertex2f(50, 75);
GL11.glVertex2f(75, 75);
GL11.glVertex2f(75, 50);
GL11.glEnd();
GL11.glFlush();

Display.makeCurrent();
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0); GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(0,128); GL11.glVertex2f(0, 200);
GL11.glTexCoord2f(128,128); GL11.glVertex2f(200, 200);
GL11.glTexCoord2f(128,0); GL11.glVertex2f(200, 0);
GL11.glEnd();
GL11.glFlush();

napier

You may want to start with something simpler at first.  You can render to the frame buffer, and copy the rendering to a texture, without using pbuffers at all.  Pbuffers pose some problems of their own that you may want to avoid till you've got texturing down.

The technique is to create a blank texture, do some drawing to the frame buffer, then call glCopyTexSubImage2D() to copy a portion (or all) of the framebuffer to a texture.  Then clear the framebuffer and render your scene.  You can use the copied texture as you would any other texture.  I use this technique to save and restore frame images.  

Some code I've used to do this:

   /**
     * Allocate a texture (glGenTextures) and return the handle to it.
     */
    public static int allocateTexture()
    {
        IntBuffer textureHandle = allocInts(1);
        GL11.glGenTextures(textureHandle);
        return textureHandle.get(0);
    }

    /**
     * Create a texture from the given pixels in RGBA format.  Set the texture
     * to repeat in both directions and use LINEAR for magnification.
     * @return  the texture handle
     */
    public static int makeTexture(ByteBuffer pixels, int w, int h)
    {
        // get a new empty texture
        int textureHandle = allocateTexture();
        // 'select' the new texture by it's handle
        GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle);
        // set texture parameters
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); //GL11.GL_NEAREST);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); //GL11.GL_NEAREST);
        // Create the texture from pixels
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, w, h, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixels);
        return textureHandle;
    }

    /**
     * Copy the frame buffer to a texture.  Texture must be big enough to
     * hold entire screen and dimensions must be powers of 2, ie 1024x1024.
     */
    public void frameSave(int txtrHandle)
    {
	// turn off alpha and color tints
        GL11.glColor4f(1,1,1,1);                
        GL11.glReadBuffer(GL11.GL_BACK);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D,txtrHandle);
	// copy the full frame into the given texture
        GL11.glCopyTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0,0, 0,0, DM.getWidth(),DM.getHeight());
    }


    /**
     * Meant to be used in ORTHO mode (2D)
     */
    public static void drawQuad(int textureHandle, int x, int y, float w, float h) {
        GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle);
        // draw  textured quad
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0f, 0f);
        GL11.glVertex3f( (float)x, (float)y, (float)0);
        GL11.glTexCoord2f(1f, 0f);
        GL11.glVertex3f( (float)x+w, (float)y, (float)0);
        GL11.glTexCoord2f(1f, 1f);
        GL11.glVertex3f( (float)x+w, (float)y+h, (float)0);
        GL11.glTexCoord2f(0f, 1f);
        GL11.glVertex3f( (float)x, (float)y+h, (float)0);
        GL11.glEnd();
    }


I use makeTexture() to create a blank texture (has to be square, and powers of two ie. 32x32 or 128x128 etc.), and call frameSave() to copy the whole screen (DM is the displayMode), but you could copy a portion as well.  Then that texture can be passed to drawQuad() to draw it onto a rectangle on screen.
penGL/Java/LWJGL demos and code: http://potatoland.org/code/gl