2013-08-03 42 views
17

Tôi có một số đa giác đơn giản (ít hơn 20 đỉnh) vẽ phẳng trên mặt phẳng xy đơn giản, sử dụng GL_TRIANGLES và màu phẳng, mô phỏng 2d.Vẽ một đường viền trên đa giác 2d với bóng đổ phân đoạn

Tôi muốn thêm đường viền có độ dày biến đổi và màu khác với các đa giác này. Tôi có một cái gì đó thực hiện bằng cách sử dụng cùng một đỉnh và glLineWidth/GL_LINE_LOOP, mà làm việc, nhưng là một vượt qua rendering và lặp đi lặp lại tất cả các biến đổi đỉnh. Tôi nghĩ rằng tôi sẽ có thể làm điều này trong shader mảnh bằng cách sử dụng gl_FragCoord và dữ liệu đỉnh và/hoặc tọa độ kết cấu, nhưng tôi không chắc chắn, và những nỗ lực ngây thơ của tôi rõ ràng là không chính xác.

Tôi hình dung một cái gì đó như sau.

uniform vec2 scale; // viewport h/w 
uniform float line_width; 
uniform vec4 fill_color; 
uniform vec4 border_color; 

varying vec4 vertex; // in world coords 

void main() 
{ 
    if (distance_from_edge(gl_FragCoord, vertex, scale) < line_width) 
    { 
     // we're close to the edge the polygon, so we're the border. 
     gl_FragColor = border_color; 
    } 
    else 
    { 
     gl_FragColor = fill_color; 
    } 
} 

Phần tôi đang cố gắng tìm ra là hàm distance_from_edge - làm cách nào để tính được? Đang sử dụng gl_FragCoord cách tiếp cận sai - tôi có nên sử dụng một số loại ánh xạ kết cấu không? Là một thử nghiệm, tôi đã thử chuyển đổi đỉnh sang không gian pixel với tỷ lệ và sau đó tính khoảng cách giữa giá trị đó và gl_FragCoord theo pixel, nhưng điều đó cho kết quả lạ mà tôi không thực sự hiểu. Ngoài ra, tôi cần khoảng cách đến cạnh , không phải là đỉnh, nhưng tôi không chắc chắn cách thực hiện điều đó.

Bất kỳ ý tưởng nào?

EDIT: dựa trên phản ứng Nicol của, câu hỏi của tôi trở thành:

Giả sử tôi có một hình tam giác với đỉnh 3 góc đánh dấu là đỉnh cạnh, và một đỉnh ở giữa được đánh dấu là không cạnh (để diễn tả với 3 hình tam giác trong tổng cộng), sau đó làm cách nào để nội suy trong trình đổ bóng phân đoạn để vẽ một đường viền có độ dày nhất định? Tôi giả sử tôi chuyển cờ cạnh cho trình đổ bóng, cũng như độ dày đường mong muốn, và tính toán nội suy để tìm ra khoảng cách giữa cạnh và không cạnh đỉnh, và các ngưỡng màu như viền/tô khi thích hợp ?

+1

'gl_FragCoord' sẽ là ồ ạt vô ích cho bạn. Điều đó chỉ cho bạn biết mảnh vỡ nằm trên màn hình; nó không nói gì về nơi mảnh vỡ liên quan đến tam giác. Vị trí đỉnh sẽ tương tự không được trợ giúp. Bạn sẽ cần sự trợ giúp của dữ liệu đổ bóng/dữ liệu do người dùng cung cấp, đặt giá trị trên các đỉnh dựa trên đó có phải là đỉnh cạnh hay không và nội suy giá trị. Điều đó có nghĩa là bạn không thể phát hiện ra cạnh của một tam giác đơn; bạn phải chia tam giác thành nhiều hình tam giác, sao cho các đỉnh bên trong và đỉnh cạnh có thể được phân biệt. –

+0

Cảm ơn, tôi nghi ngờ tôi đã bỏ lỡ điều gì đó. Vì vậy, nếu tôi có một tam giác với 3 đỉnh được đánh dấu là đỉnh cạnh, và một ở giữa không phải là (do đó kết xuất với 4 hình tam giác), sau đó làm thế nào để tôi nội suy cho một chiều rộng dòng nhất định cho biên giới? – bloodearnest

Trả lời

23

Tất cả những gì bạn cần là tọa độ barycentric, vì bạn đang xử lý các hình tam giác. Gán mỗi đỉnh của tam giác một bản sắc, và sau đó sử dụng nội suy tích hợp của phần cứng giữa các giai đoạn đỉnh và đoạn để tìm ra khoảng cách tương đối từ mỗi đỉnh trong đổ bóng phân đoạn của bạn.

Bạn có thể nghĩ rằng các tọa độ barycentric cho mỗi đỉnh là khoảng cách từ cạnh đối diện. Trong biểu đồ bên dưới, cạnh đối diện của đỉnh P0 là e1, và khoảng cách của nó được biểu diễn bằng h1; tọa độ barycentric của nó là <0.0, h1, 0.0>. GPU có thể sử dụng không gian tọa độ nội bộ này để nội suy các thuộc tính đỉnh cho các hình tam giác khi các đoạn được tạo ra trong quá trình rasterization, nó làm cho việc tính trọng số của mỗi thuộc tính đỉnh dựa trên vị trí trong tam giác.

Diagram illustrating the calculation of distance from each edge

Dưới đây là hai bài hướng dẫn để giải thích làm thế nào để làm điều này, điển hình này được sử dụng để hiển thị một lớp phủ wireframe, do đó bạn có thể có may mắn hơn tìm kiếm cho điều đó. Vì mục đích của bạn, vì đây là một chuyên môn hóa về kết xuất khung dây (với sự bổ sung mà bạn muốn ném ra các đường không thuộc các cạnh đa giác bên ngoài), bạn sẽ cần xác định các đỉnh cạnh và thực hiện xử lý bổ sung.Ví dụ, nếu một đỉnh không phải là một phần của cạnh bên ngoài, thì bạn sẽ muốn gán cho nó một tọa độ barycentric của một cái gì đó như < 1,100,0> và đỉnh được kết nối < 0,100,1> và cạnh bên trong sẽ được bỏ qua (giả sử nó là một cạnh đối diện với đỉnh được chỉ định < 0,1,0>, như được thấy trong biểu đồ bên dưới). Ý tưởng là bạn không bao giờ muốn một điểm dọc theo cạnh này để nội suy bất cứ nơi nào gần 0,0 (hoặc bất kỳ ngưỡng nào bạn sử dụng để che một đoạn như một phần của biên giới), làm cho nó rất xa trung tâm của tam giác theo hướng của đối diện đỉnh sẽ giải quyết điều này.

Diagram showing how to exclude interior edges

Without Geometry Shaders (OpenGL ES thân thiện):

Dưới đây là một liên kết để giải thích làm thế nào để làm điều này, nếu bạn có thể sửa đổi dữ liệu đỉnh của bạn để giữ tọa barycentric. Nó có yêu cầu lưu trữ và xử lý trước cao hơn (đặc biệt, chia sẻ các đỉnh giữa các cạnh liền kề có thể không còn khả thi vì bạn cần mỗi tam giác bao gồm ba đỉnh mà mỗi đỉnh có một tọa độ barycentric đầu vào khác nhau - đó là lý do tại sao giải pháp mong muốn). Tuy nhiên, nó sẽ chạy trên nhiều phần cứng lớp OpenGL ES hơn so với các giải pháp tổng quát hơn đòi hỏi các trình tạo bóng hình học.

http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/

Với Geometry Shaders ( Không OpenGL ES thân thiện):

Ngoài ra, bạn có thể sử dụng một Shader hình học để tính toán barycentric phối cho mỗi tam giác tại làm cho thời gian như đã thấy trong hướng dẫn này. Rất có thể là trong OpenGL ES, bạn sẽ không có quyền truy cập vào shaders hình học, do đó, điều này có thể có thể được bỏ qua.

http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_10.html http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_11.html

Cơ sở lý thuyết cho giải pháp này có thể được tìm thấy ở đây (lịch sự của Internet Archive Wayback Machine):

http://web.archive.org/web/ */http://cgg-journal.com/2008-2/06/index.html

+0

Cảm ơn, điều này đã cho tôi trên con đường bên phải. Tôi đã triển khai wireframing shader hình học và nó hoạt động độc đáo. Bây giờ tôi chỉ cần thêm vào các đỉnh không có chu vi bổ sung và đánh dấu một cách thích hợp. Tôi đã một phần đã đi xuống con đường đó trong các thí nghiệm của riêng tôi, bất kỳ cách nào, nhưng với 1 điều phối, không 3. – bloodearnest

+3

Liên kết cơ sở lý thuyết là xuống, đây là [liên kết thay thế (lưu trữ web)] (https: //web.archive. org/web/20130607004602/http: //cgg-journal.com/2008-2/06/index.html). Một bài báo khác từ cùng một kẻ: [Hai phương pháp để vẽ khung dây Antialiased với loại bỏ dòng ẩn] (http: //orbit.dtu.dk/fedora/objects/quỹ đạo: 55459/datastreams/file_3735323/content) – fedab

+0

Thật không may, kỹ thuật này dẫn đến hiện vật nơi biên giới tiếp cận đỉnh. Cạnh tam giác bên trong có thể "cắt" các phần của đường viền: http://imgur.com/Btl6h2Y. – John