Java-Gaming.org    
Featured games (78)
games approved by the League of Dukes
Games in Showcase (429)
Games in Android Showcase (89)
games submitted by our members
Games in WIP (466)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  LWJGL using multiple textures  (Read 2151 times)
0 Members and 1 Guest are viewing this topic.
Offline vastrolorde

Senior Newbie





« Posted 2014-01-24 09:53:52 »

How can i use multiple textures on a model? I have the .OBJ loader and .MTL loader and everything is working fine. I can use a single texture. But i have a model that has 2 textures. How can i use both of the textures?
Offline opiop65

JGO Kernel


Medals: 130
Projects: 7
Exp: 3 years


Team Alluminum


« Reply #1 - Posted 2014-01-24 12:08:16 »

You'll need to use a spritesheet. If you haven't used one, get comftorable with using them because they will pretty much greatly boost your performance by allowing you to bind fewer textures, which is an expensive function.

A spritsheet is just a large texture that contains other, smaller, textures inside it. In your program you need to figure out where each texture is in your spritesheet relative to its coordinate constraints of [0, 1]. Then you tell your renderer to use those coordinates on the specific face you want to render. This way you can pack a bunch of textures into a larger one, bind less, and maybe even have a smaller memory footprint.

If you're confused, just ask, or Google is always you're best friend Smiley

Offline vastrolorde

Senior Newbie





« Reply #2 - Posted 2014-01-24 12:22:58 »

Problem is. Im using a Blender model i downloaded from internet. Its a superman Cheesy. And it has a Different Texture for it cape. And the textures are in 2 different files. So i dont know if i can combine those two into a spritesheet and then successfully use em.
Although yes, this model is only for the purpose to complete my model class to fully support Textures and stuff.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline opiop65

JGO Kernel


Medals: 130
Projects: 7
Exp: 3 years


Team Alluminum


« Reply #3 - Posted 2014-01-24 12:31:26 »

Of course you can, just make sure the renderer knows what texture file to use, and see if Blender can export both on the same texture.

Offline vastrolorde

Senior Newbie





« Reply #4 - Posted 2014-01-24 12:53:15 »

As much as i know about blender and could find, it doesent have the support to export textures in 1 file. And i cant but them together manually either cause then i have to do some changes to the texture coordinates and well my mind is blown. 1 texture is 1024X1024 the other is 512X512. So if there is any Blender pro who could tell me how to export a model with Textures in one file and the coordinates in .OBJ would correspond to it as well as the file name in .MTL
Offline vastrolorde

Senior Newbie





« Reply #5 - Posted 2014-01-24 14:20:53 »

And if i make a sprite sheet, then how can i make sure that the coordinates are taken from the right sprite is a model uses multiple sprites.
Offline vastrolorde

Senior Newbie





« Reply #6 - Posted 2014-01-24 17:28:56 »

Textures always come in a square or rectangle right? I mean that width = height. or width = x * height. No irregular shapes.
Offline opiop65

JGO Kernel


Medals: 130
Projects: 7
Exp: 3 years


Team Alluminum


« Reply #7 - Posted 2014-01-24 17:38:01 »

No they don't have to. Its just easier to calculate coordinates if they are the same width and height.

Offline vastrolorde

Senior Newbie





« Reply #8 - Posted 2014-01-24 17:47:09 »

Thats what i was thinking. That if they are width = height, then i can easily build a spritesheet and workout the coordinate system to multitexture it.
Online EgonOlsen
« Reply #9 - Posted 2014-01-24 18:23:42 »

I think that this sprite sheet thing is misleading in this context. Yes, texture changes can be expensive but you can't avoid them in a reasonable complex 3d scene. You can't stuff everything into one texture and adjust the texture coordinates. It would be a complete nightmare to handle this.
In your case, you have to split the rendering into at least as many batches as you have textures (or shaders or whatever causes a state change). When loading the model, you put everything that uses one texture in the first batch and everything else into the second. Then bind texture 1, render batch 1, bind texture 2, render batch 2.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline vastrolorde

Senior Newbie





« Reply #10 - Posted 2014-01-24 19:56:19 »

Cant the texture be binded during the VBO generation? My brain is breaking down with this multitexture problem.


Could this work, if i make my main model consist of submodels. each model is rendered separtely there is just 1 function that calls the renderings.
Offline opiop65

JGO Kernel


Medals: 130
Projects: 7
Exp: 3 years


Team Alluminum


« Reply #11 - Posted 2014-01-24 20:06:38 »

Yes, but I don't think in the way you are thinking about it. You specify the coordinates of the texture, but you can't actually keep the texture bound. Well you could, but only if you don't use any other textures in the entire program because you wouldn't need to unbind the first texture. However you can't tell OpenGL to store an entire texture. It can only store coordinates.

Offline Phibedy

Senior Member


Medals: 8



« Reply #12 - Posted 2014-01-24 20:14:41 »

I would prefer using a spritesheet because in my opinion all textures of one "mapobject" should be on one "texture". Like always there are exceptions. For example if you don't have to care about performance or if you want to use use gl_repeat it's not usefull to use a spritesheet  Smiley
You might wanna have a look at: Vertex Attributes -> https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson1
Online EgonOlsen
« Reply #13 - Posted 2014-01-24 20:17:50 »

Think of it this way: The vbo or vertex array or whatever you are using defines what is being rendered but it doesn't define how. If the 'how' changes for a part of the scene or a single model, you have to split your draw calls. You can abstract this away on a higher level, but down in GL, you have to deal with it.

Offline Gef
« Reply #14 - Posted 2014-01-24 20:30:41 »

A easy way to do this is certainly like EgonOlsen said : split your model into batchs per texture, using one vbo for the whole model, and as many rendering pass as textures needed.
The spriteseheet solution needs a big work on the texture coordinates (even more if you have 2, 3 or more textures used in your model) but allows to render the model in one pass.
There are other solutions, like using texture channels if few textures needed, but to understand and test the mechanics I would use first batchs...

Offline vastrolorde

Senior Newbie





« Reply #15 - Posted 2014-01-24 20:56:37 »

So basicly i need to create 6 buffers to house 2 textures. normals1Buffer, normals2buffer, vertex1Buffer, vertex2buffer, texture1buffer, texture2buffer. and with each new texture i need 3 more buffers?
Online EgonOlsen
« Reply #16 - Posted 2014-01-24 21:02:21 »

So basicly i need to create 6 buffers to house 2 textures. normals1Buffer, normals2buffer, vertex1Buffer, vertex2buffer, texture1buffer, texture2buffer. and with each new texture i need 3 more buffers?
Either that, or you could interleave the data in one buffer and render parts of it. But to keep things simple in the beginning, i would go with multiple buffers.

Offline vastrolorde

Senior Newbie





« Reply #17 - Posted 2014-01-25 09:39:51 »

Ok... it was easier for me to understand the interleaving buffer, than to get the idea how to get it into baches. So could you give me an example of how to draw the baches. Are each batch in different buffers or all in one buffer and i just have to know how big of a jump i have to make to get the next bach or what?
Online EgonOlsen
« Reply #18 - Posted 2014-01-25 09:50:14 »

Either way will work.

Offline vastrolorde

Senior Newbie





« Reply #19 - Posted 2014-01-25 12:24:46 »

2 problems.
1. how to jump to next bach within a buffer?
2. how do i actually bind the 2 textures?

there was something with GL_TEXTURE0, GL_TEXTUR1 etc. but i cant find it anymore.
Online EgonOlsen
« Reply #20 - Posted 2014-01-25 14:07:25 »

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.

Offline vastrolorde

Senior Newbie





« Reply #21 - Posted 2014-01-25 16:08:49 »

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.<init>(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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
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);
      }
   }
Offline Gef
« Reply #22 - Posted 2014-01-25 16:44:21 »

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 :

Offline vastrolorde

Senior Newbie





« Reply #23 - Posted 2014-01-25 17:29:12 »

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.
Offline quew8

JGO Coder


Medals: 23



« Reply #24 - Posted 2014-01-26 01:37:15 »

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.
Offline vastrolorde

Senior Newbie





« Reply #25 - Posted 2014-01-26 09:22:41 »

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.
Offline vastrolorde

Senior Newbie





« Reply #26 - Posted 2014-01-26 10:48:33 »

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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
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);

     
   }
   
Offline vastrolorde

Senior Newbie





« Reply #27 - Posted 2014-01-26 15:42:34 »

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 -.-

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
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);
      }
   }
Offline SwordsMiner

JGO Coder


Medals: 8
Projects: 2
Exp: 10-12 months


Head of the Indie Developing team Revereor.


« Reply #28 - Posted 2014-01-26 16:58:46 »

You'll need to use a spritesheet.

ewwww. spritesheets. Those are a disgrace.

- The one and only, SwordsMiner.

YOUTUBE
TWITTER
INACTIVE WEBSITE
Offline opiop65

JGO Kernel


Medals: 130
Projects: 7
Exp: 3 years


Team Alluminum


« Reply #29 - Posted 2014-01-26 17:06:39 »

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.

Pages: [1] 2
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (80 views)
2014-04-15 18:08:23

BurntPizza (72 views)
2014-04-15 03:46:01

UprightPath (83 views)
2014-04-14 17:39:50

UprightPath (67 views)
2014-04-14 17:35:47

Porlus (83 views)
2014-04-14 15:48:38

tom_mai78101 (107 views)
2014-04-10 04:04:31

BurntPizza (167 views)
2014-04-08 23:06:04

tom_mai78101 (263 views)
2014-04-05 13:34:39

trollwarrior1 (213 views)
2014-04-04 12:06:45

CJLetsGame (222 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!