Могу ли я текстурировать этот куб, который отображается в режиме GL_TRIANGLE_STRIP? - PullRequest
2 голосов
/ 05 марта 2020

Я пытаюсь визуализировать и текстурировать куб, используя режим GL_TRIANGLE_STRIP.

Базовая информация о кубе находится в следующих массивах. Он загружается правильно, и форма в порядке.

    float vertexData[24] = { //Coordinates for the vertices of a cube.
    //vertices
     1, 1, -1,
     -1, 1, -1,
     1, -1, -1,
     -1, -1, -1,
     1, 1, 1,
     -1, 1, 1,
     -1, -1, 1,
     1, -1, 1
    };

    int vertexDrawIndices[14] = {  //Draw order for vertices in GL_TRIANGLE_STRIP mode.
       3,2,6,7,4,2,0,3,1,6,5,4,1,0
    };

Чтобы построить эти упрощенные c данные куба, я ссылался на это изображение: rendering a cube in one triangle strip

Теперь для текстурирования, я могу добавить координаты текстуры к этому кубу? Или это проклято, чтобы быть заштрихованным плоскими цветами?

Если бы я должен был ответить на свой вопрос с помощью логики c, я бы сказал, что текстурирование невозможно, как это, но, возможно, кто-то знает способ?

1 Ответ

2 голосов
/ 05 марта 2020

Какая замечательная головоломка ... - Просто правильная разминка, прежде чем вернуться к делу.

Я вижу два возможных решения:

  1. Использование текстуры куба
  2. Изменение данных вершин.

Для отображения текстуры куба я хотел бы обратиться к Learn OpenGL - Cubemaps . Таким образом, координаты вершин также должны использоваться в качестве текстурных координат.

Оригинальный подход OP не будет работать с одной текстурой, поскольку есть вершины с такими же координатами, но с разными координатами текстуры.

Итак, я получу новый массив пар с 14 координатами и 14 координатами текстуры (или двумя соответствующими массивами).

Пока я пытался применить это для развертывания OP, я пришел к выводу что даже это невозможно. Например, координаты 3 и 4 появляются в верхней и нижней части развернутого куба → в результате снова получаются две разные текстурные координаты для одной и той же вершины.

К счастью, я уже решил куб-с-одним-треугольником- Стрип-пазл (много) лет go (когда OpenGL Performer все еще был современным). Просматривая мои старые заметки, я обнаружил, что моя распаковка намного лучше подходила для предполагаемого текстурирования.

a cube unwrapped into a triangle strip, начиная с красного треугольника и заканчивая синим.

Я скопировал / вставил координаты из этого старого образца:

  const GLfloat x0 = -1, x1 = 1, y0 = -1, y1 = 1, z0 = -1, z1 = 1;
  const GLfloat coords[] = {
    x0, y1, z1,
    x0, y0, z0,
    x0, y0, z1,
    x1, y0, z1,
    x0, y1, z1,
    x1, y1, z1,
    x1, y1, z0,
    x1, y0, z1,
    x1, y0, z0,
    x0, y0, z0,
    x1, y1, z0,
    x0, y1, z0,
    x0, y1, z1,
    x0, y0, z0
  };

Итак, все, что мне нужно было сделать, это использовать эскиз в качестве текстуры и записать соотв. координаты текстуры:

  const GLfloat s0 = 0, s1 = 1.f / 5, s2 = 2.f / 5, s3 = 3.f / 5, s4 = 4.f / 5, s5 = 1;
  const GLfloat t0 = 0, t1 = 1.f / 5, t2 = 2.f / 5, t3 = 3.f / 5, t4 = 4.f / 5, t5 = 1;
  const GLfloat texCoords[] = {
    s0, t1,
    s1, t0,
    s1, t1,
    s2, t1,
    s1, t2,
    s2, t2,
    s2, t3,
    s3, t2,
    s3, t3,
    s4, t3,
    s3, t4,
    s4, t4,
    s4, t5,
    s5, t4
  };

Чтобы проверить это, я применил это к минимальному семплу QOpenGLWidget, который я нашел в своей личной папке, используя изображение выше в качестве текстуры.

testQOpenGLTexCube.cc :

#include <QtWidgets>
#include <QOpenGLFunctions_3_3_Compatibility>

class GLWidget: public QOpenGLWidget,
  protected QOpenGLFunctions_3_3_Compatibility
{
  private:
    QOpenGLTexture *_pGLTex;
    QOpenGLShaderProgram *_pGLPrg;
    GLuint _coordAttr;
    GLuint _texCoordAttr;
    GLuint _matUniform;
    double _t;
    QMatrix4x4 _matProj;
    QTimer _qTimerAnim;

  public:

    GLWidget(QWidget *pQParent = nullptr):
      QOpenGLWidget(pQParent),
      _pGLTex(nullptr), _pGLPrg(nullptr), _t(0)
    {
      QObject::connect(&_qTimerAnim, &QTimer::timeout,
        [this]() { _t += 0.1; update(); });
    }

    virtual ~GLWidget() = default;

    GLWidget(const GLWidget&) = delete;
    GLWidget& operator=(const GLWidget&) = delete;

  public:

    virtual QSize minimumSizeHint() const
    {
      return QSize(50, 50);
    }
    virtual QSize sizeHint() const
    {
      return QSize(400, 400);
    }

  protected:

    virtual void initializeGL();
    virtual void resizeGL(int width, int height);
    virtual void paintGL();

};

static const char *vertexShaderSource =
  "# version 330\n"
  "layout (location = 0) in vec3 coord;\n"
  "layout (location = 1) in vec2 texCoord;\n"
  "uniform mat4 mat;\n"
  "out vec2 texCoordVtx;\n"
  "void main() {\n"
  "  texCoordVtx = texCoord;\n"
  "  gl_Position = mat * vec4(coord, 1.0);\n"
  "}\n";

static const char *fragmentShaderSource =
  "#version 330\n"
  "in vec2 texCoordVtx;\n"
  "uniform sampler2D tex;\n"
  "out vec4 colorFrag;\n"
  "void main() {\n"
  "  colorFrag = texture2D(tex, texCoordVtx.xy);\n"
  "}\n";

void GLWidget::initializeGL()
{
  initializeOpenGLFunctions();
  glClearColor(0.525f, 0.733f, 0.851f, 1.0f);
  _qTimerAnim.start();
}

void GLWidget::resizeGL(int w, int h)
{
  _matProj.setToIdentity();
  _matProj.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f);
}

void GLWidget::paintGL()
{
  const qreal retinaScale = devicePixelRatio();
  glViewport(0, 0, width() * retinaScale, height() * retinaScale);
  // clear screen
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  // create texture if not yet done
  if (!_pGLTex) {
    _pGLTex = new QOpenGLTexture(QImage("cube-tex.png").mirrored());
    _pGLTex->setMagnificationFilter(QOpenGLTexture::Nearest);
    _pGLTex->setMinificationFilter(QOpenGLTexture::Nearest);
  }
  // create shader program if not yet done
  if (!_pGLPrg) {
    _pGLPrg = new QOpenGLShaderProgram(this);
    _pGLPrg->addShaderFromSourceCode(QOpenGLShader::Vertex,
      vertexShaderSource);
    _pGLPrg->addShaderFromSourceCode(QOpenGLShader::Fragment,
      fragmentShaderSource);
    _pGLPrg->link();
    _coordAttr = _pGLPrg->attributeLocation("coord");
    _texCoordAttr = _pGLPrg->attributeLocation("texCoord");
    _matUniform = _pGLPrg->uniformLocation("mat");
    _pGLPrg->setUniformValue("tex", 0);
  }
  // render textured cube
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  _pGLPrg->bind();
  _pGLTex->bind();
  QMatrix4x4 mat = _matProj;
  mat.translate(0, 0, -5);
  mat.rotate(_t, -1.0, -1.0, 1.0);
  _pGLPrg->setUniformValue(_matUniform, mat);
  const GLfloat x0 = -1, x1 = 1, y0 = -1, y1 = 1, z0 = -1, z1 = 1;
  const GLfloat coords[] = {
    x0, y1, z1,
    x0, y0, z0,
    x0, y0, z1,
    x1, y0, z1,
    x0, y1, z1,
    x1, y1, z1,
    x1, y1, z0,
    x1, y0, z1,
    x1, y0, z0,
    x0, y0, z0,
    x1, y1, z0,
    x0, y1, z0,
    x0, y1, z1,
    x0, y0, z0
  };
  const GLfloat s0 = 0, s1 = 1.f / 5, s2 = 2.f / 5, s3 = 3.f / 5, s4 = 4.f / 5, s5 = 1;
  const GLfloat t0 = 0, t1 = 1.f / 5, t2 = 2.f / 5, t3 = 3.f / 5, t4 = 4.f / 5, t5 = 1;
  const GLfloat texCoords[] = {
    s0, t1,
    s1, t0,
    s1, t1,
    s2, t1,
    s1, t2,
    s2, t2,
    s2, t3,
    s3, t2,
    s3, t3,
    s4, t3,
    s3, t4,
    s4, t4,
    s4, t5,
    s5, t4
  };
  glVertexAttribPointer(_coordAttr, 3, GL_FLOAT, GL_FALSE, 0, coords);
  glVertexAttribPointer(_texCoordAttr, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
  glDisableVertexAttribArray(1);
  glDisableVertexAttribArray(0);
  // done
  _pGLTex->release(); _pGLPrg->release();
}

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  // setup GUI
  QMainWindow qMainWin;
  GLWidget glWidget;
  qMainWin.setCentralWidget(&glWidget);
  qMainWin.show();
  // runtime loop
  return app.exec();
}

Выход:

Snapshot of testQOpenGLTexCube

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...