binding texture to a quad..... ????

Started by padam1989, September 15, 2009, 14:07:53

Previous topic - Next topic

Evil-Devil

I think it is more suitable than PNG. PNG offers custom compression and a its not that easy to read a png file when not using helpers like ImageIO. The drawback of TGA is that it comes with no compression and RLE is not really an issue to take care about. But it is very easy to read/write imho.

But as you said you're going for a graphics application and not a game i understand your point in adding PNG support.

NateS

In TWL, there is a possibly newer version of the PNG loader that is in Slick (same author, MatthiasM):
http://twl.l33tlabs.org/

padam1989

Hola.
I am getting an exception when loading rle tga. Here is the exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 524288
        at com.gaanza.engine.test.TGALoader.loadCompressedData(TGALoader.java:119)
        at com.gaanza.engine.test.TGALoader.<init>(TGALoader.java:51)
        at com.gaanza.engine.test.WindowTest.init(WindowTest.java:96)
        at com.gaanza.engine.test.WindowTest.main(WindowTest.java:35)
Java Result: 1


and line which is throwing an exception is:
                   textureData[currentByte]=colorBuffer[0];    //R byte


Help !!

Gracias.

Evil-Devil

Weird, did the RLE work with the provided LWJGL TGA RLE file or does it crash too? Because i tested the tutorial code with both files and both had been displayed/loaded fine.

padam1989

Quote from: Evil-Devil on September 21, 2009, 11:45:09
Weird, did the RLE work with the provided LWJGL TGA RLE file or does it crash too?

I was talking about the TGA RLE file that was provided by the tutorial. non-RLE file worked fine but RLE didn't worked.

Gracias.

Evil-Devil

Yea, that is what me makes wondering. Because the TGA RLE i put into the archive worked when i wrote and testet the tutorialcode. Will check it when iam home.

Evil-Devil

I can't see a difference, maybe iam blind ^^"

Here is the original full code i used for the tutorial. Just tested with the RLE file and it works fine.
TextureLoader.java
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameteri;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import org.lwjgl.opengl.EXTBgra;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;


/* =============================================================================
 * TextureLoader.java LWJGL_Tests 
 * 
 * Copyright (c) 2009 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -------------------------------------------------------------------------- */

/** 
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 09.03.2009
 */
public class TextureLoader {
	
	private FileInputStream fis = null;
	private DataInputStream dis = null;
	
	public TextureLoader() {
	}
	
	public Texture load(String fileName) {
		return loadFromFile(fileName);
	}
	
	private Texture loadFromFile(String file) {
		Texture tex = null;
		
		try {
			if (dis != null) {
				dis.close();
				dis = null;
			}
			
			/* TGA Header
			 * see http://en.wikipedia.org/wiki/Truevision_TGA for more info
			 */
			
			dis = new DataInputStream(new FileInputStream(new File(file)));
			byte[] TGARAWHEADER = new byte[12];
			dis.readFully(TGARAWHEADER);
						
			/* Uncompressed or compressed?
			 * 2 = Uncompressed
			 * 10 = Compressed
			 */
			if (TGARAWHEADER[2] == 2) {				
				tex = loadUncompressedData();
			} else if (TGARAWHEADER[2] == 10) {
				tex = loadCompressedData();
			}
			TGARAWHEADER = null;
			dis.close();
			dis = null;
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return tex;
	}
	
	private Texture loadUncompressedData() throws IOException {
		byte[] TGAHEADER = new byte[6];
		Texture tex = new Texture();
		
		dis.readFully(TGAHEADER);		
		setTextureInfo(TGAHEADER,tex);
		
		final byte[] textureData = new byte[tex.width * tex.height * tex.bpp];
	
		dis.readFully(textureData);
					
		tex = createTexture(tex, textureData);
		
		return tex;
	}
	
	private Texture loadCompressedData() throws IOException {
		byte[] TGAHEADER = new byte[6];
		Texture tex = new Texture();
		
		dis.readFully(TGAHEADER);		
		setTextureInfo(TGAHEADER,tex);
		
		final byte[] textureData = new byte[tex.width * tex.height * tex.bpp];	
		
		final int pixelCount = tex.width * tex.height;	// amount of pixels in this image
		int currentByte		= 0;	// the byte we read from
		int currentPixel	= 0;	// the pixel we handle
		int chunkHeader		= 0;
		byte[] chunkByte	= new byte[1];
		byte[] colorBuffer	= new byte[tex.bpp];
		
		do {
			dis.readFully(chunkByte);
			chunkHeader = chunkByte[0] & 0xFF;			
				
			// RAW Chunk
	    	if (chunkHeader < 128) {
	    		chunkHeader++;		// number of raw pixels
	    		
	    		// pixel reading
	    		for (int counter = 0; counter < chunkHeader; counter++) {
	    			dis.readFully(colorBuffer);
	    			
	    			// PLAIN READ
	    			textureData[currentByte] = colorBuffer[0];		// R Byte
	    			textureData[currentByte+1] = colorBuffer[1];	// G Byte
	    			textureData[currentByte+2] = colorBuffer[2];	// B Byte*/
	    			
	    			// 32bit (alpha) check
	    			if (tex.bpp == 4)
	    				textureData[currentByte+3] = colorBuffer[3];	// A Byte        			
	    			
	    			// increase the currByte counter
	    			currentByte+=tex.bpp;
	    			currentPixel++;
				}
	    	} else {	// RLE Header
	    		chunkHeader -= 127;
	    		// read the data        		
	    		dis.readFully(colorBuffer);
	    		
	    		// pixel loop
	    		for (int counter = 0; counter < chunkHeader; counter++) {       			
	    			
	    			textureData[currentByte] = colorBuffer[0];		// R Byte
	    			textureData[currentByte+1] = colorBuffer[1];	// G Byte
	    			textureData[currentByte+2] = colorBuffer[2];	// B Byte
	    			
	    			// 32bit (alpha) check
	    			if (tex.bpp == 4)
	    				textureData[currentByte+3] = colorBuffer[3];	// A Byte
	    			
					// increase the currByte counter
	    			currentByte+=tex.bpp;
	    			currentPixel++;
	    		}
	    	}
			
		} while (currentPixel < pixelCount);
		
		tex = createTexture(tex, textureData);
		
		return tex;
	}	
		
	private void setTextureInfo(byte[] header, Texture tex) {		
		tex.width		= header[1] * 256 + header[0];
		tex.height		= header[3] * 256 + header[2];
		tex.bitdepth	= header[4];
		tex.bpp			= (byte)(header[4] / 8);		
	}
	
	private Texture createTexture(Texture tex, byte[] textureData) {		
    	final ByteBuffer textureBuffer = ByteBuffer.allocateDirect(textureData.length).order(ByteOrder.nativeOrder());
    	
    	textureBuffer.clear();
    	textureBuffer.put(textureData);
    	textureBuffer.flip();
    	
    	final IntBuffer glName = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
    	
    	GL11.glGenTextures(glName);
    	tex.name = glName.get(0);
    	
    	GL11.glBindTexture(GL_TEXTURE_2D,tex.name);
    	
    	GL11.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GL11.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        
        GL11.glTexParameteri(GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
        
        // RGB OR RGBA - We assume that it is at least 24 bit
    	int glColor = tex.bitdepth == 32 ? GL12.GL_BGRA : GL12.GL_BGR;
        int glColor2 = tex.bitdepth == 32 ? GL11.GL_RGBA : GL11.GL_RGB;
    	GL11.glTexImage2D(GL_TEXTURE_2D,0,glColor2,tex.width,tex.height,0,glColor,GL11.GL_UNSIGNED_BYTE,textureBuffer);    	
    	 	
    	return tex;
	}
	
	
}

/* very simple texture class */
class Texture {
	public int	width		= 0;	// the width
	public int	height		= 0;	// the height
	public byte	bitdepth	= 0;	// the bitdepth, ie: 24bit
	public int	name		= -1;	// the opengl name by creation
	public byte bpp			= 0; 	// bits per pixel
}


/* =============================================================================
 * TextureTest.java LWJGL_Tests 
 * 
 * Copyright (c) 2009 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -------------------------------------------------------------------------- */

/** 
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 09.03.2009
 */

import org.lwjgl.opengl.GL11;

public class TextureTest extends Core {
	
	private TextureLoader loader;
	private Texture tex;
	
	public static void main(String[] args) {
		new TextureTest();
	}
	
	protected void initData() {
		loader = new TextureLoader();
		//tex = loader.load("lwjgl_logo.tga");		
		tex = loader.load("lwjgl_logo_rle.tga");
	}
	
	protected void initOpenGL() {
		super.initOpenGL();
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		// Enable Alphatesting
		GL11.glAlphaFunc(GL11.GL_GREATER, 0.01f);
        GL11.glEnable(GL11.GL_ALPHA_TEST);
	}
	
	protected void render() {
		GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT);
		GL11.glLoadIdentity();
		GL11.glTranslatef(0f,0f,-10f);
		
		GL11.glBindTexture(GL11.GL_TEXTURE_2D,tex.name);
		
		GL11.glBegin(GL11.GL_QUADS);		
		
			GL11.glTexCoord2f(0,0);
			GL11.glVertex3f(-4f,-3f,0f);	// bottom left
			
			GL11.glTexCoord2f(1,0);
			GL11.glVertex3f(4f,-3f,0f);		// bottom right
			
			GL11.glTexCoord2f(1,1);
			GL11.glVertex3f(4f,3f,0f);		// top right
			
			GL11.glTexCoord2f(0,1);
			GL11.glVertex3f(-4f,3f,0f);		// top left;
			
		GL11.glEnd();
	}
}


import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.OpenGLException;
import org.lwjgl.opengl.Util;
import org.lwjgl.util.glu.*;


/* =============================================================================
 * Core.java LWJGL_Tests 
 * 
 * Copyright (c) 2007 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -------------------------------------------------------------------------- */

/** 
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 21.08.2007
 */
public abstract class Core {
	
	private long startTime = 0L;
	
	protected Core() {
		this.init();
	}	
	
	private void init() {
		try {
			this.initDisplay();
			this.initKeyboard();
			this.initMouse();			
		} catch (LWJGLException e) {
			System.out.println("Error while init:");
			e.printStackTrace();
		}
		
		this.initOpenGL();
		this.reSizeGLScene(Display.getDisplayMode().getWidth(),Display.getDisplayMode().getHeight());
		this.initData();
		this.initLight();		
		
		this.run();
	}
	
	private void initMouse() throws LWJGLException {
		if (!Mouse.isCreated())
			Mouse.create();
	}

	private void initKeyboard() throws LWJGLException{
		if (!Keyboard.isCreated())
			Keyboard.create();		
	}

	private void initDisplay() throws LWJGLException {
		Display.setFullscreen(false);
		Display.setDisplayMode(new DisplayMode(640,480));
		Display.create();		
	}
	
	protected void initLight() {}
	
	protected void initData() {}
	
	protected void initOpenGL() {
		GL11.glShadeModel(GL11.GL_SMOOTH);
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // black background
        GL11.glClearDepth(1.0f); // depth of 0 to 1        
        GL11.glDepthFunc(GL11.GL_LEQUAL);
        GL11.glEnable(GL11.GL_DEPTH_TEST); // enable depth testing
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
	}
	
	private void reSizeGLScene(int width, int height) {
        if (height == 0)
            height = 1;

        GL11.glViewport(0, 0, width, height);

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();

        // a nice 45° perspective
        GLU.gluPerspective(45.0f, (float) width / (float) height, 0.1f, 100.0f);
        // ortho view
        //GL11.glOrtho(0.0f,width,height,0.0f,0.0f,1.0f);

        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
    }
	
	private void cleanup() {
		if (Display.isCreated()) {
			Display.destroy();
	        System.exit(0);
	    }
	}
	
	protected void run() {		
        this.startTime = Sys.getTime() + 1000;
        int FPS = 0;
        long frameTime = 0L;
       
        while (true) {
            
            if (Display.isCloseRequested()) {
                cleanup();
                break;
            }
            if (Display.isVisible()) {
            
                try {                	
                    this.render(); // render our magnificent scene o_O
                    Display.update(); // update the display ^__^
                                        
                } catch (OpenGLException e) {
                    e.printStackTrace();
                }
                // catch keyboard/mouse events
                checkKeyboardInput();
                checkMouseInput();
            }
            
            if (this.startTime > Sys.getTime()) 
	            FPS++;
            else {
        		frameTime = 1000 + (this.startTime - Sys.getTime());
	            this.startTime = Sys.getTime() + 1000;
	            System.out.println(FPS + " frames in " + (frameTime / 1000f) + " seconds = " + (FPS / (frameTime / 1000f)));
            	FPS = 0;
            }
            if (GL11.glGetError() != GL11.GL_NO_ERROR) {
            	System.out.println(Util.translateGLErrorString(GL11.glGetError()));
            }
        }
	}
	
	protected void checkMouseInput() {}

	protected void checkKeyboardInput() {
		if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
			this.cleanup();
		}
	}

	protected void render() {}
	
}