AAAAAAH! I spent hours looking up tutorials trying to understand vbos, ibos, and textures, and I can’t even display a simple textured vbo! I DID manage to get rendering working in immediate mode, but only because it is infinitely more simplistic.
I should probably tell you what I am trying to make. I am making a class called TexturedMesh that will store a VBO for coordinates, another VBO for texture coordinates, and an IBO for vertex data.
Here is my class:
package render;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import core.Disposable;
import core.Renderable;
import core.Texture;
/**
* 2-Dimensional Mesh object that can be rendered. Uses VBOs to render data.
* @author William Andrew Cahill
*/
public class TexturedMesh2D implements Renderable, Disposable
{
// Buffered objects
private Texture tex; // Texture to use
private int vbo; // Verticies to draw
private int ibo; // Index buffer to use
private int tvbo; // Texture vbo to use
// Vertex buffers
private FloatBuffer vertices, texCoords; // Vertex and Texture coordinates
private IntBuffer indices; // Indices
/**
* Constructs the mesh
* @param vertices List of vertices to connect to
* @param texCoords Texture coordinates for mapping
* @param indices Order in which to connect vertices
* @param tex Texture to map to Mesh2D
*/
public TexturedMesh2D(FloatBuffer vertices, FloatBuffer texCoords, IntBuffer indices, Texture tex)
{
create(vertices, texCoords, indices, tex);
}
/**
* Constructs a TexturedMesh with the mesh simply wrapping the entire texture.
* @param tex Texture to use
*/
public TexturedMesh2D(Texture tex)
{
// Creates vertices
FloatBuffer vertices = BufferUtils.createFloatBuffer(8).put(new float[]
{
0, 0,
tex.getWidth(), 0,
tex.getWidth(), tex.getHeight(),
0, tex.getHeight()
});
// Creates texture coordinates
FloatBuffer texCoords = BufferUtils.createFloatBuffer(8).put(new float[]
{
0, 0,
1, 0,
1, 1,
0, 1
});
// Creates indices
IntBuffer indices = BufferUtils.createIntBuffer(4).put(new int[]{0, 1, 2, 3});
// Creates mesh
create(vertices, texCoords, indices, tex);
}
/**
* Creates the mesh
*/
private void create(FloatBuffer vertices, FloatBuffer texCoords, IntBuffer indices, Texture tex)
{
// Checks arguments
if(vertices == null || texCoords == null || indices == null || tex == null)
throw new IllegalArgumentException("Arguments cannot be null");
// Stores arguments
this.vertices = vertices;
this.texCoords = texCoords;
this.indices = indices;
this.tex = tex;
// Creates coordinate vbo
vbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// Creates texture vbo
tvbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, tvbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, texCoords, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// Creates ibo
ibo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
}
/**
* Sets up object pointers before using them
*/
private void setupPointers()
{
// Points to vertices
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
// Points to texture vertices
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, tvbo);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
// Points to indices
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo);
}
@Override
public void render()
{
render(0, 0);
}
@Override
public void render(float x, float y)
{
// Translates
GL11.glTranslatef(x, y, 0);
// Sets up buffer pointers
setupPointers();
// Binds texture
tex.bind();
// Draws elements
GL11.glDrawElements(GL11.GL_TRIANGLE_STRIP, indices.capacity(), GL11.GL_UNSIGNED_INT, 0);
// Disables states
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
// Translates back
GL11.glTranslatef(-x, -y, 0);
}
@Override
public boolean isDisposed()
{
// Later, later...
return false;
}
@Override
public void dispose()
{
// Later, later...
}
/**
* Disposes of the TextureMesh2D's underlying resources
* @param disposeChildren Flag that determines if underlying resources besides the Texture coordinates
* should be disposed of
*/
public void dispose(boolean disposeChildren)
{
// I'll get to this later...
}
}
I had to implement a lot of code before I could even think of testing it, so I’m not surprised that nothing shows up on my screen. I don’t even know where to look in order start fixing it, though. Help?
Edit: When testing, I use the constructor in which only the Texture is supplied. I made a Texture class from scratch, and there haven’t been any problems with it yet. Oh, and a shout out to theagentd for helping in this post regarding binding textures: http://www.java-gaming.org/index.php?topic=25516.0 Helped me out a lot.
Edit2: When I call GL11.glGetError(), I get an error code of 1285 which means out of memory. Hrm… It happens after GL11.glDrawElements(GL11.GL_TRIANGLE_STRIP, indices.capacity(), GL11.GL_UNSIGNED_INT, 0);