最近因为工作所需,需要采用GPU绘制视频,那么就需要学习OpenGL了; 在学习纹理时,接触的第一个例子是《霍亚飞-Qt Creator快速入门_第三版》中第12章-12.4-使用纹理绘图,然而按照书中所示代码运行时,运行时只显示一个黑窗口,并没有将纹理给贴出来;倒腾了一番功夫,终于跑起来了,先记录一下,后续,,,,,,
QOpenGLShader::compile(Fragment): ERROR: 3:6: ‘texture’ : no matching overloaded function found (using implicit conversion)
ERROR: 3:6: ‘texture’ : function is not known
ERROR: 3:5: ‘assign’ : cannot convert from ‘const highp float’ to ‘FragUserData 4-component vector of highp float’
*** Problematic Fragment shader source code ***
#version 130 core
#define lowp
#define mediump
#define highp
#line 1
uniform sampler2D tex;
in vec4 texCoord;
out vec4 fColor;
void main() {
fColor = texture(tex, texCoord);
}
1. 定位到的报错的代码:
2. 错误的运行结果:
以上是截取的部分关键代码,从错误提示以及运行测试,可以明确的定位错误就是由于红框中的texture()函数引起的,这个是OpenGL内置的函数;但是为什么出错,这心里是一点思路都没有,毕竟这个OpenGL对我来说还是相当陌生的;百度了一圈,也没有相关解答,试了各种方法,均是不行;
最后参考可Qt自带的OpenGL相关的demo,发现需要将texture()函数中的第二个参数加.st后缀,
此时运行就ok了!
3. 改变后的代码:
4. 运行的正确结果:
5. 源码:
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QMatrix4x4>
#include <QOpenGLTexture>
#include <QDebug>
/*纹理贴图*/
class OpenGLWidget5 : public QOpenGLWidget, QOpenGLFunctions
{
Q_OBJECT
public:
OpenGLWidget5(QWidget* parent = nullptr);
protected:
void initializeGL() override;
void paintGL() override;
private:
QOpenGLShaderProgram* m_program = nullptr;
QOpenGLBuffer* m_buffer = nullptr;
QOpenGLTexture* m_textures[2] ;
};
#include "OpenGLWidget5.h"
OpenGLWidget5::OpenGLWidget5(QWidget *parent)
:QOpenGLWidget(parent)
{
m_buffer = new QOpenGLBuffer;
}
void OpenGLWidget5::initializeGL()
{
initializeOpenGLFunctions();
for(int i = 0; i < 2; i++) {
m_textures[i] = new QOpenGLTexture(QImage(QString(":/image/side%1.png").arg(i+1)).mirrored());
}
const char* vsrc = "in vec4 vPosition;\n"
"in vec4 vTexCoord;\n"
"out vec4 texCoord;\n"
"uniform mat4 matrix;\n"
"void main() {\n"
" texCoord = vTexCoord;\n"
" gl_Position = matrix * vPosition;\n"
"}\n";
QOpenGLShader* vsShader = new QOpenGLShader(QOpenGLShader::Vertex, this);
vsShader->compileSourceCode(vsrc);
/***********************************************************************************/
const char* fsrc = "#version 130 core\n"
"uniform sampler2D tex;\n"
"in vec4 texCoord;\n"
"out vec4 fColor;\n"
"void main() {\n"
" fColor = texture(tex, texCoord.st);\n"
"}\n";
QOpenGLShader* fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
fshader->compileSourceCode(fsrc);
/***********************************************************************************/
m_program = new QOpenGLShaderProgram;
m_program->addShader(vsShader);
m_program->addShader(fshader);
m_program->link();
m_program->bind();
}
void OpenGLWidget5::paintGL()
{
int side = qMin(width(), height());
glViewport((width() - side) / 2, (height() - side) / 2, side, side);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
GLfloat vertices[2][4][3] = {
{
{ -0.8f, 0.8f, 0.8f },
{ -0.8f, -0.8f, 0.8f },
{ 0.8f, -0.8f, 0.8f },
{ 0.8f, 0.8f, 0.8f }
},
{
{ 0.8f, 0.8f, 0.8f },
{ 0.8f, -0.8f, 0.8f },
{ 0.8f, -0.8f, -0.8f },
{ 0.8f, 0.8f, -0.8f }
}
};
//
m_buffer->create();
m_buffer->bind();
m_buffer->allocate(vertices, 48 * sizeof(GLfloat));
//
GLuint vPosition = m_program->attributeLocation("vPosition");
m_program->setAttributeBuffer(vPosition, GL_FLOAT, 0, 3, 0);
glEnableVertexAttribArray(vPosition);
//
GLfloat coords[2][4][2] = {
{
{ 1.0f, 0.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f },
{ 1.0f, 1.0f }
},
{
{ 1.0f, 0.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f },
{ 1.0f, 1.0f }
}
};
m_buffer->write(24 * sizeof(GLfloat), coords, 16 * sizeof(GLfloat));
GLuint vTexCoord = m_program->attributeLocation("vTexCoord");
m_program->setAttributeBuffer(vTexCoord, GL_FLOAT, 24 * sizeof(GLfloat), 2, 0);
glEnableVertexAttribArray(vTexCoord);
m_program->setUniformValue("tex", 0);
//
QMatrix4x4 matrix;
matrix.perspective(45.0f, (GLfloat)width() / (GLfloat)height(), 0.1f, 100.0f);
matrix.translate(0, 0, -3);
matrix.rotate(-60, 0, 1, 0);
m_program->setUniformValue("matrix", matrix);
//
for(int i = 0 ;i < 2; i++) {
m_textures[i]->bind();
glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
}
}