2011-03-01 12 views
9

मैं एक बहुत ही सरल शेडर लिखने की कोशिश कर रहा हूं जो लागू वस्तुओं पर यादृच्छिक चमक डालता है। जिस तरह से मैं यह करना चाहता हूं वह पिक्सेल शेडर के भीतर पिक्सेल मान पर सफेद (आर = जी = बी) की एक यादृच्छिक छाया जोड़कर है।क्या मैं एक पिक्सेल शेडर के अंदर यादृच्छिक संख्या उत्पन्न कर सकता हूं?

ऐसा लगता है कि जिस तरह से noise() मुझे आशा है कि यह करता है काम नहीं करता:

float multiplier = noise(float3(Input.Position[0], Input.Position[1], time)); 

यह मुझे देता है "त्रुटि X4532: पिक्सेल शेडर अनुदेश सेट करने के लिए अभिव्यक्ति मैप नहीं कर सकते" noise() करने के लिए कॉल का जिक्र है।

चूंकि मुझे शेडर को कॉल के बीच कोई संख्या बनाए रखने का कोई तरीका नहीं पता है, इसलिए मुझे नहीं लगता कि मैं प्रतिपादन से पहले पारित बीज के आधार पर एक साधारण यादृच्छिक संख्या उत्पादन कार्य लिख सकता हूं।

क्या पिक्सल शेडर के अंदर से यादृच्छिक संख्या उत्पन्न करने का कोई तरीका है? अगर कोई रास्ता है, तो कैसे?

उत्तर

5

ऐसा कुछ भी नहीं है जो कहता है कि आपको एक यादृच्छिक जनरेटर के लिए चलाने के लिए बीज का पुन: उपयोग करना है, आपको बस किसी भी बीज की आवश्यकता है।

यदि आप पिक्सेल समन्वय का उपयोग करते हैं, तो आप एक निश्चितवादी परिणाम (यानी पिक्सेल एक्स, वाई हमेशा एक ही यादृच्छिक भड़कना होगा) के साथ समाप्त हो जाएगा, लेकिन कुल मिलाकर पूरे चेहरे को इसे यादृच्छिक रूप से वितरित किया जाएगा ।

अब, अगर आप पर्यावरण के आधार पर कुछ इनपुट के रूप में उपलब्ध हैं (मुझे पिक्सेल शेडर्स के बारे में कुछ भी पता नहीं है), जैसे दृश्य/कैमरा संयोजन की वैश्विक जगह में पिक्सेल की समग्र नियुक्ति की तरह बहुभुज के सापेक्ष, फिर, विशेष रूप से तेजी से चलने वाले वातावरण में, आपके परिणाम प्रभावी ढंग से यादृच्छिक होंगे।

यदि वैश्विक वातावरण में सब कुछ ठीक वही होता है, तो हाँ, आपके पास सटीक "यादृच्छिक" वितरण होगा। लेकिन यह उन कारकों में से कोई भी बदलता है (विशेष रूप से उपयोगकर्ता इनपुट पर आधारित, जो संभवतः आप सबसे अधिक गतिशील "शोर स्रोत") पर प्रभाव डालते हैं, तो कुल मिलाकर प्रभाव "पर्याप्त यादृच्छिक" होगा।

तो, कुंजी ले लेना यह है कि आपके बीज को यादृच्छिक संख्या जनरेटर के पिछले भाग का नतीजा नहीं होना चाहिए। यह कुछ भी हो सकता है। इसलिए, अपने स्वयं के आरएनजी में शेडर को इनपुट के आधार पर प्रत्येक पिक्सेल के लिए बीज का विरोध करने से आपको वह प्रभाव मिल सकता है जो आपको चाहिए।

+0

हालांकि दोनों उत्तर उपयोगी हैं, यह एक बेहतर है जो मैं ढूंढ रहा था। धन्यवाद! – chaosTechnician

8

जब आप पिक्सेल शेडर में यादृच्छिक मान चाहते हैं तो आमतौर पर आप शोर युक्त बनावट में गुजरना चाहते हैं। हालांकि यह वास्तव में "यादृच्छिक" नहीं है - यह यादृच्छिक दिखता है।

float3 random = (tex2D(noiseTexture, texCoord * noiseScale + noiseOffset)); 

बनावट का उपयोग मैं एक आरजीबी शोर बनावट है, जो काम में कुछ समय आ सकते हैं:

उदाहरण के लिए, यहाँ मैं चारों ओर झूठ बोल रही है एक पिक्सेल शेडर से कुछ कोड है। लेकिन एक ही तकनीक एक ग्रेस्केल के लिए काम करेगी।

इसे स्केल करके मैं सुनिश्चित करता हूं कि शोर बनावट में पिक्सेल ऑन-स्क्रीन पिक्सल तक लाइन (आप बनावट नमूना को "पॉइंट" मोड में भी सेट करना चाहते हैं ताकि आप शोर बनावट को धुंधला न करें)।

ऑफसेट का उपयोग करके आप बनावट को स्क्रॉल कर सकते हैं - जो एक यादृच्छिक संख्या जनरेटर बीजिंग की तरह है। यदि आप उस "स्क्रॉलिंग" लुक से बचना चाहते हैं तो एक यादृच्छिक ऑफ़सेट का उपयोग करें।

24

अद्यतन जुलाई 2017:

float random(vec2 p) 
{ 
    // e^pi (Gelfond's constant) 
    // 2^sqrt(2) (Gelfond–Schneider constant) 
    vec2 K1 = vec2(23.14069263277926, 2.665144142690225); 

    //return fract(cos(mod(12345678., 256. * dot(p,K1)))); // ver1 
    //return fract(cos(dot(p,K1)) * 123456.); // ver2 
    return fract(cos(dot(p,K1)) * 12345.6789); // ver3 
} 

// Minified version 3: 
float random(vec2 p){return fract(cos(dot(p,vec2(23.14069263277926,2.665144142690225)))*12345.6789);} 

एक बनावट शोर उत्पन्न करने के लिए पासिंग: मैं "छद्म अनियमितता" और अधिक स्थिर कर दिया है

// Version 3 
float random(vec2 p) 
{ 
    vec2 K1 = vec2(
     23.14069263277926, // e^pi (Gelfond's constant) 
     2.665144142690225 // 2^sqrt(2) (Gelfond–Schneider constant) 
    ); 
    return fract(cos(dot(p,K1)) * 12345.6789); 
} 

इस संस्करण हैं इंजीनियर (आमतौर पर) इंजीनियर पर है। ऐसे समय होते हैं जहां यह आसान होता है लेकिन अधिकांश मामलों के लिए यह यादृच्छिक संख्या की गणना करने के लिए सरल और तेज़ है।

चूंकि शेडर चर प्रति खंड स्वतंत्र हैं क्योंकि वे उनके बीच मौजूदा चर का पुन: उपयोग करने में असमर्थ हैं। तब समस्या "अच्छा" यादृच्छिक संख्या बीज का उपयोग करने में से एक बन जाती है। लगता है कि क्रांतिकारी संख्या बिल के साथ शुरू करने के लिए उपयुक्त है। फिर यह एक अच्छा "परमिट" फ़ंक्शन चुनने का एक 'सरल' मामला है।

// Input: It uses texture coords as the random number seed. 
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive. 
// Author: Michael Pohoreski 
// Copyright: Copyleft 2012 :-) 
// NOTE: This has been upgraded to version 3 !! 
float random(vec2 p) 
{ 
    // We need irrationals for pseudo randomness. 
    // Most (all?) known transcendental numbers will (generally) work. 
    const vec2 r = vec2(
    23.1406926327792690, // e^pi (Gelfond's constant) 
    2.6651441426902251); // 2^sqrt(2) (Gelfond–Schneider constant) 
    return fract(cos(mod(123456789., 1e-7 + 256. * dot(p,r)))); 
} 

को समझने के लिए यह कैसे काम करता है, तो हम उसके घटक भागों में नीचे सूत्र तोड़ यह कल्पना करने के लिए क्या चल रहा है आसान हो जाता है:

यहाँ कुछ मुक्त कोड है जो काम कर देता है है

const vec2 k = vec2(23.1406926327792690,2.6651441426902251); 
float rnd0(vec2 uv) {return dot(uv,k); } 
float rnd1(vec2 uv) { return 1e-7 + 256. + dot(uv,k); } 
float rnd2(vec2 uv) { return mod(123456789., 256. * dot(uv,k)); } 
float rnd3(vec2 uv) { return cos(mod(123456789., 256. * dot(uv,k))); } 

// We can even tweak the formula 
float rnd4(vec2 uv) { return fract(cos(mod(1234., 1024. * dot(uv,k)))); } 
float rnd5(vec2 uv) { return fract(cos(mod(12345., 1024. * dot(uv,k)))); } 
float rnd6(vec2 uv) { return fract(cos(mod(123456., 1024. * dot(uv,k)))); } 
float rnd7(vec2 uv) { return fract(cos(mod(1234567., 1024. * dot(uv,k)))); } 
float rnd8(vec2 uv) { return fract(cos(mod(12345678., 1024. * dot(uv,k)))); } 
float rnd9(vec2 uv) { return fract(cos(mod(123456780., 1024. * dot(uv,k)))); } 

void mainImage(out vec4 fragColor, in vec2 fragCoord) 
{ 
    mediump vec2 uv = fragCoord.xy/iResolution.xy; 
    float i = rnd9(uv); 
    fragColor = vec4(i,i,i,1.); 
} 

मैं भी 2 शोर काम करता है, और 2 यादृच्छिक कार्यों के साथ एक "तुलना" ShaderToy उदाहरण बना लिया है:

शोर का उपयोग करने का डेमो "[2TC 15] धब्बा क्रॉस फीका "

एक "क्लासिक" यादृच्छिक समारोह, कभी कभी snoise3 इस bad one है:

return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); 

आप तुलना "छद्म यादृच्छिक" कार्यों डेव Hash without sine शेडर की जाँच करना चाहते हैं।

+0

अच्छा: डी धन्यवाद! – Raptormeat

+0

दिलचस्प। हालांकि मैं असहमत हूं कि बनावट विधि अति-इंजीनियरिंग है। आप निर्देशों की एक गैर-महत्वहीन संख्या के लिए बनावट बना रहे हैं। और आपको अभी भी प्रत्येक फ्रेम को एक यादृच्छिक ऑफ़सेट में पास करना होगा। मैं कहूंगा कि दोनों विधियां मान्य हैं। –

+0

@AndrewRussell आधुनिक जीपीयू के साथ यह गणना (सीपीयू बाध्य) तो बनावट (आईओ बाध्य) करने के लिए (आमतौर पर) बहुत तेज है। यदि आपको प्रति पिक्सल की "यादृच्छिक" संख्या की आवश्यकता है तो यह केवल बनावट निर्देशांक में गुजरने के लिए तुच्छ है। मैंने आमतौर पर शब्द कोष्ठक में रखा क्योंकि * * * * * के लिए * * * के लिए एकमात्र तरीका समय है। ;-) – Michaelangel007

संबंधित मुद्दे

 संबंधित मुद्दे