Link

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::addTextureImage 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.

Figura 13 – Modelo 3D com textura carregada dinamicamente

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.


Anterior Próximo