PDA

View Full Version : How to store a texture in memory and render a small portion of it



nuerofuzz
08-09-2017, 09:48 AM
This is probably a newbie question: I have a texture that I would like to store in memory. Then I would like to render a portion of this texture onto an OpenGL context. I would like to know how to do this.

So far I've set up my vertex data.


GLfloat texture[] =
{
-0.5f, 0.5f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 1.0f, // top rght
0.5f, 0.5f, 0.0f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, // bottom right
0.5f, -0.5f, 0.0, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, // bottom left
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, // top left
};


I then go through the usual steps of creating a VBO, and using the OpenGL functions


GLuint indices[] =
{
0, 1, 3, //First triangle
1, 2, 3 //Second triangle
};

GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1,& VBO);
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VB);
glBufferData(GL_ARRAY_BUFFER, sizeof(texture), texture, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//position attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
//colour attributes
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//TexCoord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0); //unbind VAO

//load and create a texture
GLuint texture0;

int width, height;
unsigned char* image[1];

glGenTextures(1, &texture0);
glBindTexture(GL_TEXTURE_2D, texture0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//set texture wrapping to GL_REPEAT (usually basic wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
image[0] = SOIL_load_image("Textures/texture.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image[0]);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image[0]);
glBindTexture(GL_TEXTURE_2D, texture0);


I then use a while loop to activate the shader and then draw the texture. However want I now want to do is store this texture in memory and render only a small portion of it. Do I use a Renderbuffer object or a PBO, or is there some other way of acheiving this?

Dark Photon
08-09-2017, 06:19 PM
However want I now want to do is store this texture in memory and render only a small portion of it.

If you only want to render a small portion of it, just change the texture coordinates in your vertices to sample only from that small portion. With your code as-is, you are maintaining the texture in memory (GPU memory).

Another approach to your problem (which is a little more work) would be to only upload to the GL texture a sub-region of your loaded image, and then render the entire GL texture. However, unless the whole texture is "huge" (relative to your GPU memory size), then this probably isn't worth the trouble. Just tweak the texture coordinates to render a smaller portion.