【问题标题】:Custom shaders/material not working in a custom QQuickItem object自定义着色器/材质在自定义 QQuickItem 对象中不起作用
【发布时间】:2021-09-20 17:34:15
【问题描述】:

我尝试按照 QT 的在线文档 (QtQuick Scenegraph CustomMaterial Example) 给出的教程进行操作,但是当我调试我的程序时,该对象没有显示,看起来是透明的。但是,当我尝试用QSGFlatColorMaterial 替换我的自定义着色器类并设置颜色时,该对象确实显示没有任何问题。我使用示例 git repo 中的示例代码仔细检查了本教程的实现。

这是我的代码

/* MapDisplay Class */

MapDisplay::MapDisplay(QQuickItem* parent) : QQuickItem(parent) {
  this->setFlag(ItemHasContents, true);
};

QSGNode* MapDisplay::updatePaintNode(QSGNode* old, UpdatePaintNodeData*) {
  auto* node = static_cast<MapNode*>(old);

  if (!node) {
    node = new MapNode();
  }
  if (this->flag_geo_changed) {
    node->ChangeRectBounds(this->boundingRect());
    this->flag_geo_changed = false;
  }
  const QRectF rect = this->boundingRect();
  auto* vertices = node->geometry()->vertexDataAsPoint2D();
  vertices[0].set(rect.bottomLeft().x(), 1);
  vertices[1].set(200, 0);
  vertices[2].set(0, 200);
  vertices[3].set(200, 200);
  node->markDirty(QSGNode::DirtyGeometry);
  return node;
}

void MapDisplay::geometryChange(const QRectF& new_geo, const QRectF& old_geo) {
  this->flag_geo_changed = false;
  this->update();
  QQuickItem::geometryChange(new_geo, old_geo);
}

/* MapShader Class */

MapShader::MapShader() {
  this->setShaderFileName(VertexStage, ":/geo/shader/map.vert.qsb");
  this->setShaderFileName(FragmentStage, ":/geo/shader/map.frag.qsb");
};

/* MapMaterial Class */

MapMaterial::MapMaterial(){};
MapMaterial::~MapMaterial(){};
QSGMaterialType* MapMaterial::type() const {
  static QSGMaterialType type;
  return &type;
}

int MapMaterial::compare(const QSGMaterial* o) const {
  Q_ASSERT(o && this->type() == o->type());
  const auto* other = static_cast<const MapMaterial*>(o);
  return other == this ? 0 : 1;
}

QSGMaterialShader* MapMaterial::createShader(
    QSGRendererInterface::RenderMode) const {
  return new MapShader();
}

/* MapNode Class */

MapNode::MapNode() {
  // Material
  auto* mat = new MapMaterial();
  this->setMaterial(mat);
  this->setFlag(QSGGeometryNode::OwnsMaterial, true);
  // Geometry
  auto* geo = get_geo_data::GetRectShape();
  this->setGeometry(geo);
  this->setFlag(QSGGeometryNode::OwnsGeometry, true);
}

void MapNode::ChangeRectBounds(const QRectF& bounds) {
  QSGGeometry::updateTexturedRectGeometry(this->geometry(), bounds,
                                          QRectF(0, 0, 0, 0));
  this->markDirty(QSGNode::DirtyGeometry);
}

这是我与customitem.cpp交叉检查的示例代码的链接

这也是我的着色器,

#version 460
// map.vert

layout(location = 0) in vec4 vertex_object;
layout(location = 1) in vec2 atex_coord;
layout(location = 0) out vec2 vtex_coord; 

void main() {
  gl_Position = vertex_object;
  vtex_coord = atex_coord;
}
#version 460

// map.frag
layout(location = 0) out vec4 frag_color;

void main() {
  frag_color = vec4(0.0, 1.0, 0.0, 1.0);
}

这里还有一些截图:

如果我使用QSGFlatColorMaterial

如果我使用自定义材质和着色器

【问题讨论】:

    标签: c++ qt qml qt6


    【解决方案1】:

    好的,所以在浏览完示例 repo 之后,我没有将垂直着色器中的 vertex_object 与对象的矩阵相乘。

    所以在将文档中的方法和 glsl 代码实现到我的之后,我让着色器正确显示。原来我没有正确设置着色器位置

    map.cpp

    bool MapShader::updateUniformData(RenderState& state, QSGMaterial* new_material,
                                      QSGMaterial* old_material) {
      bool changed = false;
      QByteArray* buf = state.uniformData();
      Q_ASSERT(buf->size() >= 64);
    
      if (state.isMatrixDirty()) {
        const QMatrix4x4 m = state.combinedMatrix();
        std::memcpy(buf->data(), m.constData(), 64);
        changed = true;
      }
      auto* cus_masterial = static_cast<MapMaterial*>(new_material);
      if (old_material != new_material || cus_masterial->uniform.dirty) {
        cus_masterial->uniform.dirty = false;
        changed = true;
      }
      return changed;
    }
    

    map.vert

    #version 460
    
    layout(location = 0) in vec4 vertex_object;
    layout(location = 1) in vec2 atex_coord;
    layout(location = 0) out vec2 vtex_coord; 
    
    layout(std140, binding=0) uniform buf {
      mat4 qt_matrix; // offset 0
    } ubuf;
    
    void main() {
      gl_Position = ubuf.qt_matrix /* Very important */ * vertex_object;
      vtex_coord = atex_coord;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-17
      • 2022-01-20
      • 2019-06-21
      • 1970-01-01
      • 2021-10-05
      • 2017-09-23
      • 2017-06-16
      • 1970-01-01
      • 2020-09-20
      相关资源
      最近更新 更多