Cách hiệu quả để vẽ phác thảo xung quanh các họa tiết


21

Tôi đang sử dụng XNA để lập trình một trò chơi và đã thử nghiệm nhiều cách khác nhau để đạt được hiệu ứng 'được chọn' trên các họa tiết của tôi. Vấn đề tôi gặp phải là mỗi lần nhấp được vẽ trong spritebatch được vẽ bằng cách sử dụng nhiều hơn một sprite (mỗi đối tượng có thể được tạo thành tối đa 6 sprite).

Tôi đánh giá cao nếu ai đó có thể tư vấn cho tôi về cách tôi có thể đạt được việc thêm một phác thảo vào các họa tiết X pixel của mình (vì vậy chiều rộng của phác thảo có thể là số lượng khác nhau của toàn bộ pixel).

Cảm ơn trước,

  • Greg.

Câu trả lời:


20

Cho đến nay, cách dễ nhất để làm điều này (có lẽ là cách tốt nhất, trừ khi bạn thực sự bị ràng buộc về hiệu suất) là có hai bản sao của các họa tiết của bạn.

  • Phiên bản thông thường
  • Một phiên bản "không béo", không màu - về cơ bản là phiên bản màu trắng của sprite X - nhiều pixel của bạn "béo hơn" so với bản gốc.

Vẽ toàn bộ đối tượng của bạn bằng phiên bản "béo", sau đó vẽ phiên bản thông thường lên trên cùng.

Bằng cách làm cho phiên bản "béo" thành màu trắng, bạn có thể sử dụng pha màu tích hợp của SpriteBatch để thay đổi màu sắc lựa chọn một cách linh hoạt.

Để tạo bản án "béo" của bạn, tôi khuyên bạn nên viết Tiện ích mở rộng đường ống nội dung có thể tự động lấy các họa tiết gốc của bạn, đọc kênh alpha của chúng, tạo kênh alpha mới bằng cách lấy mẫu kênh alpha tối đa trong ảnh gốc X - nhiều pixel xung quanh mỗi pixel, và đặt RGB = (1,1,1).

Bạn sẽ phải đảm bảo tất cả các họa tiết của bạn có đủ đường viền trong suốt để thêm đường viền (bạn có thể kiểm tra điều này trong bộ xử lý nội dung - và thậm chí nhường chỗ nếu cần thiết).

Nếu bạn chỉ có một vài họa tiết, thì bạn chỉ có thể sử dụng trình chỉnh sửa hình ảnh tốt (GIMP, Photoshop) và thực hiện bằng tay: Kênh Alpha để chọn, mở rộng lựa chọn, chọn thành alpha, tô màu kênh trắng.


4

Tôi đoán bạn cần phải vẽ tất cả các phần mà mỗi đối tượng vào một sprite đầu tiên. Sau đó, tôi nghĩ rằng bạn phải viết một shader để phát hiện các cạnh của sprite vẽ một pixel bất cứ khi nào nó tìm thấy một cạnh. Tôi hy vọng phải có một số shader ngoài đó để làm điều này, mà bạn có thể sử dụng hoặc cổng.


11
Loại shader này gây khó chịu một cách đáng ngạc nhiên khi viết, tôi đã nghe (chúng tôi đã sử dụng nó trong một trong những trò chơi 3D của chúng tôi và tiếp tục chạy vào các trường hợp khó coi). Một điều bạn có thể muốn xem xét là mã hóa phác thảo trực tiếp vào kết cấu sprite với một màu cụ thể như (0, 255, 255, 0) và chỉ cần shader biến đổi màu đó khi sprite được chọn. Sau đó, shader là một sự thay đổi màu sắc tầm thường, và bạn có mức độ kiểm soát nghệ sĩ cao đối với phác thảo và bất kỳ chi tiết nào bạn muốn.

4

Tùy thuộc vào yêu cầu, những gì cũng có thể có hiệu quả chỉ là tạo ra một phác thảo theo yêu cầu cho sprite. Tôi cho rằng các họa tiết của bạn có độ trong suốt và có hình dạng bất thường thay vì chỉ là hình chữ nhật (trong khi điều này sẽ hoạt động tốt cho điều đó, hình chữ nhật phác thảo nên là Trivial).

when selected:
   outline = new sprite canvas of appropriate size
   for sprite in object:
      # use larger numbers for thicker outlines
      for x in (-1, 0, 1) and y in (-1, 0, 1):
         render sprite mask into canvas at x,y with desired color

Lưu ý rằng bạn không cần phải làm điều này mỗi lần vẽ (mặc dù tôi cho rằng bạn có thể), nhưng chỉ cần tạo sprite phác thảo mới khi chuyển sprite.


Vâng, đây là những gì tôi muốn đề nghị là tốt. Kết xuất sprite mặt nạ 1 pixel sang trái, phải, trên và dưới của sprite gốc, bên dưới sprite hiện có. Nhiều trò chơi đã sử dụng phương pháp này để phác thảo văn bản được hiển thị hoặc chỉ có 2 trong số 4 vị trí để tạo bóng đổ.
Kaj

1

Cách tiếp cận đơn giản nhất là xây dựng hai bản sao của mỗi sprite, một bản thường và một bản được tô sáng. Sau đó chỉ cần trao đổi chúng khi được tô sáng.

Nếu bạn có bộ nhớ dự phòng thì không cần phải phức tạp hơn nữa. Các nghệ sĩ Plus có toàn quyền kiểm soát giao diện khi được tô sáng để bạn có thể phác thảo hoặc bất cứ điều gì bạn muốn.


Tôi nghĩ một phần của vấn đề là OP nói rằng mỗi đối tượng có thể được tạo thành từ nhiều họa tiết. Vì vậy, tôi đoán rằng phác thảo phải là phác thảo của đối tượng kết hợp, thay vì có một phác thảo riêng xung quanh mỗi sprite thành phần.
Chris Howe

1
Chris, nó không phải là phác thảo của đối tượng kết hợp, và nó sẽ hoạt động tốt đối với một đối tượng được tạo từ nhiều họa tiết. Chỉ cần làm chính xác những gì wkerslake đã nói, nhưng hãy chắc chắn rằng bạn vẽ các họa tiết được tô sáng đằng sau tất cả các họa tiết thông thường cho đối tượng đó. Theo cách đó, cho dù có bao nhiêu sprite một đối tượng được tạo ra, phần tô sáng sẽ chỉ sử dụng nhiều hơn gấp đôi thời gian vẽ cho đối tượng đó, ít hơn rất nhiều so với việc tạo ra các phác thảo tại thời điểm kết hợp với các sprite kết hợp.
Tấn

1

Làm thế nào về mỗi sprite, cũng có một sprite khác đó là một phác thảo của sprite cơ sở. Khi vẽ một đối tượng được phác thảo, vẽ các họa tiết cơ sở, sau đó tạo mặt nạ kết xuất kết hợp, sau đó vẽ các họa tiết phác thảo không bao gồm mặt nạ.


2
Tại sao không chỉ vẽ các họa tiết phác thảo đầu tiên và vẽ các họa tiết thông thường lên trên chúng?
Chris Howe

Một lý do để không làm điều này (hoặc gợi ý của Chris) là vì nó sử dụng gấp đôi bộ nhớ kết cấu; một lý do khác là quy trình làm việc của nghệ sĩ là tào lao vì bạn cần cập nhật hai tệp mỗi khi bạn thay đổi một sprite.

2
Vâng, lý tưởng là bạn sẽ không có hai tài sản sprite thực tế. Nếu bạn đang sử dụng kiểm tra alpha cho các họa tiết của mình, bạn có thể đặt phác thảo vào sprite và cho nó cao hơn một chút so với các khu vực trong suốt của bạn. Sau đó, bằng cách kiểm soát giá trị tham chiếu kiểm tra alpha, bạn có thể kiểm soát xem phác thảo có hiển thị hay không. Tất cả những gì tôi đã nói là nếu bạn có 2 phiên bản của các họa tiết (cho dù là 2 tài sản hoặc 2 trạng thái của cùng một tài sản), bạn nên vẽ phiên bản phác thảo trước, sau đó là phiên bản bình thường. Bằng cách này, bạn không yêu cầu bất kỳ shader ưa thích, mặt nạ, hoặc bất cứ điều gì.
Chris Howe

1
Ý tưởng của Chris có công; ngoài ra, có thể tránh được việc cập nhật 2 tệp (hoặc thậm chí cùng một tài sản) nếu bạn sản xuất một công cụ để tạo alpha cho các họa tiết phác thảo chạy như một phần của đường dẫn nội dung / nội dung của bạn. Bộ nhớ kết cấu có thể có hoặc không có vấn đề, nhưng các họa tiết phác thảo riêng biệt nên có khả năng nén DXT cao; có thể bằng 1/6 kích thước của kết cấu ban đầu trong bộ nhớ video và không mất độ trung thực.
jpaver

1

Một vài giải pháp khác nhau với sự đánh đổi khác nhau.

Dễ nhất: Kết xuất đối tượng bằng cách sử dụng màu phẳng nhiều lần và làm biến đổi vị trí (bù trái, lên, xuống, phải, v.v.), điều này sẽ tạo ra một phiên bản phác thảo của bất cứ thứ gì bạn hiển thị trên nó, nhưng có chi phí hiệu năng và sẽ không cho phép các đường viền chất béo mà không có nhiều kết xuất thêm. Đường viền một hoặc hai pixel có thể ổn với 4x.

Nhanh nhất: Xử lý trước kết cấu và có một bản sao đã được viền, hoặc chỉ là đường viền hoặc là mặt nạ 8 bit màu xám phẳng mà bạn có thể tô màu trong một shader. Điều này có thể sẽ nhanh chóng với chi phí của bộ nhớ.

Tốt nhất: Ý kiến ​​của tôi, nhưng việc tạo đại diện Trường khoảng cách đã ký (SDF) cho đối tượng của bạn có thể sẽ là giải pháp tốt nhất. Các kết cấu này có thể nhỏ hơn nhiều so với kết cấu nguồn và vẫn thu được dữ liệu hữu ích. Về cơ bản, mỗi pixel mã hóa khoảng cách từ đối tượng được sử dụng để tạo ra nó. Với dữ liệu này trong tay, bạn có thể viết tất cả các loại hiệu ứng từ phát sáng đến phác thảo. Đường viền có thể thay đổi kích thước và màu sắc, v.v., và vẫn là một shader tương đối rẻ và chỉ có một lần rút thêm. Nhược điểm là dụng cụ, và tiền xử lý.


0

Tôi không chắc chắn về sự hiệu quả, nhưng cách dễ nhất tôi có thể thấy là vẽ một phiên bản lớn hơn của sprite theo màu bạn muốn chọn trước. Vẽ sprite trên đó. Bạn sẽ chỉ nhìn thấy cạnh của sprite đầu tiên, cho hiệu ứng lựa chọn.

EDIT: Tuy nhiên, như bạn có thể thấy từ các bình luận, đây không phải là một ý tưởng tốt.


1
Chỉ cần nhân rộng một sprite không đưa ra một phác thảo thực sự
Iain

2
Tôi không nghĩ nó sẽ như vậy, nhưng nó sẽ dễ dàng.
Vịt Cộng sản

2
Rất nhiều thứ dễ dàng nhưng không giải quyết được vấn đề. Đối với các sprite với bất kỳ loại hình bóng thú vị nào, việc mở rộng quy mô sẽ tạo ra rác tuyệt đối.

Mở rộng quy mô sẽ chỉ nhìn tốt cho các đối tượng hình vuông hoặc tròn rắn. Nếu hình dạng thực sự rộng, hoặc cao, hoặc có những khoảng trống, nó sẽ trông rất xấu.
Tấn

3
Mở rộng quy mô sẽ cho kết quả tốt hơn là không làm gì và cũng sẽ là một bước hữu ích trên con đường dẫn đến "sự hoàn hảo". Mặc dù kết quả đồ họa sẽ không hoàn hảo, nhưng nếu đây là một công cụ nội bộ thì nó có thể đủ tốt.
dash-tom-bang

0

Tôi đồng ý với việc nhân rộng sprite. Bởi Xa tuyến đường dễ nhất, và bạn có thể áp dụng nó để chọn BẤT K sp sprite nào mà không phải tạo thêm các họa tiết đặc biệt cho mục đích này.

  • tức là spriteOutline.Scale = spriteOrigen.Scale * 0.1f; spriteOutline.Color = Màu mới (255, 0, 0, 255);

0

Thay thế màu của sprite ban đầu bằng màu phác thảo (hoặc thậm chí pha màu nếu bạn muốn). Kết xuất sprite phẳng hoặc tô màu này bốn lần với độ lệch 1 pixel: tại x, y = (- 1, -1), sau đó (+ 1, -1), sau đó (-1, + 1) sau đó (+1 , +1). Lặp lại cho tất cả các sprite tạo nên đối tượng.

Sau đó, kết xuất các họa tiết gốc theo thứ tự thích hợp trên đầu tại (0,0).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.