I made the following class to simpify texture loading in LWJGL 3, and modeled it after the slick-util API:
public class Texture {
private ByteBuffer data;
private int id;
private int width;
private int height;
private ByteBuffer resizeBuffer(ByteBuffer buffer, int size) {
ByteBuffer newBuffer = BufferUtils.createByteBuffer(size);
buffer.flip();
newBuffer.put(buffer);
return newBuffer;
}
private ByteBuffer imageToByteBuffer(String path, int size) throws IOException {
ByteBuffer buffer;
URL url = Thread.currentThread().getContextClassLoader().getResource(path);
File file = new File(url.getFile());
if (file.isFile()) {
FileInputStream stream = new FileInputStream(file);
FileChannel channel = stream.getChannel();
buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
channel.close();
stream.close();
} else {
buffer = BufferUtils.createByteBuffer(size);
InputStream source = url.openStream();
if (source == null) {
throw new FileNotFoundException(path);
}
try {
ReadableByteChannel channel = Channels.newChannel(source);
try {
while (true) {
int bytes = channel.read(buffer);
if (bytes == -1) {
break;
}
if (buffer.remaining() == 0) {
buffer = resizeBuffer(buffer, buffer.capacity() * 2);
}
}
buffer.flip();
} finally {
channel.close();
}
} finally {
source.close();
}
}
return buffer;
}
public Texture(String path) throws IOException {
IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1);
IntBuffer components = BufferUtils.createIntBuffer(1);
data = STBImage.stbi_load_from_memory(imageToByteBuffer(path, 1024), width, height, components, 4);
id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL14.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
this.width = width.get(0);
this.height = height.get(0);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, this.width, this.height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
STBImage.stbi_image_free(data);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getID() {
return id;
}
public ByteBuffer getByteBuffer() {
return data;
}
public byte[] getByteArray() {
return data.array();
}
public void bind() {
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
}
public void release() {
GL11.glDisable(GL11.GL_TEXTURE_2D);
}
}
I use it as follows:
bg.bind();
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0F, 0F);
GL11.glVertex2f(-1F, 1F);
GL11.glTexCoord2f(1F, 0F);
GL11.glVertex2f(1F, 1F);
GL11.glTexCoord2f(1F, 1F);
GL11.glVertex2f(1F, -1F);
GL11.glTexCoord2f(0F, 1F);
GL11.glVertex2f(-1F, -1F);
GL11.glEnd();
bg.release();
where bg
is a declared Texture
that throws no errors.