简体   繁体   English

Qt 和 OpenGL:渲染 2D 纹理

[英]Qt & OpenGL : render a 2D texture

I'm trying to render my first texture with Qt & OpenGL.我正在尝试使用 Qt 和 OpenGL 渲染我的第一个纹理。

This is the code.这是代码。

initializeGL function初始化GL函数

void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    glEnable(GL_DEBUG_OUTPUT);
    glDebugMessageCallback(debugCallback, nullptr);

    program = genProgram("../06_HelloTexture/vert.glsl", "../06_HelloTexture/frag.glsl");
    glUseProgram(program);

    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);

    // vertices is std::vector<QVector3D>
    vertices = {
        {-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 0.0f},
        {-0.5f, +0.5f, 0.0f}, {0.0f, 1.0f, 0.0f},
        {+0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f},
        {+0.5f, +0.5f, 0.0f}, {1.0f, 1.0f, 0.0f},
    };

    // indices is std::vector<GLuint>
    indices = {
        0, 1, 2,
        1, 2, 3,
    };

    GLuint VAO, VBO, EBO;

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(QVector3D), &vertices[0], GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLuint), &indices[0], GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2*sizeof(QVector3D), static_cast<void*>(nullptr));
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 2*sizeof(QVector3D), (void*)sizeof(QVector3D));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    QImage image("../lightbulb-solid.svg");
    // QImage image("../test.png");
    qDebug() << image;
    // this outputs
    // QImage(QSize(352, 512),format=6,depth=32,devicePixelRatio=1,bytesPerLine=1408,sizeInBytes=720896)

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
    // glGenerateMipmap(GL_TEXTURE_2D);

    lightbulbSolidLocation = glGetUniformLocation(program, "lightbulbSolid");
    glUniform1i(lightbulbSolidLocation, 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
}

paintGL function PaintGL函数

void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, nullptr);
}

vertex shader顶点着色器

#version 450 core
layout (location = 0) in vec3 vertPosition;
layout (location = 1) in vec3 vertTexCoord;

out vec3 fragTexCoord;

void main()
{
    gl_Position = vec4(vertPosition, 1.0);
    fragTexCoord = vertTexCoord;
}

fragment shader片段着色器

#version 450 core
in vec3 fragTexCoord;
out vec4 pixelColor;

uniform sampler2D lightbulbSolid;

void main()
{
    // pixelColor = vec4(fragColor, 1.0f);
    // pixelColor = texture(lightbulbSolid, vec2(fragTexCoord.x, fragTexCoord.y));

    vec4 temp = texture(lightbulbSolid, vec2(fragTexCoord.x, fragTexCoord.y));

    if (!all(equal(temp.xyz, vec3(0.0f))))
    {
        pixelColor = temp;
    }
    else
    {
        pixelColor = vec4(fragTexCoord, 1.0f);
    }
}

And this is the result这就是结果

在此处输入图片说明

As you can see, all the colors generated by the texture function in the fragment shader are black, so the if statement choose the texture coordinate as color rather than the real texture color.如您所见,片段着色器中纹理函数生成的所有颜色都是黑色,因此if语句选择纹理坐标作为颜色而不是真实的纹理颜色。

I tried to catch some error, but the callback function didn't find something wrong in the code.我试图捕捉一些错误,但回调函数没有发现代码中的错误。 I also tried with another image (of PNG format rather than SVG), but the result is the same.我还尝试了另一个图像(PNG 格式而不是 SVG),但结果是一样的。

If you want to load a PNG file, then you can load it to a QImage directly,如果你想加载一个PNG文件,那么你可以直接将它加载到一个QImage

QImage image("../test.png");

but if you want to render SVG file, then you have to use the QSvgRenderer and QPainter to paint the content to an QImage .但是如果你想渲染 SVG 文件,那么你必须使用QSvgRendererQPainter将内容绘制到QImage You have to choose the format, the resolution and the background color of the target bitmap:您必须选择目标位图的格式、分辨率和背景颜色:

eg:例如:

#include <Qtsvg/QSvgRenderer>

QSvgRenderer renderer(QString("../lightbulb-solid.svg"));

QImage image(512, 512, QImage::Format_RGBA8888);  // 512x512 RGBA
image.fill(0x00ffffff);                           // white background

QPainter painter(&image);
renderer.render(&painter);

const uchar *image_bits = image.constBits();
int          width      = image.width();
int          height     = image.height();

Note, you have to link qt5svgd.lib (debug) respectively qt5svg.lib (release).请注意,您必须分别链接qt5svgd.lib (调试)和qt5svg.lib (发布)。


The default minifying function parameter ( GL_TEXTURE_MIN_FILTER ) is GL_NEAREST_MIPMAP_LINEAR .默认的缩小函数参数( GL_TEXTURE_MIN_FILTER )是GL_NEAREST_MIPMAP_LINEAR See glTexParameteriglTexParameteri

This means either you have to change the GL_TEXTURE_MIN_FILTER parameter to GL_LINEAR这意味着您必须将GL_TEXTURE_MIN_FILTER参数更改为GL_LINEAR

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, image_bits);

or you have to create mipmaps或者你必须创建 mipmap

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, image_bits);

glGenerateMipmap(GL_TEXTURE_2D);

In the initializeGL method the texture is bound to texture unit 0, but it is not guaranteed, that this is still the current state in the paintGL method.initializeGL方法中,纹理绑定到纹理单元 0,但不能保证这仍然是paintGL方法中的当前状态。 You have to bind the texture in the paintGL method:你必须在paintGL方法中绑定纹理:

void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, nullptr);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM