# VertexBuffer & Texturen?



## faustdonner (28. Sep 2012)

Hallo ich benutze momentan Vertexbuffer für meine Voxel-Engine (LWJGL). Ich habe zwar die Möglichkeit Farben hinzuzufügen aber ich würde gerne Texturen dadrauf sehen und wenn möglich scharfe Texturen. Momentan benutze ich die Texturen und Texte von Slick würde aber gerne auf andere Weise an die Texturen und den Text kommen. Ich möchte wenigstens eine Textur auf meinen Blöcken sehen .

Also hier mein Chunk-Code:


```
import java.awt.Point;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.Color;

public class Chunk {
	public static final int CHUNK_WIDTH = 16;
	public static final int CHUNK_HEIGHT = 64;
	public static final int CHUNK_DEPTH = 16;

	private int VBOVertexHandle;
	private int VBOColorHandle;
	
	public int[][][] blocks;
	
	private boolean draw = false;
	
	public int startX, startY, startZ;
	
	public int x, z;
	
	public Chunk(Point pos, boolean generate, boolean draw) {
		this.x = pos.y;
		this.z = pos.x;
		
		this.draw = draw;
		
		this.startX = (int) (z * CHUNK_WIDTH * Block.BLOCK_SIZE);
		this.startY = 0;
		this.startZ = (int) (x * CHUNK_DEPTH * Block.BLOCK_SIZE);
		
		blocks = new int[CHUNK_WIDTH][CHUNK_HEIGHT][CHUNK_DEPTH];

		if(draw) {
			VBOColorHandle = GL15.glGenBuffers();
			VBOVertexHandle = GL15.glGenBuffers();
		}
		
		if(generate && draw) {
			generate();
		}
		else if(generate) {
			generateWithoutDraw();
		}
	}

	private void generate() {
		for(int x = 0; x < CHUNK_WIDTH; x++) {
			for(int y = 0; y < CHUNK_HEIGHT; y++) {
				for(int z = 0; z < CHUNK_DEPTH; z++) {
	                if(y > 32) {
	                	blocks[x][y][z] = Block.air.ID;
	                }
	                else if(y == 32) {
	                	blocks[x][y][z] = Block.grass.ID;
	                }
	                else if(y < 32 && y >= 32 - 4) {
	                	blocks[x][y][z] = Block.dirt.ID;
	                }
	                else {
	                	blocks[x][y][z] = Block.stone.ID;
	                }
				}
			}
		}
		
		VBOColorHandle = GL15.glGenBuffers();
		VBOVertexHandle = GL15.glGenBuffers();
		
		FloatBuffer VertexPositionData = BufferUtils.createFloatBuffer((CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) * 6 * 12);
		FloatBuffer VertexColorData = BufferUtils.createFloatBuffer((CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) * 6 * 12);
		
		for(int x = 0; x < CHUNK_WIDTH; x++) {
			for(int y = 0; y < CHUNK_HEIGHT; y++) {
				for(int z = 0; z < CHUNK_DEPTH; z++) {
					try {
						if(blocks[x][y][z] == 0) throw new NullPointerException();
						VertexPositionData.put(Block.CreateBlock(new Point(this.x, this.z), new Vector3f((float) startX + x * Block.BLOCK_SIZE, (float) startY + y * Block.BLOCK_SIZE, (float) startZ + z * Block.BLOCK_SIZE)));
						Color color = BlockMaterial.getBlockMaterialById(Block.getBlockById(blocks[x][y][z]).blockMaterial).texture;
						VertexColorData.put(CreateCubeVertexCol(new float[] {color.r, color.g, color.b}));
					} catch(NullPointerException e) {
						VertexPositionData.put(new float[] {});
						VertexColorData.put(CreateCubeVertexCol(new float[] {}));
					}
				}
			}
		}
		
		VertexColorData.flip();
		VertexPositionData.flip();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertexHandle);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, VertexPositionData, GL15.GL_STATIC_DRAW);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOColorHandle);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, VertexColorData, GL15.GL_STATIC_DRAW);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		onChange();
	}
	
	private void generateWithoutDraw() {
		for(int x = 0; x < CHUNK_WIDTH; x++) {
			for(int y = 0; y < CHUNK_HEIGHT; y++) {
				for(int z = 0; z < CHUNK_DEPTH; z++) {
	                if(y > 32) {
	                	blocks[x][y][z] = Block.air.ID;
	                }
	                else if(y == 32) {
	                	blocks[x][y][z] = Block.grass.ID;
	                }
	                else if(y < 32 && y >= 32 - 4) {
	                	blocks[x][y][z] = Block.dirt.ID;
	                }
	                else {
	                	blocks[x][y][z] = Block.stone.ID;
	                }
				}
			}
		}
		
		onChange();
	}
	
	private float[] CreateCubeVertexCol(float[] CubeColorArray) {
		float[] cubeColors = new float[CubeColorArray.length * 4 * 6];
		for (int i = 0; i < cubeColors.length; i++) {
			cubeColors[i] = CubeColorArray[i % CubeColorArray.length];
		}
		return cubeColors;
	}
	
	public void paint() {
		if(!draw) return;
		
		GL11.glPushMatrix();
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertexHandle);
		GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOColorHandle);
		GL11.glColorPointer(3, GL11.GL_FLOAT, 0, 0L);
		GL11.glDrawArrays(GL11.GL_QUADS, 0, CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH * 24);

		GL11.glPopMatrix();
	}
	
	public boolean hasCoordinate(int blockX, int blockZ) {
		for(int x = 0; x < CHUNK_WIDTH; x++) {
	        for(int z = 0; z < CHUNK_DEPTH; z++) {
	            if(x + this.x * CHUNK_WIDTH == blockX && z + this.z * CHUNK_DEPTH == blockZ) return true;
	        }
	    }
		return false;
	}
	
	public void run() {

	}
	
	public void onChange() {
		save();
	}

	public String save() {
		String sep = System.getProperty("file.separator");
		
		File chunkFile = new File("."+sep+"worlds"+sep+World.worldName+sep+"region"+sep+x+"."+z+".cbr");
		
		String data = "";
		for(int x = 0; x < CHUNK_WIDTH; x++) {
			for(int y = 0; y < CHUNK_HEIGHT; y++) {
				for(int z = 0; z < CHUNK_DEPTH; z++) {
					if(blocks[x][y][z] != Block.air.ID) {
						data += blocks[x][y][z] + ":";
					}
					else {
						data += ":";
					}
				}
			}
		}
		
		try {
			FileWriter fw = new FileWriter(chunkFile);
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write(data);
			bw.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		return data;
	}
	
	public static Chunk load(int chunkX, int chunkZ, boolean draw) {
		String sep = System.getProperty("file.separator");
		
		Chunk chunk = new Chunk(new Point(chunkX, chunkZ), false, draw);
		
		File chunkFile = new File("."+sep+"worlds"+sep+World.worldName+sep+"region"+sep+chunkX+"."+chunkZ+".cbr");
		
		try {
			FileReader fr = new FileReader(chunkFile);
			BufferedReader br = new BufferedReader(fr);
			String[] coords = br.readLine().split(":");
			int i = 0;
			for(int x = 0; x < CHUNK_WIDTH; x++) {
				for(int y = 0; y < CHUNK_HEIGHT; y++) {
					for(int z = 0; z < CHUNK_DEPTH; z++) {
						try {
							chunk.blocks[x][y][z] = Integer.valueOf(coords[i]);
						} catch(Exception e) {
							chunk.blocks[x][y][z] = Block.air.ID;
						}
						i++;
					}
				}
			}
			br.close();
		} catch(IOException e) {}
		
		return chunk;
	}

	public boolean isDraw() {
		return draw;
	}

	public void setDraw(boolean draw) {
		if(draw) {
			VBOColorHandle = GL15.glGenBuffers();
			VBOVertexHandle = GL15.glGenBuffers();
			
			FloatBuffer VertexPositionData = BufferUtils.createFloatBuffer((CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) * 6 * 12);
			FloatBuffer VertexColorData = BufferUtils.createFloatBuffer((CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) * 6 * 12);
			
			for(int x = 0; x < CHUNK_WIDTH; x++) {
				for(int y = 0; y < CHUNK_HEIGHT; y++) {
					for(int z = 0; z < CHUNK_DEPTH; z++) {
						try {
							if(blocks[x][y][z] == 0) throw new NullPointerException();
							VertexPositionData.put(Block.CreateBlock(new Point(this.x, this.z), new Vector3f((float) startX + x * Block.BLOCK_SIZE, (float) startY + y * Block.BLOCK_SIZE, (float) startZ + z * Block.BLOCK_SIZE)));
							Color color = BlockMaterial.getBlockMaterialById(Block.getBlockById(blocks[x][y][z]).blockMaterial).texture;
							VertexColorData.put(CreateCubeVertexCol(new float[] {color.r, color.g, color.b}));
						} catch(NullPointerException e) {
							VertexPositionData.put(new float[] {});
							VertexColorData.put(CreateCubeVertexCol(new float[] {}));
						}
					}
				}
			}
			
			VertexColorData.flip();
			VertexPositionData.flip();
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertexHandle);
			GL15.glBufferData(GL15.GL_ARRAY_BUFFER, VertexPositionData, GL15.GL_STATIC_DRAW);
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOColorHandle);
			GL15.glBufferData(GL15.GL_ARRAY_BUFFER, VertexColorData, GL15.GL_STATIC_DRAW);
			GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		}
		
		this.draw = draw;
	}
}
```

Ich hoffe ihr könnt mir weiterhelfen 

MFG faustdonner


----------



## Guest2 (28. Sep 2012)

Moin,

hier ist ein Beispiel wie eine Textur geladen werden kann und wie der zugehörige IBO/VBO aussehen sollte (für die von Dir verwendete fixed function pipeline).

(Quellcode ist dort verlinkt.)

Viele Grüße,
Fancy


----------



## faustdonner (29. Sep 2012)

Vielen Dank Fancy aber nun habe ich irgendwie ein neues Problem . Also ich versuche die Textur von einem Inventar Bild zu zeichnen also 2D. Ich habe es schon mit und ohne Ortho-Modus versucht. Es gibt keinen Fehler aber er zeigt auch nix an. (Aus dem Tutorial habe ich statt GL_TRIANGLE, GL_QUADS genommen.) Also so initialisiere ich mein OpenGL:


```
GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glShadeModel(GL11.GL_SMOOTH);
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		GL11.glClearDepth(1.0);
		GL11.glEnable(GL11.GL_DEPTH_TEST);
		GL11.glDepthFunc(GL11.GL_LEQUAL);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

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

		GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 700.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);

		GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
```

und das ist meine Inventory-Klasse:


```
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.glTexCoordPointer;
import static org.lwjgl.opengl.GL11.glVertexPointer;

import java.util.ArrayList;

public class InventoryPlayer extends Inventory {
	public ArrayList<ItemStack> items = new ArrayList<ItemStack>();
	
	private int bagNum = 1;
	
	private int slotNum = bagNum * 20;
	
	private static final int FLOAT_SIZE = Float.SIZE / Byte.SIZE;
	
	// Zeichenveriablen
	private static final int[] RectangleIBO = {
			0,1,2,3
	};
	
	private static final float[] RectangleVBO = new float[] {
        610, 100,
        790, 100,
        790, 370,
        610, 370
    };
	
	IBO ibo = new IBO(RectangleIBO);
	VBO vbo = new VBO(RectangleVBO);
	
	public InventoryPlayer() {
		vbo.glInit();
		ibo.glInit();
	}
	
	public void paint() {
		if(World.player.isInventoryEnabled) {
			Textures.inventory.glBind();
			
			vbo.glBind();
			glVertexPointer(3, GL_FLOAT, 5 * FLOAT_SIZE, 0 * FLOAT_SIZE);
	        glTexCoordPointer(2, GL_FLOAT, 5 * FLOAT_SIZE, 3 * FLOAT_SIZE);
			
			ibo.glDraw();
		}
	}
	
	public boolean addBag() {
		if(bagNum == 5) return false;
		
		bagNum++;
		slotNum = bagNum * 20;
		return true;
	}
	
	public boolean removeBag(boolean clearInventory) {
		if(bagNum == 1) return false;
		
		if(clearInventory) {
			// Slots beim entfernen leeren
			for(int i = (bagNum-1) * 20; i < (bagNum) * 20; i++) {
				
			}
		}
		else {
			World.player.dropItems(this, (bagNum-1) * 20, (bagNum) * 20);
		}
		
		bagNum--;
		slotNum = bagNum * 20;
		return true;
	}
	
	public int addItemStack(ItemStack itemStack) {
		if(!this.hasNotFullItemStack(itemStack.item)) {
			if(!this.hasFreeItemSlot()) return -1;
			items.add(itemStack);
			return 0;
		}
		else {
			for(int i = 0; i < slotNum; i++) {
				if(items.get(i).item.equals(itemStack.item)) {
					ItemStack rest = new ItemStack(itemStack.item, items.get(i).increaseAmount(itemStack.amount));
					if(items.get(i).isFull() && rest.amount > 0 && this.hasFreeItemSlot()) {
						this.addItemStack(rest);
						return 0;
					}
					return rest.amount;
				}
			}
			return -1;
		}
	}

	private boolean hasFreeItemSlot() {
		for(int i = 0; i < slotNum; i++) {
			if(items.get(i).item == null) return true;
		}
		return false;
	}

	public boolean hasItem(Item item) {
		for(int i = 0; i < slotNum; i++) {
			if(items.get(i).item.equals(item)) return true;
		}
		return false;
	}

	public boolean hasNotFullItemStack(Item item) {
		for(int i = 0; i < slotNum; i++) {
			if(items.get(i).item.equals(item) && items.get(i).amount < maxStackSize) return true;
		}
		return false;
	}
}
```

Er führt die paint() Methode auch 100% aus. Liegt es an diesen glVertexPointer und dem anderen Pointer? Bitte hilf mir :/.


----------



## Guest2 (30. Sep 2012)

Ja, die Parameter der beiden Pointer-Methoden ändern sich, da Dein VBO anders aussieht. Allerdings scheinen mir die Werte in Deinem RectangleVBO auch nicht vollständig zu sein. Darein müssen die Vertexkoordinaten und die Texturkoordinaten. Im original Beispiel sind das die x, y, z, s, t Werte (für jeweils 1 Eckpunkt (Vertex)). 

x,y,z sind die Koordinaten des Vertex
s,t sind die Texturkoordinaten (0/0 = links/unten; 1/1 = rechts/oben)

Da fehlt in Deinem RectangleVBO also was.

Bei den beiden Pointer-Methoden gibt der 1. Parameter jeweils an, wie viele Werte der Parameter hat (x,y,z = 3; x,y = 2; s,t = 2). Der 3. Parameter wie groß der Datensatz eines Vertex ist (x,y,z,s,t = 5 *  FLOAT_SIZE; x,y,s,t = 4 * FLOAT_SIZE). Und der letzte Parameter gibt an wo der aktuelle Parameter liegt (bei Vertexkoordinaten = 0; bei Texturkoordinaten die Größe der Vertexkoordinaten (die Texturkoordinaten liegen halt hinten den Vertexkoordinaten)).

Wenn Du dein  RectangleVBO auf x,y,z,s,t anpasst stimmen die Pointer-Methoden so. Änderst Du sie auf x,y,s,t dann sollte das dieses hier sein:


```
glVertexPointer(2, GL_FLOAT, 4 * FLOAT_SIZE, 0 * FLOAT_SIZE);
glTexCoordPointer(2, GL_FLOAT, 4 * FLOAT_SIZE, 2 * FLOAT_SIZE);
```

Viele Grüße,
Fancy


----------



## faustdonner (30. Sep 2012)

Vielen Dank... Ich kann net mal den Danke-Button drücken XD

Aber trotzdem... Ich brauche mal ein Beispiel. Ich möchte Texturen 3D aber auch 2D darstellen! wie?


----------



## Guest2 (1. Okt 2012)

Nuja, ohne zu wissen, wo genau Du Probleme hast, ist das etwas schwierig. Was genau fehlt Dir den an dem oben verlinkten Beispiel?

Ein anderes Beispiel für gültige Werte wäre (basierend of dem obrigen Beispiel):


```
private static final int[]   QUAD_IBO   = new int[] {

        0, 1, 2, 3

    };


    // x, y, s, t
    private static final float[] QUAD_VBO   = new float[] {

        -0.5f, -0.5f, 0.0f, 0.0f,
        +0.5f, -0.5f, 1.0f, 0.0f,
        +0.5f, +0.5f, 1.0f, 1.0f,
        -0.5f, +0.5f, 0.0f, 1.0f,

    };

[..]

    glOrtho(-1, +1, -1, +1, 0, 1);

[..]

    glVertexPointer(2, GL_FLOAT, 4 * FLOAT_SIZE, 0 * FLOAT_SIZE);
    glTexCoordPointer(2, GL_FLOAT, 4 * FLOAT_SIZE, 2 * FLOAT_SIZE);

[..]

    glDrawElements(GL_QUADS, buffer.capacity(), GL_UNSIGNED_INT, 0);
```

Viele Grüße,
Fancy


----------

