Reputation: 33
I have a list of images that I want to display, using OpenGL textures (Android NDK/SDK). I have put the image data into an array to be used by glTexImage2D
. I initialized the variables and ran glDeleteTextures(1, &hedy);
for uploading and displaying each image.
Everything is OK but it works slowly (2.5ms for loading a texture). How can I improve the app's performance? Can I upload the image data into GPU memory once and use it many times? Do you have any solution or recommendation to display images at high speed?
glGenTextures(1, &hedy);
glBindTexture(GL_TEXTURE_2D, hedy);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
Upvotes: 2
Views: 680
Reputation: 2268
You only need to Generate a Texture once.
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
Now we can keep using texture with the call
glBindTexture(GL_TEXTURE_2D, texture);
The same goes for shaders we need to compile them only once .
Shader loadShaderFromFile(const GLchar *vShaderFile, const GLchar *fShaderFile, const GLchar *gShaderFile)
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::string geometryCode;
try
{
// Open files
std::ifstream vertexShaderFile(vShaderFile);
std::ifstream fragmentShaderFile(fShaderFile);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vertexShaderFile.rdbuf();
fShaderStream << fragmentShaderFile.rdbuf();
// close file handlers
vertexShaderFile.close();
fragmentShaderFile.close();
// Convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
// If geometry shader path is present, also load a geometry shader
if (gShaderFile != nullptr)
{
std::ifstream geometryShaderFile(gShaderFile);
std::stringstream gShaderStream;
gShaderStream << geometryShaderFile.rdbuf();
geometryShaderFile.close();
geometryCode = gShaderStream.str();
}
}
catch (std::exception e)
{
QMessageBox message;
message.setText("ERROR::SHADER: Failed to read shader files");
message.exec();
}
const GLchar *vShaderCode = vertexCode.c_str();
const GLchar *fShaderCode = fragmentCode.c_str();
const GLchar *gShaderCode = geometryCode.c_str();
// 2. Now create shader object from source code
Shader shader;
shader.Compile(vShaderCode, fShaderCode, gShaderFile != nullptr ? gShaderCode : nullptr);
return shader;
}
Now you can keep bind this shader when you need it with this call.
glUseProgram(ShaderId);
Generate all the textures and Compile the shaders when your application initializes and than keep using them.
Upvotes: 1