Search code examples
opengljoglrender-to-texture

Render to texture, the texture is not shown completely


Basically when I am rendering to texture, it looks like some part of the texture got lost.

package org.yourorghere;

import com.jogamp.opengl.util.GLBuffers;
import java.awt.Component;
import java.nio.ByteBuffer;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;


public class GLRenderer implements GLEventListener {

int[] textureID = new int[1];
private int floorWidth=48, floorHeight=48;
int[] frameBufferID = new int[1];
int[] depthRenderBufferID = new int[1];
ByteBuffer pixels;
GLU glu;

public void init(GLAutoDrawable drawable) {
    glu = new GLU();

    System.out.println("init");

    GL2 gl = drawable.getGL().getGL2();
    System.err.println("INIT GL IS: " + gl.getClass().getName());

    // Setup the drawing area and shading mode
    gl.glShadeModel(GL2.GL_SMOOTH); // try setting this to GL_FLAT and see what happens.

    renderShadowsToTexture(gl);

    gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
}

public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}

public void display(GLAutoDrawable drawable) {
    GL2 gl = drawable.getGL().getGL2();

    System.out.println("display");

    float a = 1.0f;

    gl.glMatrixMode(GL2.GL_PROJECTION);
    // Reset the current matrix to the "identity"
    gl.glLoadIdentity();
    glu.gluPerspective(60.0f, (((Component)drawable).getWidth()/
            ((Component)drawable).getHeight()), 1.0f, 50.0f);

    gl.glMatrixMode(GL2.GL_MODELVIEW);
    gl.glLoadIdentity();
    glu.gluLookAt(0.0f, 0.0f, 0.0f, 
                  0.0f, 0.0f, 1.0f, 
                  0.0f, 1.0f, 0.0f);

    // Clear the drawing area
    gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

    gl.glTranslatef(-2.5f, 0.0f, 0.0f);

    gl.glEnable(GL2.GL_TEXTURE_2D);

    gl.glBindTexture(GL2.GL_TEXTURE_2D, textureID[0]);

        gl.glColor3f(1.0f, 1.0f, 1.0f);
        gl.glBegin(GL2.GL_QUADS);
            gl.glTexCoord2f(0, 0);
            gl.glVertex3f(-1.0f,-1.0f, 0.0f);
            gl.glTexCoord2f(0, a);
            gl.glVertex3f(-1.0f, 1.0f, 0.0f);
            gl.glTexCoord2f(1.0f, 1.0f);
            gl.glVertex3f( 1.0f, 1.0f, 0.0f);
            gl.glTexCoord2f(a, 0);
            gl.glVertex3f( 1.0f,-1.0f, 0.0f);
        gl.glEnd();
    gl.glDisable(GL2.GL_TEXTURE_2D);

    gl.glRasterPos2d(3, -2);
    gl.glDrawPixels(floorWidth, floorHeight, GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE, pixels);

}

private void renderShadowsToTexture(GL2 gl) {
    gl.glGenTextures(1, textureID, 0);
    gl.glBindTexture(GL2.GL_TEXTURE_2D, textureID[0]);

    gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
    gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);

    // null means reserve texture memory, but texels are undefined
    gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGB, floorWidth, floorHeight,
                                                0, GL2.GL_RGB, GL2.GL_FLOAT, null);

    gl.glGenFramebuffers(1, frameBufferID, 0);
    gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, frameBufferID[0]);

    //Attach 2D texture to this FBO
    gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_COLOR_ATTACHMENT0, 
                                    GL2.GL_TEXTURE_2D, textureID[0], 0);

    // depth buffer
    gl.glGenRenderbuffers(1, depthRenderBufferID, 0);
    gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, depthRenderBufferID[0]);
    gl.glRenderbufferStorage(GL2.GL_RENDERBUFFER, GL2.GL_DEPTH_COMPONENT, 
                                            floorWidth, floorHeight);
    gl.glFramebufferRenderbuffer(GL2.GL_FRAMEBUFFER, GL2.GL_DEPTH_ATTACHMENT,
                                        GL2.GL_RENDERBUFFER, depthRenderBufferID[0]);

    if(gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER) == GL2.GL_FRAMEBUFFER_COMPLETE)
        System.out.println("[Viewer] GL_FRAMEBUFFER_COMPLETE!!");
    else
        System.out.println("..cazzo ^^");

    gl.glMatrixMode(GL2.GL_MODELVIEW);
    gl.glPushMatrix();
    gl.glLoadIdentity();

    gl.glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
    gl.glClear(GL2.GL_COLOR_BUFFER_BIT);

    gl.glPointSize(10.0f);
    gl.glBegin(GL2.GL_POINTS);
        gl.glColor3f(0.0f, 1.0f, 0.0f);
        gl.glVertex2d(1.0f, 1.0f);        // THIS IS NOT SHOWN
        gl.glColor3f(0.0f, 0.0f, 1.0f);
        gl.glVertex2d(-1.0f, -1.0f);
        gl.glVertex2d(-0.9f, -0.9f);
    gl.glEnd();

    gl.glPopMatrix();

    pixels = GLBuffers.newDirectByteBuffer(floorWidth*floorHeight*4);

    gl.glReadPixels(0, 0, floorWidth, floorHeight, GL2.GL_RGBA, 
                                                GL2.GL_UNSIGNED_BYTE, pixels);


    System.out.println("glIsTexture: "+gl.glIsTexture(textureID[0]));

    //  bind the back buffer for rendering
    gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
}

public void dispose(GLAutoDrawable glad) {
//        throw new UnsupportedOperationException("Not supported yet.");
        System.out.println("dispose");
    }

}

Starting from the left, the triangle and the first quad are rendered normally using the display() while the last quad on the right and the one below are respectively the quad rendered with the texture mapped on it and the quad showing what is inside the texture itself.

Basically I do not see the red point, only the blue ones. Why?

enter image description here


Solution

  • I'm not familiar with this particular OpenGL wrapper, but what I notice about your code is that in renderShadowsToTexture you do not configure two things: the viewport and the projection matrix. Both of these will affect the scaling of the resulting image.

    The projection matrix will probably be the identity matrix (since you haven't run gluPerspective at all yet), which is reasonable for the coordinates you're using. But it is still good practice to set it explicitly to what you want for the sake of clarity and robustness (possibly with a pushMatrix/popMatrix around).

    But I don't see where your code configures the viewport at all? Perhaps JOGL does that for you? If so, it will be the size of your window, not the size of the texture. This too-large viewport will cause portions of your scene to be cut off at the high-coordinate end, which is consistent with the texture you are seeing (note that the second blue point should be very close to the first one but shows up far away). So, you need to add to renderShadowsToTexture:

    glViewport(0, 0, floorWidth, floorHeight)
    

    and probably restore it afterward (or use glPushAttrib/glPopAttrib of GL_VIEWPORT_BIT).

    Also, color components are red-green-blue, so your missing point will be green, not red.