I have been recently learning LWJGL since I've been with Java for some time now, and I've learned that since there aren't very many LWJGL tutorials/reference material, I just use search OpenGL tutorials and since I know that LWJGL is like a Java port of OpenGL (I think that's how you'd describe) they'd be basically the exact same, except I always have to tweak it a bit, and I made this code (basically all by myself) and when I run it, it only displays one tile map, but it should display 16 tiles in all! Why is this?
package testandothertutorials;
import static org.lwjgl.opengl.GL11.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
public class TileMapTest {
int tilemap[][] = {
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 1, 0, 0, 1 }
};
int TILE_SIZE = 32;
int WORLD_SIZE = 4;
Texture stone_texture, dirt_texture;
public TileMapTest() {
try {
Display.setDisplayMode(new DisplayMode(640, 480));
Display.setTitle("Game");
Display.create();
} catch(LWJGLException e) {
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
//Load the stone and dirt textures before the render loop
try {
stone_texture = TextureLoader.getTexture("PNG", new FileInputStream(new File("C://Users//Gannon//Desktop//Java//workspace//Test Game//res//stone.png")));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
dirt_texture = TextureLoader.getTexture("PNG", new FileInputStream(new File("C://Users//Gannon//Desktop//Java//workspace//Test Game//res//dirt.png")));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
while(!Display.isCloseRequested()) {
glClear(GL_COLOR_BUFFER_BIT);
drawTiles();
Display.update();
Display.sync(60);
}
Display.destroy();
}
public void drawTiles() {
for(int x = 0; x < WORLD_SIZE; x++) {
for(int y = 0; y < WORLD_SIZE; y++) {
if(tilemap[x][y] == 0) { //If the selected tile in the tilemap equals 0, set it to the stone texture to draw
stone_texture.bind();
} else if(tilemap[x][y] == 1) { //If the selected tile equals 1, set it to the dirt texture to draw
dirt_texture.bind();
}
glPushMatrix();
glTranslatef(x, y, 0);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(32, 0);
glTexCoord2f(1, 1);
glVertex2f(32, 32);
glTexCoord2f(0, 1);
glVertex2f(0, 32);
glEnd();
glPopMatrix();
}
}
}
public static void main(String args[]) {
new TileMapTest();
}
}
Try using glpushmatrix() and glpopmatrix(), currently your GL_QUADS are reletive to the last one drawn and so the positioning get far apart the higher x and y do:
glPushMatrix();
glTranslatef(x, y, 0);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(32, 0);
glTexCoord2f(1, 1);
glVertex2f(32, 32);
glTexCoord2f(0, 1);
glVertex2f(0, 32);
glEnd();
glPopMatrix();
This will allow each quad to be back in world space coordinates instead of the last drawn quad - I had the same problem once.
Also loading identity should only be done at the start of each new frame and try loading both textures outside the loop and choosing inside, loading for each tile is a real waste on the hard-drive, make use of RAM.
Your problem occurs, because your not translating the tiles enough, so you end up rendering all the tiles on top of each other!
Currently your doing glTranslatef(x, y, 0); and remember that your tiles have a 32 pixels width and height, but the range that you translate in is only 0 to 4 (since you only render 16 tiles) you need to change your translation.
This is how you should translate.
glTranslatef(x * TILE_SIZE, y * TILE_SIZE, 0);
So at the rendering part it ends up looking like this.
glPushMatrix();
glTranslatef(x * TILE_SIZE, y * TILE_SIZE, 0);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(32, 0);
glTexCoord2f(1, 1);
glVertex2f(32, 32);
glTexCoord2f(0, 1);
glVertex2f(0, 32);
glEnd();
glPopMatrix();
Related
I'm trying to create some code for loading and drawing 2D textures in LWJGL. Here is my code for drawing:
glfwShowWindow(window);
GL.createCapabilities();
loadTextures();
glClearColor(1f, 1f, 1f, 1f);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//draw
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glTranslatef(100, 100, 0);
glBindTexture(GL_TEXTURE_2D, testTexture);
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(TEXTURE_WIDTH, 0);
glTexCoord2f(1, 1);
glVertex2f(TEXTURE_WIDTH, TEXTURE_HEIGHT);
glTexCoord2f(0, 1);
glVertex2f(0, TEXTURE_HEIGHT);
}
glEnd();
glPopMatrix();
//end draw
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
glfwSetErrorCallback(null).free();
And this is my texture loading code:
try
{
BufferedImage image = ImageIO.read(file);
/*
if (image.getType() != BufferedImage.TYPE_INT_ARGB)
{
throw new TextureException("Invalid image!");
}
*/
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer byteBuffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);
for (int x = 0; x < image.getWidth(); x++)
{
for (int y = 0; y < image.getHeight(); y++)
{
int pixel = pixels[y * image.getWidth() + x];
byteBuffer.put((byte)((pixel >> 16) & 0xFF));
byteBuffer.put((byte)((pixel >> 8) & 0xFF));
byteBuffer.put((byte)(pixel & 0xFF));
byteBuffer.put((byte)((pixel >> 24) & 0xFF));
}
}
byteBuffer.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, byteBuffer);
return textureID;
}
catch (Exception e)
{
e.printStackTrace();
throw new TextureException("Failed to load image!");
}
However, when I run this code all I get is a white screen. I checked the value of testTexture and it was set to 1, so I assume that's the texture's ID which makes me believe that worked, but I think there's something going wrong when drawing.
Two-dimensional texturing has to be enabled by glEnable and can be disabled by glDisable:
glEnable(GL_TEXTURE_2D);
If texturing is enables then the texture wich is currently bound is applied, when the geometry is drawn by the glBegin/glEnd sequences.
If you want to draw the geometry in window (pixel) coordinates, then you've to set an orthographic projection with. The orthographic projection can be set by glOrtho.
If you dont set the orthographic projection, the vertex coordinates would have to be in normalized device space in range [-1.0, 1.0].
In the following windowWidth an windowHeight is assumed to be the width and height of the window:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, windowWidth, windowHeight, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// [...]
}
Whenever I draw my display list my slick util text wont render properly.
While using glCallList:
Without using glCallList:
Rendering the display list:
if (dlLocation != -1) {
GL11.glPushMatrix();
GL11.glTranslatef(x, y, 0);
GL11.glCallList(dlLocation);
GL11.glPopMatrix();
}
All of the display lists are created with this method:
private static int createDisplayList(Texture t, int width, int height) {
int returnInt = glGenLists(1);
glNewList(returnInt, GL_COMPILE);
{
t.bind();
glEnable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(width, 0);
glTexCoord2f(1, 1);
glVertex2f(width, height);
glTexCoord2f(0, 1);
glVertex2f(0, height);
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
glEndList();
return returnInt;
}
I'm rendering the text using slick-util's TrueTypeFont.
Placing glBindTexture ( in your case t.bind() ) outside of glNewList might help.
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture)
glCallList(newList)
glBindTexture(GL_TEXTURE_2D, 0)
I have been trying for hours to get a Texture in LWJGL to stretch to a quad.
Here is the code I am using for the quad:
private static void renderLoad() {
glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
texture.bind();
glPushMatrix();{
glBegin(GL_QUADS);
{
glTexCoord2f(0, 1);
glVertex2f(0, 0); //Upper-left
glTexCoord2f(1, 1);
glVertex2f(Display.getWidth(), 0); //Upper-right
glTexCoord2f(1, 0);
glVertex2f(Display.getWidth(), Display.getHeight()); //Bottom-right
glTexCoord2f(0, 0);
glVertex2f(0, Display.getHeight()); //Bottom-left
}
glEnd();
}glPopMatrix();
}
This is what the display looks like when I run it:
http://gyazo.com/376ddb0979c55226d2f63c26215a1e12
I am trying to make the image expand to the size of the window. The Quad is at the size of the window, but the texture seems to not stretch.
Here is what it looks like if I do not use a texture and I simple make the quad a color:
http://gyazo.com/65f21fe3efa2d3948de69b55d5c85424
If it helps here is my main loop:
glMatrixMode(GL_PROJECTION);
glViewport(0, 0, displaySizeX, displaySizeY);
glLoadIdentity();
glOrtho(0, displaySizeX, 0, displaySizeY, 1, -1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
texture = loadLoadingImage();
//This is the main loop for the game.
while(!Display.isCloseRequested()){
delta = getDelta();
updateFPS();
if(Display.wasResized()){
displaySizeX = Display.getWidth();
displaySizeY = Display.getHeight();
glViewport(0, 0, displaySizeX, displaySizeY);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, displaySizeX, 0, displaySizeY, -1, 1);
}
render();
checkInput();
Display.update();
Display.sync(sync);
}
cleanUp();
return true;
How do I make the image stretch to the quad?
public void stretch() {
Color.white.bind();
texture.bind
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(100,100);
GL11.glTexCoord2f(1,0);
GL11.glVertex2f(100+texture.getTextureWidth(),100);
GL11.glTexCoord2f(1,1);
GL11.glVertex2f(100+texture.getTextureWidth(),100+character.getTextureHeight());
GL11.glTexCoord2f(0,1);
GL11.glVertex2f(100,100+texture.getTextureHeight());
GL11.glEnd(); // all the 0's were originally 100 but it was off centered
}
texture = TextureLoader.getTexture("PNG",ResourceLoader.getResourceAsStream("res/texture.png"));
Try using this. This is usually how I do this.
Perhaps something is modifying the texture matrix. You could try adding a
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
to see if that affects anything.
I'm trying to make a game in Java OpenGL (JOGL), but I have a problem with textures.
When I draw a quad with a texture, the only thing I see is the image in blue scale.
The following is my code:
Texture grass;
// public void init() in Base class that implements GLEventListener
try {
grass = TextureIO.newTexture(new File("src/com/jeroendonners/main/grass.png"), false);
} catch(Exception e) {
e.printStackTrace();
}
To render a quad with this texture I use the following code:
int x = 0;
int y = 0;
gl.glColor3f(1f, 1f, 1f);
this.grass.bind(gl);
gl.glBegin(gl.GL_QUADS);
gl.glTexCoord2d(0, 0);
gl.glVertex3f(0, 0, 0);
gl.glTexCoord2d(1, 0);
gl.glVertex3f(1, 0, 0);
gl.glTexCoord2d(1, 1);
gl.glVertex3f(1, 1, 0);
gl.glTexCoord2d(0, 1);
gl.glVertex3f(0, 1, 0);
gl.glEnd();
I have read here that I have to use GL_BGR instead of the default GL_RGB, but since that question initializes textures in a different way, I don't know what to do with it.
Maybe a note: I am using an old version of JOGL, 1.0 I think. That's because I had a course on school with this version.
Ok so I am currently working on a 2d game in java with LWJGL. I have a fairly solid understanding of java and how it works and know the basics of how games work and LWJGL/openGL, but I am having this really weird issue with rendering textures. I determined that one of my draw methods here is the culprit ..
public static void texturedTriangleInverted(float x, float y, float width, float height, Texture texture) {
GL11.glPushMatrix();
{
GL11.glTranslatef(x, y, 0);
texture.bind();
GL11.glBegin(GL11.GL_TRIANGLES);
{
GL11.glVertex2f(width / 2, 0);
GL11.glTexCoord2f(width / 2, 0);
GL11.glVertex2f(0, height);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(width, height);
GL11.glTexCoord2f(1, 1);
}
GL11.glEnd();
}
GL11.glPopMatrix();
}
so what happens is if I render anything with this method the next thing rendered looks like it literally was compressed on one end and stretched on the other, even if the next thing rendered is not rendered with this method. I am almost positive that it has to do with the argument I passed into the Gl11.glTexCoord2f(float x, float y) methods, but I cant figure out how to fix it.
here is my openGL initialization code
private void initGL() {
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, Strings.DISPLAY_WIDTH, 0, Strings.DISPLAY_HEIGHT, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_TEXTURE_BINDING_2D);
GL11.glViewport(0, 0, Strings.DISPLAY_WIDTH, Strings.DISPLAY_HEIGHT);
GL11.glClearColor(0, 0, 1, 0);
GL11.glDisable(GL11.GL_DEPTH_TEST);
}
my game loop code
private void gameLoop() {
while (!Display.isCloseRequested()) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glLoadIdentity();
GL11.glTranslatef(Strings.transX, Strings.transY, 0);
this.level.update();
this.level.render();
Display.update();
Display.sync(Strings.FPS_CAP);
}
Keyboard.destroy();
Display.destroy();
}
my texture loading code (note I used slick to load my textures)
public static final Texture loadTexture(String location) {
try {
if (textureExists(location)) {
return TextureLoader.getTexture("png", new BufferedInputStream(new FileInputStream(new File(location))), false);
} else {
System.err.println("txture does not exist");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
You need to specify your glTexCoord before the glVertex it refers to, not after. This is the same as with glColor and glNormal, glVertex uses the last attributes that you set.