2013-08-20 67 views
13

Tôi đã thấy có một ví dụ về việc triển khai a Bezier curve in QML, nhưng tôi đang tìm kiếm gợi ý cách triển khai đường cong bezier đứt ​​quãng hoặc chấm chấm. Theo như tôi thấy, các tác giả của ví dụ đường cong Bezier đang sử dụng QSGGeometryNode để lưu trữ bên trong QSGGeometry với một tài liệu QSGFlatColorMaterial được áp dụng trên đó. Sau đó, họ chỉ cần tạo danh sách các điểm và vẽ các đoạn giữa chúng.Vẽ đường cong bezier đứt ​​quãng trong QML

Có thể viết một shader và áp dụng nó vào QSGFlatColorMaterial (vào dòng hiển thị như dashed, dotted, vv)?

Cuối cùng, bạn có thể lưu trữ nhiều hơn một QSGGeometry bên trong QSGGeometryNode?

CẬP NHẬT

tôi muốn thực hiện điều này trong "tinh khiết QtQuick" - không phải trong giao diện "cũ" (như QPainter etc) - bởi vì tôi không muốn sử dụng một cái gì đó, mà chuyển ngữ cảnh (CPU OpenGL và). Tôi thích các giải pháp với shader tùy chỉnh (nếu nó có thể làm được) - bởi vì tôi sẽ có nhiều khả năng trong việc thực hiện tùy chỉnh giao diện (dashed, doted, màu, có thể hoạt hình vv).

Nếu không thể, tôi sẽ sử dụng QPainter.

+0

tôi t tương đối tầm thường để thay đổi ví dụ đường cong Bezier để tạo ra hình học cho mỗi phân đoạn phụ khi cần theo kiểu đường được chọn. –

Trả lời

5

Tôi không nghĩ rằng nhiệm vụ này là một ứng cử viên tốt để triển khai sử dụng QSGGeometryNode, sẽ dễ dàng hơn khi triển khai nó bằng cách sử dụng bản vẽ dựa trên QPainterQQuickPaintedItem. Bạn vẫn sẽ nhận được những lợi ích của OpenGL, vì QPainter cũng hỗ trợ bản vẽ GL và nó vẫn nhanh hơn phần mềm. Bạn có thể sử dụng mã cổ phiếu QPen với các mẫu có dấu chấm hoặc dấu gạch ngang hoặc tạo mẫu của riêng bạn với một đơn giản QVector.

Ngoài ra, bạn có thể sử dụng phương pháp vẽ GL tùy chỉnh thay vì sử dụng các lớp do Qt cung cấp, điều này khá hạn chế khi nói đến biểu diễn hình học ghép cao cấp. Bạn thậm chí có thể sử dụng instancing (nếu có) để cải thiện hiệu suất hơn nữa, và chỉ vị trí dấu gạch ngang hoặc chấm hình học dọc theo đường cong đường dẫn.

Cuối cùng nhưng không kém phần quan trọng, bạn có thể sử dụng phần tử Canvas QML, hỗ trợ khá nhiều hoạt động tương tự như QPainter và có thể cung cấp cùng một hiệu suất.

EDIT: Theo bản cập nhật của bạn, bạn đã bỏ lỡ phần mà tôi đã nói QPainter có thể vẽ cả phần mềm và GL, với bản vẽ GL thường nhanh hơn đáng kể. Ngoài ra, bằng cách vẽ đến một bối cảnh GL, bạn không cần phải di chuyển bộ đệm khung từ bộ nhớ CPU sang GPU, nó được giữ trong bộ nhớ GPU. Vì vậy, không có phí. Đối với hoạt ảnh và các nội dung khác, chắc chắn không thể với QPainter bạn được giới hạn ở bất kỳ thứ gì QPen cung cấp - các kết nối khác nhau, mũ và các thứ khác có thể được sử dụng để sửa đổi hình dạng ở một mức độ nào đó, nhưng không có phép lạ ... Cũng không thể với các trình đổ bóng, nó sẽ chỉ có thể với hình dạng tùy chỉnh. Và nếu bạn sử dụng đối tượng dựa trên QObject cho mỗi phần tử dấu gạch ngang/dấu chấm để tạo hiệu ứng độc lập, nó sẽ kết thúc khá mở rộng, QObject rất nặng và không được sử dụng với bàn tay nhẹ như vậy. Vì vậy, tùy chỉnh GL rendering cho một FBO là khá nhiều cách để đi nếu bạn muốn loại linh hoạt, nhưng bạn sẽ phải di chuyển hoàn toàn ra khỏi API QtQuick và vào GL đất.

Ở mức độ nào, trình đổ bóng nét đứt không nên phức tạp, về cơ bản bạn tô màu đoạn dựa trên khoảng cách từ đường cong và "khoảng thời gian" dọc theo chiều dài của nó. Tôi đã tìm thấy this example, chưa thử bản thân.Bạn có thể tạo hiệu ứng cho các ngưỡng, thậm chí sử dụng chức năng sin để có kiểu dáng đẹp. Đối với triển khai QtQuick "thuần túy", API chưa thực sự được thiết kế để xử lý các tác vụ vẽ như vậy, đó là lý do tại sao phần tử Canvas được cung cấp để lấp đầy khoảng trống và nhận chức năng nâng cao từ QML/JS. Canvas thực sự là trình bao bọc xung quanh QPainter vẽ lên FBO.

Cuối cùng nó không đun sôi xuống những gì có thể/không thể nhưng cách tiếp cận nào có ý nghĩa nhất và hiệu quả nhất khi hoàn thành công việc. Trước hết, hãy thử cách tiếp cận QQuickPaintedItem vì đây là cách dễ nhất, nếu bạn không hài lòng với hiệu suất, bạn có thể triển khai một giải pháp và cấu hình phức tạp hơn so với phương pháp đầu tiên. Xét cho cùng, đó là lý do tại sao QQuickPaintedItem được giới thiệu ngay từ đầu - để xử lý bức tranh kế thừa không thuận tiện để thực hiện với lớp QQuickItem.

+2

Cảm ơn bạn rất nhiều, nhưng tôi rất thích thực hiện điều này trong 'QtQuick' thuần túy - Tôi không muốn sử dụng' QPainter' - nếu có thể. Nếu không, tôi sẽ sử dụng nó - xem câu hỏi được cập nhật. Nếu nó có thể viết một shader, nó sẽ mạnh mẽ hơn nhiều so với sử dụng các kiểu 'QPainter' được định sẵn. –

+0

Nó vẫn là một thực hiện QtQuick tinh khiết, 'QQuickPaintedItem' như tên gợi ý là một phần của API QtQuick2. Bạn có thể tạo các patters kiểu tùy chỉnh cho 'QPainter' rất dễ dàng. Tôi đã tự hỏi về nhiều hình học là tốt, nhưng nó không có vẻ là API có khả năng này. Cuối cùng, nó là một trong hai 'QPainter' hoặc render của riêng bạn với một framebuffer, mà bạn có thể vẽ trên một hình chữ nhật. Tôi cho rằng một shader là có thể nhưng không phải là giải pháp thanh lịch nhất cho vấn đề này. Bạn có thể muốn xem mã 'QPainter' vẽ theo ngữ cảnh GL, nó cũng sử dụng hình học để vẽ. – dtech

+0

Cảm ơn tất cả các giải thích! Tôi đang cố gắng thực hiện nhiệm vụ này bởi trình đổ bóng vì tôi muốn tạo hiệu ứng động và nó sẽ dễ dàng hơn khi thực hiện với các trình đổ bóng. Tôi biết các căn cứ của OGL Shaders, vì vậy sẽ không có vấn đề gì đối với tôi để viết nó. Vấn đề duy nhất là làm thế nào để sử dụng nó với 'QSGFlatColorMaterial' trong' QML' - Tôi sẽ cố gắng tìm một cách, nhưng nếu bạn biết nó, tôi sẽ biết ơn một gợi ý :) –

0

Không, bạn không thể lưu trữ nhiều hình học trong một nút hình học. API rất rõ ràng về nó. Không có lý do gì để lưu trữ nhiều hình học ở đó, vì một cặp nút hình học và vật liệu. Bạn có thể tái sử dụng hình học và vật liệu giữa các nút - đó là cách nó dự định được sử dụng, trên thực tế.

Phần còn lại của câu hỏi không thực sự hoàn chỉnh và ngay cả khi triển khai dựa trên trình tạo bóng được cung cấp, ban đầu nó sẽ không hữu ích lắm. Nó sẽ chỉ đơn thuần là một tối ưu hóa sớm. Hãy nhìn vào những gì bạn đang bỏ lỡ.

Ví dụ mục BezierCurve chỉ là bằng chứng về khái niệm. Nó không hữu ích bởi chính nó, vì bạn cần một cách để chuỗi nhiều mục được vuốt ve bằng cách sử dụng cùng một cây bút. Bạn cần một cái gì đó giống như một đơn giản QPainterPath. Thực tế, bản thân hình học có thể được tạo bởi QPainterPathQPainterPathStroker.

Khi bạn đã có hình học hoàn chỉnh cho một mục liên tục vuốt ve, sau đó bạn có thể cắt nó tiếp theo dựa trên kiểu đường kẻ hoặc sử dụng trình đổ bóng. Nó sẽ yêu cầu profiling để cho thấy rằng một bóng kiểu dòng của chính nó là một chiến thắng lớn. Nó cũng có thể là bạn cần một shader hình học để làm các stroking vv và tất cả các đạt được hiệu suất sẽ được tập trung ở đó. Hãy suy nghĩ về số lượng tính toán được thực hiện, việc tạo kiểu đường tương đối đơn giản.

+0

Cảm ơn bạn. Bạn có ví dụ nào, sử dụng cả hai - 'QML' và shaders? Tôi hoàn toàn hiểu câu trả lời của bạn, nhưng tôi mới làm quen với QML, vì vậy một ví dụ đơn giản sẽ giúp tôi nhiều. –

+0

Ở đây, bạn truy cập: http://qt-project.org/doc/qt-5.1/qtquick/shadereffects.html – dtech

1

Tại sao bạn không sử dụng phương pháp này:

Beziercurve example modified to use QSGVertexColorMaterial

Sau đó, bạn có thể chỉ định màu và alpha của bạn cho mỗi vetex, để có được những dấu gạch ngang, dấu chấm, hoặc bất cứ mẫu nào bạn chọn.

Dưới đây là những phần quan trọng:

geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), m_segmentCount); 
//geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount); 

QSGVertexColorMaterial *material = new QSGVertexColorMaterial; 
//material->setColor(QColor(255, 0, 0)); 

//QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D(); 
QSGGeometry::ColoredPoint2D *vertices = geometry->vertexDataAsColoredPoint2D(); 

vertices[i].set(x, y, 0, 0, 0, 0); 
//vertices[i].set(x, y); 
-1
import QtQuick 2.0 

Rectangle { 
    width : 1024 
    height: 600 

    Rectangle { 
     x: -3 + 158 
     y: 355 
     width: 4; height: 4; 
     color: "black"; 
     } 

    Rectangle { 
     x: 359 + 158 
     y: 220 
     width: 4; height: 4; 
     color: "black"; 
     } 

    Rectangle { 
     x: 175 + 158 
     y: 238 
     width: 2; height: 2; 
     color: "black"; 
     } 

    Rectangle { 
     x: 711 + 158 
     y: 355 
     width: 4; height: 4; 
     color: "black"; 
     } 

    Rectangle { 
     x: 533 + 158 
     y: 238 
     width: 2; height: 2; 
     color: "black"; 
     } 

    Rectangle { 
     x: -3 + 118 
     y: 355 
     width: 4; height: 4; 
     color: "darkBlue"; 
     } 

    Rectangle { 
     x: 399 + 118 
     y: 220 
     width: 4; height: 4; 
     color: "darkBlue"; 
     } 

    Rectangle { 
     x: 196 + 118 
     y: 238 
     width: 4; height: 4; 
     color: "darkBlue"; 
     } 

    Rectangle { 
     x: 791 + 118 
     y: 355 
     width: 4; height: 4; 
     color: "darkBlue"; 
     } 

    Rectangle { 
     x: 592 + 118 
     y: 238 
     width: 4; height: 4; 
     color: "darkBlue"; 
     } 


    Path { 
     id: path 
     startX: -3 
     startY: 355 
     PathQuad { x: 359; y:220; controlX: 175; controlY:238 } 
     PathQuad { x: 711; y:355; controlX: 533; controlY:238 } 
    } 

    Path { 
     id: path2 
     startX: -3 
     startY: 355 

     PathQuad { x: 399; y:220; controlX: 196; controlY:238 } 
     PathQuad { x: 791; y:355; controlX: 592; controlY:238 } 
    } 


    PathView { 
    id: pathView; 
    x: 158 
    width: 708 
    model: 300; 
    path: path 
    delegate: Rectangle { 
    id: dot; 
    width: 1; height: 1; 
    color: "red"; 
    } 
    } 

    PathView { 
    id: pathView2; 
    x: 118 
    width: 788 
    model: 300; 
    path: path2 
    delegate: Rectangle { 
    id: dot2; 
    width: 1; height: 1; 
    color: "green"; 
    } 
    } 
} 
Các vấn đề liên quan