se.angergard.engine.graphics.FrameBuffer.java Source code

Java tutorial

Introduction

Here is the source code for se.angergard.engine.graphics.FrameBuffer.java

Source

/********************************************************************************
 *
 *   Copyright 2014 Theodor Angergard
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 *******************************************************************************/

package se.angergard.engine.graphics;

import java.nio.*;

import org.lwjgl.opengl.*;

import se.angergard.engine.display.*;
import se.angergard.engine.interfaces.*;

public class FrameBuffer implements Disposable {

    public FrameBuffer(int width, int height, boolean hasDepth, boolean hasStencil) {
        this.width = width;
        this.height = height;

        if ((width + height) % 4 != 0.0) {
            new Exception("Width + Height must be divisible by 4");
        }

        frameBufferID = GL30.glGenFramebuffers();
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);

        if (hasDepth && hasStencil) {
            depthAndStencilBufferID = GL30.glGenRenderbuffers();
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthAndStencilBufferID);
            GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, width, height);
            GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT,
                    GL30.GL_RENDERBUFFER, depthAndStencilBufferID);
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, 0);
        }

        else if (hasDepth) {
            depthBufferID = GL30.glGenRenderbuffers();
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBufferID);
            GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH_COMPONENT32F, width, height);
            GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
                    depthBufferID);
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, 0);
        }

        else if (hasStencil) {
            stencilBufferID = GL30.glGenRenderbuffers();
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, stencilBufferID);
            GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_STENCIL_INDEX16, width, height);
            GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER,
                    stencilBufferID);
            GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, 0);
        }

        colorTexture = GL11.glGenTextures();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, colorTexture);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);

        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA,
                GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);

        GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D,
                colorTexture, 0);

        int result = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
        if (result != GL30.GL_FRAMEBUFFER_COMPLETE) {
            if (result == GL30.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
                new Exception("Frame Buffer Error: incomplete attachment").printStackTrace();
            }
            if (result == GL30.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER) {
                new Exception("Frame Buffer Error: incomplete draw buffer").printStackTrace();
            }
            if (result == GL30.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
                new Exception("Frame Buffer Error: missing attachment").printStackTrace();
            }
            if (result == GL30.GL_FRAMEBUFFER_UNSUPPORTED) {
                new Exception("Frame Buffer Error: unsupported combination of formats").printStackTrace();
            }
            if (result == GL30.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) {
                new Exception("Frame Buffer Error: incomplete multisample").printStackTrace();
            }
            if (result == GL30.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER) {
                new Exception("Frame Buffer Error: incomplete read buffer").printStackTrace();
            }

            new Exception("frame buffer couldn't be constructed: unknown error " + result).printStackTrace();
        }
        RenderUtil.unbindFrameBuffer();
        RenderUtil.unbindTexture();

        frameBufferShader = new ShaderProgram().createDefault2DShader();
    }

    private ShaderProgram frameBufferShader;

    private int colorTexture;

    private int width, height;
    private int frameBufferID, depthBufferID, stencilBufferID, depthAndStencilBufferID;

    public void setShaderProgram(ShaderProgram shaderProgram) {
        this.frameBufferShader = shaderProgram;
    }

    public ShaderProgram getShaderProgram() {
        return frameBufferShader;
    }

    public void begin() {
        GL11.glViewport(0, 0, width, height);
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
        RenderUtil.clearScreen();
    }

    public void end() {
        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
        GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
    }

    public int getColorTexture() {
        return colorTexture;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    @Override
    public void dispose() {
        GL11.glDeleteTextures(colorTexture);

        if (depthBufferID == 0 && stencilBufferID == 0) {
            GL30.glDeleteRenderbuffers(depthAndStencilBufferID);
        } else if (depthBufferID != 0) {
            GL30.glDeleteRenderbuffers(depthBufferID);
        } else if (stencilBufferID != 0) {
            GL30.glDeleteRenderbuffers(stencilBufferID);
        }

        GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
        GL30.glDeleteFramebuffers(frameBufferID);

    }

}