The Original Problem:
I'm making a 2d game in OpenGL that uses tiles to draw a map. At the moment, each tile is drawn individually on a quad. The code for the tile rendering is:
#Override
public void render() {
if (parentTileSet.getTexture() == null)
return;
float alpha = parentLayer.getOpacity();
if (alpha < 0)
alpha = 0;
glColor4f(1.0f, 1.0f, 1.0f, alpha); //Set alpha to parent layer's alpha
parentTileSet.getTexture().bind(); //Bind texture
float bx = parentTileSet.getTileWidth() / 2; //Half the width
float by = parentTileSet.getTileHeight() / 2; //Half the height
float x = getX(), y = getY();
float z = 0f;
glPushMatrix(); //Save the current view matrix
glTranslatef(x, y, 0f); //Translate to the tile's position
glRotatef(rotate, 0f, 0f, 1f); //Rotate the tile if it has a rotation
if ((flipType & 1) > 0) //Are we flipping horizontally?
glScalef(-1f, 1f, 1f);
if ((flipType & 2) > 0) //Are we flipping vertically?
glScalef(1f, -1f, 1f);
//Draw the tile
glBegin(GL_QUADS);
glTexCoord2f(tex_cords.bottom_left.x, tex_cords.bottom_left.y); //bottom left
glVertex3f(-bx, -by, z);
glTexCoord2f(tex_cords.bottom_right.x, tex_cords.bottom_right.y); //bottom right
glVertex3f(bx, -by, z);
glTexCoord2f(tex_cords.top_right.x, tex_cords.top_right.y); //top right
glVertex3f(bx, by, z);
glTexCoord2f(tex_cords.top_left.x, tex_cords.top_left.y); //top left
glVertex3f(-bx, by, z);
glEnd();
glPopMatrix(); //Reload the view matrix to original state
parentTileSet.getTexture().unbind(); //Unbind the texture
}
And the result looks like the following:
http://i.stack.imgur.com/maIXk.jpg
Which is good. However, the FPS could be better, and this especially becomes an issue when the maps become more detailed. (The FPS drops to about 20).
My Ideal Solution:
Since the tiles will never change position or animate, if I render all the tiles to a texture once, and just draw that texture, then performance will increase!
So, I made a framebuffer using the following class:
public class Framebuffer implements Drawable {
private int fID, tID;
protected int width, height;
public Framebuffer(int width, int height) {
this.width = width;
this.height = height;
}
public void generate() {
fID = glGenFramebuffers();
tID = glGenTextures();
glBindFramebuffer(GL_FRAMEBUFFER, fID);
glBindTexture(GL_TEXTURE_2D, tID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, (ByteBuffer) null);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tID, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
throw new RuntimeException("Framebuffer configuration error.");
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
public void begin() {
glPushMatrix();
glPushAttrib(GL_VIEWPORT_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, fID);
glViewport(0, 0, width, height);
}
public void end() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glPopMatrix();
glPopAttrib();
}
#Override
public void render() {
float x = 0f;
float y = 0f;
float z = 0f;
float bx = (this.width)/2f;
float by = (this.height)/2f;
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, tID);
glBegin(GL_QUADS);
glTexCoord2f(0f, 0f); //bottom left
glVertex3f(x - bx, y - by, z);
glTexCoord2f(1f, 0f); //bottom right
glVertex3f(x + bx, y - by, z);
glTexCoord2f(1f, 1f); //top right
glVertex3f(x + bx, y + by, z);
glTexCoord2f(0f, 1f); //top left
glVertex3f(x - bx, y + by, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
}
And then use the following code to generate the framebuffer, and render the tiles to the texture:
System.out.println("Attempting to generate frame buffer..");
try {
Framebuffer frame = new Framebuffer(tiledData.getPixelWidth(), tiledData.getPixelHeight());
frame.generate();
frame.begin();
glScalef(0.5f, 0.5f, 1f); //The game is scaled up by 2, so I'm just unscalling here.
Iterator<Drawable> drawableIterator = getSortedDrawables();
while (drawableIterator.hasNext()) {
Drawable d = drawableIterator.next();
if (d instanceof TileObject) {
TileObject t = (TileObject)d;
if (t.isGroundLayer() && !t.isParallaxLayer() && !t.isAnimated()) {
t.render(); //This render method is the one from above
drawableIterator.remove();
}
}
}
frame.end();
System.out.println("Success!");
addDrawable(frame);
} catch (RuntimeException e) {
System.out.println("Framebuffers are not supported!");
}
However, the output is this:
http://puu.sh/8Eemy.jpg
Which is not what I expected to happen. I tried scaling it, moving it, and all sorts of things but I can never get it exactly right.
My Question
What am I doing wrong? Is there another way to go about this? Am I missing something?
UPDATE
Thanks to the comments, I've got it to render correctly!
I changed the framebuffer class to be the following:
private int fID, tID;
protected int width, height;
public Framebuffer(int width, int height) {
this.width = width;
this.height = height;
}
public void generate() {
fID = glGenFramebuffers();
tID = glGenTextures();
glBindFramebuffer(GL_FRAMEBUFFER, fID);
glBindTexture(GL_TEXTURE_2D, tID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, (ByteBuffer) null);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tID, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
throw new RuntimeException("Framebuffer configuration error.");
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
public void begin() {
glBindFramebuffer(GL_FRAMEBUFFER, fID);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, width, 0, height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
public void end() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
#Override
public void render() {
float x = this.width / 2f;
float y = this.height / 2f;
float z = 0f;
float bx = (this.width)/2f;
float by = (this.height)/2f;
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, tID);
glBegin(GL_QUADS);
glTexCoord2f(0f, 0f); //bottom left
glVertex3f(x - bx, y - by, z);
glTexCoord2f(1f, 0f); //bottom right
glVertex3f(x + bx, y - by, z);
glTexCoord2f(1f, 1f); //top right
glVertex3f(x + bx, y + by, z);
glTexCoord2f(0f, 1f); //top left
glVertex3f(x - bx, y + by, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
}
The points of interest here is the begin() and end() method, where I setup a new projection matrix and save the old one, then restore it in the end() method.
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);
// [...]
}
Can someone help to make a static analogue clock in OpenGL 2.0 using Java? I used Bresenham Circle to draw a circle for the clock but is there any other way to draw a circle here? Then I drew an hour, minute, and second hand but I got an error in the render part while drawing the numbers. Can someone help me here with how to fix this? The code which I tried is following:
public class MyClock implements GLEventListener {
private int windowWidth = 1000;
private int windowHeight = 900;
public void display(GLAutoDrawable drawable) {
render(drawable);
}
//render
private void render(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glPointSize(5.0f);
//drawing circle
bresenhamCircle(new Point(100,100), 200, new Color(1, 0, 1), gl);
double x, y, d, delta_SE, delta_E;
x = 0;
double r = 200;
y = r;
d = 5-4*r;
setPixel(x ,y, gl);
setPixel(-x,y, gl);
setPixel(x,-y, gl);
setPixel(-x,-y, gl);
setPixel(y,x, gl);
setPixel(-y,x, gl);
setPixel(y,-x, gl);
setPixel(-y,-x, gl);
while (y>x) {
if (d >= 0) {
delta_SE = 4*(2*(x-y)+5);
d+=delta_SE; x++; y--;
}
else {
delta_E = 4*(2*x+3);
d+=delta_E; x++;
}
setPixel(x,y, gl);
setPixel(-x,y, gl);
setPixel(x,-y, gl);
setPixel(-x,-y, gl);
setPixel(y,x, gl);
setPixel(-y,x, gl);
setPixel(y,-x, gl);
setPixel(-y,-x, gl);
}
//hour hand
gl.glColor3d(0, 0, 1);
gl.glBegin(GL2.GL_LINES);
gl.glVertex2d(0, 00);
gl.glVertex2d(70, 70);
gl.glEnd();
//minute hand
gl.glColor3d(0, 0, 1);
gl.glBegin(GL2.GL_LINES);
gl.glVertex2d(0, 00);
gl.glVertex2d(150, 20);
gl.glEnd();
//seconds hand
gl.glColor3d(1, 0, 0);
gl.glBegin(GL2.GL_LINES);
gl.glVertex2d(0, 00);
gl.glVertex2d(120, -120);
gl.glEnd();
//drawing numbers
int AngleX, AngleY;
int radius;
double line;
for (int i=1;i<=12;i++) {
line = i/12*Math.PI*2;
radius=170;
AngleX=(int)((0)+(Math.sin(line)*radius));
AngleY=(int)((0)+(Math.cos(line)*radius));
gl.glColor3d(1, 1, 1);
String a= Integer.toString(i);
g.drawString(a,AngleX,AngleY);
}
}
//Bresenham Circle method
public void bresenhamCircle(Point center, double radius, Color color, GL2 gl) {
gl.glColor3d(0, 0, 1);
gl.glBegin(GL2.GL_POINTS);
gl.glVertex2d(00,200);
gl.glEnd();
}
private void setPixel(double x, double y,GL2 gl) {
gl.glColor3d(0.0, 1.0, 0.0);
gl.glBegin(GL2.GL_POINTS);
gl.glVertex2d(0,0);
gl.glVertex2d( x, y);
gl.glEnd();
}
public void dispose(GLAutoDrawable drawable) {
}
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glViewport(0, 0, windowWidth, windowHeight);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, 0, 1);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
gl.glEnable(GL2.GL_LINE_SMOOTH);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
GL2 gl = drawable.getGL().getGL2();
windowWidth = w;
windowHeight = h;
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-w / 2, w / 2, -h / 2, h / 2, 0, 1);
}
}
As far as I know, there isn't a simple method built into OpenGL ES 2.0 that draws text. That means you have to either find an open-source library that you can use, or you can create your own way of rendering text. This post outlines nicely the different ways that you can render text with OpenGL.
The best way I have found based on my research and which is also stated in the above link, is to render text through images. This tutorial shows how to create a basic text engine and is what I used to get an idea of how to render custom text. The idea is to take a texture atlas (a texture atlas is one image that contains all the letters, numbers, characters that you want to be able to render) and based on what string you want to draw, the engine will crop out the necessary letters, numbers, or characters from the atlas needed for your string and combine them into a square polygon that you can then render to the screen. The tutorial that I linked is a basic text engine, but once you understand how it works, you can then modify and improve it to your needs.
In a middle of developing my game I created a function to rotate a 2d triangle.
But the problem is that when I rotate an object, the rotation is very weird.
If the object's center is at the origin (the (0,0) point) of the axis then it rotates fine, but if I move the object then it rotates in a very weird way that it shouldn't be rotating in.
as you can see here is the code of the function.
public void rotate(float angle){
float x1 = x, y1 = y;
float x2 = x + width, y2 = y;
float x3 = x + width, y3 = y + height;
float x4 = x, y4 = y + height;
// Vertices in object space:
float[] vector1 = {x1, y1, 0f, 1f};
float[] vector2 = {x2, y2, 0f, 1f};
float[] vector3 = {x3, y3, 0f, 1f};
float[] vector4 = {x4, y4, 0f, 1f};
// Vertices in world space:
float[] vector1r = new float[4];
float[] vector2r = new float[4];
float[] vector3r = new float[4];
float[] vector4r = new float[4];
// Calculate the vertices in world space:
Matrix.multiplyMV(vector1r, 0, modelMatrix, 0, vector1, 0);
Matrix.multiplyMV(vector2r, 0, modelMatrix, 0, vector2, 0);
Matrix.multiplyMV(vector3r, 0, modelMatrix, 0, vector3, 0);
Matrix.multiplyMV(vector4r, 0, modelMatrix, 0, vector4, 0);
// Get the middle of the rectangle:
float[] vecMid = {(vector1r[0] + vector3r[0]) / 2,
(vector1r[1] + vector3r[1]) / 2, 0f, 1f};
move(vecMid[0], vecMid[1]); // Move to the origin
Matrix.rotateM(modelMatrix, 0, angle, 0, 0, 1f); // Rotate the object
move(-vecMid[0], -vecMid[1]); // Move back to place
if(LoggerConfig.ON)
Log.d("Middle Vertex", vecMid[0] + ", " + vecMid[1]);
}
The move method:
public void move(float x, float y){
Matrix.translateM(modelMatrix, 0, x, y, 0);
}
Can someone tell me what the problem is?
EDIT: I did some modifications to the code and added the move method.
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'm using LWJGL to create sort of a Minecraft Clone.
The problem is that i only get about 20 FPS. (with about 32 blocks in each direction)
Also when i change the chunk the view freezes for some milliseconds.
I'm loading the textures with Slick. To render the blocks I use VBOs for textures and vertices (no VAOs or Shaders or normals). Each block consists of 6 quads which consist out of 2 triangles. Faces between blocks aren't rendered. Every frame the rendering thread checks for all 32 * 32 chunks if they are loaded into a buffer and if they should be loaded (depending on player position). If they are needed the vbos are created and the handles are saved to a list. If the chunks are too far away, the buffers get deleted. While rendering, all vbos currently in the graphics cards ram (handles saved in list) are drawn.
How can i speed rendering up? Should i have the buffers in "loaded" all the time and draw only the objects needed? Can normals or VAOs or shaders help me get a drastic improvement? Still if i get the frame rate higher there will be mor blocks than just a plate and i'm planning to import .obj.
Minecraft renders in i think DisplayLists. Would that be a solution? Create a display list for every chunk or block and recompile them if block or chunk changes?
Edit: I measured with VisualVM that the most time consuming method is glDrawArrays().
Some source code:
Rendering:
public static void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for(VBO vbo : vbos)
{
//disable texture smoothing
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, vbo.texture);
glBindBuffer(GL_ARRAY_BUFFER, vbo.vertex_handle);
glVertexPointer(vbo.vertex_size, GL_FLOAT, 0, 0l);
glBindBuffer(GL_ARRAY_BUFFER, vbo.texture_handle);
glTexCoordPointer(vbo.texture_size, GL_FLOAT, 0, 0l);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, vbo.vertices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
Chunk loading detection:
int chunkX = (int)(camera.getX() * (-1) / GameData.CHUNK_SIZE);
int chunkZ = (int)(camera.getZ() * (-1) / GameData.CHUNK_SIZE);
for(int cx = 0;cx < GameData.NUMBER_OF_CHUNKS;cx++)
{
for(int cz = 0;cz < GameData.NUMBER_OF_CHUNKS;cz++)
{
boolean shouldBeLoaded = (Math.abs(chunkX - cx) <= 2 && Math.abs(chunkZ - cz) <= 2);
if(GameData.chunks[cx][cz] != shouldBeLoaded)
{
if(shouldBeLoaded)
Util.loadChunk(cx, cz);//loads every block in the chunk
else
Util.unloadChunk(cx, cz);
}
}
}
Block loading:
public void load()
{
try{
if(GameData.map[x][y+1][z] == null || GameData.map[x][y+1][z].id == 2)
top = Util.createQuad(x, y+1, z, 1, id);
}catch(IndexOutOfBoundsException e){};
try{
if(GameData.map[x][y-1][z] == null || GameData.map[x][y-1][z].id == 2)
bot = Util.createQuad(x, y, z, 1, id);
}catch(IndexOutOfBoundsException e){};
try{
if(GameData.map[x-1][y][z] == null || GameData.map[x-1][y][z].id == 2)
left = Util.createQuad(x, y, z, 0, id);
}catch(IndexOutOfBoundsException e){};
try{
if(GameData.map[x+1][y][z] == null || GameData.map[x+1][y][z].id == 2)
right = Util.createQuad(x+1, y, z, 0, id);
}catch(IndexOutOfBoundsException e){};
try{
if(GameData.map[x][y][z-1] == null || GameData.map[x][y][z-1].id == 2)
front = Util.createQuad(x, y, z, 2, id);
}catch(IndexOutOfBoundsException e){};
try{
if(GameData.map[x][y][z+1] == null || GameData.map[x][y][z+1].id == 2)
back = Util.createQuad(x, y, z+1, 2, id);
}catch(IndexOutOfBoundsException e){};
}
Util.createQuad()
public static VBO createQuad(float x, float y, float z, int axis, int id)
{
boolean xA = axis == 0;
boolean yA = axis == 1;//senkrecht
boolean zA = axis == 2;
FloatBuffer vertex_data = BufferUtils.createFloatBuffer(6 * 3);
if(xA)
{
vertex_data.put(new float[] { x, y, z, });
vertex_data.put(new float[] { x, y, z+1, });
vertex_data.put(new float[] { x, y+1, z+1, });
vertex_data.put(new float[] { x, y, z, });
vertex_data.put(new float[] { x, y+1, z, });
vertex_data.put(new float[] { x, y+1, z+1, });
}
if(yA)
{
vertex_data.put(new float[] { x, y, z, });
vertex_data.put(new float[] { x, y, z+1, });
vertex_data.put(new float[] { x+1, y, z+1, });
vertex_data.put(new float[] { x, y, z, });
vertex_data.put(new float[] { x+1, y, z, });
vertex_data.put(new float[] { x+1, y, z+1, });
}
if(zA)
{
vertex_data.put(new float[] { x, y, z, });
vertex_data.put(new float[] { x+1, y, z, });
vertex_data.put(new float[] { x+1, y+1, z, });
vertex_data.put(new float[] { x, y, z, });
vertex_data.put(new float[] { x, y+1, z, });
vertex_data.put(new float[] { x+1, y+1, z, });
}
FloatBuffer texture_data = BufferUtils.createFloatBuffer(6 * 2);
texture_data.put(new float[] { 0f, 0f, });
texture_data.put(new float[] { 1f, 0f, });
texture_data.put(new float[] { 1f, 1f, });
texture_data.put(new float[] { 0f, 0f, });
texture_data.put(new float[] { 0f, 1f, });
texture_data.put(new float[] { 1f, 1f, });
vertex_data.flip();
texture_data.flip();
int vbo_vertex_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int vbo_texture_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_texture_handle);
glBufferData(GL_ARRAY_BUFFER, texture_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
VBO vbo = new VBO(vbo_vertex_handle, vbo_texture_handle, renderEngine.textures.get(id), 6, 3, 2);
if(id == 2)//transparent
renderEngine.vbos.add(vbo);
else
renderEngine.vbos.add(0, vbo);;
return vbo;
}
I am currently using display lists because I'm still new to lwjgl and found VBO's pretty confusing, What I do is only check if the player moved 16 blocks or more, or removed/placed a block And that's when I update my lists, Otherwise I don't update the lists, You should also stop rendering any faces that you cannot see, So while checking for which faces to draw, You should also check if they are not in your view range, Here's an example of what I do; This example checks if I should render the top face of a certain block: if(PlayerY < BlockY) { then return false; }, This way you don't need to render something that you probably can't see.
Using display lists I get around 200 - 300 FPS for a view range of 48*48, At 128 you would get around 20 - 100 FPS.
EDIT:
You should also start using a texture atlas if you're not already, That reduces the bind() calls, Which makes it SO MUCH faster.
So good luck, And hope I helped :)