Carregando texturas dinamicamente para o modelo 3D
Nesta seção vamos fazer algo parecido com que fizemos para o carregamento de modelos 3D. Só que, agora, vamos carregar imagens de textura para serem aplicadas dinamicamente no modelo 3D carregado.
A primeira coisa que precisamos fazer é criar uma textura padrão para o modelo 3D recém carregado. Devemos fazer isso porque quando carregamos um modelo 3D para o nosso programa, os descritores de uniform buffer e de imagem e sampler combinados são criados juntos. Se fôssemos criar os descritores de imagem e sampler combinados apenas depois do carregamento da imagem de textura, teríamos que criar um pipeline com vertex e fragment shaders diferentes, sendo um para casa situação.
A textura padrão para o um modelo 3D recém carregado será uma imagem toda cinza. Podemos criar uma imagem de tamanho qualquer toda cinza em qualquer programa de edição de imagem, ou podemos fazer o download da imagem disponível em https://commons.wikimedia.org/wiki/File:Solid_gray.png.
Salvamos a imagem na pasta textures
com o nome default.png
. Em seguida adicionamos essa imagem aos recursos do Qt. Para fazer isso, clicamos com o botão direito no aquivo resources.qrc
no Qt Creator, depois, clicamos em Add Existing Files… e selecionamos o arquivo default.png
na pasta textures
.
Definimos uma variável estática constante em renderer.cpp
com o caminho para essa imagem:
static const QString DEFAULT_TEXTURE_PATH =
":/textures/default.png";
E modificamos a chamada para a função addTextureImage
em initObject
para carregar a imagem desse caminho:
addTextureImage(DEFAULT_TEXTURE_PATH);
Agora vamos adicionar à janela principal um botão para carregar uma textura para nosso objeto 3D. Damos um clique duplo em mainwindow.ui
na árvore do projeto, arrastamos e soltamos um objeto Push Button para a interface do usuário e posicionamos-o ao lado do botão Load Model. Alteramos a propriedade text
desse botão de “PushButton” para “Load Texture” e alteramos o campo objectName
para “loadTextureButton”.
Vamos fazer com que esse botão abra uma janela de diálogo para a escolha de um arquivo de imagem que será carregado para nosso modelo. Para isso, criamos um slot em MainWindow
chamado loadTexture
:
public slots:
void loadModel();
void loadTexture();
...
void MainWindow::loadTexture() {
const QString fileName =QFileDialog::getOpenFileName(
this,
tr("Open Image"),
QDir::homePath(),
tr("Image Files (*.png *.jpg *.bmp)")
);
}
Essa função é semelhante a função loadModel
, no lugar de “Open 3D Model” colocamos “Open Image”, no lugar de “3D Model Files (*.obj *.OBJ)”, “Image Files (*.png *.jpg *.bmp)”.
if (!fileName.isEmpty()) {
m_vulkanWindow->renderer()->addTextureImage(fileName);
}
Depois de obter a localização do arquivo de imagem, chamamos a função Renderer::addTextureImag
e com esse parâmetro.
if (!fileName.isEmpty()) {
QSharedPointer<Model> model =
QSharedPointer<Model>::create();
model->readOBJFile(fileName);
m_vulkanWindow->renderer()->addObject(model);
ui->loadTextureButton->setEnabled(true);
}
Atualizamos a função loadModel
para habilitar o botão loadTextureButton
depois que o modelo 3D for carregado.
Podemos então conectar o slot loadTexture
ao sinal loadModelButton::clicked
no construtor de MainWindow
da mesma forma que fizemos anteriormente:
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainWindow) {
...
connect(
ui->loadModelButton,
SIGNAL(clicked()),
this,
SLOT(loadModel())
);
connect(
ui->loadTextureButton,
SIGNAL(clicked()),
this,
SLOT(loadTexture())
);
ui->loadTextureButton->setEnabled(false);
}
Inicializamos o botão loadTextureButton
para desativado (false
), pois não queremos esse botão ativo antes de um modelo ser carregado.
Agora podemos carregar dinamicamente imagens de textura para o modelo 3D carregado. Para fazer um teste, podemos utilizar o arquivo de textura F16s.bmp
do modelo 3D que fizemos o download anteriormente. Após carregarmos o modelo e a textura deveremos ver o mesmo resultado que o mostrado na Figura 13.

Se carregarmos nosso modelo de avião para o programa sem carregar sua imagem de textura veremos apenas uma silhueta cinza em fundo preto; nenhum dos detalhes internos é visível. Isso ocorre porque nosso modelo esta sendo renderizado sem luz. No próximo capítulo iremos tratar da questão de iluminação no Vulkan.