// Create an input stream for the 'lookup texture', a texture that will used by the fragment shader to
// determine which colour matches which height on the heightmap
FileInputStream inputStream = new FileInputStream(path);
// Create a class that will give us information about the image file (width and height) and give us the
// texture data in an OpenGL-friendly manner
PNGDecoder decoder = new PNGDecoder(inputStream);
// Create a ByteBuffer in which to store the contents of the texture. Its size is the width multiplied by
// the height and 4, which stands for the amount of bytes a float is in Java.
ByteBuffer buffer = BufferUtils.createByteBuffer(4 * decoder.getWidth() * decoder.getHeight());
// 'Decode' the texture and store its data in the buffer we just created
decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
// Make the contents of the ByteBuffer readable to OpenGL (and unreadable to us)
buffer.flip();
// Close the input stream for the heightmap 'lookup texture'
inputStream.close();
// Generate a texture handle for the 'lookup texture'
int texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texture);
// Hand the texture data to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
return texture;