[英]Qt & OpenGL : render a 2D texture
我正在嘗試使用 Qt 和 OpenGL 渲染我的第一個紋理。
這是代碼。
初始化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函數
void OpenGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, nullptr);
}
頂點着色器
#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;
}
片段着色器
#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);
}
}
這就是結果
如您所見,片段着色器中紋理函數生成的所有顏色都是黑色,因此if語句選擇紋理坐標作為顏色而不是真實的紋理顏色。
我試圖捕捉一些錯誤,但回調函數沒有發現代碼中的錯誤。 我還嘗試了另一個圖像(PNG 格式而不是 SVG),但結果是一樣的。
如果你想加載一個PNG文件,那么你可以直接將它加載到一個QImage
,
QImage image("../test.png");
但是如果你想渲染 SVG 文件,那么你必須使用QSvgRenderer
和QPainter
將內容繪制到QImage
。 您必須選擇目標位圖的格式、分辨率和背景顏色:
例如:
#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();
請注意,您必須分別鏈接qt5svgd.lib (調試)和qt5svg.lib (發布)。
默認的縮小函數參數( GL_TEXTURE_MIN_FILTER
)是GL_NEAREST_MIPMAP_LINEAR
。 見glTexParameteri
這意味着您必須將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);
或者你必須創建 mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image_bits);
glGenerateMipmap(GL_TEXTURE_2D);
在initializeGL
方法中,紋理綁定到紋理單元 0,但不能保證這仍然是paintGL
方法中的當前狀態。 你必須在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.