package org.saintandreas.gl.textures; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.glBindTexture; import static org.lwjgl.opengl.GL11.glGenTextures; import static org.lwjgl.opengl.GL11.glTexImage2D; import static org.lwjgl.opengl.GL11.glTexParameterf; import static org.lwjgl.opengl.GL11.glTexParameteri; import java.awt.Color; import java.awt.Graphics; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.io.IOException; import java.net.URL; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Hashtable; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.saintandreas.resources.Images; import org.saintandreas.resources.Resource; public class Texture { public final int id; private final int target; public Texture(int target) { id = glGenTextures(); this.target = target; } public Texture() { this(GL_TEXTURE_2D); } public void bind() { glBindTexture(target, id); } public void unbind() { unbind(target); } public static void unbind(int target) { glBindTexture(target, 0); } public void parameter(int pname, int value) { glTexParameteri(target, pname, value); } public void parameter(int pname, float value) { glTexParameterf(target, pname, value); } public void image2d(int internalformat, int width, int height, int format, int type, ByteBuffer pixels) { glTexImage2D(target, 0, internalformat, width, height, 0, format, type, pixels); } public void loadImageData(BufferedImage image, int loadTarget) { // Flip the image vertically AffineTransform tx = AffineTransform.getScaleInstance(1, -1); tx.translate(0, -image.getHeight(null)); AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); image = op.filter(image, null); GL11.glTexImage2D(loadTarget, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, convertImageData(image)); } public static Texture loadImage(BufferedImage image, int textureType, int loadTarget) { Texture result = new Texture(textureType); result.bind(); result.loadImageData(image, loadTarget); result.unbind(); return result; } public static Texture loadImage(Resource r, int textureType, int loadTarget) { return loadImage(Images.load(r), textureType, loadTarget); } public static Texture loadImage(URL url, int textureType, int loadTarget) { return loadImage(Images.load(url), textureType, loadTarget); } public static Texture loadImage(BufferedImage image, int textureType) { return loadImage(image, textureType, textureType); } public static Texture loadImage(Resource r, int textureType) throws IOException { return loadImage(r, textureType, textureType); } public static Texture loadImage(URL url, int textureType) throws IOException { return loadImage(url, textureType, textureType); } public static Texture loadImage(BufferedImage image) { return loadImage(image, GL_TEXTURE_2D); } public static Texture loadImage(Resource r) throws IOException { return loadImage(r, GL_TEXTURE_2D); } public static Texture loadImage(URL url) throws IOException { return loadImage(url, GL_TEXTURE_2D); } /** * Convert the buffered image to a texture */ public static ByteBuffer convertImageData(BufferedImage bufferedImage) { ByteBuffer imageBuffer; WritableRaster raster; BufferedImage texImage; ColorModel glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 8 }, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, bufferedImage.getWidth(), bufferedImage.getHeight(), 4, null); texImage = new BufferedImage(glAlphaColorModel, raster, true, new Hashtable<>()); // copy the source image into the produced image Graphics g = texImage.getGraphics(); g.setColor(new Color(0f, 0f, 0f, 0f)); g.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); g.drawImage(bufferedImage, 0, 0, null); // build a byte buffer from the temporary image // that be used by OpenGL to produce a texture. byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData(); BufferUtils.createByteBuffer(data.length); imageBuffer = ByteBuffer.allocateDirect(data.length); imageBuffer.order(ByteOrder.nativeOrder()); imageBuffer.put(data, 0, data.length); imageBuffer.flip(); return imageBuffer; } }