void QSGTextMaskShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) { QSGTextMaskMaterial *material = static_cast<QSGTextMaskMaterial *>(newEffect); QSGTextMaskMaterial *oldMaterial = static_cast<QSGTextMaskMaterial *>(oldEffect); Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type()); bool updated = material->ensureUpToDate(); Q_ASSERT(material->texture()); Q_ASSERT(oldMaterial == 0 || oldMaterial->texture()); if (updated || oldMaterial == 0 || oldMaterial->texture()->textureId() != material->texture()->textureId()) { program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->cacheTextureWidth(), 1.0 / material->cacheTextureHeight())); glBindTexture(GL_TEXTURE_2D, material->texture()->textureId()); // Set the mag/min filters to be nearest. We only need to do this when the texture // has been recreated. if (updated) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } if (state.isMatrixDirty()) { QMatrix4x4 transform = state.modelViewMatrix(); qreal xTranslation = transform(0, 3); qreal yTranslation = transform(1, 3); // Remove translation and check identity to see if matrix is only translating. // If it is, we can round the translation to make sure the text is pixel aligned, // which is the only thing that works with GL_NEAREST filtering. Adding rotations // and scales to native rendered text is not a prioritized use case, since the // default rendering type is designed for that. transform(0, 3) = 0.0; transform(1, 3) = 0.0; if (transform.isIdentity()) { transform(0, 3) = qRound(xTranslation); transform(1, 3) = qRound(yTranslation); transform = state.projectionMatrix() * transform; program()->setUniformValue(m_matrix_id, transform); } else { program()->setUniformValue(m_matrix_id, state.combinedMatrix()); } } }
static void appendPin(int subdivisions, float radius, float length, const QColor &col, GeometryData* geom, const QMatrix4x4 &transform = QMatrix4x4()) { Q_ASSERT(subdivisions >= 3); GeometryData temp; temp.setDataFormat(GeometryData::PositionNormalColor); // Create vertices at the end of the pin. // These have x = 1, and y and z vary. float angleDelta = 1.0f/(float)subdivisions; for ( int i = 0; i < subdivisions; i++ ) { float rot = i * angleDelta * 2.0f * M_PI; float yDisplacement = (float)radius * qCos(rot); float zDisplacement = (float)radius * qSin(rot); // TODO: Normal temp.appendVertex(QVector3D(length, yDisplacement, zDisplacement), QVector3D(), col); } // Create the origin vertex. temp.appendVertex(QVector3D(0,0,0), QVector3D(), col); // Create each of the outer faces. int originIndex = temp.vertexCount() - 1; for ( int i = 0; i < subdivisions; i++ ) { int index0 = i; int index1 = i == (subdivisions - 1) ? 0 : i+1; temp.appendIndexTriangle(originIndex, index1, index0); } // Create the end face. for ( int i = 1; i < subdivisions-1; i++ ) { temp.appendIndexTriangle(0, i, i+1); } if ( !transform.isIdentity() ) { temp.transform(transform); } geom->append(temp); }
QDebug operator<<(QDebug d, const QSGTransformNode *n) { if (!n) { d << "TransformNode(null)"; return d; } const QMatrix4x4 m = n->matrix(); d << "TransformNode("; d << hex << (const void *) n << dec; if (m.isIdentity()) d << "identity"; else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1) d << "translate" << m(0, 3) << m(1, 3) << m(2, 3); else d << "det=" << n->matrix().determinant(); #ifdef QSG_RUNTIME_DESCRIPTION d << QSGNodePrivate::description(n); #endif d << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); d << ')'; return d; }