自定义 shaders/material 在自定义 QQuickItem 对象中不起作用
Custom shaders/material not working in a custom QQuickItem object
按照QT在线文档(QtQuick Scenegraph CustomMaterial Example)给出的教程试过,调试程序时,对象不显示,呈透明状。但是,当我尝试用 QSGFlatColorMaterial
替换我的自定义着色器 class 并设置颜色时,对象确实显示没有任何问题。我使用示例 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
交叉检查的示例代码的 link
这也是我的着色器,
#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
如果我使用自定义 material 和着色器
好的,所以在通过示例回购后,我没有将垂直着色器中的 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;
}
按照QT在线文档(QtQuick Scenegraph CustomMaterial Example)给出的教程试过,调试程序时,对象不显示,呈透明状。但是,当我尝试用 QSGFlatColorMaterial
替换我的自定义着色器 class 并设置颜色时,对象确实显示没有任何问题。我使用示例 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
交叉检查的示例代码的 link这也是我的着色器,
#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
如果我使用自定义 material 和着色器
好的,所以在通过示例回购后,我没有将垂直着色器中的 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;
}