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);
需求
- 使用哪种C++材质类及参数可绘制极淡的透明物体?
- 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
相关产品推荐
相关产品推荐

