LWJGL using multiple textures

You should be able to give an index and a count to your draw call (glDrawElements or whatever…). With that, you can draw parts of a buffer. Or just use separate buffers. GL_TEXTUREx doesn’t really matter here, because you’ll need the first stage (GL_TEXTURE0) only in this case. Just bind the first texture as you do now, draw your stuff, bind the others one, draw the rest.

Well… i dont know if im doing it right… Im trying to get glDrawElements to work but i dont understand what is the problem. And google doesent help here either.

This is the error message:
Exception in thread “main” org.lwjgl.opengl.OpenGLException: Cannot use offsets when Element Array Buffer Object is disabled
at org.lwjgl.opengl.GLChecks.ensureElementVBOenabled(GLChecks.java:105)
at org.lwjgl.opengl.GL11.glDrawElements(GL11.java:1117)
at test.OBJloader.Model.Render(Model.java:49)
at controller.Controller.(Controller.java:74)
at controller.Controller.main(Controller.java:110)

Everywhere it is said that glEnableClientState(GL_VERTEX_ARRAY); must be enabled. I have it enabled, but still doesent work.

public void Render(){
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_NORMAL_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		if(textured){
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		}
	
		glBindBuffer(GL_ARRAY_BUFFER, vboBach1ID);
		glVertexPointer(3, GL_FLOAT,44,0);
		glColorPointer(3, GL_FLOAT,44,12);		
		glNormalPointer(GL_FLOAT,44,24);
		
		if(textured){
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, faces.get(0).get(0).material.texture.getTextureID());
			
			glTexCoordPointer(2, GL_FLOAT, 44,36);
			glDrawElements(GL_TRIANGLES, koht.get(0), GL_UNSIGNED_INT, 0);
			
			glBindTexture(GL_TEXTURE_2D, faces.get(1).get(0).material.texture.getTextureID());
			glTexCoordPointer(2,GL_FLOAT, 44,36);
			glDrawElements(GL_TRIANGLES, koht.get(1) - koht.get(0), GL_UNSIGNED_INT, koht.get(0));
			
		}
		//glDrawArrays(GL_TRIANGLES, 0, koht.get(0));
		
		
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_NORMAL_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		if(textured){
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		}
	}

glDrawElements needs a vertex vbo and a index vbo (element array buffer).
glDrawArrays only needs a vertex vbo.
You can see the differences between this two methods and the way of using them on this pages :

Does gl_element_array_buffer have a pointer also like array_buffer has vertexpointer etc ?

and does the drawElements support interleaved buffer?

I get some stuff drawn when i use GL_UNSIGNED_BYTE, but it doesent draw the piece correctly, plus it laggs alot. So im still missing some stuff. in .OBJ file there are lines like f v1/t1/n1. So basicly i can use the v1, v2 and stuff as the indicies guide for the drawElements right?

And could someone explain me drawElemenst parameters in simple terms. first and third parameter i understand. First says what i want to draw and third says the data type, but what exactly are second and fourth parameter.

glDrawElements() works fine with interleaved data buffers. In fact better.

I’ve never seen a line like that in a wavefront (.obj) file. There are lines like “f 1/5/3 2/6/3 3/7/3” (meaning face vertex1=position 1, normal 5, texCoord 3 vertex2=position 2, normal 6, texCoord 3 etc.) and “v 18.2 19.8 0” (meaning position at x=18.2 y=19.8 z=0) and “vn 1 0 0” (meaning normal x = 1, y = 0, z = 0) and “vt 0.2 0.3” (meaning tex coord s = 0.2, t = 0.3) but I’ve never seen one like that.

So http://www.opengl.org/sdk/docs/man2/.

glDrawElements(mode, count, type, indices); In LWJGL indices can actually be a java.nio.Buffer (byte, short or int) or a long.

count: the number of indices you want to draw.

in the buffer variety, indices: the Buffer containing the indices you want to be drawn. In this version OpenGL draws count indices from the start of the buffer.

in the long variety, indices: the byte offset into the IBO from which you want to start reading indices. Example if you wanted to draw the final 3 indices in an IBO containing 6 integers, this would be (3 * 4) since you want to go 3 indices in and there are 4 bytes in an integer.

Well your half right about the .obj wavefront. f 1/4/5 the format is vertex/texture/normal. The coordinate system is kinda weird. While x and z coordinates are -1 to 1 the y coordinates are 0 to 4.

My interelaved buffer is in format v1x,v1y,v1z,c1r,c1g,c1b,n1x,n1y,n1z,t1x,t1t,v2x,v2y,v2z…
I have the pointers set for vertices, colors, textures, normals. But cant i use the .obj f line to get the indicies guide for drawelements? Since i need to know how to connect vertices and well the face vector basiccly says how to connect them.
Or do i need some other guideline?

Atm it seems to me that the indicies list i give it takes every value in the buffer as a vertex, so no matter what i put the count it will draw the same thing, except when the count is smaller than the amount of indecies in the indecies buffer.

Maybe this helps. So i tried to make the indicieslist to include normal and texture indicies also, but i get the same result. So i have no idea whats wrong with this.

public void prepareVBO(){
		vboBach1ID = glGenBuffers();
		vboIndeciesID = glGenBuffers();
		for(int i = 0; i < faces.size(); i++){
			total += faces.get(i).size();
		}

		FloatBuffer bach1Buffer = BufferUtils.createFloatBuffer(33 * total);
		ByteBuffer indeciesBuffer = BufferUtils.createByteBuffer(33*total);
		for(int i = 0; i < faces.size(); i++){
			for(Face face : faces.get(i)){
				Material material = face.material;
				indeciesBuffer.put((byte) (face.vertex.x - 1)).put((byte) (face.normal.x - 1)).put((byte) (face.texture.x - 1));
				indeciesBuffer.put((byte) (face.vertex.y - 1)).put((byte) (face.normal.y - 1)).put((byte) (face.texture.y - 1));
				indeciesBuffer.put((byte) (face.vertex.z - 1)).put((byte) (face.normal.z - 1)).put((byte) (face.texture.z - 1));


				
				Vector3f v1 = vertices.get((int) face.vertex.x - 1);
				bach1Buffer.put(v1.x).put(v1.y).put(v1.z);
				bach1Buffer.put(material.getDiffuse().x)
				   		  .put(material.getDiffuse().y)
				   		  .put(material.getDiffuse().z);
				
				Vector3f n1 = normals.get((int) face.normal.x -1);
				bach1Buffer.put(n1.x).put(n1.y).put(n1.z);
				
				if(textured){
					Vector2f t1 = texture.get((int) face.texture.x - 1);
					bach1Buffer.put(t1.x).put(1 - t1.y);
				}
							
				Vector3f v2 = vertices.get((int) face.vertex.y - 1);
				bach1Buffer.put(v2.x).put(v2.y).put(v2.z);
				bach1Buffer.put(material.getDiffuse().x)
		   		  		  .put(material.getDiffuse().y)
		   		  		  .put(material.getDiffuse().z);
				
				Vector3f n2 = normals.get((int) face.normal.y -1);
				bach1Buffer.put(n2.x).put(n2.y).put(n2.z);
				
				if(textured){
					Vector2f t2 = texture.get((int) face.texture.y - 1);
					bach1Buffer.put(t2.x).put(1 - t2.y);
				}
				
				Vector3f v3 = vertices.get((int) face.vertex.z - 1);
				bach1Buffer.put(v3.x).put(v3.y).put(v3.z);
				bach1Buffer.put(material.getDiffuse().x)
		   		  		  .put(material.getDiffuse().y)
		   		  		  .put(material.getDiffuse().z);
				
				Vector3f n3 = normals.get((int) face.normal.z -1);
				bach1Buffer.put(n3.x).put(n3.y).put(n3.z);
				
				if(textured){
					Vector2f t3 = texture.get((int) face.texture.z - 1);
					bach1Buffer.put(t3.x).put(1 - t3.y);				
				}
			}
			koht.add(bach1Buffer.position());
		}
			bach1Buffer.rewind();
			indeciesBuffer.rewind();
			
			glBindBuffer(GL_ARRAY_BUFFER, vboBach1ID);
			glBufferData(GL_ARRAY_BUFFER, bach1Buffer, GL_STATIC_DRAW);
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			
			glBindBuffer(GL_ARRAY_BUFFER, vboIndeciesID);
			glBufferData(GL_ARRAY_BUFFER, indeciesBuffer, GL_STATIC_DRAW);
			glBindBuffer(GL_ARRAY_BUFFER, 0);

		
	}
	

I just dont get it… no matter what i but as the final parameter in the drawElements, i still get the same result. And is till cant find a tutorial good enough that explains the drawElements really simply. English isnt my native tongue.

drawElements hates me -.-

public void Render(){
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_NORMAL_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		if(textured){
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		}
		glBindBuffer(GL_ARRAY_BUFFER, vboBach1ID);
		glVertexPointer(3, GL_FLOAT,44,0);
		glColorPointer(3, GL_FLOAT,44,12);		
		glNormalPointer(GL_FLOAT,44,24);
		
		if(textured){
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, faces.get(0).get(0).material.texture.getTextureID());			
			glTexCoordPointer(2, GL_FLOAT, 44,36);
			
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndeciesID);
			glDrawElements(GL_TRIANGLES, koht.get(0), GL_UNSIGNED_BYTE, 0);
			
		}
		//glDrawArrays(GL_TRIANGLES, 0, koht.get(0));
		
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_NORMAL_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		if(textured){
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		}
	}

I really hope you were kidding because that’s… No. How about try making a game that use more than a couple textures, and note the performance. Then switch to spritesheets and note the performance increase. Binding a texture is an expensive call, I would assume you know that.

Spritesheets are kind of used everywhere. But you know, why would anyone use them.

What about drawElements? what is wrong with my code.

I changed the vertex array a little bit, and it somewhat started working. Problem is that texture is messed up, eventhough i draw out only that part that is supposed to use that texture. Does texture also need its indecies buffer or is there some other problems?

Ok… i think i have figured it out, well atleast part of it. I just need to know 1 thing. Is there a way to check if a element already is in buffer?

And in .obj file why dont the first vertex take the first vertex normal? Line is like this f 1/7/7 … it says that take the first vertex coordinates, take 7th texture coordinates and take 7th normal coordinates. Why not first vertex and first normal. The amount of vertices is equal to the amount of normals.

This is my latest code for the VBO. I made it so that the connections and stuff are exactly like in the .OBJ file. But now i have other problems…

  1. The texture is upsidedown
  2. It doesent draw it properly anymore. Although the connections now are exactly like in .OBJ
public void prepareVBO(){

		vboIndeciesID = glGenBuffers();
		vboVertexID = glGenBuffers();

		int x = 0;
		int e = 11;

		
		for(int i = 0; i < faces.size(); i++){
			total += faces.get(i).size();
		}
		float[] buffer = new float[33 * total];

		FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(33* total);

		IntBuffer indeciesBuffer = BufferUtils.createIntBuffer(33*total);

		
		for(int i = 0; i < faces.size(); i++){
			for(Face face : faces.get(i)){
				Material material = face.material;
				indeciesBuffer.put((int) (face.vertex.x - 1)).put((int) (face.vertex.y - 1)).put((int) (face.vertex.z - 1));

				
				x = (int) face.vertex.x - 1;
				Vector3f v1 = vertices.get((int) face.vertex.x - 1);
				Vector3f n1 = normals.get((int) face.normal.x -1);
				Vector2f t1 = texture.get((int) face.texture.x - 1);
				buffer[e*x] = v1.x;
				buffer[e*x+1] = v1.y;
				buffer[e*x+2] = v1.z;
				buffer[e*x+3] = n1.x;
				buffer[e*x+4] = n1.y;
				buffer[e*x+5] = n1.z;
				buffer[e*x+6] = material.getDiffuse().x;
				buffer[e*x+7] = material.getDiffuse().y;
				buffer[e*x+8] = material.getDiffuse().z;
				buffer[e*x+9] = t1.x;
				buffer[e*x+10] = t1.y;
				
				x = (int) face.vertex.y - 1;
				Vector3f v2 = vertices.get((int) face.vertex.y - 1);
				Vector3f n2 = normals.get((int) face.normal.y -1);
				Vector2f t2 = texture.get((int) face.texture.y - 1);
				buffer[e*x+11] = v2.x;
				buffer[e*x+12] = v2.y;
				buffer[e*x+13] = v2.z;
				buffer[e*x+14] = n2.x;
				buffer[e*x+15] = n2.y;
				buffer[e*x+16] = n2.z;
				buffer[e*x+17] = material.getDiffuse().x;
				buffer[e*x+18] = material.getDiffuse().y;
				buffer[e*x+19] = material.getDiffuse().z;
				buffer[e*x+20] = t2.x;
				buffer[e*x+21] = t2.y;
				
				x = (int) face.vertex.z - 1;
				Vector3f v3 = vertices.get((int) face.vertex.z - 1);
				Vector3f n3 = normals.get((int) face.normal.z -1);
				Vector2f t3 = texture.get((int) face.texture.z - 1);
				buffer[e*x+22] = v3.x;
				buffer[e*x+23] = v3.y;
				buffer[e*x+24] = v3.z;
				buffer[e*x+25] = n3.x;
				buffer[e*x+26] = n3.y;
				buffer[e*x+27] = n3.z;
				buffer[e*x+28] = material.getDiffuse().x;
				buffer[e*x+29] = material.getDiffuse().y;
				buffer[e*x+30] = material.getDiffuse().z;
				buffer[e*x+31] = t3.x;
				buffer[e*x+32] = t3.y;

			}			
			koht.add(indeciesBuffer.position());
		}
			vertexBuffer.put(buffer);

			indeciesBuffer.rewind();
			vertexBuffer.rewind();


			
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndeciesID);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, indeciesBuffer, GL_STATIC_DRAW);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
			
			glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
			glBufferData(GL_ARRAY_BUFFER, vertexBuffer , GL_STATIC_DRAW);
			glBindBuffer(GL_ARRAY_BUFFER, 0);

		
	}

This code cave me the best results yet. But according to .OBJ the connections between vertices and normals are wrong here,
Because first vertex doesent mean first normal.

		for (int i = 0; i < vertices.size(); i++){
			vertexBuffer.put(vertices.get(i).x).put(vertices.get(i).y).put(vertices.get(i).z);
			vertexBuffer.put(normals.get(i).x). put(normals.get(i).y).put(normals.get(i).z);
			
		}

Can anyone tell me what am i doing wrong?

ok so i have got the DrawElements working. It draws put the firt piece of the model. Now how do i continue drawing from where i stopped before? And also i would like to change texture.

Maybe you can choose to sacrifice performance by actually loading in both of the textures into your program, and then programmatically choose either one of the two textures that were loaded into your program.

Note that I’m just thinking this out of my head without sleep.

  1. Load both textures in. And they must be separate.
  2. Generate and bind textures as normal.
  3. The only difference is to set the active texture unit #0 to one of the textures. And texture unit #1 to the other.
  4. Load the model the same way you use to do.
  5. See if you can switch texture unit #, texture id handle, etc. on the fly.
  6. ???
  7. Profit?

Both of the textures are loaded in. that texture1 and thexture2 stuff… i have no idea how to do that. The main thing is how do i continue drawing from where i left off. This is the point i have reached :smiley:

public void Render(){
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_NORMAL_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		if(textured){
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		}		
		glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
		glVertexPointer(3, GL_FLOAT,44,0);
		glNormalPointer(GL_FLOAT,44,12);
		glColorPointer(3, GL_FLOAT,44,24);		
		
		if(textured){
			glEnable(GL_TEXTURE_2D);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndeciesID);
			
			glBindTexture(GL_TEXTURE_2D, faces.get(0).get(0).material.texture.getTextureID());
			glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
			glTexCoordPointer(2, GL_FLOAT,44,36);

			glDrawElements(GL_TRIANGLES,koht.get(0), GL_UNSIGNED_INT,0);
			
		}
		
		//glDrawArrays(GL_TRIANGLES, 0, total);
		
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_NORMAL_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		if(textured){
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		}
	}

@tom_mai78101 is talking about texture units. Essentially you can bind a different texture to each unit and them access them all at the same time in the shader.

Yes. Example: you have an IBO with 20 indices. The first 12 need to be drawn with one texture and the last 8 with another.


setupPointersEnableArraysAndBindIBO();

glBindTexture(texture1Id);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);

glBindTexture(texture2Id);
glDrawElements(GL_TRIANGLES, 8, GL_UNSIGNED_INT, 12 * 4); //Since offset is in bytes. It is 12 indices in and there
                                                                                      //are 4 bytes per integer.

finishDrawingAndStuffLikeThat();

Also, you should probably close down the thread you started on the LWJGL forums. Having two threads just means people are going to repeat themselves. Most people on LWJGL are here as well so it won’t even help you.

OK it seems i was missing the *4. But for some reason the texture is bugged. The model consists of 3 parts. THe cape, the hair and the body. Cape is drawn perfectly, well atleast i cant see the problems right now. The hair, its hard to say since its black and everything is black. But the body is cliched and buffed. It iin places i can see through the textures and on one hand there is somekind of bugged vertex. So what might be the reason for the texture bugs?

So JGO and LWJGL forum are basicly the same?

Try drawing the texture on just a single quad. If that’s screwed up then the texture loading is wrong. If not then there is something wrong with the texture coords.

JGO is a more general forum but there is a lot of cross over yes.

I put the texture on a quad and on it it looked excactly like the picture file itself. But when i but it on the model, it looks weird and is somewhat seethrough.