You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt3D中能否使用C++实现自发光材质?

Qt3D中C++实现自发光材质的方案指引

Qt3D自带的官方材质(如QPhongMaterial、QBlinnPhongMaterial等)确实没有直接暴露自发光参数,但可以通过以下两种方式实现自发光效果:

1. 自定义材质+自定义着色器(推荐)

直接继承Qt3DRender::QMaterial,编写包含自发光逻辑的顶点和片段着色器,完全控制材质的渲染行为。

核心步骤:

  • 创建自定义材质类,继承Qt3DRender::QMaterial
  • 编写包含自发光计算的GLSL着色器
  • 在材质类中设置着色器程序,并添加控制自发光颜色/强度的uniform参数

C++代码示例:

#include <Qt3DRender/QMaterial>
#include <Qt3DRender/QShaderProgram>
#include <Qt3DRender/QEffect>
#include <Qt3DRender/QTechnique>
#include <Qt3DRender/QRenderPass>
#include <Qt3DRender/QParameter>
#include <QFile>

class EmissiveMaterial : public Qt3DRender::QMaterial
{
    Q_OBJECT
    Q_PROPERTY(QColor emissiveColor READ emissiveColor WRITE setEmissiveColor NOTIFY emissiveColorChanged)
    Q_PROPERTY(float emissiveStrength READ emissiveStrength WRITE setEmissiveStrength NOTIFY emissiveStrengthChanged)

public:
    explicit EmissiveMaterial(Qt3DCore::QNode *parent = nullptr)
        : QMaterial(parent)
    {
        // 加载着色器
        auto shaderProgram = new Qt3DRender::QShaderProgram(this);
        shaderProgram->setShaderCode(Qt3DRender::QShaderProgram::Vertex, readShader(":/shaders/emissive.vert"));
        shaderProgram->setShaderCode(Qt3DRender::QShaderProgram::Fragment, readShader(":/shaders/emissive.frag"));

        // 构建材质Effect
        auto effect = new Qt3DRender::QEffect(this);
        auto technique = new Qt3DRender::QTechnique(this);
        auto renderPass = new Qt3DRender::QRenderPass(this);

        renderPass->setShaderProgram(shaderProgram);
        technique->addRenderPass(renderPass);
        effect->addTechnique(technique);

        setEffect(effect);

        // 添加自发光参数
        m_emissiveColorParam = new Qt3DRender::QParameter("emissiveColor", QColor(255, 255, 0));
        m_emissiveStrengthParam = new Qt3DRender::QParameter("emissiveStrength", 1.0f);
        addParameter(m_emissiveColorParam);
        addParameter(m_emissiveStrengthParam);
    }

    QColor emissiveColor() const { return m_emissiveColorParam->value().value<QColor>(); }
    float emissiveStrength() const { return m_emissiveStrengthParam->value().toFloat(); }

    void setEmissiveColor(const QColor& color) {
        m_emissiveColorParam->setValue(color);
        emit emissiveColorChanged();
    }

    void setEmissiveStrength(float strength) {
        m_emissiveStrengthParam->setValue(strength);
        emit emissiveStrengthChanged();
    }

signals:
    void emissiveColorChanged();
    void emissiveStrengthChanged();

private:
    Qt3DRender::QParameter* m_emissiveColorParam = nullptr;
    Qt3DRender::QParameter* m_emissiveStrengthParam = nullptr;

    QString readShader(const QString& path) {
        QFile file(path);
        file.open(QIODevice::ReadOnly);
        return file.readAll();
    }
};

片段着色器示例(emissive.frag):

#version 450 core

in vec3 vWorldPos;
in vec3 vNormal;

uniform vec3 emissiveColor;
uniform float emissiveStrength;
// 可选:添加基础光照参数
uniform vec3 lightPos;
uniform vec3 lightColor;

out vec4 fragColor;

void main() {
    // 基础漫反射计算(可根据需求保留或移除)
    vec3 normal = normalize(vNormal);
    vec3 lightDir = normalize(lightPos - vWorldPos);
    float diff = max(dot(normal, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    // 计算自发光颜色
    vec3 emissive = emissiveColor * emissiveStrength;

    // 叠加最终颜色
    fragColor = vec4(diffuse + emissive, 1.0);
    // 如果需要纯自发光,直接输出:fragColor = vec4(emissive, 1.0);
}

2. 扩展现有材质(快速适配)

如果想基于现有材质(如QPhongMaterial)扩展自发光,可以修改其QEffect,添加包含自发光逻辑的额外QRenderPass,或者替换原有着色器代码。但这种方式灵活性较低,因为现有材质的着色器逻辑是固定的,仅适合简单的自发光叠加场景。

注意事项:

  • 自发光效果不受场景光照影响时,可直接在着色器中输出自发光颜色,无需计算光照
  • 可以通过调整emissiveStrength参数控制自发光的亮度
  • 确保Qt3D场景中启用了正确的渲染状态(如深度测试、混合模式等)

内容的提问来源于stack exchange,提问作者Peter Robertsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 17:03:38