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

标签 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,还是有其他实现方法?

最佳答案

如果您只想渲染加载纹理的一部分,只需相应地调整 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
};

一旦你将数据加载到 VAO 作为属性 1 和 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

}

片段着色器:

in vec2 interpolatedCoords;

out vec4 out_color;

uniform sampler2D texture;

void main(void) {

     out_color = texture(texture, interpolatedCoords);

}

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

关于c - 如何将纹理存储在内存中并渲染其中的一小部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45594676/

相关文章:

opengl - 在 GLSL 4.1 中使用 switch 语句

c++ - OpenGL:isampler2DArray 与 sampler2DArray 与 sampler3DArray

c - 在Linux中以编程方式运行pdftotext xpdf y.text?

c - 格式化中间带有连字符的条形码 - 分配问题

c - n & (n-1) 这个表达式是做什么的?

c++ - Opengl VAO 被覆盖

OpenGL gluLookAt() 未按预期工作

c - 异步 ReadDirectoryChangesW - GetQueuedCompletionStatus 总是超时

opengl - 经典的 "nothing is getting rendered"OpenGL 问题

python - 接近 1 的纹理坐标表现异常