2012-12-14 26 views
5

के बीच इंटरपोलेट किए जाने वाले चर को निर्दिष्ट करें, मैं Unity3D के अंदर शेडर्स लिखने के लिए GC का उपयोग कर रहा हूं।सीजी: वर्टेक्स और खंड शेडर

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

struct v2f { 
    float4 pos : SV_POSITION; 
    float2 uv : TEXCOORD0; 
    fixed4 col: COLOR;   
}; 

हैं:

struct appdata_full { 
    float4 vertex : POSITION; 
    float4 tangent : TANGENT; 
    float3 normal : NORMAL; 
    float4 texcoord : TEXCOORD0; 
    float4 texcoord1 : TEXCOORD1; 
    fixed4 color : COLOR; 
#if defined(SHADER_API_XBOX360) 
    half4 texcoord2 : TEXCOORD2; 
    half4 texcoord3 : TEXCOORD3; 
    half4 texcoord4 : TEXCOORD4; 
    half4 texcoord5 : TEXCOORD5; 
#endif 
}; 

यह संरचना टुकड़ा करने के लिए इनपुट के रूप में शिखर शेडर द्वारा दिया है:

यह संरचना मैं इनपुट के रूप में ले रहा हूँ Unity3D से शिखर शेडर है मैं बस खंडक शेडर को पैरामीटर अग्रेषित करता हूं, बेशक इसे इंटरपोलेट किया जाएगा:

v2f vert (appdata_full v) 
{ 

    v2f output; 
    //.... 
    output.col = v.color; 
} 

मैं v.color पैरामीटर पास करना चाहता हूं जो टुकड़े टुकड़े के लिए interpolated नहीं है। क्या यह संभव है? यदि हां कैसे?


संपादित

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

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

मैं इस जानकारी को खंडन शेडर तक अपरिवर्तित करने का एक तरीका ढूंढ रहा हूं (शायद वैश्विक चर या कुछ ऐसा करने के लिए संभव है? यदि हां कैसे?)।

+0

कैसे आप अगर आप मान क्या आप अगर त्रिकोण में से प्रत्येक के शिखर का मान अलग है होने की अपेक्षा करते हैं अंतर्वेशन नहीं है पिक्सेल प्रति तीन आदानों (कोने) सामंजस्य करने के लिए जा रहे हैं – Tim

+0

@Tim? : ठीक है..तुम सही हो। मैं तुम्हारी आपत्ति को समझता हूं । मुद्दा यह है कि वास्तव में रंग मेरे शेडर में रंग नहीं होते हैं। मैं अन्य प्रकार की जानकारी स्टोर करने के लिए रंग मूल्यों का उपयोग कर रहा हूं। मुझे इस कशेरुक की जानकारी को कशेरुक से खंड टुकड़े तक अग्रेषित करने की आवश्यकता है, अंततः इसे वर्टेक्स शेडर के पैरामीटर के रूप में पास नहीं किया जा रहा है, लेकिन कुछ ऐसा "ग्लोबल चर" का उपयोग करना संभव है। मुझे स्पष्ट होने की उम्मीद है। – Heisenbug

+0

यह वास्तव में कोई फर्क नहीं पड़ता कि यह रंग या सूचकांक या कुछ और है। आइए कहें कि आप एक त्रिकोण बना रहे हैं। कुछ मनमानी प्रति-वर्टेक्स गणना के आधार पर; वर्टेक्स 0 आउटपुट "5", वर्टेक्स 1 आउटपुट "10", और वर्टेक्स 2 आउटपुट "15"। आप इन टुकड़ों में से कौन सा नंबर अपने टुकड़े टुकड़े में दिखाना चाहते हैं? यदि यह वास्तव में एक वर्दी का उपयोग करने से वैश्विक मूल्य है, लेकिन अन्यथा मुझे लगता है कि आप इसे पूरी तरह से सोच नहीं रहे हैं। जब तक आप केवल "मैं हमेशा vertex 0 का मूल्य चाहता हूं और अन्य दो को अनदेखा करता हूं", यह बहुत समझ में नहीं आता है। – Tim

उत्तर

10

मुझे यकीन नहीं है कि यह एक उत्तर के लिए मायने रखता है लेकिन यह एक टिप्पणी के लिए थोड़ा सा है। जैसा कि बोजोर्के बताते हैं, टुकड़ा शेडर हमेशा एक अलग मूल्य प्राप्त करेगा। यदि/जब यूनिटी Opengl 4.0 का समर्थन करता है तो आपको Interpolation qualifiers तक पहुंच हो सकती है, अर्थात् 'फ्लैट' जो इंटरपोलेशन को अक्षम करता है, provoking vertex से सभी मान प्राप्त करता है।

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

Shader "custom/colorbyheight" { 
Properties { 
_Unique_ID ("Unique Identifier", float) = 1.0 
} 
SubShader { 
Pass { 
    CGPROGRAM 
    #pragma vertex vert 
    #pragma fragment frag 
    #include "UnityCG.cginc" 
    struct v2f { 
     float4 pos : SV_POSITION; 
     fixed4 color : COLOR; 
    }; 
    uniform float _Unique_ID; 
    v2f vert (appdata_base v) 
    { 
     v2f o; 
     o.pos = mul (UNITY_MATRIX_MVP, v.vertex); 
     float3 worldpos = mul(_Object2World, v.vertex).xyz; 
     if(worldpos[1] >= 0.0) 
     o.color.xyz = 0.35; //unique_id = 0.35 
     else 
     o.color.xyz = 0.1; //unique_id = 0.1 
     o.color.w = 1.0; 
     return o; 
    } 


    fixed4 frag (v2f i) : COLOR0 { 
    // local unique_id's set by the vertex shader and stored in the color 
    if(i.color.x >= 0.349 && i.color.x <=0.351) 
     return float4(1.0,0.0,0.0,1.0); //red 
    else if(i.color.x >= 0.099 && i.color.x <=0.11) 
     return float4(0.0,1.0,0.0,1.0); //green 

    // global unique_id set by a Unity script 
    if(_Unique_ID == 42.0) 
     return float4(1.0,1.0,1.0,1.0); //white 

    // Fallback color = blue 
    return float4(0.0,0.0,1.0,1.0); 
    } 
    ENDCG 
} 
} 
} 

अपने परिशिष्ट नोट में आप कहते हैं "असल में एक ही जाल के प्रत्येक चरम।" यदि ऐसा है, तो एक संशोधित संपत्ति का उपयोग क्यों न करें, जैसा कि मैंने ऊपर शामिल किया है। अद्वितीय जाल को बदलने के लिए प्रत्येक जाल को सिर्फ एक स्क्रिप्ट की आवश्यकता होती है।

public class ModifyShader : MonoBehaviour { 
public float unique_id = 1; 
// Use this for initialization 
void Start() { 

} 

// Update is called once per frame 
void Update() { 
    renderer.material.SetFloat("_Unique_ID", unique_id); 
} 
} 
+0

अच्छा, आपके उत्तर के लिए भी धन्यवाद।मैं SetFloat का उपयोग नहीं कर सकता क्योंकि मैं StaticBatchingUtility के माध्यम से ड्रॉ कॉल बैच कर रहा हूं। यदि मैं किसी सामग्री के मान को संशोधित करता हूं, तो एकता प्रत्येक ऑब्जेक्ट के लिए एक नया सामग्री उदाहरण तत्काल कर देगी, इसे साझा किए गए सामग्री का उपयोग करने से रोकती है और इसके परिणामस्वरूप इसे अब बैच नहीं किया जाएगा। इसलिए मुझे प्रत्येक जाल में कस्टम शेडर मान को assing करने के लिए प्रति चर निर्दिष्ट असाइन किए गए रंग पैरामीटर का उपयोग करने के लिए मजबूर होना पड़ता है। – Heisenbug

+0

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

+0

बगजर, हाँ जो आपके लिए काम नहीं करेगा। एक "समाधान", और मैं इसे नापसंद करता हूं क्योंकि यह हैकी और धीमी है, अपने जाल के सभी त्रिभुजों को अद्वितीय बनाने के लिए केवल प्रत्येक चरम को 2 किनारों का निर्माण करने की इजाजत देता है। इस तरह रैखिक इंटरपोलेशन केवल एक त्रिकोण के कविताओं के बीच होता है जो आपको सही "आईडी" देता है। – Jerdak

2

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

+0

क्या मैं कुछ ग्लोबल वैरिएबल का उपयोग वर्टेक्स शेडर इंस्टेंस और सभी संबंधित खंड शेडर्स के बीच साझा नहीं कर सकता? – Heisenbug

+0

हार्डवेयर की रखी गई नहीं है। स्थिरांक प्रति-जाल हैं, प्रति त्रिभुज नहीं हैं, और प्रत्येक जाल केवल एक कशेरुक और एक टुकड़ा शेडर हो जाता है। "कनेक्टर" रजिस्ट्रार, जो इंटरपोलेटेड होते हैं, दोनों के बीच संचार का एकमात्र चैनल हैं। – bjorke

+0

स्पष्टीकरण के लिए धन्यवाद। – Heisenbug

1

आप यह कर सकते हैं: glShadeModel(GL_FLAT)। यह सभी टुकड़े शेडर इनपुट के लिए इंटरपोलेशन बंद कर देता है, और पुराने ओपनजीएल में भी उपलब्ध है (प्री 4.0)।

यदि आपके पास कुछ इनपुट हैं जो आप इंटरपोलेट करना चाहते हैं और कुछ आप नहीं करते हैं, तो एक बार अपने आउटपुट के समान रिज़ॉल्यूशन के बनावट में GL_FLAT के साथ प्रस्तुत करें, और फिर GL_SMOOTH के साथ फिर से प्रस्तुत करें और फ्लैट मानों को पढ़ने के लिए बनावट का नमूना दें प्रत्येक पिक्सेल के लिए (सामान्य तरीके से इंटरपोलेटेड मान भी प्राप्त करते समय)।

यदि आप इसके बजाय डायरेक्टएक्स 9 का उपयोग कर सकते हैं, तो आप अलग-अलग टुकड़े शेडर इनपुट (शेडर मॉडल 4 या बाद में) पर nointerpolation संशोधक का उपयोग कर सकते हैं।

+1

glShadeModel एकता API के माध्यम से खुलासा नहीं किया गया है। – Jerdak

+0

और न ही ओपनजीएल ईएस (और इस प्रकार वेबग्ल) में – bjorke

3

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

शेडर नीचे (महत्वपूर्ण हिस्सा, #extension के साथ लाइन है अन्यथा यदि आप एक कीवर्ड फ्लैट प्रयोग करने के लिए एक संकलन त्रुटि मिलती हैं जो "

Shader "GLSL flat shader" { 
SubShader { 
    Pass { 
    GLSLPROGRAM 

    #extension GL_EXT_gpu_shader4 : require 
    flat varying vec4 color; 

    #ifdef VERTEX 
    void main() 
    { 
     color = gl_Color; 
     gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    } 
    #endif 

    #ifdef FRAGMENT 
    void main() 
    { 
     gl_FragColor = color; // set the output fragment color 
    } 
    #endif 

    ENDGLSL 
    } 
    } 
} 
इसे करने के लिए

गॉट से बातें संयोजन से काम करेगा : http://poniesandlight.co.uk/notes/flat_shading_on_osx/ http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Debugging_of_Shaders

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