views:

49

answers:

2

Hi guys!

I`m a little confused about this point.

Everything that I found in books, blogs, forums and even in OpenGl specs just talk about a very abstract techniques. Nothing about real world examples.

And I`m going crazy with this: How to put and manage multiple objects (meshes) with OpenGL ES 2.x?

In theory seems simple. You have a Vertex Shader (vsh) and Fragment Shader (fsh), then you bind the both to one Program(glGenProgram, glUseProgram, ...). In the every cycle of render, that Program will perform its VSH by each Vertex and after this will perform FSH on every "pixel" of that 3d object and finally send the final result to the buffer (obviously without talk about the per-vertex, rasterization, and other steps in the pipeline).

OK, seems simple...

All this is fired by a call to the draw function (glDrawArrays or glDrawElements).

OK again.

Now the things comes confused to me. And If you have several objects to render?

Let's talk about a real world example. Imagine that you have a landscape with trees, and a character. The grass of the landscape have one texture, the trees have texture to the trunk and leaves (Texture Atlas) and finally the character has another texture (Texture Atlas) and is animated too.

After imagine this scene, my question is simple: How you organize this?

You create a separated Program (with one VSH and FSH) for each element on the scene? Like a Program to the grass and soil's relief, a Program to the trees and a Program to the character?

I've tried it, but... when I create multiple Programs and try to use glVertexAttribPointer() the textures and colors of the objects enter in conflicts with each others. Because the location of the attributes, the indexes, of the first Program repeat in the second Program.

Let me explain, I used glGetAttribLocation() in one class that controls the floor of the scene, so the OpenGL core returned to me the index of 0,1 and 2 for the vertexes attributes. After, in the class of trees I created another Program, anothers shaders, and after used again the glGetAttribLocation() at this time the OpenGL core return with indexes of 0, 1, 2 and 3.

After in the render cycle, I started setting the first Program with glUseProgram() and I've made changes to its vertexes attributes with glVertexAttribPointer() and finally a call to glDrawElements(). After this, call again glUseProgram() to the second Program and use glVertexAttribPointer() again and finally glDrawElements(). But at this point, the things enter in conflicts, because the indexes of vertexes attributes of the second Program affects the vertexes of the first Program too.

I'm tried a lot of thing, searched a lot, asked a lot... I'm exhausted. I can't find what is wrong.

So I started to think that I'm doing everything wrong!

Now I repeat my question again: How to work with multiple meshes (with different textures and behavior) in OpenGL ES 2.x? Using multiple Programs? How?

+1  A: 

To draw multiple meshes, just call glDrawElements/glDrawArrays multiple times. If those meshes require different shaders, just set them. ONE, and only ONE shader program is active.

So each time you change your shader program (Specifically the VS), you need to reset all vertex attributes and pointers.

Just simple as that.

Matias Valdenegro
A: 

Hey Matias Valdenegro,

Thanks for answer,

But I think that you just repeat my own words... about the Draw methods, about one Program active, about everything.

Whatever.

The point is that your words give me an insight! You said: "you need to reset all vertex attributes and pointers".

Well... not exactly reseted, but what I was not updating ALL vertex attributes on render cycle, like texture coordinates. I was updating just that attributes that change. And when I cleared the buffers, I lost the older values.

Now I start to update ALL attributes, independent of change or not their values, everything works!

See, what I had before is:

glCreateProgram();
...
glAttachShader();
glAttachShader();
...
glLinkProgram();
glUseProgram();
...
glGetAttribLocation();
glVertexAttribPointer();
glEnableVertexAttribArray();
...
glDrawElements();

I repeated the process to the second Program, but just call glVertexAttribPointer() a few times.

Now, what I have is a call to glVertexAttribPointer() for ALL attributes.

What drived me crazy is the point that if I removed the First block of code to the first Program, the whole second Program worked fine. If I removed the Second block of code to the second Program, the first one worked fine.

Now seems so obvious. Of course, if the VSH is a per-vertex operation, it will work with nulled value if I don't update ALL attributes and uniforms. I though about OpenGL more like a 3D engine, that work with 3d objects, has a scene where you place your objects, set lights. But not... OpenGL just know about triangles, lines and points, nothing more. I think different now.

Anyway, the point is that now I can move forward!

Thanks