0

我有代码使用索引和顶点来绘制一组网格形状的三角形。所有顶点都是使用glDrawElements()绘制的。现在对于每个顶点,对于在网格中形成正方形的每组三角形,我将其对应的纹理坐标设置为 0 或 1。基本上我想在每个“正方形”(由两个三角形组成)中绘制一张随机纹理的拼贴画。我可以使用固定功能管道在 for 循环中使用glBegin()andglEnd()方法调用来做到这一点,但我想知道如何使用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);
}
4

1 回答 1

1

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

您需要注意一些缺点:

  1. 如果你想要高分辨率,纹理图集显然会很大。
  2. 缩小和放大可以和你开玩笑。GL_NEAREST 不会有任何问题,但使用 GL_LINEAR 或 mipmapping 的变体将平均一个像素左右的值。这可能会导致一个子图像边界处的像素出现伪影。
  3. As the UV coordinates will vary more, fewer vertices will have common vertex data, leading to a increased number of indices.

I assume you have done profiling that shows that using multiple iterations of drawing, rebinding the texture for each, is not good enough. This obvious solution can be surprisingly effective.

于 2012-09-09T05:29:56.940 回答