Java tutorial
/* * Copyright 2015-2016 Telinc1 * * 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 com.telinc1.rpjg.texture; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.ByteBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.newdawn.slick.opengl.PNGDecoder; import org.pmw.tinylog.Logger; import com.telinc1.rpjg.util.DrawingUtils; /** * Defines an OpenGL 1.1 compatible texture. * * @author Telinc1, davedes */ public class Texture { public static int DEFAULT_FILTER = GL11.GL_NEAREST; public static int DEFAULT_WRAP = GL11.GL_REPEAT; protected int id; protected int width; protected int height; /** * @see com.telinc1.rpjg.texture.Texture#Texture(int, int, int, int, int) */ protected Texture(int width, int height) { this(width, height, Texture.DEFAULT_FILTER); } /** * @see com.telinc1.rpjg.texture.Texture#Texture(int, int, int, int, int) */ protected Texture(int width, int height, int filter) { this(width, height, filter, Texture.DEFAULT_WRAP); } /** * @see com.telinc1.rpjg.texture.Texture#Texture(int, int, int, int, int) */ protected Texture(int width, int height, int filter, int wrap) { this(width, height, filter, filter, wrap); } /** * Creates a blank (transparent black) texture with the given width and height. * * @param width The width of the texture to generate * @param height The height of the texture to generate * @param minFilter The minification filter to use * @param magFilter The magnification filter to use * @param wrap The wrap mode for the texture. */ protected Texture(int width, int height, int minFilter, int magFilter, int wrap) { GL11.glEnable(this.getTarget()); this.setID(GL11.glGenTextures()); this.setWidth(width); this.setHeight(height); this.bind(); this.setFilter(minFilter, magFilter); this.setWrap(wrap); ByteBuffer buffer = BufferUtils.createByteBuffer(this.getWidth() * this.getHeight() * 4); this.upload(GL11.GL_RGBA, buffer); } /** * @see com.telinc1.rpjg.texture.Texture.Texture(java.net.URL, int, int, int) */ protected Texture(URL image) { this(image, Texture.DEFAULT_FILTER); } /** * @see com.telinc1.rpjg.texture.Texture.Texture(java.net.URL, int, int, int) */ protected Texture(URL image, int filter) { this(image, filter, Texture.DEFAULT_WRAP); } /** * @see com.telinc1.rpjg.texture.Texture.Texture(java.net.URL, int, int, int) */ protected Texture(URL image, int filter, int wrap) { this(image, filter, filter, wrap); } /** * Creates a texture out of the given URL. * * @param image - The location of the image to use. * @param minFilter - The minification filter to use. * @param magFilter - The magnification filter to use. * @param wrap - The wrap mode to use. */ protected Texture(URL image, int minFilter, int magFilter, int wrap) { InputStream input = null; try { input = image.openStream(); PNGDecoder decoder = new PNGDecoder(input); this.setWidth(decoder.getWidth()); this.setHeight(decoder.getHeight()); ByteBuffer buffer = BufferUtils.createByteBuffer(this.getWidth() * this.getHeight() * 4); decoder.decode(buffer, this.getWidth() * 4, PNGDecoder.RGBA); buffer.flip(); GL11.glEnable(this.getTarget()); this.setID(GL11.glGenTextures()); this.bind(); this.setFilter(minFilter, magFilter); this.setWrap(wrap); this.upload(GL11.GL_RGBA, buffer); } catch (IOException e) { e.printStackTrace(); } finally { if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } } public void bind() { if (!this.exists()) { throw new TextureException("Tried to load a nonexistent (destroyed) texture."); } DrawingUtils.bindTexture(this); } public void dispose() { if (this.exists()) { Logger.info("Destroying texture {}.", this.getID()); GL11.glDeleteTextures(this.getID()); this.setID(0); } } public boolean exists() { return this.getID() != 0; } public int getHeight() { return this.height; } public int getID() { return this.id; } public int getTarget() { return GL11.GL_TEXTURE_2D; } public int getWidth() { return this.width; } public void setFilter(int filter) { this.setFilter(filter, filter); } public void setFilter(int minFilter, int magFilter) { this.bind(); GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_MIN_FILTER, minFilter); GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_MAG_FILTER, magFilter); } void setHeight(int height) { this.height = height; } void setID(int id) { this.id = id; } protected void setUnpackAlignment() { GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1); } void setWidth(int width) { this.width = width; } public void setWrap(int wrap) { this.setWrap(wrap, wrap); } public void setWrap(int sWrap, int tWrap) { this.bind(); GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_WRAP_S, tWrap); GL11.glTexParameteri(this.getTarget(), GL11.GL_TEXTURE_WRAP_T, tWrap); } /** * Uploads the given image data to the texture. * * @param format - The byte order to use. * @param data - The image data to upload. */ public void upload(int format, ByteBuffer data) { this.bind(); this.setUnpackAlignment(); GL11.glTexImage2D(this.getTarget(), 0, GL11.GL_RGBA, this.getWidth(), this.getHeight(), 0, format, GL11.GL_UNSIGNED_BYTE, data); } /** * Positions an image on top of the texture. * * @param x - The X position at which to place the subimage. * @param y - The Y position at which to place the subimage. * @param width - The width of the subimage. * @param height - The height of the subimage. * @param format - The byte order of the subimage. * @param data - The data to upload. */ public void upload(int x, int y, int width, int height, int format, ByteBuffer data) { this.bind(); this.setUnpackAlignment(); GL11.glTexSubImage2D(this.getTarget(), 0, x, y, width, height, format, GL11.GL_UNSIGNED_BYTE, data); } }