Bước đầu tiên là nói với card đồ họa chúng ta cần bộ đệm stpson. Để thực hiện điều này khi bạn tạo GraphicsDeviceManager, chúng tôi đặt PreferredDepthStpsonFormat thành DepthFormat.Depth24Stpson8 để thực sự có một stprint để viết.
graphics = new GraphicsDeviceManager(this) {
PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8
};
AlphaTestEffect được sử dụng để đặt hệ tọa độ và lọc các pixel bằng alpha vượt qua thử nghiệm alpha. Chúng tôi sẽ không đặt bất kỳ bộ lọc nào và đặt hệ tọa độ thành cổng xem.
var m = Matrix.CreateOrthographicOffCenter(0,
graphics.GraphicsDevice.PresentationParameters.BackBufferWidth,
graphics.GraphicsDevice.PresentationParameters.BackBufferHeight,
0, 0, 1
);
var a = new AlphaTestEffect(graphics.GraphicsDevice) {
Projection = m
};
Tiếp theo chúng ta cần thiết lập hai DepthStpsonStates. Các trạng thái này ra lệnh khi SpriteBatch kết xuất với stprint và khi SpriteBatch kết xuất lại BackBuffer. Chúng tôi chủ yếu quan tâm đến hai biến stifFeft và stifPass.
- SttFeft ra lệnh khi SpriteBatch sẽ vẽ các pixel riêng lẻ và khi nào chúng sẽ bị bỏ qua.
- MacintoshPass ra lệnh khi các pixel được vẽ có hiệu ứng pixel.
Đối với DepthStpsonState đầu tiên, chúng tôi đặt sttFeft thành so sánh. Điều này làm cho sttTest thành công và khi sttTest SpriteBatch hiển thị pixel đó. MacintoshPass được đặt thành sttOperation. Thay thế có nghĩa là khi stentTest thành công, pixel đó sẽ được ghi vào sttBuffer bằng giá trị của ReferenceStpson.
var s1 = new DepthStencilState {
StencilEnable = true,
StencilFunction = CompareFunction.Always,
StencilPass = StencilOperation.Replace,
ReferenceStencil = 1,
DepthBufferEnable = false,
};
Tóm lại, sttTest luôn luôn vượt qua, hình ảnh được vẽ lên màn hình bình thường và đối với các pixel được vẽ trên màn hình, giá trị 1 được lưu trữ trong sttBuffer.
DepthStpsonState thứ hai phức tạp hơn một chút. Lần này, chúng tôi chỉ muốn vẽ lên màn hình khi giá trị trong sttBuffer là. Để đạt được điều này, chúng ta đã đặt sttFeft thành so sánhFess.LessEqual và ReferenceStpson thành 1. Điều này có nghĩa là khi giá trị trong bộ đệm stprint là 1 thì sttTest sẽ thành công. Thiết lập sttPass thành sttOperation. Giữ nguyên nhân khiến cho sttBuffer không cập nhật. Điều này cho phép chúng ta vẽ nhiều lần bằng cùng một mặt nạ.
var s2 = new DepthStencilState {
StencilEnable = true,
StencilFunction = CompareFunction.LessEqual,
StencilPass = StencilOperation.Keep,
ReferenceStencil = 1,
DepthBufferEnable = false,
};
Tóm lại, sttTest chỉ vượt qua khi sttBuffer nhỏ hơn 1 (các pixel alpha từ mặt nạ) và không ảnh hưởng đến sttBuffer.
Bây giờ chúng ta đã thiết lập DepthStpsonStates. Chúng ta thực sự có thể vẽ bằng mặt nạ. Đơn giản chỉ cần vẽ mặt nạ bằng DepthStpsonState đầu tiên. Điều này sẽ ảnh hưởng đến cả BackBuffer và MacintoshBuffer. Bây giờ, bộ đệm stpson có giá trị 0 trong đó mặt nạ của bạn có độ trong suốt và 1 nơi chứa màu, chúng ta có thể sử dụng sttBuffer để che các hình ảnh sau này.
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, s1, null, a);
spriteBatch.Draw(huh, Vector2.Zero, Color.White); //The mask
spriteBatch.End();
SpriteBatch thứ hai sử dụng DepthStpsonStates thứ hai. Bất kể bạn vẽ gì, chỉ những pixel mà stifBuffer được đặt thành 1 sẽ vượt qua bài kiểm tra stprint và được vẽ lên màn hình.
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, s2, null, a);
spriteBatch.Draw(color, Vector2.Zero, Color.White); //The background
spriteBatch.End();
Dưới đây là toàn bộ mã trong phương thức Draw, đừng quên đặt PreferredDepthStpsonFormat = DepthFormat.Depth24Stpson8 trong trình xây dựng trò chơi.
GraphicsDevice.Clear(ClearOptions.Target
| ClearOptions.Stencil, Color.Transparent, 0, 0);
var m = Matrix.CreateOrthographicOffCenter(0,
graphics.GraphicsDevice.PresentationParameters.BackBufferWidth,
graphics.GraphicsDevice.PresentationParameters.BackBufferHeight,
0, 0, 1
);
var a = new AlphaTestEffect(graphics.GraphicsDevice) {
Projection = m
};
var s1 = new DepthStencilState {
StencilEnable = true,
StencilFunction = CompareFunction.Always,
StencilPass = StencilOperation.Replace,
ReferenceStencil = 1,
DepthBufferEnable = false,
};
var s2 = new DepthStencilState {
StencilEnable = true,
StencilFunction = CompareFunction.LessEqual,
StencilPass = StencilOperation.Keep,
ReferenceStencil = 1,
DepthBufferEnable = false,
};
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, s1, null, a);
spriteBatch.Draw(huh, Vector2.Zero, Color.White); //The mask
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, s2, null, a);
spriteBatch.Draw(color, Vector2.Zero, Color.White); //The background
spriteBatch.End();