PDA

View Full Version : glActiveTexture before drawing?



geranimo
08-08-2015, 10:35 AM
*forget it, I downloaded the code master and it's not there so it's an error (thread resolved)*

Hello, I'm following a tutorial on OpenGL, but the tutorial doesn't explain the


glActiveTexture(GL_TEXTURE0); line in the following code (it's a draw function from a mesh class for assimp)


void Draw(Shader shader)
{
GLuint diffuseNr = 1;
GLuint specularNr = 1;
for(GLuint i = 0; i < this->textures.size(); i++)
{
glActiveTexture(GL_TEXTURE0 + i); // Activate proper texture unit before binding
// Retrieve texture number (the N in diffuse_textureN)
stringstream ss;
string number;
string name = this->textures[i].type;
if(name == "texture_diffuse")
ss << diffuseNr++; // Transfer GLuint to stream
else if(name == "texture_specular")
ss << specularNr++; // Transfer GLuint to stream
number = ss.str();

glUniform1f(glGetUniformLocation(shader.Program, ("material." + name + number).c_str()), i);
glBindTexture(GL_TEXTURE_2D, this->textures[i].id);
}
glActiveTexture(GL_TEXTURE0);

// Draw mesh
glBindVertexArray(this->VAO);
glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}

Is it necessary or it's a mistake? If I really need to do that, what's the purpose?

Thanks

Alfonse Reinheart
08-08-2015, 11:01 AM
Is it necessary or it's an mistake?

It is neither. glActiveTexture sets the current texture image unit, used by all subsequent commands that deal with texture manipulation. Setting the active texture image unit to zero is not necessary for the execution of the following VAO binding and rendering commands. But that doesn't mean it is a mistake.

Presumably, the point is to return the active texture unit to a known, well-understood state. After all, the active texture unit is context state, so it is possible that other code may expect it to be on texture unit 0. And such code would not do the right thing if it were not reset to zero.

Thus, after issuing a Draw command, the caller knows that, while new textures may have been bound to any number of texture image units, the active texture unit will always be reset to 0.

To be honest, I'd be far more concerned with the generally horrible quality of code used by the tutorial. Creating a std::stringstream for every texture in every rendering call? Has this person not heard of std::to_string (http://en.cppreference.com/w/cpp/string/basic_string/to_string)? Needlessly copying the texture's name every time you bind a texture? And why not pre-process all of this stuff? After all, you'd be generating the exact same strings (and uniform locations) every single time through the rendering call.

Also, `"material." + name + number` strongly implies that the final name for the sampler uniform will be "material.some_name1". Which is illegal; samplers are opaque types (https://www.opengl.org/wiki/Data_Type_%28GLSL%29#Opaque_types), and opaque types cannot be members of uniform blocks. And even if they could, members of uniform blocks don't have locations.

And the name of an identifier (like a non-block uniform value) cannot include the `.` character.

So I'm not sure how this code even functions.

GClements
08-08-2015, 11:52 AM
So I'm not sure how this code even functions.
Apparently, nVidia's implementation allows samplers within structures. Which suggests that the author goes by "works on my system" rather than reading the standard.

Alfonse Reinheart
08-08-2015, 12:07 PM
Apparently, nVidia's implementation allows samplers within structures.

What extension specification allows that? Because I checked both NV_bindless_texture and ARB_bindless_texture, and neither one permits it. They permit 64-bit integers in structs, but you can't declare them as actual samplers in structs.


Which suggests that the author goes by "works on my system" rather than reading the standard.

Not surprising, considering the horrible quality of the source code. Though I would have hoped that someone who cared enough to write a tutorial would also have more than a nodding acquaintance with the spec.

GClements
08-08-2015, 01:46 PM
What extension specification allows that?
Who said anything about a specification? nVidia's implementations have always been somewhat fault-tolerant (i.e. accepting things which should be an error).

geranimo
08-10-2015, 08:57 AM
Ok so if my tutorial is so bad, do you know one better than this? it's learnopengl . com (for some reason I can't post links)

I am currently doing the assimp / model loading stuff

Alfonse Reinheart
08-10-2015, 11:26 AM
Ok so if my tutorial is so bad,

No, there's no "if" in that statement. I just took a look at it and encountered this picture (http://learnopengl.com/img/getting-started/pipeline.png). It's wrong; the Geometry shader comes after tessellation, not before. That's not a minor mistake someone can make. That's someone who has little familiarity with the specification.

Not to mention, the website itself is one of those garbage websites based so intimately on JavaScript that you can't even middle-click on a link to bring it up in a new tab.


do you know one better than this?

Well, there's mine, accessible through my signature. But there are also others, as can be found through the OpenGL Wiki (https://www.opengl.org/wiki/Getting_Started#Tutorials_and_How_To_Guides).

Alfonse Reinheart
08-10-2015, 12:13 PM
Apparently, nVidia's implementation allows samplers within structures. Which suggests that the author goes by "works on my system" rather than reading the standard.

I just did some digging into the specifications, and guess what? Opaque types can be in structs after all.

I don't know how I screwed that up, since I got it right on the wiki... (https://www.opengl.org/wiki/Data_Type_%28GLSL%29#Opaque_types)

Oh, and when I informed the owner of the tutorial about the geometry shader thing, he apparently fixed it right away (https://github.com/JoeyDeVries/LearnOpenGL/issues/17).

So maybe it's not so bad after all. Through the std::stringstream usage is still inexcusable ;)