Dust3D开源项目分析——渲染与材质部分 | shadermesh绑定 Part 2

 2021SC@SDUSC

cpp文件。shadermesh绑定的具体实现。

void SimpleShaderMeshBinder::updateMesh(SimpleShaderMesh *mesh)
{
    QMutexLocker lock(&m_newMeshMutex);
    if (mesh != m_mesh) {
        delete m_newMesh;
        m_newMesh = mesh;
        m_newMeshComing = true;
    }
}

mesh更新函数,如果传入的SimpleShaderMesh与m_mesh不一致,则删除原来的,更新为传入的mesh

void SimpleShaderMeshBinder::checkNewMesh()
{
    SimpleShaderMesh *newMesh = nullptr;
    if (m_newMeshComing) {
        QMutexLocker lock(&m_newMeshMutex);
        if (m_newMeshComing) {
            newMesh = m_newMesh;
            m_newMesh = nullptr;
            m_newMeshComing = false;
        }
    }
    
    if (nullptr != newMesh) {
        QVector<QVector3D> vertices;
        QVector<int> indexes;
        
        const auto &meshVertices = *newMesh->vertices();
        const auto &meshTriangles = *newMesh->triangles();
        const auto &meshNormals = *newMesh->triangleCornerNormals();
        int i = 0;
        for (size_t triangleIndex = 0; triangleIndex < meshTriangles.size(); ++triangleIndex) {
            const auto &triangle = meshTriangles[triangleIndex];
            const auto &v0 = meshVertices[triangle[0]];
            const auto &v1 = meshVertices[triangle[1]];
            const auto &v2 = meshVertices[triangle[2]];
            vertices.push_back(QVector3D(v0[0], v0[1], v0[2]));
            vertices.push_back(QVector3D(v1[0], v1[1], v1[2]));
            vertices.push_back(QVector3D(v2[0], v2[1], v2[2]));
            indexes << i << i + 1 << i + 2;
            i += 3;
        }
        m_vertexCount = vertices.size();
        m_normalOffset = vertices.size() * int(sizeof(QVector3D));
        for (size_t triangleIndex = 0; triangleIndex < meshTriangles.size(); ++triangleIndex) {
            const auto &normals = meshNormals[triangleIndex];
            const auto &n0 = normals[0];
            const auto &n1 = normals[1];
            const auto &n2 = normals[2];
            vertices.push_back(QVector3D(n0[0], n0[1], n0[2]));
            vertices.push_back(QVector3D(n1[0], n1[1], n1[2]));
            vertices.push_back(QVector3D(n2[0], n2[1], n2[2]));
        }

        delete m_vertexBuffer;
        m_vertexBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        m_vertexBuffer->create();
        m_vertexBuffer->bind();
        m_vertexBuffer->allocate(
                static_cast<const void*>(vertices.constData()),
                vertices.size() * int(sizeof(QVector3D))
            );
        m_vertexBuffer->release();
        
        delete m_indexBuffer;
        m_indexBuffer = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
        m_indexBuffer->create();
        m_indexBuffer->bind();
        m_indexBuffer->allocate(
                  static_cast<const void*>(indexes.constData()),
                  indexes.size() * int(sizeof(int))
            );
        m_indexBuffer->release();
        
        delete newMesh;
    }
}

检查新mesh。如果updateMesh()确认更新mesh之后,将m_newMeshComing置True,则提取m_newMesh并完成对newMesh的更新操作

void SimpleShaderMeshBinder::renderShadow(const QMatrix4x4 &projectionMatrix, const QMatrix4x4 &viewMatrix)
{
    if (nullptr == m_shadowProgram) {
        if (!m_openglFunctionsInitialized) {
            QOpenGLFunctions::initializeOpenGLFunctions();
            m_openglFunctionsInitialized = true;
        }

        m_shadowProgram = new QOpenGLShaderProgram;
        m_shadowProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shadow.vert");
        m_shadowProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shadow.frag");
        m_shadowProgram->link();
    }

    checkNewMesh();
    
    if (nullptr == m_indexBuffer) {
        return;
    }
    
    m_shadowProgram->bind();
    m_vertexBuffer->bind();
    m_indexBuffer->bind();

    const QMatrix4x4 modelMatrix = m_sceneMatrix * m_matrix;
    const QMatrix4x4 lightViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix;

    m_shadowProgram->enableAttributeArray("qt_Vertex");
    m_shadowProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 3, 0);

    m_shadowProgram->setUniformValue("qt_LightViewProjectionMatrix", lightViewProjectionMatrix);

    glDrawElements(GL_TRIANGLES, m_vertexCount, GL_UNSIGNED_INT, nullptr);

    m_indexBuffer->release();
    m_vertexBuffer->release();
    m_shadowProgram->release();
}

渲染阴影函数。首先检测用于阴影渲染的着色器是否存在,如果不存在就从../shaders/下读入新的Vertex Shader和Fragment Shader并完成绑定和编译,将Light View Projection矩阵和顶点数据读入缓存后,调用glDrawElements()绘制三角面,然后释放各类buffer。

void SimpleShaderMeshBinder::renderScene(const QVector3D &eyePosition, const QVector3D &lightDirection,
            const QMatrix4x4 &projectionMatrix, const QMatrix4x4 &viewMatrix,
            const QMatrix4x4 &lightViewMatrix)
{
    if (nullptr == m_sceneProgram) {
        if (!m_openglFunctionsInitialized) {
            QOpenGLFunctions::initializeOpenGLFunctions();
            m_openglFunctionsInitialized = true;
        }

        m_sceneProgram = new QOpenGLShaderProgram;
        m_sceneProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/scene.vert");
        m_sceneProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/scene.frag");
        m_sceneProgram->link();
    }
    
    checkNewMesh();
    
    if (nullptr == m_indexBuffer || 0 == m_shadowMapTextureId) {
        return;
    }
    
    m_sceneProgram->bind();
    m_vertexBuffer->bind();
    m_indexBuffer->bind();

    const QMatrix4x4 modelMatrix = m_sceneMatrix * m_matrix;
    const QMatrix4x4 modelViewMatrix = (viewMatrix * modelMatrix);
    const QMatrix4x4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
    const QMatrix4x4 normalMatrix = modelMatrix.inverted().transposed();

    m_sceneProgram->enableAttributeArray("qt_Vertex");
    m_sceneProgram->setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 3, 0);

    m_sceneProgram->enableAttributeArray("qt_Normal");
    m_sceneProgram->setAttributeBuffer("qt_Normal", GL_FLOAT, m_normalOffset, 3, 0);

    m_sceneProgram->setUniformValue("qt_ViewMatrix", viewMatrix);
    m_sceneProgram->setUniformValue("qt_NormalMatrix", normalMatrix);
    m_sceneProgram->setUniformValue("qt_ModelMatrix", modelMatrix);
    m_sceneProgram->setUniformValue("qt_ModelViewMatrix", modelViewMatrix);
    m_sceneProgram->setUniformValue("qt_ProjectionMatrix", projectionMatrix);
    m_sceneProgram->setUniformValue("qt_ModelViewProjectionMatrix", modelViewProjectionMatrix);

    m_sceneProgram->setUniformValue("qt_LightMatrix", lightViewMatrix);
    m_sceneProgram->setUniformValue("qt_LightViewMatrix", lightViewMatrix * modelMatrix);
    m_sceneProgram->setUniformValue("qt_LightViewProjectionMatrix", projectionMatrix * lightViewMatrix * modelMatrix);

    if (m_shadowMapTextureId > 0) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, m_shadowMapTextureId);
        m_sceneProgram->setUniformValue("qt_ShadowMap", 0);
        m_sceneProgram->setUniformValue("qt_ShadowEnabled", true);
    } else {
        m_sceneProgram->setUniformValue("qt_ShadowEnabled", false);
    }
    
    m_sceneProgram->setUniformValue("qt_Light.ambient", QColor(255, 255, 255));
    m_sceneProgram->setUniformValue("qt_Light.diffuse", QColor(Qt::white));
    m_sceneProgram->setUniformValue("qt_Light.specular", QColor(Qt::white));
    m_sceneProgram->setUniformValue("qt_Light.direction", lightDirection);
    m_sceneProgram->setUniformValue("qt_Light.eye", eyePosition);
    
    QColor ambient = Qt::white;
    ambient.setRgbF(
            ambient.redF() * qreal(0.1f),
            ambient.greenF() * qreal(0.1f),
            ambient.blueF() * qreal(0.1f)
        );

    QColor diffuse = Qt::white;
    diffuse.setRgbF(
            diffuse.redF() * qreal(1.0f),
            diffuse.greenF() * qreal(1.0f),
            diffuse.blueF() * qreal(1.0f)
        );

    QColor specular = Qt::white;

    m_sceneProgram->setUniformValue("qt_Material.ambient", ambient);
    m_sceneProgram->setUniformValue("qt_Material.diffuse", diffuse);
    m_sceneProgram->setUniformValue("qt_Material.specular", specular);
    m_sceneProgram->setUniformValue("qt_Material.specularPower", 0.0f);
    m_sceneProgram->setUniformValue("qt_Material.brightness", 1.0f);
    m_sceneProgram->setUniformValue("qt_Material.opacity", 1.0f);
    
    glDrawElements(GL_TRIANGLES, m_vertexCount, GL_UNSIGNED_INT, nullptr);

    if (m_shadowMapTextureId > 0) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, 0);
    }

    m_indexBuffer->release();
    m_vertexBuffer->release();
    m_sceneProgram->release();
}

renderScene()执行对整个场景的渲染。首先检测是否存在用于scene渲染的着色器程序,如果没有就从../shaders/下读入新的shader并完成绑定和编译。之后就是进行各种缓存的写入和数据的传递,绑定ambient,diffuse,specular,specularPower,brightness,opacity等uniform变量的值,然后调用glDrawElements()绘制场景中的三角面片,最后释放缓存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值