Còn những thứ như thế này thì sao?
Đừng vẽ ánh sáng của bạn bằng cách pha màu gạch của bạn. Vẽ các ô không hợp lệ của bạn vào mục tiêu kết xuất, sau đó vẽ đèn chiếu sang mục tiêu kết xuất thứ hai, đại diện cho mỗi ô như một hình chữ nhật màu xám bao phủ khu vực của ô. Để kết xuất cảnh cuối cùng, sử dụng một shader để kết hợp hai mục tiêu kết xuất, làm tối từng pixel của cái đầu tiên theo giá trị của cái thứ hai.
Điều này sẽ sản xuất chính xác những gì bạn có bây giờ. Điều đó không giúp ích gì cho bạn, vì vậy hãy thay đổi nó một chút.
Thay đổi kích thước của mục tiêu kết xuất ánh sáng của bạn để mỗi ô được thể hiện bằng một pixel , thay vì một khu vực hình chữ nhật. Khi kết hợp cảnh cuối cùng, sử dụng trạng thái lấy mẫu với lọc tuyến tính. Nếu không thì để mọi thứ khác như cũ.
Giả sử bạn đã viết đúng shader của mình, lightmap sẽ được "thu nhỏ" một cách hiệu quả trong quá trình tổng hợp. Điều này sẽ giúp bạn có được hiệu ứng chuyển màu đẹp miễn phí thông qua bộ lấy mẫu kết cấu của thiết bị đồ họa.
Bạn cũng có thể cắt bỏ shader và làm điều này đơn giản hơn với BlendState 'làm tối', nhưng tôi phải thử nghiệm nó trước khi tôi có thể cung cấp cho bạn thông tin cụ thể.
CẬP NHẬT
Tôi đã có một thời gian ngày hôm nay để thực sự chế nhạo điều này. Câu trả lời ở trên phản ánh thói quen sử dụng shader của tôi như là câu trả lời đầu tiên của tôi cho mọi thứ, nhưng trong trường hợp này chúng không thực sự cần thiết và việc sử dụng chúng không cần thiết làm phức tạp mọi thứ.
Như tôi đã đề xuất, bạn có thể thực hiện chính xác hiệu ứng tương tự bằng cách sử dụng BlendState tùy chỉnh. Cụ thể, BlendState tùy chỉnh này:
BlendState Multiply = new BlendState()
{
AlphaSourceBlend = Blend.DestinationAlpha,
AlphaDestinationBlend = Blend.Zero,
AlphaBlendFunction = BlendFunction.Add,
ColorSourceBlend = Blend.DestinationColor,
ColorDestinationBlend = Blend.Zero,
ColorBlendFunction = BlendFunction.Add
};
Phương trình pha trộn là
result = (source * sourceBlendFactor) blendFunction (dest * destBlendFactor)
Vì vậy, với BlendState tùy chỉnh của chúng tôi, điều đó trở thành
result = (lightmapColor * destinationColor) + (0)
Điều đó có nghĩa là màu nguồn của màu trắng tinh khiết (1, 1, 1, 1) sẽ giữ màu đích, màu nguồn của màu đen thuần khiết (0, 0, 0, 1) sẽ làm tối màu đích thành màu đen thuần khiết và bất kỳ màu nào màu xám ở giữa sẽ làm tối màu đích đến một lượng trung bình.
Để áp dụng điều này vào thực tế, trước tiên hãy làm bất cứ điều gì bạn cần làm để tạo ánh sáng của bạn:
var lightmap = GetLightmapRenderTarget();
Sau đó, chỉ cần vẽ cảnh không thích hợp của bạn trực tiếp vào backbuffer như bình thường:
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
/* draw the world here */
spriteBatch.End();
Sau đó vẽ sơ đồ ánh sáng bằng BlendState tùy chỉnh:
var offsetX = 0; // you'll need to set these values to whatever offset is necessary
var offsetY = 0; // to align the lightmap with the map tiles currently being drawn
var width = lightmapWidthInTiles * tileWidth;
var height = lightmapHeightInTiles * tileHeight;
spriteBatch.Begin(SpriteSortMode.Immediate, Multiply);
spriteBatch.Draw(lightmap, new Rectangle(offsetX, offsetY, width, height), Color.White);
spriteBatch.End();
Điều này sẽ nhân màu đích (gạch không sáng) với màu nguồn (ánh sáng), làm tối màu gạch không thích hợp và tạo hiệu ứng chuyển màu do kết cấu ánh sáng được thu nhỏ theo kích thước cần thiết.