com.timvisee.voxeltex.module.texture.Texture.java Source code

Java tutorial

Introduction

Here is the source code for com.timvisee.voxeltex.module.texture.Texture.java

Source

/******************************************************************************
 * Copyright (c) Tim Visee 2016. All rights reserved.                         *
 *                                                                            *
 * @author Tim Visee                                                          *
 * @website http://timvisee.com/                                              *
 *                                                                            *
 * Open Source != No Copyright                                                *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included    *
 * in all copies or substantial portions of the Software.                     *
 *                                                                            *
 * You should have received a copy of The MIT License (MIT) along with this   *
 * program. If not, see <http://opensource.org/licenses/MIT/>.                *
 ******************************************************************************/

package com.timvisee.voxeltex.module.texture;

import com.timvisee.voxeltex.module.Color;
import com.timvisee.voxeltex.util.BufferUtil;
import org.lwjgl.opengl.GL13;

import java.nio.ByteBuffer;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.GL_BGR;
import static org.lwjgl.opengl.GL13.glActiveTexture;

public class Texture {

    /**
     * Number of components for RGB textures.
     */
    public static final int COMPONENTS_RGB = Image.COMPONENTS_RGB;

    /**
     * Number of components for RGBA textures.
     */
    public static final int COMPONENTS_RGBA = Image.COMPONENTS_RGBA;

    /**
     * Unique texture ID, for OpenGL.
     */
    private int id;

    /**
     * Texture width.
     */
    private float width;

    /**
     * Texture height.
     */
    private float height;

    /**
     * Filter option for this image.
     *
     * Possible options:
     * - GL_LINEAR
     * - GL_NEAREST
     */
    private static int filter = GL_LINEAR;

    /**
     * Wrap option for this image.
     *
     * Possible options:
     * - GL_REPEAT
     * - GL_CLAMP
     */
    private static int wrap = GL_REPEAT;

    /**
     * Constructor.
     */
    private Texture() {
        // Assign a texture ID from OpenGL
        this.id = glGenTextures();

        // Add the texture to the texture manager
        TextureTracker.trackTexture(this);
    }

    /**
     * Generate a solid colored texture based on the given color. It is possible to use the alpha channels of the color.
     *
     * @param color Solid color.
     * @param width Texture width.
     * @param height Texture height.
     *
     * @return The generated texture.
     */
    public static Texture fromColor(Color color, int width, int height) {
        // Create a buffer to put the color components in
        ByteBuffer buffer = BufferUtil.createByteBuffer(width * height * 4);

        // Fill the buffer with the image data
        for (int x = 0; x < width; x++)
            for (int y = 0; y < height; y++)
                buffer.put((byte) (color.getRed() * 255.0f)).put((byte) (color.getGreen() * 255.0f))
                        .put((byte) (color.getBlue() * 255.0f)).put((byte) (color.getAlpha() * 255.0f));

        // Flip the buffer so we can read
        buffer.flip();

        // Create a texture from the byte buffer, return the result
        return fromByteBuffer(buffer, width, height, Image.COMPONENTS_RGBA);
    }

    /**
     * Create a texture based on the given image.
     *
     * @param image Image to use for the texture.
     *
     * @return Texture.
     */
    public static Texture fromImage(Image image) {
        // Create and return the texture
        return fromByteBuffer(image.getImage(), image.getWidth(), image.getHeight(), image.getComponents());
    }

    /**
     * Create a texture based on the given image and consume/dispose the image.
     *
     * @param image Image to use for the texture.
     *
     * @return Texture.
     */
    public static Texture consumeImage(Image image) {
        // Create the texture
        Texture texture = fromImage(image);

        // Dispose/consume the image since we're done
        image.dispose();

        // Return the texture that was created
        return texture;
    }

    /**
     * Create a texture from a byte buffer.
     *
     * @param buffer The byte buffer containing the texture data.
     * @param width Texture width.
     * @param height Texture height.
     * @param components Number of components in the texture buffer. Choose from COMPONENTS_RGBA or COMPONENTS_RGB.
     *
     * @return Texture.
     */
    public static Texture fromByteBuffer(ByteBuffer buffer, int width, int height, int components) {
        // Create a new texture instance
        Texture texture = new Texture();

        // Bind the texture
        texture.bind(GL13.GL_TEXTURE0);

        // Set the texture parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);

        // Configure the texture and write the buffer to the texture
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, components == 4 ? GL_RGBA : GL_RGB,
                GL_UNSIGNED_BYTE, buffer);

        // Done using the texture, unbind
        Texture.unbind();

        // Set the width and height
        texture.width = width;
        texture.height = height;

        // Return the created texture
        return texture;
    }

    /**
     * Get the OpenGL texture ID.
     *
     * @return Texture ID.
     */
    public int getId() {
        return this.id;
    }

    /**
     * Get the texture width.
     *
     * @return Texture width.
     */
    public float getWidth() {
        return this.width;
    }

    /**
     * Get the texture height.
     *
     * @return Texture height.
     */
    public float getHeight() {
        return this.height;
    }

    /**
     * Get the texture filter mode.
     *
     * Possible options:
     * - GL_LINEAR
     * - GL_NEAREST
     *
     * @return Texture filter.
     */
    public static int getFilter() {
        return Texture.filter;
    }

    /**
     * Get the texture wrap mode.
     *
     * Possible options:
     * - GL_REPEAT
     * - GL_CLAMP
     *
     * @return Texture wrap.
     */
    public static int getWrap() {
        return Texture.wrap;
    }

    /**
     * Set the texture filter mode.
     *
     * Possible options:
     * - GL_LINEAR
     * - GL_NEAREST
     *
     * @param filter Texture filter.
     */
    public static void setFilter(int filter) {
        Texture.filter = filter;
    }

    /**
     * Set the texture wrap mode.
     *
     * Possible options:
     * - GL_REPEAT
     * - GL_CLAMP
     *
     * @param wrap Texture wrap.
     */
    public static void setWrap(int wrap) {
        Texture.wrap = wrap;
    }

    /**
     * Bind the current texture to OpenGL.
     *
     * @param glTextureId The OpenGL texture ID.
     */
    public void bind(int glTextureId) {
        // Activate the first texture
        glActiveTexture(glTextureId);

        // Bind the texture
        glBindTexture(GL_TEXTURE_2D, this.id);
    }

    /**
     * Unbind any textures from OpenGL.
     */
    public static void unbind() {
        glBindTexture(GL_TEXTURE_2D, 0);
    }

    /**
     * Get the current texture from OpenGL.
     *
     * @param format Texture format.
     *
     * @return Byte buffer with texture.
     */
    public ByteBuffer getImage2D(int format) {
        return getImage2D(format, GL_FLOAT);
    }

    /**
     * Get the current texture from OpenGL.
     *
     * @param format Texture format.
     * @param type Texture type.
     *
     * @return Byte buffer with texture.
     */
    public ByteBuffer getImage2D(int format, int type) {
        // Determine the number of components, use RGBA as default
        int size = Image.COMPONENTS_RGBA;

        // Switch to RGB for some formats
        switch (format) {
        case GL_RGB:
        case GL_BGR:
            size = 3;
            break;
        }

        // Calculate the byte buffer size
        size = (int) (size * width * height * 4);

        // Create a byte buffer with the given size
        ByteBuffer buffer = BufferUtil.createByteBuffer(size);

        // Get and return the texture
        return getImage2D(format, type, buffer);
    }

    /**
     * Get the current texture from OpenGL.
     *
     * @param format Texture format.
     * @param type Texture type.
     * @param buffer Byte buffer for texture.
     *
     * @return Byte buffer with texture.
     */
    private ByteBuffer getImage2D(int format, int type, ByteBuffer buffer) {
        // Get the texture from OpenGL
        glGetTexImage(GL_TEXTURE_2D, 0, format, type, buffer);

        // Return the buffer with the texture
        return buffer;
    }

    /**
     * Dispose the texture.
     * This will free the memory used by this texture.
     */
    public void dispose() {
        // Remove the texture from OpenGL
        if (glIsTexture(id))
            glDeleteTextures(id);

        // Remove the image from the texture manager
        TextureTracker.untrackTexture(this);
    }
}