c++ - 具有不同纹理 UV 的矩形实例

标签 c++ opengl vbo opengl-3 vao

我是现代 OpenGL VBO/VAO 的新手,我为一件事而苦恼:我已经根据 this tutorial 编写了一个 RectangleAsset。 ,但我不确定如何将有关纹理 UV 的信息移动到 RactangleAssetInstance(我的矩形可以有不同的纹理)。


我是否必须为其创建新的 VAO,或者我是否可以通过其他方式传递 UV?或者为 UV 添加第二个 VBO?最重要的是:解决这个问题的最佳做法是什么?

struct RectangleAsset {
    GLuint VBO;
    GLuint VAO;
};

struct RectangleAssetInstance { //this is actually more complex class in my code
    RectangleAsset rect;        //but tried to extract the most imporatant code
    glm::mat4 transform;
    Texture * texture;
    void UpdateTransform(int,int,int,int);
private:
    int x,y,width,height;
};

和加载 RectangleAsset 的函数:

void GUIRenderer::init()
{
    image = new Program ("vs.glsl", "fs.glsl");
    glGenVertexArrays(1, &rect.VAO);
    glBindVertexArray(rect.VAO);
    glGenBuffers(1, &rect.VBO);
    glBindBuffer(GL_ARRAY_BUFFER, rect.VAO);

    GLfloat vertexData[] = {
        //  X     Y     Z       U     V   
         0.0f, 0.0f, 0.0f,   0.0f, 0.0f,
         1.0f, 0.0f, 0.0f,   1.0f, 0.0f,
         0.0f, 1.0f, 0.0f,   0.0f, 1.0f,
         1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 
         1.0f, 1.0f, 0.0f,   1.0f, 1.0f,
         0.0f, 1.0f, 0.0f,   0.0f, 1.0f,
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(image->attrib("vert"));
    glVertexAttribPointer(image->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), NULL);

    glEnableVertexAttribArray(image->attrib("vertTexCoord"));
    glVertexAttribPointer(image->attrib("vertTexCoord"), 2, GL_FLOAT, GL_TRUE,  5*sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));
    glBindVertexArray(0);
}

注意:我计划只在一个地方使用 RectangleAssetInstances,在一个 std::vector 中用于 GUI 渲染(非静态 gui)。将所有矩形合并到一个 VBO 和 VAO 中(并在添加/删除 UIElement 时重新创建它)可能是个好主意吗?
欢迎任何学习 OpenGL 最佳实践的建议。

最佳答案

VAO 存储输入数据的格式和输入数据的来源位置。这实际上是两个不同的概念。如果您想更改 UV 的来源,您必须再次调用 glVertexAttribPointer。这个调用看起来像 glVertexAttribPointer(uvLoc, GL_FLOAT, false, sizeof(float) * 5, (const GLvoid*)(sizeof(float) * 3)) 注意这不会改变 VBO您的位置信息来自。

现在您提到您想要这样做是因为您的矩形实例可能具有不同的纹理。您无需更改 UV 即可实现此目的。在一般位置,UV 和法线都是网格的一部分,您只需要它们的一个拷贝。要更改纹理,只需调用 glActiveTexture(GL_TEXTURE0 + i),然后调用 glBindTexture(GL_TEXTURE_2D, tex),然后在着色器中设置采样器制服以使用正确的图像单元glUniform1i(samplerLoc, i)

还有 ARB_vertex_attrib_binding 扩展,它成为 OpenGL 4.3 的核心。这允许您将属性布局与数据位置分开。文章在OpenGL wiki提供了有关如何执行此操作的信息,但同样最好使用相同的 UV 为给定网格创作所有纹理。

关于将所有内容合并为一个 VAO 和 VBO 的问题:如果您只想要矩形,则没有必要这样做,因为您可以获得任何类型的矩形,您希望使用具有非均匀缩放分量的仿射变换。这样一共只需要一个VAO和一个VBO,不需要合并任何东西。

关于c++ - 具有不同纹理 UV 的矩形实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25046849/

相关文章:

c++ - 只允许访问某些方法以引导子项

c++ - 如何用C++获取MongoDB的当前实例?

c++ - 没有纹理图像单元的 Opengl 纹理

c++ - 不同大小的着色器存储缓冲区内容 "transfered"到数组缓冲区

c++ - OpenGL:未定义 VBO 函数

c++ - 无法继承 clang 和 gcc 中同一类的显式模板特化

c++ - 将字符缓冲区转换为结构

c++ - 如何根据时间或某些功能动态更改每个顶点的颜色?

java - 网格 : some triangles are connected and shouldn't [2D] 的 VBO 不正确

c++ - 使用 VBO 的 OpenGL 绘图