如何在内存中存储纹理并渲染其中的一小部分

时间:2017-08-09 15:19:18

标签: c opengl glsl

我有一个纹理,我想存储在内存中。然后我想将这个纹理的一部分渲染到OpenGL上下文中。我想知道如何做到这一点。

到目前为止,我已经设置了顶点数据。

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
};

然后,我将完成创建VBO和使用OpenGL函数

的常规步骤
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

加载并创建纹理:

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); 

然后我使用while循环激活着色器,然后绘制纹理。但是,我现在想要做的是将此纹理存储在内存中并仅渲染其中的一小部分。我是否使用Renderbuffer对象或PBO,还是有其他方法可以实现这一目标?

1 个答案:

答案 0 :(得分:2)

如果您只想渲染已加载纹理的部分,只需相应调整VBO中的纹理坐标。

在着色器程序中传递给texture(...)函数的纹理坐标将左下角映射为(0,0),将右上角映射为(1,1)。因此,如果我们只想将纹理的右上角映射到平面四边形,我们的纹理坐标将包含(0.5,0.5)(0.5,1.0)(1.0,1.0)(1.0,0.5)

这里是顶点和纹理坐标VBO数据:

float[] vertices = {
      0.5,  0.5, 0.0,     // upper left triangle
     -0.5,  0.5, 0.0,
     -0.5, -0.5, 0.0,

      0.5,  0.5, 0.0,     // lower right triangle
     -0.5, -0.5, 0.0,
      0.5, -0.5, 0.0
};

float[] textureCoords = {
     1.0, 1.0,
     0.5, 1.0,
     0.5, 0.5,

     1.0, 1.0,
     0.5, 0.5,
     1.0, 0.5
};

您的数据加载vertices作为属性1的VAO和textureCoords作为属性2.然后您的着色器应如下所示:

顶点着色器:

in vec3 vertex;
in vec2 textureCoords;

out vec2 interpolatedCoords;

void main(void) {

     interpolatedCoords = textureCoords;

     gl_Position = vertex; // You transform these coordinates or whatever you'd like here

}

Fragment Shader:

in vec2 interpolatedCoords;

out vec4 out_color;

uniform sampler2D texture;

void main(void) {

     out_color = texture(texture, interpolatedCoords);

}

这将是将纹理的某些部分映射到简单的2D四边形上的最简单的例子。