【问题标题】:OpenGL Mapping Textures to a Grid Stored Inside Vertex ArrayOpenGL 将纹理映射到存储在顶点数组中的网格
【发布时间】:2012-09-09 03:27:25
【问题描述】:

我的代码使用索引和顶点来绘制一组网格形状的三角形。所有顶点均使用glDrawElements() 绘制。现在对于每个顶点,对于在网格中形成正方形的每组三角形,我将其对应的纹理坐标设置为 0 或 1。基本上我想在每个“正方形”(由两个三角形组成)中绘制一个collage 的随机纹理。我可以使用固定功能管道在 for 循环中使用 glBegin()glEnd() 方法调用来做到这一点,但我想知道如何使用 Vertex Arrays 做到这一点。下面是我正在尝试做的代码视图。

#include "glwidget.h"

GLWidget::GLWidget(QWidget *parent, QGLWidget *glparent) :
    QGLWidget(parent, glparent),
    texture_ids_(NULL),
    col_(30),
    row_(30),
    step_(16.0)
{
    texture_ids_ = new GLuint[row_ * col_];
}

GLWidget::~GLWidget()
{
    if (texture_ids_) {
        glDeleteTextures(row_ * col_, texture_ids_);
    }
}

void GLWidget::resizeEvent(QResizeEvent * /*event*/) {
    initGL();

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0, 0, width(), height());
    glOrtho(0, width(), 0, height(), -1, 1);
}

void GLWidget::initGL()
{
    makeCurrent();
    // Variables for vertices
    vertices_.clear();
    int32_t start_y = step_;
    int32_t start_x = step_;

    // Varaibles for indices
    indices_.clear();
    int32_t vertices_per_row = col_ + 1;
    int32_t vertex_num = 0;

    for (int32_t j = 0; j <= row_; ++j) {
        // Generate Vertices on row j
        for (int32_t i = 0; i <= col_; ++i) {
            vertices_.push_back(Vertex<GLfloat>((start_x + (i * step_)),
                (start_y + (j * step_)), 0.0f));
        }

        if (j == row_) {
            break;
        }

        // Generate Indices to get right vertices for traingle
        for (int32_t i = 0; i < col_; ++i) {
            indices_.push_back(Indices<GLuint>(vertex_num, (vertex_num + 1), 
                (vertex_num + vertices_per_row)));

            indices_.push_back(Indices<GLuint>((vertex_num + 1), 
                (vertex_num + vertices_per_row), 
                (vertex_num + vertices_per_row + 1)));

            vertex_num++;
        }
        vertex_num++;
    }
}


void GLWidget::textureInit()
{
    makeCurrent();
    for (int32_t i = 0; i < row_ * col_; ++i) {
        QImage tmpQImage(step_, step_, QImage::Format_ARGB32);
        tmpQImage = QGLWidget::convertToGLFormat(tmpQImage);

        QPainter tmpQPainter;
        tmpQPainter.begin(&tmpQImage);
            tmpQPainter.fillRect(QRect(0, 0, width(), height()),
                QColor(255, 0, 0));
            tmpQPainter.setRenderHint(QPainter::Antialiasing, true);
        tmpQPainter.end();

        glGenTextures(1, &texture_ids_[i]);
        glBindTexture(GL_TEXTURE_2D, texture_ids_[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tmpQImage.width(),
            tmpQImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
            tmpQImage.bits());
    }
}

void GLWidget::updateGL() {
    if (first_render_) {
        textureInit();
        first_render_ = false;
    }

    glMatrixMode(GL_MODELVIEW);
    glScissor(0, 0, width(), height());
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
    glLoadIdentity();

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices_.data());
    glDrawElements(GL_TRIANGLES, indices_.size() * 3, GL_UNSIGNED_INT,
        indices_.data());
    glDisableClientState(GL_VERTEX_ARRAY);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

【问题讨论】:

  • 如何在没有 for 循环的情况下在网格内映射多个纹理?
  • 如何在一个网格中映射多个纹理with for 循环?您是在谈论绘制一个四边形,然后绑定一个新纹理,然后绘制一个新的四边形吗?还是您只是在谈论绘制多个独立的四边形?
  • Subversion 提交弄乱了我的代码,我正在更正,然后将在几秒钟内重新发布。当我将代码粘贴到窗口中时,我注意到了代码中的错误。给我5,我应该把它备份。简而言之。我创建了一次网格,并将其存储到 std::vector 中。然后我使用 glDrawElements 通过一个方法调用将顶点渲染到屏幕上。因此,我无法加载多个纹理并将它们绑定到一对“GL_TRIANGLES”。

标签: opengl textures vertex-array


【解决方案1】:

因此,您想使用大量纹理进行绘制,但显然无法重新绑定新纹理,因为它们都是从一个数组中绘制的。一种解决方案是使用texture atlas。它是一个包含所有纹理的位图。例如,如果您有 16 个不同的纹理,您可以制作一个具有 4x4 部分的位图。您将使用 0 到 0.25,或 0.25 到 0.50 等,而不是使用从 0 到 1 的纹理坐标。

您需要注意一些缺点:

  1. 如果你想要高分辨率,纹理图集显然会很大。
  2. 缩小和放大可以和你开玩笑。 GL_NEAREST 不会有任何问题,但使用 GL_LINEAR 或 mipmapping 的变体将平均一个像素左右的值。这可能会导致一个子图像边界处的像素出现伪影。
  3. 随着 UV 坐标的变化更大,具有公共顶点数据的顶点将减少,从而导致索引数量增加。

我假设您已经完成了配置文件,表明使用多次绘图迭代,为每个迭代重新绑定纹理是不够的。这种显而易见的解决方案可能非常有效。

【讨论】:

  • 阵列纹理怎么样?这会是一个选择吗? opengl.org/wiki/Array_Texture
  • 是的,他们会做同样的事情。您将需要三个 UV 编号来使用它们(两个用于坐标,一个用于数组索引)。但是那样的话,你就不会有边界问题的缺点了。
猜你喜欢
  • 2014-04-23
  • 2012-04-16
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多