[英]Can I texture this cube that is rendered in GL_TRIANGLE_STRIP mode?
I'm trying to render and texture a cube using GL_TRIANGLE_STRIP mode.我正在尝试使用 GL_TRIANGLE_STRIP 模式渲染和纹理立方体。
The cube's base info is in the following arrays.多维数据集的基本信息在以下数组中。 It gets loaded correctly, and the shape is OK.
它被正确加载,形状还可以。
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
};
In order to construct this simplistic cube data, I referenced this image:为了构建这个简单的立方体数据,我引用了这张图片:
Now for texturing, can I add texture coordinates to this cube?现在对于纹理,我可以向这个立方体添加纹理坐标吗? Or is it cursed to be shaded with flat colors?
还是被诅咒被单色遮蔽?
If I had to answer my own question with logic, I'd say texturing it is impossible like this, but maybe someone knows a way?如果我必须用逻辑来回答我自己的问题,我会说像这样纹理化它是不可能的,但也许有人知道一种方法?
What a nice puzzle… – Just the right warm-up before going back to business.多么美妙的谜题…… – 重新开始工作前的正确热身。
I see two possible solutions:我看到两种可能的解决方案:
For the cube texture mapping, I'd like to refer to Learn OpenGL – Cubemaps .对于立方体纹理映射,我想参考Learn OpenGL – Cubemaps 。
So, the vertex coordinates should be usable as texture coordinates as well.因此,顶点坐标也应该可用作纹理坐标。
The original approach of OP won't work with a single texture because there are vertices with same coordinates but distinct texture coordinates. OP 的原始方法不适用于单个纹理,因为存在具有相同坐标但不同纹理坐标的顶点。
So, I would end up with a new array of pairs with 14 coordinates and 14 texture coordinates (or two corresponding arrays).所以,我最终会得到一个包含 14 个坐标和 14 个纹理坐标(或两个相应的数组)的新数组。
While I tried to apply this to the unwrapping of OP, I came to the conclusion that even this is not possible.当我尝试将其应用于 OP 的展开时,我得出的结论是,即使这也是不可能的。 Eg coordinates 3 and 4 appear at the top and bottom of the unwrapped cube → resulting again in two distinct texture coordinates for the same vertex.
例如坐标 3 和 4 出现在展开立方体的顶部和底部 → 再次导致同一顶点的两个不同的纹理坐标。
For my luck, I already solved the cube-with-one-triangle-strip-puzzle (many) years ago (when OpenGL Performer still was state-of-the-art).幸运的是,我已经在很多年前(当时OpenGL Performer仍然是最先进的)解决了带有一个三角形条带的立方体拼图。 Looking into my old notes, I found that my unwrapping was much better fitting for the intended texturing.
查看我的旧笔记,我发现我的展开更适合预期的纹理。
starting with the red triangle and ending with the blue.
以红色三角形开始,以蓝色结束。
I copy/pasted the coordinates from that old sample:我复制/粘贴了那个旧样本的坐标:
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
};
So, all I had to do was to use the sketch as texture and write down the resp.所以,我所要做的就是使用草图作为纹理并写下相应的内容。 texture coordinates:
纹理坐标:
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
};
To check this out, I applied this to a minimal QOpenGLWidget
sample which I found in my personal folder using the above image as texture.为了检查这一点,我将其应用于我在个人文件夹中找到的最小
QOpenGLWidget
示例,使用上面的图像作为纹理。
testQOpenGLTexCube.cc
: 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();
}
Output:输出:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.