Fix segfault binding unloaded texture.

This commit is contained in:
Shaun Reed 2025-03-22 12:55:31 -04:00
parent c5e21bd731
commit fb9c320633
6 changed files with 55 additions and 32 deletions

View File

@ -22,18 +22,7 @@ ExampleScene::~ExampleScene() = default;
void ExampleScene::init() void ExampleScene::init()
{ {
setSkybox(new Qtk::Skybox(":/textures/skybox/right.png", setSkybox(new Qtk::Skybox);
":/textures/skybox/top.png",
":/textures/skybox/front.png",
":/textures/skybox/left.png",
":/textures/skybox/bottom.png",
":/textures/skybox/back.png",
"Skybox"));
std::string spartanPath = QTK_EXAMPLE_SOURCE_DIR;
spartanPath += "/../resources/models/spartan/spartan.obj";
auto spartan = addObject(new Model("spartan", spartanPath.c_str()));
spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f);
auto mesh = addObject( auto mesh = addObject(
new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS))); new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ELEMENTS)));

View File

@ -121,9 +121,7 @@ void MeshRenderer::draw()
bindShaders(); bindShaders();
mVAO.bind(); mVAO.bind();
if (mTexture.hasTexture()) { mTexture.bind();
mTexture.getOpenGLTexture().bind();
}
// TODO: Automate uniforms some other way // TODO: Automate uniforms some other way
setUniformMVP(); setUniformMVP();
@ -138,9 +136,7 @@ void MeshRenderer::draw()
mShape.mIndices.data()); mShape.mIndices.data());
} }
if (mTexture.hasTexture()) { mTexture.bind();
mTexture.getOpenGLTexture().release();
}
mVAO.release(); mVAO.release();
releaseShaders(); releaseShaders();

View File

@ -17,9 +17,28 @@ using namespace Qtk;
* Constructors / Destructors * Constructors / Destructors
******************************************************************************/ ******************************************************************************/
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) Skybox::Skybox(const std::string & name) :
mVBO(QOpenGLBuffer::VertexBuffer),
mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData())
{ {
mTexture.setTexture(cubeMap); QImage image({1024, 1024}, QImage::Format_RGBA8888);
image.fill(Qt::darkGray);
mTexture.setCubeMap(image, image, image, image, image, image);
init();
}
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) :
mVBO(QOpenGLBuffer::VertexBuffer),
mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData())
{
if (cubeMap == Q_NULLPTR) {
qDebug()
<< "[Qtk] Failed to set cubemap for skybox with null QOpenGLTexture.";
} else {
mTexture.setTexture(cubeMap);
}
init(); init();
} }
@ -34,13 +53,13 @@ Skybox::Skybox(const std::string & right,
mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()), mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData()) mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData())
{ {
init();
mTexture.setCubeMap(QImage(right.c_str()).mirrored(), mTexture.setCubeMap(QImage(right.c_str()).mirrored(),
QImage(top.c_str()), QImage(top.c_str()),
QImage(front.c_str()), QImage(front.c_str()),
QImage(left.c_str()), QImage(left.c_str()),
QImage(bottom.c_str()), QImage(bottom.c_str()),
QImage(back.c_str())); QImage(back.c_str()));
init();
} }
/******************************************************************************* /*******************************************************************************
@ -54,7 +73,7 @@ void Skybox::draw()
mVAO.bind(); mVAO.bind();
mProgram.bind(); mProgram.bind();
mTexture.getOpenGLTexture().bind(); mTexture.bind();
mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix()); mProgram.setUniformValue("uProjectionMatrix", Scene::getProjectionMatrix());
mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix()); mProgram.setUniformValue("uViewMatrix", Scene::getCamera().toMatrix());
@ -62,7 +81,7 @@ void Skybox::draw()
glDrawElements( glDrawElements(
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data()); GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
mTexture.getOpenGLTexture().bind(); mTexture.bind();
mProgram.release(); mProgram.release();
mVAO.release(); mVAO.release();

View File

@ -34,7 +34,12 @@ namespace Qtk
* Constructors / Destructors * Constructors / Destructors
************************************************************************/ ************************************************************************/
// Delegate this constructor to use default skybox images /**
* Construct a skybox with a default texture.
*
* @param name The objectName to use for the Skybox.
*/
explicit Skybox(const std::string & name = "Skybox");
/** /**
* Construct a skybox with an existing QOpenGLTexture. * Construct a skybox with an existing QOpenGLTexture.

View File

@ -104,9 +104,9 @@ QOpenGLTexture * OpenGLTextureFactory::initCubeMap(const QImage & right,
QOpenGLTexture::CubeMapNegativeZ}; QOpenGLTexture::CubeMapNegativeZ};
int i = 0; int i = 0;
for (const auto & face : faces) { for (const auto & face : faces) {
QImage faceImage(faceTextures[i]); QImage & faceImage = faceTextures[i];
if (faceImage.isNull()) { if (faceImage.isNull()) {
qDebug() << "Error loading cube map image\n"; qDebug() << "[libqtk] Error loading cube map image\n";
faceImage = defaultTexture(); faceImage = defaultTexture();
} }
faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888); faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888);

View File

@ -217,6 +217,20 @@ namespace Qtk
return mOpenGLTexture != Q_NULLPTR; return mOpenGLTexture != Q_NULLPTR;
} }
/**
* Bind the OpenGL texture if it exists, avoiding segmentation faults.
*/
bool bind() const
{
if (hasTexture()) {
// TODO: It would be nice to warn here but some objects may not have
// a texture. Factor Texture out of those objects so we don't bind.
mOpenGLTexture->bind();
return true;
}
return false;
}
/************************************************************************* /*************************************************************************
* Accessors * Accessors
************************************************************************/ ************************************************************************/
@ -300,12 +314,12 @@ namespace Qtk
/** /**
* Sets this Texture to be a cube map with provided sides. * Sets this Texture to be a cube map with provided sides.
* *
* @param right Path to texture to use for right cube map side. * @param right QImage texture to use for right cube map side.
* @param top Path to texture to use for top cube map side. * @param top QImage texture to use for top cube map side.
* @param front Path to texture to use for front cube map side. * @param front QImage texture to use for front cube map side.
* @param left Path to texture to use for left cube map side. * @param left QImage texture to use for left cube map side.
* @param bottom Path to texture to use for bottom cube map side. * @param bottom QImage texture to use for bottom cube map side.
* @param back Path to texture to use for back cube map side. * @param back QImage texture to use for back cube map side.
*/ */
virtual inline void setCubeMap(const QImage & right, virtual inline void setCubeMap(const QImage & right,
const QImage & top, const QImage & top,