मॉडल के लिए एनिमेटेड बनावट; कैसे एक shader लिखने के लिए?


9

कुछ रॉकेट लीग देख रहा था और नोटिस में एनिमेटेड डिकल्स और पहिए थे।

छवि

मैं ऊपर की छवि में प्रभावों के समान कुछ लागू करना चाहूंगा।

मैं पहिया प्रभाव को करने के लिए यूनिटी शेडर लिखने के बारे में कैसे जाऊंगा?

मैं शेडर्स के बारे में ज्यादा नहीं जानता, लेकिन क्या मैं एनीमेशन प्रभाव को करने के लिए मानक एकता शेडर को संपादित कर सकता हूं?


3
शेडर्स निश्चित रूप से यहां जाने के लिए समाधान हैं, यहां तक ​​कि एक स्क्रॉल बनावट के रूप में सरल कुछ के लिए भी। एकता में एक अंतर्निहित _Timeवैरिएबल है जिसे आप स्क्रॉलिंग प्रभाव गंदगी को सस्ते में प्राप्त करने के लिए (वर्टेक्स) शेडर में अपनी बनावट निर्देशांक में जोड़ सकते हैं। षट्भुज प्रभाव बहुत सीधा भी होगा। यदि आप अपने प्रश्न को केवल एक प्रभाव को उजागर करने के लिए संपादित करते हैं और पूछते हैं कि "मैं इसे यूनिटी शैडर में कैसे लागू करूंगा," तो हम शायद आपकी मदद कर सकते हैं। यह निर्दिष्ट करना सुनिश्चित करें कि क्या छायाकार को प्रकाश / छायांकन का जवाब देने की आवश्यकता है, क्योंकि उस पर इसका प्रभाव है कि यह कैसे लिखा जाएगा।
DMGregory

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

3
मैं थोड़ी देर बाद आज रात एक उत्तर में इसका विस्तार करूंगा (हालांकि मुझे इसे पीटने के लिए स्वतंत्र महसूस हो सकता है, अगर कोई भी अब जवाब देना चाहता है!) - लेकिन आप आमतौर पर एक यूनिटी शेडर लिखेंगे जो "सरफेस शेडर" के रूप में प्रकाश व्यवस्था का उपयोग करता है। जबकि जिसे प्रकाश की आवश्यकता नहीं होती है, उसे अक्सर "अनलिस्ट शेडर" के रूप में लिखना सरल होता है। यह मुझे ऐसा लगता है जैसे उन पहियों को अनलिमिटेड किया गया है (किनारे पर थोड़ा सा छाया एसएसएओ की तरह दिखता है), इसलिए मैं शुरुआत के लिए तस्वीर से रोशनी छोड़ दूंगा। क्या आप स्पष्ट कर सकते हैं: क्या आप वास्तव में यहां दिखाए गए ज्यामितीय पैटर्न, या मनमाने ढंग से बनावट को बाहर की ओर स्क्रॉल करने की क्षमता चाहते हैं और इंद्रधनुष-टिंट उन्हें पसंद करते हैं?
DMGregory

बहुत बहुत धन्यवाद, जो भी जानकारी आप मुझे आरंभ करने के लिए दे सकते हैं वह बहुत अच्छी होगी। मैं वास्तव में उन लोगों की प्रशंसा करता हूं जो शेड्स लिख सकते हैं, मैंने एकता शेडर्स के लिए कुछ लेखों पर ध्यान दिया है, और हाँ, बहुत भ्रामक है। मुझे लगता है कि बस बनावट (या बनावट uvs?) के माध्यम से स्क्रॉल करना काफी अच्छा होगा, और टिंट की क्षमता के साथ।
जैकेटपोटेटोफैन

जवाबों:


13

मैं इसे कुछ परतों में बनाऊंगा ताकि आप देख सकें कि यह एक साथ कैसे आता है।

Create --> Shader --> Unlitप्रोजेक्ट विंडो में या तो एसेट्स मेनू या राइट-क्लिक संदर्भ मेनू का चयन करके एकता में एक नया शेडर बनाने से शुरू करें ।

शीर्ष ब्लॉक में हम _ScrollSpeedsयह नियंत्रित करने के लिए एक पैरामीटर जोड़ेंगे कि बनावट प्रत्येक दिशा में कितनी तेजी से चलती है:

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5, -20, 0, 0)
}

यह सामग्री इंस्पेक्टर में एक नया 4-घटक फ्लोट संपत्ति उजागर करता है, दोस्ताना नाम "स्क्रॉल गति" ( एक स्क्रिप्ट में एक चर publicया जोड़ने के समान ) के साथSerializedMonoBehaviour

अगली बार हम इस चर का उपयोग डिफरेंश शॉडर में o.uvसिर्फ दो पंक्तियों को जोड़कर बनावट निर्देशांक ( ) को शिफ्ट करने के लिए करेंगे:

sampler2D _MainTex;
float4 _MainTex_ST;
// Declare our new parameter here so it's visible to the CG shader
float4 _ScrollSpeeds;

v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);

    // Shift the uvs over time.
    o.uv += _ScrollSpeeds * _Time.x;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

थप्पड़ कि एक ट्रैक्टर पर ( केनी द्वारा एक सुंदर मुक्त जिराफ़ बनावट के साथ ) और आपको मिलता है:

एक दोहराव वाला जिराफ़ स्क्रॉल के साथ एक चौकोर।

एक रिंग में बनावट को बाहर की ओर स्क्रॉल करने के लिए, हम बस मकड़ी की तरह उप-विभाजित एक जाल का उपयोग कर सकते हैं, केंद्र के बाहर से uv v समन्वय बढ़ेगा। लेकिन यह अपने आप पर कुछ sawblade के आकार की कलाकृतियों देगा। इसके बजाय, मैं दिखाता हूँ कि हम अपने UVs की गणना कैसे कर सकते हैं।

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

v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);

    // Shift the UVs so (0, 0) is in the middle of the quad.
    o.uv = v.uv - 0.5f;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

fixed4 frag (v2f i) : SV_Target
{
    // Convert our texture coordinates to polar form:
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x)/(2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Apply texture scale
    polar *= _MainTex_ST.xy;

    // Scroll the texture over time.
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample using the polar coordinates, instead of the original uvs.
    // Here I multiply by MainTex
    fixed4 col = tex2D(_MainTex, polar);

    // apply fog
    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

यह हमें कुछ इस तरह देता है (यहाँ मैंने सामग्री में टाइलिंग मापदंडों को बढ़ा दिया है ताकि यह स्पष्ट हो जाए कि क्या हो रहा है - सर्कल के चारों ओर टाइल का केवल एक दोहराव लपेटना विकृत और अजीब दिखता है)

टाइलिंग जिराफ एक चतुर्भुज के केंद्र से बाहर की ओर विकिरण करते हैं

अंत में, एक स्क्रॉल ढाल द्वारा बनावट को टिंट करने के लिए, हम बस ढाल को दूसरी बनावट के रूप में जोड़ सकते हैं और उन्हें एक साथ गुणा कर सकते हैं।

पहले हम शीर्ष पर नया बनावट पैरामीटर जोड़ते हैं:

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _TintTex("Tint Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5.0, -20.0, 0, 0)
}

और इसे हमारे CGPROGRAM ब्लॉक में घोषित करें ताकि CG shader इसे देख सके:

sampler2D _MainTex;
float4 _MainTex_ST;

// Declare our second texture sampler and its Scale/Translate values
sampler2D _TintTex;
float4 _TintTex_ST;

float4 _ScrollSpeeds;

फिर दोनों बनावट का उपयोग करने के लिए हमारे टुकड़े टुकड़े को अपडेट करें:

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    fixed4 col = tex2D(_MainTex, polar);
    // Tint the colour by our second texture.
    col *= tex2D(_TintTex, tintUVs);

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

और अब हमारा जिराफ वास्तव में त्रासद हो गया है:

बहुत दूर, यार ...।

बनावट और स्क्रॉलिंग दरों के थोड़ा अधिक कलात्मक चयन के साथ, यह प्रश्न में दिखाए गए एक के समान प्रभाव पैदा कर सकता है।


आप ऊपर दिखाए गए संस्करण के साथ दो छोटी कलाकृतियों को देख सकते हैं:

  • सर्कल के केंद्र के पास के चेहरे एक फैला / पतला / नुकीला मिलता है, फिर जैसे ही वे बाहर की ओर बढ़ते हैं वे चौड़ी / चौड़ी हो जाती हैं।

    यह विकृति इसलिए होती है क्योंकि हमारे पास परिधि के चारों ओर निश्चित संख्या में चेहरे होते हैं, लेकिन वे जिस परिधि में फैले होते हैं, वह दायरा व्यापक हो जाता है, जबकि उनकी ऊंचाई समान रहती है।

    हम इसे एक लघुगणकीय वक्र का पालन करने के लिए बनावट के नमूने के ऊर्ध्वाधर घटक को फिर से निर्धारित करके ठीक कर सकते हैं, इसलिए बनावट का दोहराव आगे बढ़ने के साथ-साथ त्रिज्या बढ़ता है, और केंद्र की ओर करीब होता है। (वास्तव में, यह हमें छोटे और छोटे जिराफों का एक अनंत प्रतिफल देता है ...)

  • क्वाड के मध्य-बाएँ के साथ एक या दो धुंधले पिक्सेल की एक पंक्ति है।

    ऐसा इसलिए होता है क्योंकि GPU दो आसन्न बनावट के नमूने को देखता है ताकि यह पता लगाया जा सके कि किस फ़िल्टरिंग का उपयोग करना है। जब नमूने एक साथ पास होते हैं, तो यह प्रदर्शित होता है कि बनावट बड़ी / करीब दिखाई दे रही है और सबसे विस्तृत मील स्तर दिखाती है। जब नमूने दूर तक अलग हो जाते हैं, तो यह अनुमान लगाता है कि हमें बनावट को छोटे ज़ूम या दूर की ओर दिखाना होगा, और यह सुनिश्चित करने के लिए कि हम स्पार्कली एलियासिंग कलाकृतियाँ न प्राप्त करें, यह सुनिश्चित करने के लिए एक छोटे / ब्लिपर माइपमैप से नमूने लें।

    यह परेशानी यहाँ है, हम ध्रुवीय निर्देशांक में रैप-अराउंड पॉइंट पर हैं, -180 से 180 डिग्री तक। इसलिए हम वास्तव में हमारे दोहराए जाने वाले बनावट स्थान में बहुत समान बिंदुओं से नमूना ले रहे हैं, भले ही उनके संख्यात्मक निर्देशांक उन्हें ऐसे दिखते हैं जैसे वे बहुत दूर हैं। तो हम इसके लिए सही करने के लिए अपने स्वयं के नमूना ढाल वैक्टर प्रदान कर सकते हैं।

यहाँ इन सुधारों के साथ एक संस्करण है:

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           log(dot(i.uv, i.uv)) * 0.5f                       // log-radius
        );

    // Check how much our texture sampling point changes between
    // neighbouring pixels to the sides (ddx) and above/below (ddy)
    float4 gradient = float4(ddx(polar), ddy(polar));

    // If our angle wraps around between adjacent samples,
    // discard one full rotation from its value and keep the fraction.
    gradient.xz = frac(gradient.xz + 1.5f) - 0.5f;

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample with our custom gradients.
    fixed4 col = tex2Dgrad(_MainTex, polar, 
                           _MainTex_ST.xy * gradient.xy,
                           _MainTex_ST.xy * gradient.zw
                         );

    // Since our tint texture has its own scale,
    // its gradients also need to be scaled to match.
    col *= tex2Dgrad(_TintTex, tintUVs,
                          _TintTex_ST.xy * gradient.xy,
                          _TintTex_ST.xy * gradient.zw
                         );

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

2
कुछ छोटे सुधार जो एक कर सकते हैं: 1) v दिशा के लिए एक लघुगणक वक्र का उपयोग करके बनावट को अपने आकार को बनाए रखने में मदद करता है क्योंकि यह बाहर की ओर स्क्रॉल करता है (बीच में एक बिंदु पर संकीर्ण करने के बजाय, आपको बस छोटी प्रतियों की एक अनंत श्रृंखला मिलती है। एमआईपी इसे बाहर निकालता है) 2) अपने स्वयं के बनावट ग्रेडिएंट्स की गणना tex2Dgradकरता है और फ़िल्टरिंग विरूपण साक्ष्य का उपयोग करता है जहां कोण को -pi से + पीआई (बाईं ओर धुंधली पिक्सेल की पतली रेखा) के आसपास लपेटता है। यहाँ और अधिक नीले रंग के साथ छुआ-अप परिणाम है
DMGregory

कमाल है, ब्रेक डाउन के लिए भी धन्यवाद। मुझे लगता है कि शेड्स कुछ ऐसे हैं जो मैं कभी नहीं लिख सकता (विशेष रूप से सामान जैसे कि आपने "ध्रुवीय" के लिए क्या किया है, गणित के सामान का मतलब मेरे लिए कुछ भी नहीं है, क्योंकि मुझे केवल बहुत ही बुनियादी गणित कौशल मिला है)।
जैकेटपोटेटोफैन

1
सामान की तरह है कि लोग आमतौर पर सिर्फ ऊपर देखेंगे। ;) मैं बस यह पर्याप्त है कि यह कीबोर्ड से रोल करता है। यद्यपि विभिन्न गणित कार्यों के साथ खेलने की कोशिश करें और परिणामों को देखें - इस तरह का एक उपकरण होने से मुझे यह देखने में मदद मिलेगी कि गणित ज्यामितीय रूप से क्या कर रहा था कि मुझे पहली बार में मेरा अभ्यास कैसे मिला। (विशेष रूप से शेड्स के साथ नहीं, बल्कि व्हाइटकैप नामक एक पुराने WinAmp विज़ुअलाइज़र ...) यहां तक ​​कि जब shader गणित बुरी तरह से गलत हो जाता है तो यह देखने में अक्सर अजीब होता है। : डी
DMGregory
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.