Hallo,
ich versuche momentan ein Voxel-Game zu erstellen. Dies funktioniert ganz gut. Es soll ähnlich wie Minecraft funktionieren.
Die Chunks werden durch ein 16x16x16 Byte-Array beschrieben (als Klasse definiert).
Blöcke zeichne ich mit GL_QUADS, bei denen die Texturkoordinaten gleich mit übergeben werden. Bei der Initialisierung von OpenGL (s.u.) werden die benötigten Texturen geladen und in der Methode drawBlock mit glBindTexture(GL_TEXTURE_2D,textureID[?]) verwendet.
Die Blöcke werden aneinander gerendert. Wird ein Block von 6 Blöcken umschlossen (es also unmöglich ist, den Block zu sehen), so soll er nicht gerendert werden (s. Funktion unten).
Problem:Beim Bewegen und Rotieren in der Welt, flackern alle Texturen. Aus einem Steinblock wird manchmal ein Erdblock und umgekehrt (s. Bilder weiter unten).
Aktuell habe ich als Test nur Erde und Stein als Textur mit eingebunden.
Frage: Wo ist das Problem bzw. was muss ich bei OpenGL konfigurieren, damit die Texturen richtig dargestellt werden?
Es gilt:
init-Methode, die OpenGL initialisiert:
loadTexture-Methode, die Texturen lädt und eine ID zuweist (vllt. liegt es an evtl. falsch eingestellten Mipmap-Werten?):
draw-Methode, die Blöcke in die Szene zeichnet:
drawChunk-Methode, die einen Chunk in die Szene zeichnet:
checkBlock-Methode, die überprüft, ob ein Block gezeichnet werden muss:
drawBlock, die einen Block in die Welt zeichnet (glBindTexture evtl. falsch?):
Zwei Bilder noch: Das zweite Bild ist leicht nach links rotiert (man sieht, dass die Erdtexturen durch Steintexturen ersetzt wurden (es flackert)).
Danke im Voraus!
Mit freundlichen Grüßen
Seikuassi
ich versuche momentan ein Voxel-Game zu erstellen. Dies funktioniert ganz gut. Es soll ähnlich wie Minecraft funktionieren.
Die Chunks werden durch ein 16x16x16 Byte-Array beschrieben (als Klasse definiert).
Blöcke zeichne ich mit GL_QUADS, bei denen die Texturkoordinaten gleich mit übergeben werden. Bei der Initialisierung von OpenGL (s.u.) werden die benötigten Texturen geladen und in der Methode drawBlock mit glBindTexture(GL_TEXTURE_2D,textureID[?]) verwendet.
Die Blöcke werden aneinander gerendert. Wird ein Block von 6 Blöcken umschlossen (es also unmöglich ist, den Block zu sehen), so soll er nicht gerendert werden (s. Funktion unten).
Problem:Beim Bewegen und Rotieren in der Welt, flackern alle Texturen. Aus einem Steinblock wird manchmal ein Erdblock und umgekehrt (s. Bilder weiter unten).
Aktuell habe ich als Test nur Erde und Stein als Textur mit eingebunden.
Frage: Wo ist das Problem bzw. was muss ich bei OpenGL konfigurieren, damit die Texturen richtig dargestellt werden?
Es gilt:
ID 0=Luft (nichts zeichnen)
ID 1=Erdblock
ID 2=Steinblock
init-Methode, die OpenGL initialisiert:
Java:
public static void init()
throws FileNotFoundException,IOException{
glEnable(GL_CULL_FACE); // Backface Culling aktivieren
glEnable(GL_DEPTH_TEST); // Tiefenpuffer aktivieren
glEnable(GL_NORMALIZE); // automatisches Normalisieren aktivieren
glEnable(GL_TEXTURE_2D); // Texturenrendering aktivieren
glClearColor(0.54f,0.89f,1f,1f); // Hintergrundfarbe (hellblau) festlegen
{ // Nebel konfigurieren
FloatBuffer buf=BufferUtils.createFloatBuffer(4);
buf.put(new float[]{0.9f,0.9f,0.9f,1f}).flip();
glFogi(GL_FOG_MODE,GL_LINEAR); // linearen Modus festlegen
glFog(GL_FOG_COLOR,buf); // Farbe des Nebels festlegen
glFogf(GL_FOG_START,1f); // Entfernung festlegen, in der Nebel sichtbar ist
glFogf(GL_FOG_END,5f); // Entfernung festlegen, in der der Nebel und die Sichtweite zu Ende ist
glHint(GL_FOG_HINT,GL_FASTEST); // Berechnung des Nebels auf Vertexbasis
glEnable(GL_FOG); // Nebel aktivieren
}
{ // Texturen laden
textureID[0]=loadTexture("/resources/textures/dirt.png");
textureID[1]=loadTexture("/resources/textures/stone.png");
}
return;
}
Java:
private static int loadTexture(String path)
throws FileNotFoundException,IOException{
ByteBuffer buffer;
BufferedImage img=classes.util.ResourceLoader.loadImage(path);
int[]pixels=new int[img.getWidth()*img.getHeight()];
int textureID;
img.getRGB(0,0,img.getWidth(),img.getHeight(),pixels,0,img.getWidth());
buffer=BufferUtils.createByteBuffer(img.getWidth()*img.getHeight()*4);
for(int pixel=0,y=0;y<img.getHeight();y++){
for(int x=0;x<img.getWidth();x++){
pixel=pixels[y*img.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();
textureID=glGenTextures();
glBindTexture(GL_TEXTURE_2D,textureID);
{ // Textureeinstellungen vornehmen
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,img.getWidth(),img.getHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,buffer);
glGenerateMipmap(GL_TEXTURE_2D);
return textureID;
}
Java:
public static void draw(float x,float y,float z,float roll,float yaw){
glMatrixMode(GL_MODELVIEW); // Modell-Matrix aktivieren
{
glLoadIdentity(); // Standard-Matrix laden
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glRotatef(-roll,1f,0f,0f); // X-Achse rotieren
glRotatef(yaw,0f,1f,0f); // Y-Achse rotieren
glTranslatef(-x,-y,z); // Position festlegen
for(int i=0;i<classes.Game.chunks.size();i++){ // alle Chunks zeichnen
ChunkDrawer.drawChunk(classes.Game.chunks.get(i));
}
}
return;
}
Java:
public static void drawChunk(Chunk c){
glPushMatrix(); // Matrix auf den Stack legen
glTranslatef((float)c.getXPos()*Chunk.X_size*BlockSize,(float)c.getYPos()*Chunk.Y_size*BlockSize,(float)c.getZPos()*Chunk.Z_size*BlockSize); // Chunk-Position festlegen
for(short x=0;x<Chunk.X_size;x++){
if(x!=0){
glTranslatef(BlockSize*2,0f,0f); // Position auf der X-Achse verschieben
}
for(short y=0;y<Chunk.Y_size;y++){
if(y!=0){
glTranslatef(0f,BlockSize*2,0f); // Position auf der Y-Achse verschieben
}
for(short z=0;z<Chunk.Z_size;z++){
if(z!=0){
glTranslatef(0f,0f,BlockSize*2); // Position auf Z-Achse verschieben
}
if(checkBlock(c,x,y,z)==true){ // wenn Block gezeichnet werden muss
drawBlock(c.getBlock(x,y,z),c.getBlockData(x,y,z)); // Block zeichnen
}
}
glTranslatef(0f,0f,(float)-(Chunk.Z_size-1)*BlockSize*2); // Position auf der Z-Achse zuruecksetzen
}
glTranslatef(0f,(float)-(Chunk.Y_size-1)*BlockSize*2,0f); // Position auf der Y-Achse zuruecksetzen
}
glPopMatrix(); // Matrix vom Stack nehmen
return;
}
Java:
private static boolean checkBlock(Chunk c,int x,int y,int z){
if(c.getBlock(x,y,z)==0){ // wenn der Block Luft ist
return false;
}else if(x>0&&x<Chunk.X_size-1&&y>0&&y<Chunk.Y_size-1&&z>0&&z<Chunk.Z_size-1){ // wenn sich Bloecke um den Block befinden koennten
if(c.getBlock(x-1,y,z)==0&&c.getBlock(x,y-1,z)==0&&c.getBlock(x,y,z-1)==0&&c.getBlock(x+1,y,z)==0&&c.getBlock(x,y+1,z)==0&&c.getBlock(x,y,z+1)==0){
return false;
}
}
return true;
}
Java:
private static void drawBlock(byte ID,byte data){
if(ID==1){ // wenn ein Erdblock gezeichnet werden soll
glBindTexture(GL_TEXTURE_2D,OpenGL.textureID[0]);
}else if(ID==2){ // wenn ein Steinblock gezeichnet werden soll
glBindTexture(GL_TEXTURE_2D,OpenGL.textureID[1]);
}
glBegin(GL_QUADS);
{ // Zeichnung starten
glColor3f(1f,1f,1f); // Farbe (weiss) festlegen
// vorne
glNormal3f(0f,0f,BlockSize);
glTexCoord2s((short)1,(short)1);
glVertex3f(BlockSize,BlockSize,BlockSize);
glTexCoord2s((short)0,(short)1);
glVertex3f(-BlockSize,BlockSize,BlockSize);
glTexCoord2s((short)0,(short)0);
glVertex3f(-BlockSize,-BlockSize,BlockSize);
glTexCoord2s((short)1,(short)0);
glVertex3f(BlockSize,-BlockSize,BlockSize);
// hinten
glNormal3f(0f,0f,-BlockSize);
glTexCoord2s((short)1,(short)1);
glVertex3f(-BlockSize,BlockSize,-BlockSize);
glTexCoord2s((short)0,(short)1);
glVertex3f(BlockSize,BlockSize,-BlockSize);
glTexCoord2s((short)0,(short)0);
glVertex3f(BlockSize,-BlockSize,-BlockSize);
glTexCoord2s((short)1,(short)0);
glVertex3f(-BlockSize,-BlockSize,-BlockSize);
// links
glNormal3f(-BlockSize,0f,0f);
glTexCoord2s((short)1,(short)1);
glVertex3f(-BlockSize,BlockSize,BlockSize);
glTexCoord2s((short)0,(short)1);
glVertex3f(-BlockSize,BlockSize,-BlockSize);
glTexCoord2s((short)0,(short)0);
glVertex3f(-BlockSize,-BlockSize,-BlockSize);
glTexCoord2s((short)1,(short)0);
glVertex3f(-BlockSize,-BlockSize,BlockSize);
// rechts
glNormal3f(BlockSize,0f,0f);
glTexCoord2s((short)1,(short)1);
glVertex3f(BlockSize,BlockSize,-BlockSize);
glTexCoord2s((short)0,(short)1);
glVertex3f(BlockSize,BlockSize,BlockSize);
glTexCoord2s((short)0,(short)0);
glVertex3f(BlockSize,-BlockSize,BlockSize);
glTexCoord2s((short)1,(short)0);
glVertex3f(BlockSize,-BlockSize,-BlockSize);
// oben
glNormal3f(0f,BlockSize,0f);
glTexCoord2s((short)1,(short)1);
glVertex3f(BlockSize,BlockSize,-BlockSize);
glTexCoord2s((short)0,(short)1);
glVertex3f(-BlockSize,BlockSize,-BlockSize);
glTexCoord2s((short)0,(short)0);
glVertex3f(-BlockSize,BlockSize,BlockSize);
glTexCoord2s((short)1,(short)0);
glVertex3f(BlockSize,BlockSize,BlockSize);
// unten
glNormal3f(0f,-BlockSize,0f);
glTexCoord2s((short)1,(short)1);
glVertex3f(BlockSize,-BlockSize,BlockSize);
glTexCoord2s((short)0,(short)1);
glVertex3f(-BlockSize,-BlockSize,BlockSize);
glTexCoord2s((short)0,(short)0);
glVertex3f(-BlockSize,-BlockSize,-BlockSize);
glTexCoord2s((short)1,(short)0);
glVertex3f(BlockSize,-BlockSize,-BlockSize);
}
glEnd();
return;
}
Danke im Voraus!
Mit freundlichen Grüßen
Seikuassi