ฉันจะผสมผสาน 2 lightmaps สำหรับรอบกลางวัน / กลางคืนใน Unity ได้อย่างไร


16

ก่อนที่ฉันจะพูดอะไรอีก: ฉันใช้ lightmaps คู่หมายความว่าฉันต้องผสมผสานทั้งใกล้และไกล

ดังนั้นฉันจึงได้ทำสิ่งนี้มาระยะหนึ่งแล้วฉันมีวงจรตลอดทั้งวัน / คืนสำหรับผู้สร้างภาพและแสงและทุกอย่างทำงานได้ดีและไม่ต้องใช้ความพยายามมาก

ปัญหาเดียวที่ฉันมีคือการหาวิธีที่ฉันสามารถผสมผสานสองแผนที่แสงร่วมกันฉันได้คิดวิธีการเปลี่ยนแผนที่แสง แต่ปัญหาคือดูเหมือนจะฉับพลันและขัดจังหวะประสบการณ์

ฉันได้ทำการค้นคว้าเกี่ยวกับสิ่งนี้มาหลายชั่วโมงแล้วลองใช้เฉดสีทุกชนิดการผสมพิกเซลแบบพิกเซลต่อพิกเซลและทุกอย่างอื่นก็ไม่มีประโยชน์จริง การผสมพิกเซลต่อพิกเซลใน C # กลายเป็นกระบวนการที่ค่อนข้างเข้มข้นสำหรับความชอบของฉันแม้ว่าฉันจะยังคงพยายามทำความสะอาดและทำให้มันทำงานได้ราบรื่นขึ้น Shaders ดูมีแนวโน้ม แต่ฉันไม่พบ shader ที่สามารถผสมผสานสอง lightmaps ได้อย่างเหมาะสม

ไม่มีใครมีโอกาสในการเป็นผู้นำในการทำสิ่งนี้ให้สำเร็จหรือไม่? ฉันต้องการการเปลี่ยนระหว่างแผนที่แสงกลางวันและกลางคืนอย่างราบรื่น บางทีฉันสามารถซ้อนทับสองพื้นผิวและใช้ช่องอัลฟ่าได้หรือไม่ หรืออะไรแบบนั้น


หากคุณมีมืออาชีพบางทีคุณสามารถแสดงพื้นผิว Lightmap ที่สองเป็นหนึ่งในสามและจากนั้นใช้พื้นผิวที่สามเป็น Lightmap? ที่ควรจะเหมือนกับการผสมพิกเซล แต่เร็วขึ้นอย่างหนาแน่น
ไม่เป็นไร

ฉันมีโปร ฉันจะทำอย่างไรกับการเรนเดอร์เนื้อผ้าสองแบบด้วยกัน นี่คือเป้าหมายหลักของฉัน แต่ฉันพยายามคิดรหัส / กระบวนการเพื่อให้สำเร็จ
Timothy Williams

อืมสร้างวัสดุที่ผสมผสานพื้นผิวสองอย่างใช้Graphics.Blit()เพื่อแสดงมันหรือไม่? ฉันไม่เคยทำแบบนี้มาก่อน แต่เมื่อดูในคู่มือแล้วมันน่าจะใช้ได้
ไม่เป็นไร

ดังนั้นสร้างวัสดุใหม่ที่สามารถผสมผสานสองพื้นผิวกับเอาท์พุทใช้ Afar-1 และ Bfar-1 จากนั้นใช้พื้นผิวขาออกสำหรับตัวแปร lightmap หรือไม่
Timothy Williams

ใช่อะไรแบบนั้น ฉันจะทดสอบ แต่ฉันไม่สามารถเข้าถึงรุ่น Pro ได้ในขณะนี้
ไม่เป็นไร

คำตอบ:


3

ดังนั้นเมื่อเร็ว ๆ นี้ฉันลองใช้มือของฉันที่นี่และพบปัญหามากมายที่คุณมี การแก้ปัญหาพื้นผิวการแสดงผลเป็นปลาเฮอริ่งแดงเล็กน้อย ฉันสามารถแก้ไขได้โดยใช้การจัดการพิกเซลแบบมัลติเธรดบนเธรดแยกต่างหาก

https://www.youtube.com/watch?v=T_zpFk1mdCI

ตามปกติแล้วจะใช้graphics.blit()และส่งภาพพื้นผิวการแสดงผลไปยังทุกที่ที่ต้องการ แต่ข้อมูล Lightmap ไม่รองรับพื้นผิวพวกเขาต้องการ texture2ds ขั้นตอนตรรกะถัดไปคือการคัดลอกข้อมูลไปยัง texture2d แล้วฟีดนั้นไปยังข้อมูล lightmap เทคนิคนี้ทำลายอัตราเฟรมเนื่องจากมันทำให้แผงวงจร GPU ส่งข้อมูลไปยัง CPU มากกว่าการอ้างอิงไปยังข้อมูล

วิธีแก้ปัญหาคือไม่ใช้ GPU

การเปลี่ยนแผนที่แสงเกิดขึ้นในช่วงเวลาที่ยาวนานดังนั้นจึงไม่จำเป็นต้องอัปเดตแผนที่แสงทุกเฟรม ตามความเป็นจริงแล้วผู้เล่นอาจไม่สังเกตเห็นว่าแผนที่ไฟถูกอัพเดทเพียง 20-40 นาทีในเวลาเล่นเกมเท่านั้น

ดังนั้นสิ่งที่คุณทำคือคุณออกงานให้ CPU ในหัวข้อที่แยกต่างหากสำหรับแต่ละแผนที่แสง

โดยทั่วไปแล้ว Unity ไม่รองรับการใช้งานหลายเธรด แต่ก็ไม่เป็นไร C # ทำ ผู้ชายคนนี้มีงานที่ยอดเยี่ยมอธิบายการมัลติเธรดใน Unity ดังนั้นถ้าคุณไม่เคยได้ยินหรือไม่เคยรู้วิธีการมัลติเธรดใน Unity นี่คือวิดีโอ:

https://www.youtube.com/watch?v=ja63QO1Imck

สิ่งที่คุณต้องทำก็คือสร้างคลาสเธรดของผู้ปฏิบัติงานซึ่งจะทำสำเนาข้อมูลพิกเซลของ Lightmap ใน Color Array และสร้างฟังก์ชั่นการผสมผสาน

lerp อย่างง่ายจากสีหนึ่งไปอีกสีหนึ่งจะทำ

จากนั้นสร้างเธรดเริ่มต้นและเมื่อ Lightmaps ทั้งหมดเสร็จสิ้นในเธรดแยกต่างหากคุณสามารถคัดลอกข้อมูลพิกเซลกลับเข้าไปใน lightmap data texture2d

ฉันโพสต์โค้ดตัวอย่างบางส่วนด้านล่าง แน่นอนว่าไม่ใช่เวอร์ชันที่นำมาใช้อย่างสมบูรณ์ แต่จะแสดงแนวคิดหลักในการสร้างคลาสสร้างเธรดจากนั้นตั้งค่า lightdata

สิ่งอื่น ๆ ที่คุณต้องทำคือเรียกใช้ฟังก์ชั่นทุก ๆ ครั้งเพื่อกระตุ้นการอัพเดทแผนที่แสง นอกจากนี้คุณต้องคัดลอกข้อมูลพิกเซลทั้งหมดลงในคลาสผู้ปฏิบัติงานในตอนเริ่มต้นหรือในเวลารวบรวม ขอให้โชคดีกับทุกคนที่พบสิ่งนี้ ฉันคิดว่า op ได้ดำเนินต่อไปกับชีวิตของพวกเขา แต่ฉันรู้ว่าคนอื่นที่มีปัญหาคล้ายกันอาจสะดุดกับเรื่องนี้

public class work
{
    Color[] fromPixels;
    Color[] toPixels;

    public float LerpValue = 0;
    public bool Finished = false;
    public Color[] mixedPixels;

    public work(Color[] FromPix, Color[] ToPix)
    {
        fromPixels= FromPix;
        toPixels= ToPix;
        Finished = false;
        mixedPixels = new Color[FromPix.Length];
    }
    public void DoWork()
    {
        for (int x = 0; x < fromPixels.Length; x++)
        {
            mixedPixels[x] = Color.Lerp(fromPixels[x], toPixels[x], LerpValue);
        }
        Finished = true;
    }
}

IEnumerator LightMapSet()
{
    Thread workerThread = new Thread(someworker.DoWork);
    someworker.LerpValue = lerpValue;
    workerThread.Start();
    yield return new WaitUntil(() => someworker.Finished);
    mixedMap.SetPixels(someworker.mixedPixels);
    mixedMap.Apply(true);
    LightmapData someLightmapData;
    someLightmapData.lightmapColor = mixedMap;
    lightDatas = { someLightmapData};
    LightmapSettings.lightmaps = lightDatas;
}

1

มีส่วนแบ่งสกายบ็อกซ์ที่ผสมผสานระหว่างพื้นผิวสกายบ็อกซ์สองชุด คิดว่าวัฏจักรกลางวันและกลางคืน!

หากคุณต้องการสร้างหรือทำให้สกายบ็อกซ์เคลื่อนไหวจากสคริปต์ให้ใช้skyboxmaterial.SetFloat("_Blend", yourBlend)เพื่อเปลี่ยนการผสม ยังสามารถใช้SetTextureฟังก์ชั่นวัสดุเพื่อตั้งค่าหรือเปลี่ยนพื้นผิว

วิดีโอแนะนำเกี่ยวกับรอบวัน / คืน: http://www.youtube.com/watch?v=FTfv9JhkmIA

โค้ดตัวอย่างจะเป็นดังนี้:

Shader "RenderFX/Skybox Blended" {
Properties {
    _Tint ("Tint Color", Color) = (.5, .5, .5, .5)
    _Blend ("Blend", Range(0.0,1.0)) = 0.5
    _FrontTex ("Front (+Z)", 2D) = "white" {}
    _BackTex ("Back (-Z)", 2D) = "white" {}
    _LeftTex ("Left (+X)", 2D) = "white" {}
    _RightTex ("Right (-X)", 2D) = "white" {}
    _UpTex ("Up (+Y)", 2D) = "white" {}
    _DownTex ("Down (-Y)", 2D) = "white" {}
    _FrontTex2("2 Front (+Z)", 2D) = "white" {}
    _BackTex2("2 Back (-Z)", 2D) = "white" {}
    _LeftTex2("2 Left (+X)", 2D) = "white" {}
    _RightTex2("2 Right (-X)", 2D) = "white" {}
    _UpTex2("2 Up (+Y)", 2D) = "white" {}
    _DownTex2("2 Down (-Y)", 2D) = "white" {}
}

SubShader {
    Tags { "Queue" = "Background" }
    Cull Off
    Fog { Mode Off }
    Lighting Off        
    Color [_Tint]
    Pass {
        SetTexture [_FrontTex] { combine texture }
        SetTexture [_FrontTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_FrontTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_BackTex] { combine texture }
        SetTexture [_BackTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_BackTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_LeftTex] { combine texture }
        SetTexture [_LeftTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_LeftTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_RightTex] { combine texture }
        SetTexture [_RightTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_RightTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_UpTex] { combine texture }
        SetTexture [_UpTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_UpTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_DownTex] { combine texture }
        SetTexture [_DownTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_DownTex2] { combine previous +- primary, previous * primary }
    }
}

Fallback "RenderFX/Skybox", 1
}

2
คำถามที่ถามเกี่ยวกับ lightmaps ไม่ใช่ skybox ขอบคุณสำหรับลิงค์แม้ว่ามันจะเป็นประโยชน์กับฉัน
jhocking

0

หากคุณรู้วิธีเปลี่ยนทำไมไม่ทำต่อไปด้วยการสร้าง lightmaps การเปลี่ยนแปลงจำนวนมากบนเธรดพื้นหลังแล้วเปิดใช้งานการเปลี่ยนภาพเมื่อ lightmaps พร้อมหรือไม่

นอกจากนี้คุณยังสามารถดูเนื้อหาที่น่าสนใจใน AssetStore: https://www.assetstore.unity3d.com/th/#!/content/5674

ฉันเดาว่ามันรวมถึง lightmaps ที่ผสมกันแม้ว่าฉันจะไม่รู้วิธีก็ตาม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.