Search code examples
javaopengllwjgl

Close objects are only partially rendered - LWJGL


I'm working on a LWJGL project and I'm experiencing a weird problem: close objects stop being fully rendered as I move slightly away. I'm not very expert in OpenGL so I can't figure out what is causing this.

Here two photos of what I'm talking about: Pic1, Pic2

And here's a photo to prove that the objects are fully loaded: http://prntscr.com/r7joyc

Code used to load a texture

Code used to initialize the window

I think the error is somewhere here

@Override
    public Texture loadTexture(String filename) {
        try (MemoryStack stack = MemoryStack.stackPush()) {
            //Height, width and colour channels are 1 byte each
            IntBuffer w = stack.mallocInt(1);
            IntBuffer h = stack.mallocInt(1);
            IntBuffer channels = stack.mallocInt(1);

            //Load image into the ByteBuffer
            this.byteBuffer = stbi_load(filename, w, h, channels, 4);
            if (this.byteBuffer == null) {
                throw new FileNotFoundException("Texture file [" + filename + "] not loaded. Reason: " + stbi_failure_reason());
            }

            //Get width and height of image
            this.width = w.get();
            this.height = h.get();

            int textureID = this.generateTexture();
            this.generateMipMap();
            this.clean();
            return new Texture(textureID, this.width, this.height);
        } catch (Exception e) {
            logger.error(e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    //For scaled textures
    private void generateMipMap() {
        glGenerateMipmap(GL_TEXTURE_2D);
    }

    private int generateTexture() {
        int textureId = glGenTextures();
        // Bind the texture
        glBindTexture(GL_TEXTURE_2D, textureId);
        //Tell OpenGL how to unpack RGBA. 1 byte for pixel
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
         /*Args:
              1. Type of texture;
              2. Number of colour components in the texture;
              3. Colour components in texture;
              4. Texture width;
              5. Texture height;
              6. Texture border size;
              7. Format of the pixel data (RGBA);
              8. Each pixel is represented by an unsigned int;
              9. Data to load is stored in a ByteBuffer
         */
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this.width, this.height,
                0, GL_RGBA, GL_UNSIGNED_BYTE, this.byteBuffer);
        return textureId;
    }

    private void clean() {
        //Free ByteBuffer
        stbi_image_free(this.byteBuffer);
    } 

Or here

public void init() {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // the window will be resizable
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

        boolean maximized = false;
        // If no size has been specified set it to maximized state
        if (width == 0 || height == 0) {
            // Set up a fixed width and height so window initialization does not fail
            width = 100;
            height = 100;
            glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
            maximized = true;
        }

        windowHandle = glfwCreateWindow(width, height, title, NULL, NULL);
        // Create the window
        if (windowHandle == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }
        logger.trace("Window handle: " + windowHandle);
        // Setup resize callback
        glfwSetFramebufferSizeCallback(windowHandle, (window, width, height) -> {
            this.width = width;
            this.height = height;
            this.setResized(true);
        });

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(windowHandle, (window, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
            }
        });

        if (maximized) {
            glfwMaximizeWindow(windowHandle);
        } else {
            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
            // Center our window
            glfwSetWindowPos(
                    windowHandle,
                    (vidmode.width() - width) / 2,
                    (vidmode.height() - height) / 2
            );
        }


        // Make the OpenGL context current
        glfwMakeContextCurrent(windowHandle);

        if (isvSync()) {
            // Enable v-sync
            glfwSwapInterval(1);
        }

        // Make the window visible
        glfwShowWindow(windowHandle);

        GL.createCapabilities();

        // Set the clear color
        setClearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);

        glEnable(GL_DEPTH_TEST);

        // Support for transparencies
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);

        if(debug){
            glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
        }
    }

Solution

  • This solved my problem

    First render your skybox, then clear the depth bit after rendering the skybox, and finally render everything else. That way the depth of the skybox won't affect the scene.