สุ่มหมายเลข hlsl


13

คุณจะสร้างหมายเลขสุ่มใน HLSL ได้อย่างไร

ฉันขอเพราะผมต้องการที่จะลองGPU ray การติดตาม คุณต้องสร้างเส้นทางแบบสุ่มในตัวแบ่งพิกเซล ดังนั้นฉันต้องการrandFloat()ที่ผลคือตัวเลขสุ่มระหว่าง -1 และ +1

นอกจากนี้การจัดการกับคำแนะนำเสียง hlsl คืออะไร? เอกสารบอกว่ามันถูกลบออกจาก HLSL 2.0 ขึ้นไป ทำไม ?

ฉันอ่านเกี่ยวกับวิธีการที่คุณเติมพื้นผิวด้วยค่าแบบสุ่มแล้วให้มีการประสานงานพื้นผิวในแต่ละจุดยอดที่มีดัชนีลงในพื้นผิวนั้น แต่นั่นคือจุดสุดยอดต่อฉันต้องการคำแนะนำที่ฉันสามารถโทรหาในส่วนพิกเซลได้ ยิ่งไปกว่านั้นวิธีนี้ต้องใช้ "reseeding" เท็กซัสต่อยอดถ้าคุณต้องการค่าที่แตกต่างกันในแต่ละเฟรมและนั่นต้องใช้การปรับปรุงบัฟเฟอร์เท็กซ์ในแต่ละเฟรม (ซึ่งอาจมีราคาแพง!)

ด้วยรายละเอียดคุณจะสร้างตัวเลขสุ่มบน GPU ได้อย่างไร?


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

สิ่งที่ฉันหมายถึงคือถ้าค่าพื้นผิว 2 ค่าใกล้กันเกินไปจะมีการพึ่งพานี้ (คุณจะได้รับค่า "ผสม") สมมติว่าหนึ่งจุดยอดมี (0.5,0.5) สำหรับ u, v และจุดสุดยอดที่อยู่ติดกันมี (0.51,0.52) และมี 500 ชิ้นในส่วนนั้น .. ผลลัพธ์จะเป็น 2 หรือ 3 ค่าสุ่มจริง (เงยหน้าขึ้นมองจาก พื้นผิว) แต่ส่วนที่เหลือจะเป็นการประมาณเชิงเส้นตรงตามใบหน้าและไม่สุ่มอย่างแท้จริง ฉันต้องการกำจัดความเป็นไปได้นั้นและมีฟังก์ชั่น rand () ที่ฉันสามารถโทรหาในส่วนของพิกเซลได้
bobobobo

ทำไมคุณถึงบอกว่าจุดสุดยอดหนึ่งมี 0.5 และ 0.51 อื่น ๆ ที่ไม่ได้สุ่มเลยคุณต้อง "สุ่ม" คอร์ดเท็กซัสเหล่านี้ด้วยคุณสามารถทำได้ในพิกเซลเชดเดอร์ถ้าคุณต้องการ แต่นั่นเป็นการทำงานที่มากขึ้น . Coords tex เหล่านั้นไม่จำเป็นต้องถูกสร้างขึ้นจากตำแหน่งของพวกมันดังนั้นมันจึงไม่สำคัญว่าพวกมันจะอยู่ใกล้กันแค่ไหน คุณจะได้ลิ้มลองเนื้อสุ่มครั้งใน Shader ที่ (โดยใช้ตำแหน่งปกติ texcoords * พารามิเตอร์บางส่วนเป็น texcoords) และนี่จะทำให้คุณ texcoords คุณส่งผ่านไป Shader พิกเซล
Kikaimaru

@ Kikaimaru ฉันหมายถึงสิ่งเลวร้ายที่เกิดขึ้นมันเป็นไปได้ ..
bobobobo

ใช่ในลำดับแบบสุ่มเป็นไปได้ที่จะมีค่าเหมือนกันสองค่า
Kikaimaru

คำตอบ:


14

การสุ่มตัวเลขหลอกในพิกเซลเชดเดอร์ไม่ใช่เรื่องง่ายที่จะได้รับ ตัวสร้างตัวเลขสุ่มหลอกบน CPU จะมีสถานะบางอย่างที่ทั้งอ่านและเขียนทุกครั้งที่เรียกใช้ฟังก์ชัน คุณไม่สามารถทำเช่นนั้นในพิกเซลเชดเดอร์

นี่คือตัวเลือกบางอย่าง:

  1. ใช้ตัวประมวลผลแทนตัวประมวลผลพิกเซลซึ่งรองรับการอ่าน - เขียนในบัฟเฟอร์ดังนั้นคุณสามารถใช้ PRNG มาตรฐานใด ๆ ได้

  2. ตัวอย่างจากหนึ่งหรือมากกว่าหนึ่งพื้นผิวที่มีข้อมูลแบบสุ่มขึ้นอยู่กับพารามิเตอร์เช่นตำแหน่งพื้นที่หน้าจอ นอกจากนี้คุณยังสามารถทำคณิตศาสตร์ในตำแหน่งก่อนที่จะใช้เพื่อค้นหาพื้นผิวซึ่งจะช่วยให้คุณสามารถนำพื้นผิวกลับมาใช้ใหม่ได้หากคณิตศาสตร์เกี่ยวข้องกับค่าคงที่ของการสุ่ม shader แบบสุ่มต่อการวาด

  3. ค้นหาฟังก์ชันทางคณิตศาสตร์ของตำแหน่งพื้นที่หน้าจอที่ให้ผลลัพธ์ที่ 'สุ่มพอ'

การค้นหา google อย่างรวดเร็วพบหน้านี้พร้อมฟังก์ชั่นเหล่านี้:

float rand_1_05(in float2 uv)
{
    float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453));
    return abs(noise.x + noise.y) * 0.5;
}

float2 rand_2_10(in float2 uv) {
    float noiseX = (frac(sin(dot(uv, float2(12.9898,78.233) * 2.0)) * 43758.5453));
    float noiseY = sqrt(1 - noiseX * noiseX);
    return float2(noiseX, noiseY);
}

float2 rand_2_0004(in float2 uv)
{
    float noiseX = (frac(sin(dot(uv, float2(12.9898,78.233)      )) * 43758.5453));
    float noiseY = (frac(sin(dot(uv, float2(12.9898,78.233) * 2.0)) * 43758.5453));
    return float2(noiseX, noiseY) * 0.004;
}

Re: คำนวณเฉดสีคุณยังสามารถเก็บสถานะ RNG ในหน่วยความจำที่ใช้ร่วมกันของกลุ่มด้าย เพื่อประสิทธิภาพคุณไม่ต้องการเพียงหนึ่งสถานะ RNG (การต่อสู้จะเป็นคอขวดขนาดใหญ่ที่ทุกเธรดพยายามอัปเดต) แต่หลาย ๆ อาจจะมากถึงหนึ่งต่อเธรดหรืออาจจะหนึ่งต่อ 4 หรือ 8 เธรดหรือบางอย่าง - ตราบใดที่รัฐมีขนาดเล็กพอที่จะทำให้เป็นไปได้ (เช่นอาจไม่ใช่ Mersenne Twister) มีการออกแบบ RNG ที่หัวข้อ SIMD หลายรายการสามารถร่วมมือเพื่อสร้างตัวเลขสุ่มหลายรายการพร้อมกันได้หรือไม่? นั่นจะมีประโยชน์มากที่นี่
นาธานรีด

1
ลิงค์ภายนอกเสีย
George Birbilis

2

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

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

// Source
// http://www.gamedev.net/topic/592001-random-number-generation-based-on-time-in-hlsl/
// Supposebly from the NVidia Direct3D10 SDK
// Slightly modified for my purposes
#define RANDOM_IA 16807
#define RANDOM_IM 2147483647
#define RANDOM_AM (1.0f/float(RANDOM_IM))
#define RANDOM_IQ 127773u
#define RANDOM_IR 2836
#define RANDOM_MASK 123459876

struct NumberGenerator {
    int seed; // Used to generate values.

    // Returns the current random float.
    float GetCurrentFloat() {
        Cycle();
        return RANDOM_AM * seed;
    }

    // Returns the current random int.
    int GetCurrentInt() {
        Cycle();
        return seed;
    }

    // Generates the next number in the sequence.
    void Cycle() {  
        seed ^= RANDOM_MASK;
        int k = seed / RANDOM_IQ;
        seed = RANDOM_IA * (seed - k * RANDOM_IQ ) - RANDOM_IR * k;

        if (seed < 0 ) 
            seed += RANDOM_IM;

        seed ^= RANDOM_MASK;
    }

    // Cycles the generator based on the input count. Useful for generating a thread unique seed.
    // PERFORMANCE - O(N)
    void Cycle(const uint _count) {
        for (uint i = 0; i < _count; ++i)
            Cycle();
    }

    // Returns a random float within the input range.
    float GetRandomFloat(const float low, const float high) {
        float v = GetCurrentFloat();
        return low * ( 1.0f - v ) + high * v;
    }

    // Sets the seed
    void SetSeed(const uint value) {
        seed = int(value);
        Cycle();
    }
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.