Implement Reverse Z projection matrix for skin model

Signed-off-by: Dylan Schooner <dschooner05@gmail.com>
This commit is contained in:
Dylan Schooner
2025-10-31 12:20:28 -04:00
parent 2982e6e7c9
commit b488547054
5 changed files with 85 additions and 24 deletions

View File

@@ -56,12 +56,19 @@ SkinOpenGLWindow::~SkinOpenGLWindow()
}
delete m_backgroundTexture;
}
if (m_program) {
if (m_program->isLinked()) {
m_program->release();
if (m_modelProgram) {
if (m_modelProgram->isLinked()) {
m_modelProgram->release();
}
m_program->removeAllShaders();
delete m_program;
m_modelProgram->removeAllShaders();
delete m_modelProgram;
}
if (m_backgroundProgram) {
if (m_backgroundProgram->isLinked()) {
m_backgroundProgram->release();
}
m_backgroundProgram->removeAllShaders();
delete m_backgroundProgram;
}
doneCurrent();
}
@@ -125,21 +132,40 @@ void SkinOpenGLWindow::initializeGL()
void SkinOpenGLWindow::initShaders()
{
m_program = new QOpenGLShaderProgram(this);
// Skin model shaders
m_modelProgram = new QOpenGLShaderProgram(this);
// Compile vertex shader
if (!m_program->addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl"))
if (!m_modelProgram->addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader_skin_model.glsl"))
close();
// Compile fragment shader
if (!m_program->addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"))
if (!m_modelProgram->addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"))
close();
// Link shader pipeline
if (!m_program->link())
if (!m_modelProgram->link())
close();
// Bind shader pipeline for use
if (!m_program->bind())
if (!m_modelProgram->bind())
close();
// Background shaders
m_backgroundProgram = new QOpenGLShaderProgram(this);
// Compile vertex shader
if (!m_backgroundProgram->addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader_skin_background.glsl"))
close();
// Compile fragment shader
if (!m_backgroundProgram->addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"))
close();
// Link shader pipeline
if (!m_backgroundProgram->link())
close();
// Bind shader pipeline for use (verification)
if (!m_backgroundProgram->bind())
close();
}
@@ -148,13 +174,24 @@ void SkinOpenGLWindow::resizeGL(int w, int h)
// Calculate aspect ratio
qreal aspect = qreal(w) / qreal(h ? h : 1);
const qreal zNear = .1, zFar = 1000., fov = 45;
const qreal zNear = 15., fov = 45;
// Reset projection
m_projection.setToIdentity();
// Set perspective projection
m_projection.perspective(fov, aspect, zNear, zFar);
// Build the reverse z perspective projection matrix
double radians = qDegreesToRadians(fov / 2.);
double sine = std::sin(radians);
if (sine == 0)
return;
double cotan = std::cos(radians) / sine;
m_projection(0, 0) = cotan / aspect;
m_projection(1, 1) = cotan;
m_projection(2, 2) = 0.;
m_projection(3, 2) = -1.;
m_projection(2, 3) = zNear;
m_projection(3, 3) = 0.;
}
void SkinOpenGLWindow::paintGL()
@@ -172,9 +209,10 @@ void SkinOpenGLWindow::paintGL()
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_program->bind();
m_backgroundProgram->bind();
renderBackground();
m_backgroundProgram->release();
// Calculate model view transformation
QMatrix4x4 matrix;
float yawRad = qDegreesToRadians(m_yaw);
@@ -186,10 +224,11 @@ void SkinOpenGLWindow::paintGL()
QVector3D(0, -8, 0), QVector3D(0, 1, 0));
// Set modelview-projection matrix
m_program->setUniformValue("mvp_matrix", m_projection * matrix);
m_modelProgram->bind();
m_modelProgram->setUniformValue("mvp_matrix", m_projection * matrix);
m_scene->draw(m_program);
m_program->release();
m_scene->draw(m_modelProgram);
m_modelProgram->release();
}
void SkinOpenGLWindow::updateScene(SkinModel* skin)
@@ -246,10 +285,8 @@ void SkinOpenGLWindow::renderBackground()
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE); // Disable depth buffer writing
m_backgroundTexture->bind();
QMatrix4x4 matrix;
m_program->setUniformValue("mvp_matrix", matrix);
m_program->setUniformValue("texture", 0);
m_background->draw(m_program);
m_backgroundProgram->setUniformValue("texture", 0);
m_background->draw(m_backgroundProgram);
m_backgroundTexture->release();
glDepthMask(GL_TRUE); // Re-enable depth buffer writing
glEnable(GL_DEPTH_TEST);