Sprites kết xuất mờ với vận tốc


9

Sau khi thêm vận tốc vào trò chơi của tôi, tôi cảm thấy như kết cấu của mình đang co giật. Tôi nghĩ rằng đó chỉ là đôi mắt của tôi, cho đến khi cuối cùng tôi đã chụp được nó trong một ảnh chụp màn hình:

nhập mô tả hình ảnh ở đây

Người bên trái là những gì tái hiện trong trò chơi của tôi; cái bên phải là bản gốc, được dán. (Đây là ảnh chụp màn hình từ Photoshop, được phóng to 6 lần.)

Lưu ý các cạnh là răng cưa - nó trông gần giống như hiển thị pixel phụ. Trong thực tế, nếu tôi không buộc các họa tiết của mình (có vị trí và vận tốc là int) vẽ bằng các giá trị nguyên, tôi sẽ thề rằng MonoGame đang vẽ với các giá trị dấu phẩy động. Nhưng nó không phải là.

Điều gì có thể là nguyên nhân của những điều này xuất hiện mờ? Nó không xảy ra mà không áp dụng vận tốc.

Nói chính xác, SpriteComponentlớp tôi có một Vector2 Positionlĩnh vực. Khi tôi gọi Draw, tôi chủ yếu sử dụng new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))cho vị trí này.

Tôi đã có một lỗi trước khi các đối tượng đứng yên thậm chí sẽ bị giật - đó là do tôi sử dụng Positionvectơ thẳng và không làm tròn các giá trị ints. Nếu tôi sử dụng Floor/ Ceilingthay vì tròn, sprite chìm / dao động (một pixel khác nhau theo cách nào đó) nhưng vẫn vẽ mờ.


1
Điều này có thể liên quan đến việc lọc kết cấu đang được áp dụng?
OriginalDaemon

Bạn có mã cho shader của bạn? Một số người thêm một nửa pixel trên cả hai trục để lấy pixel ở giữa. Mặc dù không chắc chắn, tôi nghĩ đó chỉ là một thứ DirectX.
William Mariager

3
Vô hiệu hóa lọc là một giải pháp không phải là một giải pháp.
Archy

1
Kết xuất không biết bất cứ điều gì về vận tốc của bạn, do đó, vị trí, kích thước hoặc bất cứ điều gì khác mà bạn vượt qua với SpriteBatch.Draw là khác nhau hoặc lỗi đã xuất hiện trước khi bạn thêm vận tốc. Làm thế nào để bạn gọi SpriteBatch.Draw chính xác?
Archy

1
@ ashes999 bạn đã gỡ lỗi cuộc gọi này và kiểm tra this.X, this.Y và this.origin? This.origin được đặt thành gì? Về cơ bản, không có cách nào kết quả kết xuất khác nhau khi cuộc gọi Draw này giống nhau.
Archy

Câu trả lời:


3

Vâng, điều này là xấu hổ.

Hóa ra tôi không vẽ bằng các vị trí số nguyên, mà là các vị trí nổi. Archy chỉ cho tôi xuống con đường đúng với nhận xét của mình@ashes999 did you debug this call and checked this.X, this.Y and this.origin?

Ngay khi tôi thêm một tuyên bố dấu vết, tôi nhận thấy rằng không có gì phát hiện ra. Hóa ra SpriteComponentlớp tôi đã sử dụng đúng các giá trị nguyên, nhưng SpriteSheetComponentgiá trị float của tôi vẫn được sử dụng từ raw Vector2 Position.

Mặc dù tôi đã không thử lọc và kẹp kết cấu, tôi đã nghi ngờ rằng đây không phải là sự thay đổi chính xác, bởi vì tôi đang vẽ một hình ảnh 2D ở cùng chiều rộng và chiều cao như hình ảnh nguồn (không chia tỷ lệ).


1
Xong, rất vui vì bạn đã tìm thấy nó!
Archy

2

XNA sử dụng DirectX9 sử dụng trung tâm của pixel làm vị trí của nó. Điều này là đáng chú ý khi sử dụng quá tải dựa trên Vector2 của lớp vẽ. Tôi tin rằng việc trừ (.5, .5) sẽ khắc phục vấn đề của bạn.

Thêm thông tin ở đây.


Về mặt kỹ thuật tôi không thể làm điều này, bởi vì tôi chuyển qua Vector2 với int, inttư cách là đối số. Ngoài ra, mọi thứ trông hoàn toàn ổn khi tôi không có bất kỳ vật thể nào chuyển động.
tro999

Bạn có ý nghĩa gì bởi đối tượng đang chuyển động? XNA không có khái niệm về chuyển động, nó cũng vẽ ra những điều mà bạn nói với nó. Đó là một loạt các bức ảnh chụp tĩnh. Ngoài ra, hãy thử sử dụng quá tải hình chữ nhật vì bạn đang làm tròn đến một hình chữ nhật.
ClassicThunder

Tôi có thực hiện vận tốc của riêng tôi. SpriteComponentcó một Vector2vị trí, tăng lên như phao tùy thuộc vào vận tốc; Khi tôi vẽ, tôi tạo một Vector2phiên bản mới với số nguyên (làm tròn) của positionX và Y. Đây không phải là vấn đề, vì các vật thể đứng yên không có vận tốc có vẻ tốt.
tro999

Vì vậy, bạn nói rằng bạn có một vectơ vị trí p và vectơ vận tốc v, thêm chúng như p + = v, sau đó tạo một bản sao của p bằng các giá trị làm tròn. Và rằng các giá trị này khác nhau sau đó có một vị trí giống với p + = v trước đó mặc dù các lệnh gọi có giống nhau không? Bởi vì điều đó không có ý nghĩa.
ClassicThunder

Đúng, đó là những gì @Archy đang nói quá. Hãy để tôi gỡ lỗi và kiểm tra lại. Tôi thêm p += vtrong Updatevà kết xuất với new Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y))).
tro999

2

Kết xuất không biết bất cứ điều gì về vận tốc của bạn, do đó, vị trí, kích thước hoặc bất cứ điều gì khác mà bạn vượt qua với SpriteBatch.Draw là khác nhau hoặc lỗi đã xuất hiện trước khi bạn thêm vận tốc. Làm thế nào để bạn gọi SpriteBatch.Draw chính xác?

Bạn đã gỡ lỗi cuộc gọi này và kiểm tra this.X, this.Y và this.origin? This.origin được đặt thành gì? Về cơ bản, không có cách nào kết quả kết xuất với vận tốc là khác nhau khi cuộc gọi Draw này giống nhau.


1

Vấn đề có thể là lọc kết cấu được bật. Nếu bạn không chắc điều đó có nghĩa là gì, hãy xem xét một tình huống trong đó bạn có một hình ảnh rộng 2 pixel: pixel đầu tiên là màu đen, pixel thứ hai có màu trắng. Nếu bạn phóng to kết cấu này, nếu bật tính năng lọc kết cấu, bạn sẽ thấy nó bị mờ và khu vực giữa pixel đen và trắng sử dụng màu xám gradient.

Một ví dụ kinh điển về các trò chơi có và không có bộ lọc là Super Mario 64 có bộ lọc trong khi Doom thì không.

Khi bạn không sử dụng vận tốc, Sprite của bạn có khả năng được định vị sao cho tâm của kết cấu nằm ở điểm mẫu mà XNA (hoặc bất kỳ api cơ bản nào đang được sử dụng) đang lấy màu. Khi bạn di chuyển với vận tốc nổi, thì vị trí Sprite của bạn sẽ thay đổi, do đó điểm mẫu có thể không thẳng hàng với tâm của pixel, do đó, kết quả cuối cùng là màu trung bình của các pixel gần nhất đang được dùng để kết xuất

Bạn có thể xác minh rằng tính năng lọc được bật bằng cách đơn giản hiển thị Sprite của bạn thực sự lớn trên màn hình. Nếu nó mờ, thì đó là vấn đề.

Nếu bạn phải có độ chính xác hoàn hảo pixel trong kết xuất, bạn sẽ muốn có một giá trị float cho vị trí được lưu trữ ở đâu đó, nhưng sử dụng các giá trị nguyên cho vị trí của đối tượng bạn đang kết xuất ... hoặc tất nhiên bạn có thể tắt tính năng lọc nếu trò chơi của bạn không cần nó.

Bạn cũng có thể muốn đọc này .


Giống như tôi đã đề cập trong câu hỏi của mình, tôi đã sử dụng số nguyên cho vị trí của mình và kích thước hình ảnh gốc khi tôi gọi Draw. Vì vậy, tôi không chắc làm thế nào có thể xảy ra - nhưng tôi sẽ thử kết xuất quy mô lớn và xem nếu tắt tính năng lọc kết cấu sẽ giúp ích.
tro999

1

Hãy thử đặt SamplerState của bạn thành SamplerState.PointClamp trong lệnh gọi SpriteBatch.Begin.

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.