Reputation: 19
So I'm trying to texture an object in OpenGL and I have two textures that I want to mix together in the fragment shader (rock.tga and grass.tga). My fragment shader:
out vec3 color;
in vec2 uv;
uniform sampler2D grasstexture;
uniform sampler2D rocktexture;
To load a sampler2D texture here's what I did in my header file in C++:
OpenGP::EigenImage<vec3> image;
OpenGP::imread("grass.tga", image);
glGenTextures(0, &_tex);
glBindTexture(GL_TEXTURE_2D, _tex);
check_error_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
check_error_gl();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F,
image.cols(), image.rows(), 0,
GL_RGB, GL_FLOAT, image.data());
check_error_gl();
tex_id = glGetUniformLocation(_pid, "grasstexture");
glUniform1i(tex_id, 0);
Which loads the grass texture into my fragment shader. Now what I want to know is how do I load in multiple textures. I can't copy the above code twice because one texture is always over-written by the other. So how can I load in multiple textures into the fragment shader?
EDIT: Here's where my _tex
is declared:
class Mesh{
protected:
GLuint _tex;
GLuint _vpoint; ///< memory buffer
GLuint _vnormal; ///< memory buffer
public:
GLuint getProgramID(){ return _pid; }
void init(){
//code for the textures goes in here
Here's my updated code:
OpenGP::EigenImage<vec3> image;
glActiveTexture(GL_TEXTURE0);
OpenGP::imread("grass.tga", image);
//glGenTextures(1, &_tex);
glBindTexture(GL_TEXTURE_2D, _tex);
check_error_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
check_error_gl();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F,
image.cols(), image.rows(), 0,
GL_RGB, GL_FLOAT, image.data());
check_error_gl();
tex_id = glGetUniformLocation(_pid, "grasstexture");
glUniform1i(tex_id, 0);
glActiveTexture(GL_TEXTURE1);
OpenGP::imread("rock.tga", image);
//glGenTextures(0, &_tex);
glBindTexture(GL_TEXTURE_2D, _tex);
check_error_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
check_error_gl();
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB32F,
image.cols(), image.rows(), 0,
GL_RGB, GL_FLOAT, image.data());
check_error_gl();
tex_id = glGetUniformLocation(_pid, "rocktexture");
glUniform1i(tex_id, 1);
Upvotes: 1
Views: 1521
Reputation: 5675
Opengl hides a lot of its context so you need to keep it in mind. You have three parts of the texture:
GL_TEXTURE0
...Here is what you need to do in order to get a 2d texture working:
glGenTextures
Set up the texture with following set of actions:
2.1 Set active texture unit with glActiveTexture
2.2 Specify the target of the active texture unit to which the named texture is bound glBindTexture
. For this all three texture parts should be "under control".
2.3 Specify a two-dimensional texture image for the active texture unit with glTexImage2D
2.4 Set parameters for the active texture unit with glTexParameteri
In order to simultaneously use multiple textures make sure that they have unique name and texture unit:
3.1 Set active texture unit to 0
3.2 Bind one named texture to active texture unit
3.3 Pass texture unit (0) to shader
3.4 Set active texture unit to 1
3.5 Bind another named texture to active texture unit
3.6 Pass texture unit (1) to shader
...
glDeleteTextures
The order of commands is not the only one possible and the set of commands is not minimal - it is just typical.
Original answer:
You need to set next active texture like this:
glActiveTexture(GL_TEXTURE1);
before you bind bind the next texture. It will also work like:
std::vector<std::string> textures = {"grass.tga", "rock.tga"};
for(int i = 0; i < textures.size(); i++) {
glActiveTexture(GL_TEXTURE0 + i);
// create the texture
}
Upvotes: 4