我正在学习如何在OpenGL中对四边形进行纹理处理。这个想法是让图像在整个四边形上重复,但是我正在拉伸图像并且形成四边形的两个三角形是可见的。
我错过了什么?代码如下所示
void GLViewer::initializeGL()
{
float vertices[] =
{
-0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.5, 0.5, 0.0
};
// Setup viewport
glViewport(0, 0,this->width(), this->height());
// OpenGL configuration
glClearColor(0.0f,0.0f,0.0f,1.0f);
// Setup shaders
m_triangleShader.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl");
m_triangleShader.addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl");
m_triangleShader.link();
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glPointSize(10);
glGenBuffers(1, &m_VBO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
float quad[] =
{
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0
};
float uv[] =
{
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
};
m_backgroundShader.addShaderFromSourceFile(QGLShader::Vertex, ":/vbackground.glsl");
m_backgroundShader.addShaderFromSourceFile(QGLShader::Fragment, ":/fbackground.glsl");
m_backgroundShader.link();
glGenVertexArrays(1, &m_backgroundVAO);
glBindVertexArray(m_backgroundVAO);
glGenBuffers(1, &m_quadVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &m_uvVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenTextures(1, &m_textureID);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
QImage image(":/background.png");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(),
0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void GLViewer::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
m_backgroundShader.bind();
glBindVertexArray(m_backgroundVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glUniform1i(glGetUniformLocation(m_backgroundShader.programId(),"tex"),0);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
m_triangleShader.bind();
glBindVertexArray(m_VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
update();
}
为什么你希望你的纹理被你使用的代码重复(以及重复多少次)?
但是,按原样代码与您的观察结果一致。您使用的是 [0,1] 范围内的 texcoord,因此,如果您在对纹理进行采样之前没有调整 texcoord,您应该只看到划到四边形的图像。 您可以通过到目前为止尚未粘贴的着色器来执行此操作。如果希望纹理沿u
维度平铺显示 n
次平铺,沿v
平铺显示 m
次,则需要分别对u
范围使用 [0,n]
,对v
范围使用 [0,m]
。
第二个问题是您的 texcoords 与您的几何图形不匹配。这可能会导致您描述的"形成四边形的两个三角形是可见的"。你的两个三角形不会在你期望的纹理空间中建立四边形,你应该交换最后两行:
float uv[] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, /* should be 0.0, 1.0 */ 0.0, 1.0 /* should be 1.0, 1.0 */ };