I’m using OpenGL 3.3 and GLSL 3.3.
Is it possible to share textures across multiple shader programs so I don’t have to upload the texture to the GPU more than once?
For example, let’s say I have one 2D noise texture and two objects to render. Each object has its own associated vertex+fragment shader. In both of the fragment shaders, it uses the same noise texture (uniform sampler2D) and the texture parameters do not change.
At the moment, I have to call glTexImage2D twice (once for each shader program) to upload the texture to the GPU. Here is some simplied example code:
Image myImage;
ShaderProgram shaderProgram[2];
init();
For every frame, call draw();
void init(){
... Load image from disk ...
... Compile and install shader program 1. ...
glUseProgram(shaderProgram[0].id);
setTexture(myImage, 0);
... Compile and install shader program 2. ...
glUseProgram(shaderProgram[1].id);
setTexture(myImage, 1);
}
void setTexture( myImage, shaderProgramIndex ){
glGenTextures(1, &shaderProgram[shaderProgramIndex].textureID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shaderProgram[shaderProgramIndex].textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myImage.width(), myImage.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, myImage.data());
GLint loc = glGetUniformLocation(shaderProgram[shaderProgramIndex].id, "myTexture");
glUniform1i(loc, 0);
}
void draw(){
// Draw object 1.
glUseProgram(shaderProgram[0].id);
glBindTexture(GL_TEXTURE_2D, shaderProgram[0].textureID);
glBindVertexArray(vao0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo0);
glDrawElements(GL_TRIANGLES, ...);
// Draw object 2.
glUseProgram(shaderProgram[1].id);
glBindTexture(GL_TEXTURE_2D, shaderProgram[1].textureID);
glBindVertexArray(vao1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo1);
glDrawElements(GL_TRIANGLES, ...);
swapBuffers();
}
I’ve looked into Uniform Buffer Objects, Sampler Objects (glGenSamplers), and glTextureView. I read that UBOs don’t work with textures so they won’t help. I don’t think Sampler objects are what I need since the texture parameters don’t change. I think glTextureView is what I need but this is only available starting with OpenGL 4.3. My graphics card can only support up to OpenGL 3.3.
Combining the shader programs is not an option. How to I share a texture between more than one shader program?