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
相关产品推荐
相关产品推荐

