Need help finding out why the texture doesn't load - java

Trying to find a way to render a simple 2D image in Java using OpenGL I stumbled upon a more or less understandable class that does all of the image loading for you which I could not understand how to do. I believe it belongs to a person named Krythic and I assume that it works fine, I even preinted out the height and width of the image it is reading to see if it reads the proper image, which it does.
But here is said class nonetheless (I don't fully understand how it works):
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL12;
import static org.lwjgl.opengl.GL11.*;
public class TextureLoader {
private static final int BYTES_PER_PIXEL = 4;//3 for RGB, 4 for RGBA
public static int loadTexture(BufferedImage image){
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
// You now have a ByteBuffer filled with the color data of each pixel.
// Now just create a texture ID and bind it. Then you can load it using
// whatever OpenGL method you want, for example:
int textureID = glGenTextures(); //Generate texture ID
glBindTexture(GL_TEXTURE_2D, textureID); //Bind texture ID
//Setup wrap mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
//Setup texture scaling filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Send texel data to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
//Return the texture ID so we can bind it later again
return textureID;
}
public static BufferedImage loadImage(String loc)
{
try {
return ImageIO.read(Main.class.getResource(loc));
} catch (IOException e) {
//Error Handling Here
}
return null;
}
And here is the code I wrote thinking it would render the image on a quad, and that is probably where the problem lies.
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
BufferedImage image = TextureLoader.loadImage("test.png");
int textureID = TextureLoader.loadTexture(image);
glBindTexture(GL_TEXTURE_2D, textureID);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1f, -1f);
glTexCoord2f(1, 0);
glVertex2f( 0f, -1f);
glTexCoord2f(1, 1);
glVertex2f( 0f, 0f);
glTexCoord2f(0, 1);
glVertex2f(-1f, 0f);
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
So it draws a quad in the lower left corner of the screen as it did before, but it's white and the texture is supposed to be brown. It doesn't give me any exceptions so I don't know exactly where I messed up.

Enable textures with
glEnable(GL_TEXTURE_2D);

Related

How can I load bufferedImage as opengl texture?

I'm trying to create a texture from a loaded Buffered image like this:
public static long loadTexture(String img) throws IOException{
File imgPath = new File(img);
BufferedImage bufferedImage = ImageIO.read(imgPath);
byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
int id = glGenTextures();
glBindTexture(GL_TEXTURE_2D, id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferedImage.getWidth(), bufferedImage.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, ByteBuffer.wrap(pixels));
glGenerateMipmap(GL_TEXTURE_2D);
return id;
}
But this code gives me a java sigsegv error. I am using a Java.nio.Bytebuffer because the sun one isn't supported in java 11.
So what am I doing wrong? The Image is loaded correctly, with 4bpp:
//last 2 digits are lenght
FF-AD-6F-CB-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-00-00-FF-FF-00-00-FF-FF-FF-FF-00-FF-FF-FF-00-FF-00-00-FF-FF-00-00-FF-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-64
Heres the image:
its pretty small of course but the data is correct.
So why am I getting a sigsegv? the log is pretty useless and long so I can't post it.
And how do I create an opengl texture from a 4bpp byte array?
As suggested in Java Code Examples for org.lwjgl.opengl.GL11.glTexImage2D() (Example 5) you have to copy the data to a ByteBuffer in loops:
public static long loadTexture(String img) throws IOException{
File imgPath = new File(img);
BufferedImage image = ImageIO.read(imgPath);
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = ByteBuffer.allocateDirect(image.getWidth() * image.getHeight() * 4);
for(int h = 0; h < image.getHeight(); h++) {
for(int w = 0; w < image.getWidth(); w++) {
int pixel = pixels[h * image.getWidth() + w];
buffer.put((byte) ((pixel >> 16) & 0xFF));
buffer.put((byte) ((pixel >> 8) & 0xFF));
buffer.put((byte) (pixel & 0xFF));
buffer.put((byte) ((pixel >> 24) & 0xFF));
}
}
buffer.flip();
int id = glGenTextures();
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(),
0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glGenerateMipmap(GL_TEXTURE_2D);
return id;
}
Note, glPixelStorei(GL_UNPACK_ALIGNMENT, 1) is unnecessary in that case, because the size of a RGBA pixel is 4 bytes, so each row is aligned to 4 bytes and GL_UNPACK_ALIGNMENT by default is 4.
Furthermore, if you want to use Mipmaps (glGenerateMipmap), then the minifying function (GL_TEXTURE_MIN_FILTER) has to be GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR. (See glTexParameter)

LWJGL: Getting Texture from .png with multiple textures

I am making a game with LWJGL and by using openGL, I believe my best option is to use Textures and render them with quads. However, I can only seem to find information on loading a texture from an image where the entire image is only ONE texture. What I would like to do is read an entire spritesheet in and be able to separate it into different textures. Is there a somewhat simple way to do this?
You could load the image, from e.g. a .png file to a BufferedImage with
public static BufferedImage loadImage(String location)
{
try {
BufferedImage image = ImageIO.read(new File(location));
return image;
} catch (IOException e) {
System.out.println("Could not load texture: " + location);
}
return null;
}
Now you are able to call getSubimage(int x, int y, int w, int h) on that resulting BufferedImage, giving you the seperated part. You now just need to create a Texture of the BufferedImage. This code should do the work:
public static int loadTexture(BufferedImage image){
if (image == null) {
return 0;
}
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
// You now have a ByteBuffer filled with the color data of each pixel.
// Now just create a texture ID and bind it. Then you can load it using
// whatever OpenGL method you want, for example:
int textureID = glGenTextures();
glBindTexture(GL_TEXTURE_2D, textureID);
//setup wrap mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
//setup texture scaling filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Send texel data to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); //GL_RGBA8 was GL_RGB8A
return textureID;
}
You are now able to bind the returned textureID with glBindTexture(GL_TEXTURE_2D, textureID); if you need the texture.
This way you only have to split the BufferedImage in the desired parts.
I recommend reading this: LWJGL Textures and Strings

LWJGL Texture is flipped upside down when displayed

I followed a tutorial for reading a picture and creating a texture out of it, however, it shows up flipped upside down when rendered. The image is power of two.
Main class
public class Main {
public static void main(String args[]) throws IOException{
Main quadExample = new Main();
quadExample.start();
}
public void start() throws IOException {
try {
Display.setDisplayMode(new DisplayMode(1280,720));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
// init OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 1280, 0, 720, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glClearColor(0, 1, 0, 0);
GL11.glEnable(GL11.GL_TEXTURE_2D);
BufferedImage image = TextureLoader.loadImage("C:\\test.png");
final int textureID = TextureLoader.loadTexture(image);
while (!Display.isCloseRequested()) {
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(256, 0);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(256, 256);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(0, 256);
GL11.glEnd();
Display.update();
}
Display.destroy();
}
}
Texture Loader
public class TextureLoader {
private static final int BYTES_PER_PIXEL = 4;
public static int loadTexture(BufferedImage image) {
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0,
image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth()
* image.getHeight() * BYTES_PER_PIXEL);
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF));
buffer.put((byte) ((pixel >> 8) & 0xFF));
buffer.put((byte) (pixel & 0xFF));
buffer.put((byte) ((pixel >> 24) & 0xFF));
}
}
buffer.flip();
int textureID = glGenTextures();
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(),
image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
return textureID;
}
public static BufferedImage loadImage(String location) {
try {
return ImageIO.read(new File(location));
} catch (IOException e) {
System.out.println(Errors.IOException);
e.printStackTrace();
}
return null;
}
Is there something wrong with the code or do I have to flip the image before creating the texture?
Most image formats store the data top to bottom. Unless you reshuffle the data while loading the image, this is also the sequence in memory after reading the image.
When you create an OpenGL texture from the loaded image, this memory order is maintained unless you explicitly change the order. So the order in texture memory is still top to bottom.
OpenGL does not really have an image/texture orientation. But when you use texture coordinates, they address the texture in the order it's stored in memory. This means for the two extreme values of the t-coordinate:
t = 0.0 corresponds to the start of the image in memory, which is the top edge of the image.
t = 1.0 corresponds to the end of the image in memory, which is the bottom edge of the image.
Now, looking at your draw calls:
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(256, 0);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(256, 256);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(0, 256);
In the default OpenGL coordinate system, the y-coordinate goes bottom to top. So the first two vertices are the bottom vertices of the quad (since they have the smaller y-coordinate), the remaining two are the top two vertices.
Since you used t = 0.0 for the first two vertices, which are at the bottom of the quad, and t = 0.0 corresponds to the top of the image, the top of the image is at the bottom of the quad. Vice versa, you use t = 1.0 for the second two vertices, which are at the top of the quad, and t = 1.0 corresponds to the bottom of the image. Therefore, your image appears upside down.
By far the easiest way to fix this is to change the texture coordinates. Use t = 1.0 for the bottom two vertices, and t = 0.0 for the top two vertices, and the image orientation now matches the orientation of the quad on the screen:
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(0.0f, 0.0f);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(256.0f, 0.0f);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex2f(256.0f, 256.0f);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f(0.0f, 256.0f);
Another option is that you flip the image while reading it in, for example by changing the order of your for loop from:
for (int y = 0; y < image.getHeight(); y++) {
to:
for (int y = image.getHeight() - 1; y >= 0; y--) {
But it's very common to have images in top-down order in memory, and you often don't have control over it if you're using system libraries/frameworks for reading them. So using the texture coordinates to render them in the desired direction is a frequently used approach, and IMHO preferable over shuffling the data around.

Textured Quad issue in Java OpenGL

First, I'll start with my code because I've identified which block is causing the issue.
// init
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
// BEGINNING OF OFFENDING CODE
BufferedImage image = ImageIO.read(new File("res/button.png"));
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
IntBuffer buffer = BufferUtils.createIntBuffer(pixels.length);
for (int pixel : pixels)
buffer.put(pixel);
buffer.flip();
int button = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
//Setup wrap mode
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
// END OF OFFENDING CODE
This is what things are supposed to look like without the textured quad.
This is what happens when I render with the offending code (with the textured quad).
This is what happens when I render with the offending code (without the textured quad).
For reference, this is the texture
I can't seem to figure out which GL11 call is affecting the rest of the Display and why it would be affecting the rest of the display. From what I understand, all of the calls that follow GL11.glBindTexture are limited to the bound texture, aren't they?
Edit: Additional Rendering Code
private static void renderQuad(int x, int y, int width, int height) {
GL11.glPushMatrix();
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(x, y);
GL11.glVertex2f(x + width, y);
GL11.glVertex2f(x + width, y + height);
GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
}
The method used for the red quads.
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(0.5f,0.5f,1.0f);
renderQuad(0, 0, 800, 600);
// render action bar
GL11.glColor3f(0.2f,0.2f,1.0f);
renderQuad(0, 0, 800, 200);
GL11.glColor3f(1.0f,0.0f,0.0f);
renderQuad(50, 50, 100, 60);
renderQuad(200, 50, 100, 60);
// render textured quad
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2d(0.0,1.0);
GL11.glVertex2f(x, y);
GL11.glTexCoord2d(1.0,1.0);
GL11.glVertex2f(x + width, y);
GL11.glTexCoord2d(1.0,0.0);
GL11.glVertex2f(x + width, y + height);
GL11.glTexCoord2d(0.0,0.0);
GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
First of all, I think there's a problem with your texture loading. I believe the order of the bytes is reversed or something similar, which is why you get the red on black. Here's a working load-texture-from-BufferedImage example taken from my own code:
BufferedImage image = ImageIO.read(new File("<file path>.png"));
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
// You now have a ByteBuffer filled with the color data of each pixel.
// Now just create a texture ID and bind it. Then you can load it using
// whatever OpenGL method you want, for example:
int textureID = GL11.glGenTextures(); //Generate texture ID
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); //Bind texture ID
//Setup wrap mode
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);
//Setup texture scaling filtering
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
//Send texel data to OpenGL
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
Now, to the actual rendering problem:
For OpenGL, GL_TEXTURE_2D must be enabled or disabled depending on whether or not the polygon you are drawing is textured. If you do not supply texture coordinates for each vertex, then the last texture coords call still holds and is used for each vertex. So, you'll get a quad using one pixel's worth of texture. This is what's causing the black quads - it's taking from one pixel from a corner of your improperly loaded texture. So, your fixed rendering code:
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glColor3f(0.5f,0.5f,1.0f);
renderQuad(0, 0, 800, 600);
// render action bar
GL11.glColor3f(0.2f,0.2f,1.0f);
renderQuad(0, 0, 800, 200);
GL11.glColor3f(1.0f,0.0f,0.0f);
renderQuad(50, 50, 100, 60);
renderQuad(200, 50, 100, 60);
GL11.glEnable(GL11.GL_TEXTURE_2D);
// render textured quad
GL11.glColor3f(1.0f, 1.0f, 1.0f);
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2d(0.0,1.0);
GL11.glVertex2f(x, y);
GL11.glTexCoord2d(1.0,1.0);
GL11.glVertex2f(x + width, y);
GL11.glTexCoord2d(1.0,0.0);
GL11.glVertex2f(x + width, y + height);
GL11.glTexCoord2d(0.0,0.0);
GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
On a side note, you can use simply glEnable() instead of GL11.glEnable() if you do:
import static org.lwjgl.opengl.GL11.*;
instead of simply
import org.lwjgl.opengl.GL11;

OpenGL Textures without Slick

I searched for Texture Implementations without the Slick Utils library.
I found 2 ways, to do this:
The first, saves the pixels with strange byteshifting in a byte buffer:
int loadTexture(){
try{
BufferedImage img = ImageIO.read(getClass().getClassLoader().getResourceAsStream("background.png"));
int pixels[] = new int[img.getWidth() * img.getHeight()];
img.getRGB(0, 0, img.getWidth(), img.getHeight(), pixels, 0, img.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(img.getWidth() * img.getHeight() * 3);
for(int x = 0; x < img.getWidth(); x++){
for(int y = 0; y < img.getHeight(); y++){
int pixel = pixels[y * img.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF));
buffer.put((byte) ((pixel >> 8) & 0xFF));
buffer.put((byte) (pixel & 0xFF));
}
}
buffer.flip();
int textureId = glGenTextures();
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, img.getWidth(), img.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
return textureId;
}
catch(Exception e){
e.printStackTrace();
return 0;
}
}
This returns a texture id as well, and i haven't any idea how tu use this id.
The second way doesnt do any byteshifting, and uses a IntBuffer: Also, it is a ready class to save different textures with names and so on.
The Code of these:
ublic class TextureIO {
private final IntBuffer texture;
private final int width;
private final int height;
private int id;
public TextureIO(final InputStream inputStream) throws IOException {
BufferedImage image = ImageIO.read(inputStream);
width = image.getWidth();
height = image.getHeight();
final AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -height);
final AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
image = op.filter(image, null);
final int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
texture = BufferUtils.createIntBuffer(pixels.length);
texture.put(pixels);
texture.rewind();
}
public void init() {
GL11.glEnable(GL11.GL_TEXTURE_2D);
final IntBuffer buffer = BufferUtils.createIntBuffer(1);
GL11.glGenTextures(buffer);
id = buffer.get(0);
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);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, texture);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
public void bind() {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
}
public void unbind() {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
}
Im really new to lwjgl development, and want to know which version is better. Cause im a friend of implementing such things by myself, i want the lwjgl.jar to be the own library im using.
I read on different sites, the buffer.flip() method would be necassary. but why? And why the second version doesnt do this? Also, i want to understand the difference between this two implementations, what happens in the first and what in the second?
Thank you!
Both of those are pretty bad implementations IMO. I would recommend watching this video for a more standard approach. Although you would have to also use the PNGDecoder.jar library it is like an extension to the lwjgl library.

Categories

Resources