แล้วเรื่องแบบนี้ล่ะ?
อย่าวาดแสงโดยการย้อมสีสไปรต์กระเบื้องของคุณ วาดไทล์กระเบื้องของคุณไปยังเป้าหมายการเรนเดอร์จากนั้นวาดไฟไทล์ไปยังเป้าหมายเรนเดอร์ตัวที่สองซึ่งแทนแต่ละอันเป็นสี่เหลี่ยมสีเทาซึ่งครอบคลุมพื้นที่ของไทล์ ในการเรนเดอร์ฉากสุดท้ายให้ใช้ shader เพื่อรวมเป้าหมายการเรนเดอร์ทั้งสองเข้าด้วยกันโดยทำให้แต่ละพิกเซลของฉากแรกมืดลงตามค่าของวินาที
สิ่งนี้จะสร้างสิ่งที่คุณมีอยู่ในปัจจุบัน แต่นั่นไม่ได้ช่วยอะไรคุณลองเปลี่ยนมันซักหน่อย
เปลี่ยนขนาดของเป้าหมายการแสดงผล Lightmap ของคุณเพื่อให้แต่ละไทล์แสดงด้วยพิกเซลเดียวแทนที่จะเป็นพื้นที่สี่เหลี่ยม เมื่อประกอบฉากสุดท้ายให้ใช้สถานะตัวอย่างด้วยการกรองเชิงเส้น มิฉะนั้นปล่อยให้ทุกอย่างอื่นเหมือนกัน
สมมติว่าคุณเขียน shader ของคุณอย่างถูกต้องแล้วแผนที่แสงควร "ขยายขนาด" อย่างมีประสิทธิภาพระหว่างการผสม นี่จะทำให้คุณได้เอฟเฟกต์การไล่ระดับสีที่ดีฟรีผ่านอุปกรณ์เก็บตัวอย่างของอุปกรณ์กราฟิก
คุณอาจจะสามารถตัดส่วนที่ตัดออกและทำสิ่งนี้ได้ง่ายขึ้นด้วย 'การทำให้มืดลง' BlendState แต่ฉันต้องทดลองกับมันก่อนที่จะให้รายละเอียดที่เฉพาะเจาะจงแก่คุณ
UPDATE
ฉันมีเวลาวันนี้เพื่อเยาะเย้ยเรื่องนี้ คำตอบข้างต้นสะท้อนให้เห็นถึงนิสัยของฉันในการใช้ shaders เป็นคำตอบแรกของฉันกับทุกสิ่ง แต่ในกรณีนี้พวกเขาไม่จำเป็นจริง ๆ และการใช้งานของพวกเขายุ่งยากโดยไม่จำเป็น
ตามที่ฉันแนะนำคุณสามารถบรรลุผลเช่นเดียวกันโดยใช้ BlendState ที่กำหนดเอง โดยเฉพาะ BlendState ที่กำหนดเองนี้:
BlendState Multiply = new BlendState()
{
AlphaSourceBlend = Blend.DestinationAlpha,
AlphaDestinationBlend = Blend.Zero,
AlphaBlendFunction = BlendFunction.Add,
ColorSourceBlend = Blend.DestinationColor,
ColorDestinationBlend = Blend.Zero,
ColorBlendFunction = BlendFunction.Add
};
สมการผสมคือ
result = (source * sourceBlendFactor) blendFunction (dest * destBlendFactor)
ดังนั้นด้วย BlendState ที่กำหนดเองของเรานั่นจะกลายเป็น
result = (lightmapColor * destinationColor) + (0)
ซึ่งหมายความว่าสีแหล่งที่มาของสีขาวบริสุทธิ์ (1, 1, 1, 1) จะรักษาสีปลายทางสีแหล่งที่มาของสีดำบริสุทธิ์ (0, 0, 0, 1) จะทำให้สีปลายทางมืดลงเป็นสีดำบริสุทธิ์และอื่น ๆ สีเทาในระหว่างนั้นจะทำให้สีปลายทางมืดลงด้วยปริมาณที่ปานกลาง
หากต้องการนำสิ่งนี้ไปใช้ในทางปฏิบัติอันดับแรกให้ทำสิ่งที่คุณต้องทำเพื่อสร้าง Lightmap ของคุณ:
var lightmap = GetLightmapRenderTarget();
จากนั้นเพียงแค่วาดฉากที่ไม่ส่องแสงของคุณโดยตรงไปที่ backbuffer ตามปกติ:
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
/* draw the world here */
spriteBatch.End();
จากนั้นวาด Lightmap โดยใช้ BlendState ที่กำหนดเอง:
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();
สิ่งนี้จะเพิ่มสีปลายทาง (ไทล์กระเบื้องที่ไม่มีแสง) ด้วยสีของแหล่งที่มา (lightmap) ปรับความเข้มของกระเบื้องที่ไม่มีแสงให้เหมาะสมและสร้างเอฟเฟกต์การไล่ระดับสีอันเป็นผลมาจาก