com.w67clement.openw67render.utils.Texture.java Source code

Java tutorial

Introduction

Here is the source code for com.w67clement.openw67render.utils.Texture.java

Source

/*
 * Copyright  2016 Clment "w67clement" Wagner
 *
 * This file is part of OpenW67Render.
 *
 * OpenW67Render is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * OpenW67Render is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with OpenW67Render.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.w67clement.openw67render.utils;

import com.w67clement.openw67render.registry.TextureRegistry;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL13;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.stb.STBImage.*;

/**
 * <h1>Texture</h1>
 * <p>
 * Representation of a texture.
 * </p>
 */
public class Texture {

    /**
     * Width of the texture.
     */
    protected final int width;

    /**
     * Height of the texture.
     */
    protected final int height;

    protected final ByteBuffer data;
    private final TextureWrapMode textureWrapMode;
    private final TextureFilterMode textureFilterMode;

    /**
     * Stores the handle of the texture.
     */
    protected int id;

    /**
     * Creates a texture with specified width, height, data and modes.
     *
     * @param width  Width of the texture
     * @param height Height of the texture
     * @param data   Picture Data in RGBA format
     */
    public Texture(int width, int height, ByteBuffer data, TextureWrapMode textureWrapMode,
            TextureFilterMode textureFilterMode) {
        this.width = width;
        this.height = height;
        this.data = data;
        this.textureWrapMode = textureWrapMode;
        this.textureFilterMode = textureFilterMode;
        init();
    }

    /**
     * Loads texture from AWT image.
     *
     * @param image AWT image to load.
     *
     * @return Texture from specified AWT image.
     */
    public static Texture loadTexture(ByteBuffer image, int width, int height) {
        return loadTexture(image, width, height, TextureWrapMode.CLAMP_TO_EDGE, TextureFilterMode.NEAREST);
    }

    /**
     * Loads texture from AWT image.
     *
     * @param image             AWT image to load.
     * @param textureWrapMode   Wrap mode of the texture.
     * @param textureFilterMode Filter mode of texture.
     *
     * @return Texture from specified AWT image.
     */
    public static Texture loadTexture(ByteBuffer image, int width, int height, TextureWrapMode textureWrapMode,
            TextureFilterMode textureFilterMode) {
        Texture texture = new Texture(width, height, image, textureWrapMode, textureFilterMode);
        TextureRegistry.getInstance().add(texture);
        return texture;
    }

    /**
     * Loads texture from file.
     *
     * @param path File path of the texture.
     *
     * @return Texture from specified file
     */
    public static Texture loadTexture(String path) {
        return loadTexture(path, TextureWrapMode.CLAMP_TO_EDGE, TextureFilterMode.NEAREST);
    }

    /**
     * Loads texture from file.
     *
     * @param path            File path of the texture.
     * @param textureWrapMode Wrap mode of the texture.
     *
     * @return Texture from specified file
     */
    public static Texture loadTexture(String path, TextureWrapMode textureWrapMode) {
        return loadTexture(path, textureWrapMode, TextureFilterMode.NEAREST);
    }

    /**
     * Loads texture from file.
     *
     * @param path              File path of the texture.
     * @param textureWrapMode   Wrap mode of the texture.
     * @param textureFilterMode Filter mode of texture.
     *
     * @return Texture from specified file
     */
    public static Texture loadTexture(String path, TextureWrapMode textureWrapMode,
            TextureFilterMode textureFilterMode) {
        /* Prepare image buffers */
        IntBuffer w = BufferUtils.createIntBuffer(1);
        IntBuffer h = BufferUtils.createIntBuffer(1);
        IntBuffer comp = BufferUtils.createIntBuffer(1);

        /* Load image */
        stbi_set_flip_vertically_on_load(1);
        ByteBuffer image = stbi_load(path, w, h, comp, 4);
        if (image == null) {
            throw new RuntimeException(
                    "Failed to load a texture file!" + System.lineSeparator() + stbi_failure_reason());
        }

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

        // Original:
        //return new Texture(width, height, image);

        // Modified:
        Texture texture = new Texture(width, height, image, textureWrapMode, textureFilterMode);
        TextureRegistry.getInstance().add(texture);
        return texture;
    }

    /**
     * Loads texture from AWT image.
     *
     * @param image AWT image to load.
     *
     * @return Texture from specified AWT image.
     */
    public static Texture loadTexture(BufferedImage image) {
        return loadTexture(image, TextureWrapMode.CLAMP_TO_EDGE, TextureFilterMode.NEAREST);
    }

    /**
     * Loads texture from AWT image.
     *
     * @param image             AWT image to load.
     * @param textureWrapMode   Wrap mode of the texture.
     * @param textureFilterMode Filter mode of texture.
     *
     * @return Texture from specified AWT image.
     */
    public static Texture loadTexture(BufferedImage image, TextureWrapMode textureWrapMode,
            TextureFilterMode textureFilterMode) {
        int[] pixels = new int[image.getWidth() * image.getHeight()];
        image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

        ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4); //4 for RGBA, 3 for RGB

        for (int y = image.getHeight() - 1; y > 0; y--) {
            for (int x = 0; x < image.getWidth(); x++) {
                int pixel = pixels[y * image.getWidth() + x];
                buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
                buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
                buffer.put((byte) (pixel & 0xFF)); // Blue component
                buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
            }
        }

        buffer.flip();

        return loadTexture(buffer, image.getWidth(), image.getHeight(), textureWrapMode, textureFilterMode);
    }

    protected void init() {
        id = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, id);

        if (textureWrapMode != null) {
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapMode.getPointer());
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapMode.getPointer());
        }
        if (textureFilterMode != null) {
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, textureFilterMode.getPointer());
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, textureFilterMode.getPointer());
        }

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    }

    /**
     * Binds the texture.
     */
    public void bind() {
        GL13.glActiveTexture(id);
        glBindTexture(GL_TEXTURE_2D, id);
    }

    public void unbind() {
        glBindTexture(GL_TEXTURE_2D, 0);
    }

    /**
     * Deletes the texture.
     */
    public void delete() {
        glDeleteTextures(id);
    }

    /**
     * Gets the texture width.
     *
     * @return Texture width
     */
    public int getWidth() {
        return width;
    }

    /**
     * Gets the texture height.
     *
     * @return Texture height
     */
    public int getHeight() {
        return height;
    }

    /**
     * Gets the texture id.
     *
     * @return Texture id.
     */
    public final int getId() {
        return id;
    }

    /**
     * Gets the texture wrap mode.
     *
     * @return Texture wrap mode.
     */
    public TextureWrapMode getTextureWrapMode() {
        return textureWrapMode;
    }

    /**
     * Gets the texture filter mode.
     *
     * @return Texture filter mode.
     */
    public TextureFilterMode getTextureFilterMode() {
        return textureFilterMode;
    }

    /**
     * Reloads the texture.
     */
    public void reload() {
        delete();
        init();
    }

    @Override
    public String toString() {
        return "Texture{" + "width=" + width + ", height=" + height + ", textureWrapMode=" + textureWrapMode
                + ", textureFilterMode=" + textureFilterMode + ", id=" + id + '}';
    }

    public enum TextureWrapMode {
        CLAMP(0x2900), CLAMP_TO_EDGE(0x812D), REPEAT(GL_REPEAT);

        private int pointer;

        TextureWrapMode(int pointer) {
            this.pointer = pointer;
        }

        /**
         * Gets the pointer of the Texture Wrap Mode.
         *
         * @return Texture wrap mode's pointer.
         */
        public int getPointer() {
            return pointer;
        }
    }

    public enum TextureFilterMode {
        LINEAR(GL_LINEAR), NEAREST(GL_NEAREST);

        private int pointer;

        TextureFilterMode(int pointer) {
            this.pointer = pointer;
        }

        /**
         * Gets the pointer of the Texture Wrap Mode.
         *
         * @return Texture wrap mode's pointer.
         */
        public int getPointer() {
            return pointer;
        }
    }
}