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

Qt3D C++程序中实现高透明度锥形网格的材质方案咨询

Qt3D C++实现极淡透明锥形网格的问题

我正在用C++编写仿真程序,通过QML的Scene3D对象渲染3D场景,目前运行正常,但希望添加近乎完全透明的锥形网格。

尝试过的方法(未成功)

使用Qt3DExtras::QDiffuseSpecularMaterial并设置低alpha值,但透明度不足,甚至alpha为0时显示为纯白色实体。代码如下:

Qt3DExtras::QConeMesh *m_cone = new Qt3DExtras::QConeMesh(e);

Qt3DExtras::QDiffuseSpecularMaterial *conemat = new Qt3DExtras::QDiffuseSpecularMaterial(e);
QColor coneColor = QColor::fromRgbF(0,0.5,0,0);
conemat->setDiffuse(coneColor);
conemat->setAlphaBlendingEnabled(true);

m_cone->setBottomRadius(1798444);
m_cone->setTopRadius(0);
m_cone->setLength(sat->orbitRadius()-EARTH_RADIUS);

需求

  1. 使用哪种C++材质类及参数可绘制极淡的透明物体?
  2. QML中通过片段着色器实现透明效果很简单,如何在C++中实现?

QML示例代码

CustomMaterial {
    shadingMode: CustomMaterial.Shaded
    fragmentShader: "material_transparent.frag"
}

Transparent.frag代码

void MAIN()
{
    vec2 size = vec2(textureSize(SCREEN_TEXTURE, 0));
    vec2 uv = FRAGCOORD.xy / size;

    vec3 view = normalize(VIEW_VECTOR);
    vec3 projection = view - view * normalize(NORMAL);
    vec3 refraction = projection * projection;
    uv += refraction.xy * 0.5;

    vec3 col = texture(SCREEN_TEXTURE, uv).rgb;
    col = col * 0.8 + vec3(0.2);

    BASE_COLOR = vec4(col, 1.0);
}

补充问题:QEffect实现失败

按照建议尝试使用QEffect,但最终glShader状态始终为“NotReady”,代码如下:

Qt3DRender::QEffect *effect = new Qt3DRender::QEffect();

// Create technique, render pass and shader
Qt3DRender::QTechnique *gl3Technique = new Qt3DRender::QTechnique();
Qt3DRender::QRenderPass *gl3Pass = new Qt3DRender::QRenderPass();
Qt3DRender::QShaderProgram *glShader = new Qt3DRender::QShaderProgram();

// Set the shader on the render pass
gl3Pass->setShaderProgram(glShader);

// Add the pass to the technique
gl3Technique->addRenderPass(gl3Pass);

// Set the targeted GL version for the technique
gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL);
gl3Technique->graphicsApiFilter()->setMajorVersion(3);
gl3Technique->graphicsApiFilter()->setMinorVersion(1);
gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile);

// Add the technique to the effect
effect->addTechnique(gl3Technique);

QByteArray prog = glShader->loadSource(QUrl("qrc:/material_transparent.frag"));
glShader->setFragmentShaderCode(prog);

请问问题出在哪里?


解答

一、解决QDiffuseSpecularMaterial透明度问题

QDiffuseSpecularMaterial透明度失效,核心原因是缺少透明渲染的关键状态配置,修改代码如下:

// 原有材质设置保留,添加渲染状态配置
Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet();

// 禁用深度写入:透明物体需关闭深度写入,避免遮挡后方物体
Qt3DRender::QDepthMask *depthMask = new Qt3DRender::QDepthMask();
depthMask->setMask(false);
renderStateSet->addRenderState(depthMask);

// 设置标准混合模式:源alpha混合
Qt3DRender::QBlendFunc *blendFunc = new Qt3DRender::QBlendFunc();
blendFunc->setSource(Qt3DRender::QBlendFunc::SourceAlpha);
blendFunc->setDestination(Qt3DRender::QBlendFunc::OneMinusSourceAlpha);
renderStateSet->addRenderState(blendFunc);

// 将渲染状态集绑定到材质的effect
conemat->effect()->addRenderStateSet(renderStateSet);

// 可选:开启双面渲染,避免透明锥形背面不可见
conemat->setCullMode(Qt3DRender::QCullFace::NoCull);

二、修复QEffect实现的错误

你之前的QEffect代码有3个关键问题:缺少顶点着色器、着色器加载方式错误、未将Effect绑定到实体组件,修正后的完整代码:

// 1. 创建完整ShaderProgram:必须同时包含顶点和片段着色器
Qt3DRender::QShaderProgram *glShader = new Qt3DRender::QShaderProgram();
// 加载顶点着色器(可使用Qt3D默认模板,示例见下方)
glShader->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl("qrc:/default.vert")));
// 加载你的透明片段着色器
glShader->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl("qrc:/material_transparent.frag")));

// 2. 创建RenderPass并绑定Shader,添加透明渲染状态
Qt3DRender::QRenderPass *gl3Pass = new Qt3DRender::QRenderPass();
gl3Pass->setShaderProgram(glShader);

Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet();
Qt3DRender::QDepthMask *depthMask = new Qt3DRender::QDepthMask();
depthMask->setMask(false);
renderStateSet->addRenderState(depthMask);

Qt3DRender::QBlendFunc *blendFunc = new Qt3DRender::QBlendFunc();
blendFunc->setSource(Qt3DRender::QBlendFunc::SourceAlpha);
blendFunc->setDestination(Qt3DRender::QBlendFunc::OneMinusSourceAlpha);
renderStateSet->addRenderState(blendFunc);

gl3Pass->addRenderStateSet(renderStateSet);

// 3. 创建Technique并设置GL版本
Qt3DRender::QTechnique *gl3Technique = new Qt3DRender::QTechnique();
gl3Technique->addRenderPass(gl3Pass);
gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL);
gl3Technique->graphicsApiFilter()->setMajorVersion(3);
gl3Technique->graphicsApiFilter()->setMinorVersion(1);
gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile);

// 4. 创建Effect并绑定Technique
Qt3DRender::QEffect *effect = new Qt3DRender::QEffect();
effect->addTechnique(gl3Technique);

// 5. 创建自定义材质并绑定Effect
Qt3DRender::QMaterial *customMaterial = new Qt3DRender::QMaterial();
customMaterial->setEffect(effect);

// 6. 将材质绑定到锥形实体
Qt3DCore::QEntity *coneEntity = new Qt3DCore::QEntity(e);
coneEntity->addComponent(m_cone);
coneEntity->addComponent(customMaterial);
// 添加变换组件(根据需求调整位置/旋转)
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform();
coneEntity->addComponent(transform);

配套的顶点着色器示例(default.vert):

attribute vec3 vertexPosition;
attribute vec3 vertexNormal;
attribute vec2 vertexTexCoord;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;

varying vec3 v_normal;
varying vec2 v_texCoord;

void main()
{
    v_normal = normalize(normalMatrix * vertexNormal);
    v_texCoord = vertexTexCoord;
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(vertexPosition, 1.0);
}

三、更简单的替代方案:使用QTransparentMaterial

如果不需要自定义着色器,直接用Qt3D内置的QTransparentMaterial更高效:

Qt3DExtras::QTransparentMaterial *transMat = new Qt3DExtras::QTransparentMaterial(e);
// 设置极淡透明色,最后一个参数为alpha值(0~1)
QColor transColor = QColor::fromRgbF(0, 0.5, 0, 0.1);
transMat->setDiffuse(transColor);

// 添加透明渲染状态
Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet();
Qt3DRender::QDepthMask *depthMask = new Qt3DRender::QDepthMask();
depthMask->setMask(false);
renderStateSet->addRenderState(depthMask);
transMat->effect()->addRenderStateSet(renderStateSet);

// 绑定到实体
coneEntity->addComponent(transMat);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:47:05