LWJGL FBO - 深度测试不起作用(更简单的代码)

时间:2014-01-18 17:43:22

标签: java opengl lwjgl fbo depth-testing

当我渲染到FBO时,深度测试似乎失败了,但是当我不这样做时,它的工作效果非常好。奇怪的是,在更复杂的版本(我没有测试过这个版本)上,当我在学校的计算机上测试它时(当然我不应该工作!:-)),即使没有FBO,它仍然会失败。 / p>

很遗憾,我在此网站上没有足够的声誉来发布图片,因此我会将其发布为链接here。 (这是更复杂的一个,但效果仍然相同(无论如何,彩色立方体的渲染方式与此版本相同)。)

最后,这是代码:

Main.java:

package Main;


import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;

import java.nio.ByteBuffer;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class Main {
    //This just allows me to move around the scene - it's surely not the cause of the bug... 
    CamController camera;
    int /*ID of FBO*/fboID, /*Texture FBO will render to*/renderTexture;

    public Main() {
        //Init display
        try {
            Display.setDisplayMode(new DisplayMode(1280, 720));
            Display.setTitle("Example of a fail");
            //Display.setVSyncEnabled(true);
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_TEXTURE_2D);
        setTo3d();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        Mouse.setGrabbed(true);
        //Tested it with, and without this...
        glClearDepth(1);
        glEnable(GL_DEPTH_TEST);
        glShadeModel (GL_SMOOTH);                                   // Select Smooth Shading
        glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
        init();
        initFBO();
        loop();
    }
    /**Initiates any objects I use.*/
    public void init(){
        camera = new CamController();
    }
    public void initFBO(){
        renderTexture = createTexture(1280, 720, false);
        fboID = glGenFramebuffers();
        glBindFramebuffer(GL_FRAMEBUFFER, fboID);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, /*Mipmap Level*/0);
        int i = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if(i != GL_FRAMEBUFFER_COMPLETE){
            System.err.println("Framebuffer is not working! Fault: "+org.lwjgl.util.glu.GLU.gluErrorString(i));
        }
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }
    /*Main running loop*/
    public void loop(){
        while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
            //Checks the keyboard, and mouse to move camera
            camera.update();
            setTo3d();  
            //Rotates and translates the image to camera's perspective.
            camera.camera.lookThrough();
            glBindTexture(GL_TEXTURE_2D, 0);
            glBindFramebuffer(GL_FRAMEBUFFER, fboID);

            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
            draw();

            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            setTo2d();
            drawFBO();
            Display.update();
            glFlush();
            Display.sync(60);
        }
        Display.destroy();
        System.exit(0);
    }
    /*Draws objects to FBO - I can use VBOs, but was just saving time.*/
    public void draw(){
        glBegin(GL_QUADS);            
        glColor3f(0.0f, 1.0f, 0.0f);     
        glVertex3f(1.0f, 1.0f, -1.0f);  
        glVertex3f(-1.0f, 1.0f, -1.0f);  
        glVertex3f(-1.0f, 1.0f, 1.0f);   
        glVertex3f(1.0f, 1.0f, 1.0f);   

        glColor3f(1.0f, 0.5f, 0.0f);    
        glVertex3f(1.0f, -1.0f, 1.0f);   
        glVertex3f(-1.0f, -1.0f, 1.0f); 
        glVertex3f(-1.0f, -1.0f, -1.0f); 
        glVertex3f(1.0f, -1.0f, -1.0f); 

        glColor3f(1.0f, 0.0f, 0.0f);     
        glVertex3f(1.0f, 1.0f, 1.0f);   
        glVertex3f(-1.0f, 1.0f, 1.0f);  
        glVertex3f(-1.0f, -1.0f, 1.0f); 
        glVertex3f(1.0f, -1.0f, 1.0f);   

        glColor3f(1.0f, 1.0f, 0.0f);     
        glVertex3f(1.0f, -1.0f, -1.0f); 
        glVertex3f(-1.0f, -1.0f, -1.0f); 
        glVertex3f(-1.0f, 1.0f, -1.0f); 
        glVertex3f(1.0f, 1.0f, -1.0f);   

        glColor3f(0.0f, 0.0f, 1.0f);     
        glVertex3f(-1.0f, 1.0f, 1.0f);  
        glVertex3f(-1.0f, 1.0f, -1.0f);  
        glVertex3f(-1.0f, -1.0f, -1.0f); 
        glVertex3f(-1.0f, -1.0f, 1.0f);  

        glColor3f(1.0f, 0.0f, 1.0f);     
        glVertex3f(1.0f, 1.0f, -1.0f);  
        glVertex3f(1.0f, 1.0f, 1.0f);    
        glVertex3f(1.0f, -1.0f, 1.0f);   
        glVertex3f(1.0f, -1.0f, -1.0f); 
        glEnd();                        
        glColor3f(1,1,1);
    }

    //Draws the FBO rect - Again, can use VBOs, just saving time...
    public void drawFBO(){
        glBindTexture(GL_TEXTURE_2D, renderTexture);
        glLoadIdentity();
        glBegin(GL_QUADS);
            glTexCoord2f(0,0);
            glVertex2f(0,0);
            glTexCoord2f(1,0);
            glVertex2f(1280,0);
            glTexCoord2f(1,1);
            glVertex2f(1280,720);
            glTexCoord2f(0,1);
            glVertex2f(0,720);
        glEnd();
    }

    public static void main(String[] args) {    
        new Main();
    }
    /*I know there are better ways of doing this, but I'm doing it this way for the sake of time...*/
    public void setTo2d(){
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, 1280, 0, 720, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
    public void setTo3d(){
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        //The problem is not caused by too small a zNear value - I've already tested that...
        gluPerspective(/*FOV in degrees*/30f, /*Aspect ratio*/ 1280f/720f, /*zNear*/ 0.001f, /*zFar*/50000);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

    //This code taken from TheCPlusPlusGuy, so should work
    public int createTexture(int w, int h, boolean isDepth){
        int handle;
        handle = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, handle);
        if(isDepth){
            GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer) null);
        }else{
            GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_FLOAT, (ByteBuffer) null);
        }
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glBindTexture(GL_TEXTURE_2D, 0);
        return handle;
    }
}

请注意,我留下了几个包装器--Camera和CamController - 它们只允许你使用glTranslate()和glRotate()

移动

1 个答案:

答案 0 :(得分:2)

你正在装箱没有深度缓冲器的FBO - 因此深度测试当然不起作用。您应该创建一个具有深度可渲染格式的Renderbuffer,并将其附加为GL_DEPTH_ATTACHMENT,如下所示:

GLuint depthbuffer;
glGenRenderbuffers(1, &depthbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, wisth, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
当然,

widthheight可以匹配颜色缓冲区的大小。