এলোমেলো সংখ্যা


13

আপনি কীভাবে এইচএলএসএল এলোমেলো নম্বর তৈরি করবেন?

আমি জিপিইউ রে ট্রেসিং চেষ্টা করতে চাই বলে জিজ্ঞাসা করছি । আপনাকে পিক্সেল শেডারে এলোমেলো দিকনির্দেশ তৈরি করতে হবে। সুতরাং আমি চাই randFloat()যেখানে ফলাফলটি -1 এবং +1 এর মধ্যে একটি এলোমেলো সংখ্যা is

এছাড়াও, এইচএলএসএল শব্দের নির্দেশাবলী কী? দস্তাবেজগুলি বলে যে এটি এইচএলএসএল ২.০ থেকে উচ্চতর থেকে সরানো হয়েছে। কেন ?

আমি এমন একটি পদ্ধতির বিষয়ে পড়েছিলাম যেখানে আপনি এলোমেলো মানগুলি দিয়ে কোনও টেক্সচার পূরণ করেন, তারপরে প্রতিটি শীর্ষবিন্দুতে একটি টেক্সচার সমন্বয় থাকে যা সেই টেক্সচারের একটি সূচক থাকে। তবে এটি প্রতি ভার্টেক্স হিসাবে , আমার একটি নির্দেশিকা দরকার যা আমি পিক্সেল শেডারটিতে কল করতে পারি। এছাড়াও এই পদ্ধতির জন্য প্রতি-ভার্টেক্স টেক্সকর্ডগুলি "পুনরায় গবেষণা" করা দরকার যদি আপনি প্রতিটি ফ্রেমে আলাদা আলাদা মান চান এবং এর জন্য প্রতিটি ফ্রেমকে একটি ভার্টেক্স বাফার আপডেট করতে হয় (যা ব্যয়বহুল হতে পারে!)

বিশদ সহ, আপনি কীভাবে জিপিইউতে সস্তাভাবে একটি এলোমেলো সংখ্যা তৈরি করতে পারেন?


1
প্রতি ভারটিেক্স বলতে আপনার কী বোঝায়, টেক্সট কোর্ড পিক্সেল শেডার এবং তার প্রতি পিক্সেল লক এ র্যান্ডম টেক্সচারে ইন্টারপোল্ট হয়ে যায়।
কিকাইমারু

আমার অর্থ হ'ল যদি 2 টেক্সচারের মানগুলি খুব কাছাকাছি হয় তবে এই নির্ভরতা হতে চলেছে (আপনি একটি "মিশ্রিত" মান পাবেন)। বলুন যে আপনার, v এর জন্য একটি ভার্টেক্সের (0.5,0.5) রয়েছে এবং সংলগ্ন ভার্টেক্সের (0.51,0.52) রয়েছে, এবং সেই বিভাগে 500 টির মতো টুকরা রয়েছে .. তারপরে ফলাফলগুলি 2 বা 3 আসল এলোমেলো মান হতে পারে (উপরের দিকে তাকান) অঙ্গবিন্যাস), তবে বাকীগুলি মুখের সাথে রৈখিকভাবে বিরক্ত হবে এবং সত্যিকারের এলোমেলো নয়। আমি সেই সম্ভাবনাটি দূর করতে এবং একটি র‌্যান্ড () ফাংশন রাখতে চাই যা আমি পিক্সেল
শেডারটিতে

আপনি কেন বলবেন যে একটি ভার্টেক্সে ০.৫ এবং অন্য ০.০১ রয়েছে, যা মোটেও এলোমেলো শোনায় না, আপনার এই টেক্সট কোর্ডগুলিও "এলোমেলাইজ" করা দরকার, আপনি চাইলে পিক্সেল শেডারেও এটি করতে পারেন, তবে আরও অনেকগুলি ক্রিয়াকলাপ চালিয়ে যেতে পারেন । এই টেক্সট সমন্বয়গুলি তাদের অবস্থান থেকে উত্পন্ন করার দরকার নেই তাই তারা একে অপরের নিকটবর্তী হওয়ার বিষয়টি বিবেচনা করে না। আপনি একবার ভার্টেক্স শ্যাডারে র্যান্ডম টেক্সচারটি নমুনা করতে পারেন (পজিশন, নরমাল, টেক্সকর্ডস * টেক্সকর্ডস হিসাবে কিছু প্যারামিটার ব্যবহার করে) এবং এটি আপনাকে পিক্সেল শেডারে পাস করা টেক্সকর্ডস দেবে
কাইকাইমারু

@ কাইকাইমারু আমার অর্থ খারাপ পরিস্থিতি, এটি সম্ভব ..
বোবোবোলো

হ্যাঁ এলোমেলোভাবে ক্রমানুসারে একে অপরের পরে দুটি একই মান হওয়া সম্ভব
কিকাইমারু

উত্তর:


14

পিক্সেল শেডারে সিউডো এলোমেলো নম্বরগুলি পাওয়া সহজ নয়। সিপিইউতে একটি সিউডো এলোমেলো নম্বর জেনারেটরের কিছু স্থিতি থাকবে যা এটি ফাংশনটিতে প্রতিটি কল করে উভয়ই পাঠ করে এবং লিখেছিল। আপনি এটি পিক্সেল শেডারে করতে পারবেন না।

এখানে কিছু বিকল্প রয়েছে:

  1. পিক্সেল শেডারের পরিবর্তে একটি কম্পিউট শেডার ব্যবহার করুন - তারা একটি বাফারটিতে পঠন-লেখার অ্যাক্সেস সমর্থন করে, যাতে আপনি যে কোনও মানক PRNG বাস্তবায়ন করতে পারেন।

  2. পর্দার স্থান অবস্থানের মতো প্যারামিটারের উপর ভিত্তি করে এলোমেলো ডেটাযুক্ত এক বা একাধিক টেক্সচারের নমুনা। টেক্সচারটি সন্ধান করার জন্য আপনি পজিশনে এটি ব্যবহার করার আগে কিছু গণিতও করতে পারেন, যদি গণিতে একটি র্যান্ডম-প্রতি-ড্র-কল-শেডার ধ্রুবক থাকে তবে আপনাকে টেক্সচারটি পুনরায় ব্যবহার করতে দেওয়া উচিত।

  3. স্ক্রিন স্পেস পজিশনের কিছু গাণিতিক ফাংশন সন্ধান করুন, এটি 'এলোমেলো' এমন ফলাফল দেয়।

একটি দ্রুত গুগল অনুসন্ধান এই ফাংশনগুলির সাথে এই পৃষ্ঠাটি খুঁজে পেয়েছে :

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;
}

পুনরায়: গণনা শেডারগুলি, আপনি থ্রেডগ্রুপ শেয়ার করা মেমরিতে আরএনজি রাজ্যও সঞ্চয় করতে পারেন। দক্ষতার জন্য আপনি কেবল একটি আরএনজি রাজ্য চান না (প্রতিটি থ্রেড এটি আপডেট করার চেষ্টা করার সাথে যুক্তিটি একটি বিরাট বাধা হয়ে দাঁড়াবে), তবে অনেকগুলি - সম্ভবত প্রতি থ্রেড হিসাবে একজন, বা সম্ভবত প্রতি 4 বা 8 টি থ্রেড বা এরকম কিছু - যতদিন রাজ্য ছোট যথেষ্ট যে সম্ভবপর (অর্থাত সম্ভবত করতে না Mersenne প্রতারক)। এমন কি আরএনজি ডিজাইন রয়েছে যাতে একাধিক সিমডি থ্রেড একসাথে বেশ কয়েকটি এলোমেলো সংখ্যা তৈরি করতে সহযোগিতা করতে পারে? এটি এখানে বেশ কার্যকর হবে।
নাথান রিড

1
বাহ্যিক লিঙ্কটি নষ্ট হয়েছে
জর্জ বীরবিলিস

2

এখানে আমি একটি গণনাকারী শেডার দিয়ে আমার কণা প্রভাবের জন্য সিউডো এলোমেলো সংখ্যাগুলি তৈরি করি। এই কোডটি কতটা সত্যই এলোমেলো তা নিশ্চিত নয় তবে এটি আমার উদ্দেশ্যগুলির জন্য যথেষ্ট ভাল কাজ করে।

প্রতিটি জিপিইউ কার্নেলকে তার নিজস্ব এলোমেলো ক্রম দেওয়ার চাবি হ'ল সিপিইউ থেকে প্রাথমিক র্যান্ডম বীজ গণনা শেডারকে খাওয়ানো। প্রতিটি কার্নেল তারপরে এই বীজটিকে একটি সংখ্যা হিসাবে থ্রেড আইডি ব্যবহার করে নম্বর জেনারেটরটিকে চক্র করতে ব্যবহার করে। সেখান থেকে, প্রতিটি থ্রেডের নিজস্ব অনন্য বীজ থাকা উচিত অনন্য মান উত্পন্ন করতে।

// 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.