GLSL के लिए रैंडम / शोर फ़ंक्शन


179

जैसा कि GPU ड्राइवर विक्रेताओं आमतौर पर noiseXGLSL में लागू करने के लिए परेशान नहीं करते हैं , मैं "ग्राफिक्स रैंडमाइजेशन स्विस आर्मी चाकू" उपयोगिता फ़ंक्शन सेट की तलाश कर रहा हूं , जो कि GPU shaders के भीतर उपयोग करने के लिए अधिमानतः अनुकूलित है। मैं GLSL को पसंद करता हूं, लेकिन कोई भी भाषा मेरे लिए कोड करेगी, मैं अपने आप को GLSL में अनुवाद करने के साथ ठीक हूं।

विशेष रूप से, मुझे उम्मीद है:

क) छद्म यादृच्छिक कार्य - एन-आयामी, [-1,1] पर समान वितरण या [0,1], एम-आयामी बीज से गणना (आदर्श रूप से किसी भी मूल्य की जा रही है, लेकिन मैं बीज संयमित होने के साथ ठीक हूं , कहते हैं, समान परिणाम वितरण के लिए 0..1)। कुछ इस तरह:

float random  (T seed);
vec2  random2 (T seed);
vec3  random3 (T seed);
vec4  random4 (T seed);
// T being either float, vec2, vec3, vec4 - ideally.

ख) पेरलिन शोर की तरह लगातार शोर - फिर से, एन-आयामी, + - समान वितरण, मूल्यों के विवश सेट के साथ और, ठीक है, अच्छा लग रहा है (पेरलिन के स्तर की तरह उपस्थिति को कॉन्फ़िगर करने के लिए कुछ विकल्प उपयोगी भी हो सकते हैं)। मुझे उम्मीद है कि हस्ताक्षर जैसे:

float noise  (T coord, TT seed);
vec2  noise2 (T coord, TT seed);
// ...

मैं यादृच्छिक संख्या पीढ़ी के सिद्धांत में बहुत ज्यादा नहीं हूं, इसलिए मैं सबसे उत्सुकता से एक पूर्व-निर्मित समाधान के लिए जाऊंगा , लेकिन मैं "यहां एक बहुत अच्छा, कुशल 1D रैंड () जैसे उत्तर की सराहना करूंगा , और मुझे समझाने दूंगा आप इसके ऊपर एक अच्छा एन-आयामी रैंड () कैसे करें ... "

जवाबों:


263

बहुत ही सरल छद्म आयामी दिखने वाले सामान के लिए, मैं इस ऑनलाइनर का उपयोग करता हूं जो मुझे इंटरनेट पर कहीं मिला:

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

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

इसके अलावा, स्टीफन गुस्तावसन द्वारा पेरलिन और सिम्पलेक्स शोर के जीएलएसएल कार्यान्वयन के लिए इस फ़ाइल को देखें।


14
आप कैसे उपयोग करते हैं vec2 co? क्या यह सीमा है? बीज?
रॉस

12
इस एल्गोरिथ्म (जैसे, S3 के एआरएम माली) के साथ कम-सटीक फ़्लोटिंग-पॉइंट फ़्रेग्मेंट शेड्स से सावधान रहें: stackoverflow.com/questions/11293628/…Github.com/ashima/webgl-noise परियोजना lowp समस्याएं आती प्रतीत नहीं होता।
पीटी

4
एफडब्ल्यूआईडब्ल्यू, यहां वर्णित फ़ंक्शन पर यहां और अधिक विस्तार से चर्चा की गई है
लोमचाइल्ड

3
FYI करें: उस फ़ंक्शन का वितरण भयानक है।
तारा

3
मैं GLSL में newb हूं, क्या कोई समझा सकता है कि co.xyइसके बजाय इसका उपयोग क्यों किया जाता है co?
kelin

83

यह मेरे लिए होता है कि आप एक साधारण पूर्णांक हैश फ़ंक्शन का उपयोग कर सकते हैं और परिणाम को फ्लोट के मंटिसा में डाल सकते हैं। IIRC GLSL युक्ति 32-बिट अहस्ताक्षरित पूर्णांक और IEEE बाइनरी 32 के प्रतिनिधित्व की गारंटी देता है, इसलिए यह पूरी तरह से पोर्टेबल होना चाहिए।

मैंने अभी-अभी यह कोशिश की। परिणाम बहुत अच्छे हैं: यह वास्तव में मेरे द्वारा आजमाए गए हर इनपुट के साथ बिल्कुल स्थिर जैसा दिखता है, बिल्कुल भी दिखाई देने वाला पैटर्न नहीं है। इसके विपरीत लोकप्रिय पाप / फ्रैक्चर स्निपेट ने मेरे GPU पर समान इनपुटों को देखते हुए विकर्ण रेखाओं का काफी उच्चारण किया है।

एक नुकसान यह है कि इसके लिए GLSL v3.30 की आवश्यकता है। और यद्यपि यह काफी तेज लगता है, लेकिन मैंने इसके प्रदर्शन को अनिवार्य रूप से निर्धारित नहीं किया है। AMD के शेडर एनालाइज़र का दावा है कि HD5870 पर vec2 संस्करण के लिए प्रति घड़ी 13.33 पिक्सेल। पाप / फ्रैक्चर स्निपेट के लिए प्रति घड़ी 16 पिक्सेल के साथ विरोधाभास। तो यह थोड़ा धीमा जरूर है।

यहाँ मेरा कार्यान्वयन है। मैंने इसे अपने स्वयं के कार्यों को प्राप्त करने के लिए आसान बनाने के लिए विचार के विभिन्न क्रमपरिवर्तन में छोड़ दिया।

/*
    static.frag
    by Spatial
    05 July 2013
*/

#version 330 core

uniform float time;
out vec4 fragment;



// A single iteration of Bob Jenkins' One-At-A-Time hashing algorithm.
uint hash( uint x ) {
    x += ( x << 10u );
    x ^= ( x >>  6u );
    x += ( x <<  3u );
    x ^= ( x >> 11u );
    x += ( x << 15u );
    return x;
}



// Compound versions of the hashing algorithm I whipped together.
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y)                         ); }
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z)             ); }
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }



// Construct a float with half-open range [0:1] using low 23 bits.
// All zeroes yields 0.0, all ones yields the next smallest representable value below 1.0.
float floatConstruct( uint m ) {
    const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
    const uint ieeeOne      = 0x3F800000u; // 1.0 in IEEE binary32

    m &= ieeeMantissa;                     // Keep only mantissa bits (fractional part)
    m |= ieeeOne;                          // Add fractional part to 1.0

    float  f = uintBitsToFloat( m );       // Range [1:2]
    return f - 1.0;                        // Range [0:1]
}



// Pseudo-random value in half-open range [0:1].
float random( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
float random( vec2  v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec3  v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec4  v ) { return floatConstruct(hash(floatBitsToUint(v))); }





void main()
{
    vec3  inputs = vec3( gl_FragCoord.xy, time ); // Spatial and temporal inputs
    float rand   = random( inputs );              // Random per-pixel value
    vec3  luma   = vec3( rand );                  // Expand to RGB

    fragment = vec4( luma, 1.0 );
}

स्क्रीनशॉट:

Static.frag में यादृच्छिक (vec3) का आउटपुट

मैंने एक छवि संपादन कार्यक्रम में स्क्रीनशॉट का निरीक्षण किया। 256 रंग हैं और औसत मूल्य 127 है, जिसका अर्थ है कि वितरण समान है और अपेक्षित सीमा को कवर करता है।


17
एक अच्छा विचार और कार्यान्वयन के लिए +1। मैं दावे पर सवाल उठाऊंगा क्योंकि 256 रंग हैं और औसत मूल्य 127 है, वितरण एक समान होना चाहिए (सख्त अर्थों में)। यह एक समान हो सकता है, लेकिन मुझे नहीं लगता कि हम अभी तक जानते हैं। उदाहरण के लिए एक घंटी वक्र वितरण में समान औसत और रंगों की संख्या हो सकती है, लेकिन एक समान नहीं होगी।
लार्स

@LarsH द्वारा दिए गए कारण के लिए यह नीचे दिया गया है।
शरद ऋतु

खैर, यह अधिकांश अनुप्रयोगों के लिए पर्याप्त है जिन्हें एकरूपता की आवश्यकता नहीं है । :-)
itmuckel

5
यह हिस्टोग्राम की मेरी धारणा से बहुत समान प्रतीत होता है .... मैं कहूंगा कि यह अधिकांश अनुप्रयोगों के लिए पर्याप्त है जो एकरूपता की आवश्यकता है। (केवल वे मान जो दूसरों की तुलना में कम उत्पन्न होते हैं, वे 0 और 255 हैं)
लेविथानबर्गर

धन्यवाद। मेरी संभावना जंग है। GCN निर्देश सेट को देखने के बाद, यह नए हार्डवेयर पर बहुत तेजी से होना चाहिए क्योंकि वे सीधे अपने अनुदेश सेट में बिटफील्ड संचालन का समर्थन करते हैं। मैंने जो परीक्षण किए वे पुराने हार्डवेयर पर चले।
स्थानिक

73

गुस्तावसन के कार्यान्वयन में 1 डी बनावट का उपयोग किया गया है

नहीं, यह 2005 से नहीं है। यह सिर्फ इतना है कि लोग पुराने संस्करण को डाउनलोड करने पर जोर देते हैं। आपके द्वारा दिए गए लिंक पर संस्करण केवल 8-बिट 2D बनावट का उपयोग करता है।

आशिमा के इयान मैकएवन और खुद का नया संस्करण एक बनावट का उपयोग नहीं करता है, लेकिन कई बनावट बैंडविड्थ के साथ ठेठ डेस्कटॉप प्लेटफार्मों पर लगभग आधी गति से चलता है। मोबाइल प्लेटफ़ॉर्म पर, बनावट रहित संस्करण तेज़ हो सकता है क्योंकि बनावट अक्सर एक महत्वपूर्ण अड़चन होती है।

हमारे सक्रिय रूप से बनाए रखा स्रोत भंडार है:

https://github.com/ashima/webgl-noise

शोर के बनावट रहित और बनावट-उपयोग करने वाले संस्करणों का एक संग्रह यहाँ है (केवल 2D बनावट का उपयोग करके):

http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise-vs-noise.zip

यदि आपके कोई विशिष्ट प्रश्न हैं, तो मुझे सीधे ई-मेल करने के लिए स्वतंत्र महसूस करें (मेरा ईमेल पता classicnoise*.glslसूत्रों में पाया जा सकता है ।)


4
हां, मैं जिस कार्यान्वयन की बात कर रहा हूं, वह davidcornette.com पर आपका कोड है, जो @dep से जुड़ा हुआ है, 1D बनावट का उपयोग करता है: glBindTexture(GL_TEXTURE_1D, *texID);आदि। यह स्पष्ट नहीं है कि "आपके द्वारा आपूर्ति की गई लिंक" से आपका क्या मतलब है, क्योंकि आप मेरे जवाब से उद्धरण देते हैं। लेकिन वह उत्तर आपके कार्यान्वयन से जुड़ा नहीं था। मैं आपके द्वारा बताई गई नई जानकारी को स्पष्ट करने के लिए अपने उत्तर को अपडेट करूंगा और आपके द्वारा दी गई नई जानकारी को प्रतिबिंबित करूंगा। पुराने संस्करण को डाउनलोड करने पर लोगों को "आग्रह" के रूप में प्रस्तुत करना एक विकृति है जो आपको क्रेडिट नहीं करता है।
लक्सह

1
PS आप डेविड कॉर्नेट को लिखना चाहते हैं (वह davidcornette.com पर संपर्क जानकारी है ) और उसे अपने स्रोत रेपो से लिंक करने के लिए davidcornette.com/glsl/links.html पर अपना लिंक बदलने के लिए कहें । मैं उसे ईमेल भी करूँगा।
लार्स

1
पीपीएस क्या आप स्पष्ट कर सकते हैं कि कौन सा संस्करण केवल 8-बिट 2 डी बनावट का उपयोग करता है? ऐसा लगता है कि यह कुछ प्लेटफार्मों के लिए एक अच्छा विकल्प हो सकता है ...
लार्स

31

सोने का शोर

// Gold Noise ©2015 dcerisano@standard3d.com
// - based on the Golden Ratio
// - uniform normalized distribution
// - fastest static noise generator function (also runs at low precision)

float PHI = 1.61803398874989484820459;  // Φ = Golden Ratio   

float gold_noise(in vec2 xy, in float seed){
       return fract(tan(distance(xy*PHI, xy)*seed)*xy.x);
}

अपने ब्राउज़र में अभी गोल्ड शोर देखें!

यहां छवि विवरण दर्ज करें

इस फंक्शन ने सेप्ट 9, 2017 के रूप में @appas 'उत्तर में वर्तमान फ़ंक्शन पर यादृच्छिक वितरण में सुधार किया है:

यहां छवि विवरण दर्ज करें

@Appas फ़ंक्शन भी अधूरा है, यह देखते हुए कि कोई बीज की आपूर्ति नहीं हुई है (uv एक बीज नहीं है - हर फ्रेम के लिए समान है), और कम परिशुद्धता चिपसेट के साथ काम नहीं करता है। गोल्ड नॉइज़ डिफॉल्ट रूप से कम परिशुद्धता पर चलता है (बहुत तेज़)।


इसे पोस्ट करने के लिए धन्यवाद। क्या आप shadertoy.com पर एक रन करने योग्य संस्करण पोस्ट करने पर विचार करेंगे, ताकि लोग इसे ब्राउज़र में आज़मा सकें?
लार्स

इस महीने @snb Shadertoy.com का रखरखाव चल रहा है, थोड़ा धैर्य रखें। इसके अलावा, मैंने स्पष्ट रूप से वहाँ कोड में तर्कहीन बीज मूल्यों की आवश्यकता का दस्तावेजीकरण किया। चूंकि सोने का शोर एक स्केलर देता है, इसके साथ वैक्टर का निर्माण तुच्छ है, और कोड में भी प्रलेखित है।
डोमिनिक सेरिसानो

7
मुझे नहीं लगता कि यह अन्य शोर कार्यों की तुलना में अलग है। आपका क्या साबित है कि इसमें विशेष गुण हैं। सिर्फ इसलिए कि आप अपरिमेय संख्याओं का गुच्छा प्रयोग करते हैं, यह विशेष नहीं बनाता है।
एम। केज़म अखगीरी

2
@ मुख्य: "इसके समान कार्यों के लिए बेहतर वितरण है": यह साबित करना होगा। tan () वास्तव में बीमार है। दोनों तान () पीआई / 2 और sqrt () शून्य के पास अलग-अलग हार्डवेयर्स पर अलग-अलग परिणाम उत्पन्न करने की संभावना रखते हैं क्योंकि सभी फ्रैक्चर (गैर-रैखिक * बड़े) कम महत्वपूर्ण बिट्स पर आधारित होते हैं। छोटे या उच्च इनपुट मान इसे भी प्रभावित करेंगे। इसके अलावा, बिट्स की गतिशीलता शायद स्थानों के आधार पर बहुत भिन्न होती है।
फेब्रीस NEYRET

2
NB: आजकल GLSL के पूर्णांक होते हैं, इसलिए समान वितरण के साथ गुणवत्ता वितरण (और गतिकी) की आवश्यकता होने पर "गंभीर" इंट-बेस्ड हैश जनरेटर का उपयोग नहीं करने का कोई कारण नहीं है। (बहुत कम अंत वाले उपकरणों को छोड़कर)।
फेब्रीस NEYRET

12

McEwan और @StefanGustavson द्वारा यहां एक अच्छा कार्यान्वयन भी वर्णित है जो पेर्लिन शोर की तरह दिखता है, लेकिन "किसी भी सेटअप की आवश्यकता नहीं है, अर्थात न तो बनावट और न ही समान सरणियाँ। बस इसे अपने shader स्रोत कोड में जोड़ें और जहाँ भी आप चाहें कॉल करें"।

यह बहुत आसान है, विशेष रूप से यह देखते हुए कि गुस्तावसन के पहले के कार्यान्वयन, जो @dep से जुड़ा हुआ है, 1D बनावट का उपयोग करता है, जो GLSL ES (WebGL की shader भाषा) में समर्थित नहीं है


1
यह ओपी के बी) शोर प्रकार के अनुरोध का सबसे अच्छा जवाब है! यहाँ एक सीधा लिंक github.com/ashima/webgl-noise है । जीएलएसएल 120 कोड के रूप में 2 डी, 3 डी और 4 डी संस्करण तैयार हैं।
user362515

3

इसका उपयोग करें:

highp float rand(vec2 co)
{
    highp float a = 12.9898;
    highp float b = 78.233;
    highp float c = 43758.5453;
    highp float dt= dot(co.xy ,vec2(a,b));
    highp float sn= mod(dt,3.14);
    return fract(sin(sn) * c);
}

इसका उपयोग न करें:

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

आप OpenGL ES 2.0 के लिए कैनोनिकल वन-लाइनर GLSL रैंड () में सुधार में स्पष्टीकरण पा सकते हैं


मैंने लेख पर स्किम किया, लेकिन मुझे अभी भी यकीन नहीं है, modपीआई के एक अनुमान में 3.14 है ?
कान ई।

2

बस GPU के लिए 3 डी शोर के इस संस्करण में पाया गया है, सभी के लिए यह सबसे तेज़ उपलब्ध है:

#ifndef __noise_hlsl_
#define __noise_hlsl_

// hash based 3d value noise
// function taken from https://www.shadertoy.com/view/XslGRr
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// ported from GLSL to HLSL

float hash( float n )
{
    return frac(sin(n)*43758.5453);
}

float noise( float3 x )
{
    // The noise function returns a value in the range -1.0f -> 1.0f

    float3 p = floor(x);
    float3 f = frac(x);

    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;

    return lerp(lerp(lerp( hash(n+0.0), hash(n+1.0),f.x),
                   lerp( hash(n+57.0), hash(n+58.0),f.x),f.y),
               lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
                   lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

#endif

1
गोल्ड नॉइज़ (ऊपर) तब स्पष्ट रूप से सबसे तेज़ है, क्योंकि इसमें अभी तक बहुत कम ऑपरेशन हैं और केवल एक हैश करता है - यह एक नेस्टेड रैखिक प्रक्षेप (lerps) करते हुए 8 बार अपने हैश फ़क्शन को बुलाता है। इसके अलावा यह विशेष रूप से कम परिशुद्धता पर हीन वितरण है।
डोमिनिक सेरिसानो

1
ओह अच्छा बिंदु, यह Inigo Quilez द्वारा shadertoh से एक पर्लिन शोर प्रकार का ग्राफ है। अच्छा कोड डोमिनिक बीमार इसे l8r की जाँच करें
com.prehensible

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

कृपया कृपया, डोमिनिक, अधिक पढ़ें और उन शर्तों के बारे में दावा करने से पहले अधिक जानें जो आपको लगता है कि आप समझते हैं जबकि यह मामला नहीं है। न केवल ये शब्द पूरी तरह से सटीक हैं और अच्छी तरह से लिटरेचर में परिभाषित हैं, साथ ही मैं क्षेत्र में काम करता हूं, लेकिन ओपी यह भी साबित करता है कि वह उन उदाहरणों द्वारा शर्तों को समझता है जो उसने दिए थे। संकेत: "निरंतर" + "शोर" + "पेरलिन की तरह"। en.wikipedia.org/wiki/Perlin_noise
फेब्रीस NEYRET

निरंतर एक लूप क्लॉज जोड़ने का एक मामला है, कई शोर फ़ंक्शन लूप और एक निश्चित तरीके के बाद नीचा दिखाते हैं क्योंकि विशेष रूप से ग्राफिक्स के साथ बिट गोलाई के कारण। दोस्तों इसका सिर्फ एक संचार आप से टूटता है, महत्वपूर्ण अनुसंधान के लिए अपने समय का उपयोग करें।
com.prehensible

1

1 डी पेरलिन का एक सीधा, दांतेदार संस्करण, अनिवार्य रूप से एक यादृच्छिक एलएफओ ज़िगज़ैग।

half  rn(float xx){         
    half x0=floor(xx);
    half x1=x0+1;
    half v0 = frac(sin (x0*.014686)*31718.927+x0);
    half v1 = frac(sin (x1*.014686)*31718.927+x1);          

    return (v0*(1-frac(xx))+v1*(frac(xx)))*2-1*sin(xx);
}

मैंने shadertoy के मालिक inigo quilez perlin tutorial वेबसाइट, और voronoi पर 1-2-3-4d पेर्लिन का शोर भी पाया है और इसके बाद, उनके पास पूर्ण तेज़ कार्यान्वयन और कोड हैं।


1

हैश: आजकल webGL2.0 वहाँ पूर्णांक (w) GLSL में उपलब्ध हैं। -> गुणवत्ता वाले पोर्टेबल हैश के लिए (बदसूरत फ्लोट हैश की तुलना में समान लागत पर) अब हम "गंभीर" हैशिंग तकनीकों का उपयोग कर सकते हैं। IQ ने https://www.shadertoy.com/view/XlXcW4 (और अधिक) में कुछ लागू किया

उदाहरण के लिए:

  const uint k = 1103515245U;  // GLIB C
//const uint k = 134775813U;   // Delphi and Turbo Pascal
//const uint k = 20170906U;    // Today's date (use three days ago's dateif you want a prime)
//const uint k = 1664525U;     // Numerical Recipes

vec3 hash( uvec3 x )
{
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;

    return vec3(x)*(1.0/float(0xffffffffU));
}

0

कृपया एक उदाहरण के नीचे देखें कि प्रदान किए गए बनावट में सफेद शोर कैसे जोड़ा जाए। इसका समाधान दो बनावटों का उपयोग करना है: मूल और शुद्ध सफेद शोर, जैसे एक: विकी सफेद शोर

private static final String VERTEX_SHADER =
    "uniform mat4 uMVPMatrix;\n" +
    "uniform mat4 uMVMatrix;\n" +
    "uniform mat4 uSTMatrix;\n" +
    "attribute vec4 aPosition;\n" +
    "attribute vec4 aTextureCoord;\n" +
    "varying vec2 vTextureCoord;\n" +
    "varying vec4 vInCamPosition;\n" +
    "void main() {\n" +
    "    vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
    "    gl_Position = uMVPMatrix * aPosition;\n" +
    "}\n";

private static final String FRAGMENT_SHADER =
        "precision mediump float;\n" +
        "uniform sampler2D sTextureUnit;\n" +
        "uniform sampler2D sNoiseTextureUnit;\n" +
        "uniform float uNoseFactor;\n" +
        "varying vec2 vTextureCoord;\n" +
        "varying vec4 vInCamPosition;\n" +
        "void main() {\n" +
                "    gl_FragColor = texture2D(sTextureUnit, vTextureCoord);\n" +
                "    vec4 vRandChosenColor = texture2D(sNoiseTextureUnit, fract(vTextureCoord + uNoseFactor));\n" +
                "    gl_FragColor.r += (0.05 * vRandChosenColor.r);\n" +
                "    gl_FragColor.g += (0.05 * vRandChosenColor.g);\n" +
                "    gl_FragColor.b += (0.05 * vRandChosenColor.b);\n" +
        "}\n";

साझा किए गए टुकड़े में पैरामीटर uNoiseFactor है जो मुख्य अनुप्रयोग द्वारा हर रेंडरिंग पर अपडेट किया गया है:

float noiseValue = (float)(mRand.nextInt() % 1000)/1000;
int noiseFactorUniformHandle = GLES20.glGetUniformLocation( mProgram, "sNoiseTextureUnit");
GLES20.glUniform1f(noiseFactorUniformHandle, noiseFactor);

0

मैंने केन पेर्लिन के जावा कार्यान्वयन में से एक का जीएलएसएल में अनुवाद किया है और इसे ShaderToy पर एक दो परियोजनाओं में इस्तेमाल किया है।

नीचे GLSL व्याख्या है जो मैंने किया था:

int b(int N, int B) { return N>>B & 1; }
int T[] = int[](0x15,0x38,0x32,0x2c,0x0d,0x13,0x07,0x2a);
int A[] = int[](0,0,0);

int b(int i, int j, int k, int B) { return T[b(i,B)<<2 | b(j,B)<<1 | b(k,B)]; }

int shuffle(int i, int j, int k) {
    return b(i,j,k,0) + b(j,k,i,1) + b(k,i,j,2) + b(i,j,k,3) +
        b(j,k,i,4) + b(k,i,j,5) + b(i,j,k,6) + b(j,k,i,7) ;
}

float K(int a, vec3 uvw, vec3 ijk)
{
    float s = float(A[0]+A[1]+A[2])/6.0;
    float x = uvw.x - float(A[0]) + s,
        y = uvw.y - float(A[1]) + s,
        z = uvw.z - float(A[2]) + s,
        t = 0.6 - x * x - y * y - z * z;
    int h = shuffle(int(ijk.x) + A[0], int(ijk.y) + A[1], int(ijk.z) + A[2]);
    A[a]++;
    if (t < 0.0)
        return 0.0;
    int b5 = h>>5 & 1, b4 = h>>4 & 1, b3 = h>>3 & 1, b2= h>>2 & 1, b = h & 3;
    float p = b==1?x:b==2?y:z, q = b==1?y:b==2?z:x, r = b==1?z:b==2?x:y;
    p = (b5==b3 ? -p : p); q = (b5==b4 ? -q : q); r = (b5!=(b4^b3) ? -r : r);
    t *= t;
    return 8.0 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
}

float noise(float x, float y, float z)
{
    float s = (x + y + z) / 3.0;  
    vec3 ijk = vec3(int(floor(x+s)), int(floor(y+s)), int(floor(z+s)));
    s = float(ijk.x + ijk.y + ijk.z) / 6.0;
    vec3 uvw = vec3(x - float(ijk.x) + s, y - float(ijk.y) + s, z - float(ijk.z) + s);
    A[0] = A[1] = A[2] = 0;
    int hi = uvw.x >= uvw.z ? uvw.x >= uvw.y ? 0 : 1 : uvw.y >= uvw.z ? 1 : 2;
    int lo = uvw.x <  uvw.z ? uvw.x <  uvw.y ? 0 : 1 : uvw.y <  uvw.z ? 1 : 2;
    return K(hi, uvw, ijk) + K(3 - hi - lo, uvw, ijk) + K(lo, uvw, ijk) + K(0, uvw, ijk);
}

मैंने इस स्रोत पर केन पेर्लिन के शोर हार्डवेयर के अध्याय 2 से परिशिष्ट बी से इसका अनुवाद किया:

https://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf

यहाँ एक सार्वजनिक शेड है जो मैंने Shader Toy पर किया था जो पोस्ट किए गए शोर फ़ंक्शन का उपयोग करता है:

https://www.shadertoy.com/view/3slXzM

मेरे शोध के दौरान शोर के विषय पर कुछ अन्य अच्छे स्रोत मुझे शामिल हैं:

https://thebookofshaders.com/11/

https://mzucker.github.io/html/perlin-noise-math-faq.html

https://rmarcus.info/blog/2018/03/04/perlin-noise.html

http://flafla2.github.io/2014/08/09/perlinnoise.html

https://mrl.nyu.edu/~perlin/noise/

https://rmarcus.info/blog/assets/perlin/perlin_paper.pdf

https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch05.html

मैं शेड्स की पुस्तक की अत्यधिक अनुशंसा करता हूं क्योंकि यह न केवल शोर का एक महान इंटरैक्टिव विवरण प्रदान करता है, बल्कि अन्य shader अवधारणाओं को भी।

संपादित करें:

GLSL में उपलब्ध कुछ हार्डवेयर-त्वरित कार्यों का उपयोग करके अनुवादित कोड को अनुकूलित करने में सक्षम हो सकता है। अगर मैं ऐसा करूं तो इस पोस्ट को अपडेट कर दूंगा।


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

@Zibri दुर्भाग्य से, मैं सीधे C या .sh कमांड से सुपर परिचित नहीं हूं। लेकिन ऐसा लगता है कि फ़ंक्शन केवल एक छद्म यादृच्छिक संख्या जनरेटर है न कि शोर फ़ंक्शन। यह भी ध्यान रखें कि glsl पिक्सेल शेड्स सीधे gpu पर चलते हैं। आपके पास उन अतिरिक्त पुस्तकालयों या सीपीयू क्षमताओं में से किसी तक भी पहुंच नहीं होगी जो सी में उपलब्ध हो सकती है
एंड्रयू मेसर्वी

द बुक ऑफ़ शेड्स में इस बात की शानदार व्याख्या है कि ग्रिड को तिरछा करने और प्रति बिंदु कम आवश्यक गणनाओं के कारण सिंपलेक्स नॉइज़ पेरलिन शोर का एक अधिक कुशल संस्करण है। निश्चित रूप से पढ़ने लायक।
एंड्रयू मेसर्वली

फ्रैक्टल ब्राउनियन मोशन और वोरोनिसे पर अध्याय भी देखें
एंड्रयू मेसर्वी

एंड्रयू मेसर्वी: कोई पुस्तकालयों की जरूरत नहीं है ... मेरा शोर समारोह बहुत सरल है: 2 64 बिट इनट्स राज्य x (n) और x (n-1) हैं। सरल और तेज सूत्र x (n + 1) = ROTR (है) एक्स (एन) + x (n-1), 8)। यदि आप मेरे गिट को क्लोन करते हैं और इसे चलाते हैं तो आप इसे कार्रवाई में देखेंगे।
ज़िबरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.