2011-06-28 10 views
8

मैं ओपनगल ज्यामिति शेडर में इलाके पैदा कर रहा हूं और प्रकाश व्यवस्था के लिए मानक की गणना करने में परेशानी हो रही है। मैं ज्यामिति शेडर में लागू एक पेर्लिन शोर फ़ंक्शन के साथ प्रत्येक फ्रेम को गतिशील रूप से उत्पन्न कर रहा हूं। इस वजह से, मुझे शोर फ़ंक्शन (कोई बनावट या कुछ भी) के आधार पर प्रति-वर्टेक्स के मानदंडों की गणना करने के लिए एक प्रभावी तरीका चाहिए। मैं चेहरा मानक प्राप्त करने के लिए 2 पक्ष के क्रॉस उत्पाद को लेने में सक्षम हूं, लेकिन वे ज्यामिति के साथ गतिशील रूप से उत्पन्न होते हैं, इसलिए मैं वापस नहीं जा सकता और वर्टेक्स मानदंडों के लिए चेहरे के मानक को सुचारू बना सकता हूं। मैं केवल शोर समारोह का उपयोग करके फ्लाई पर वर्टेक्स मानक प्राप्त कर सकता हूं जो वाई विमान में मेरे इलाके की ऊंचाई उत्पन्न करता है (इसलिए ऊंचाई 1 और -1 के बीच होती है)। मेरा मानना ​​है कि मैं शोर समारोह नमूने के लिए प्रत्येक शीर्ष के लिए 4 बार है, लेकिन मैं निम्नलिखित की तरह कुछ करने की कोशिश की और यह काम नहीं किया ...पेरिन शोर से प्रति-वर्टेक्स सामान्य?

vec3 xP1 = vertex + vec3(1.0, 0.0, 0.0); 
vec3 xN1 = vertex + vec3(-1.0, 0.0, 0.0); 
vec3 zP1 = vertex + vec3(0.0, 0.0, 1.0); 
vec3 zN1 = vertex + vec3(0.0, 0.0, -1.0); 

float sx = snoise(xP1) - snoise(xN1); 
float sz = snoise(zP1) - snoise(zN1); 

vec3 n = vec3(-sx, 1.0, sz); 
normalize(n); 

return n; 

ऊपर वास्तव में उत्पन्न प्रकाश कि पर्लिन शोर की तरह चारों ओर ले जाया! तो मैं सलाह देता हूं कि मैं प्रति-वर्टेक्स मानक सही तरीके से कैसे प्राप्त कर सकता हूं?

उत्तर

5

पर सामान्य प्राप्त करते हैं आपने बिल्कुल नहीं कहा कि आप वास्तव में पदों को कैसे उत्पन्न कर रहे थे। इसलिए मैं यह मानने जा रहा हूं कि आप ऊंचाई मानचित्र में ऊंचाई मान उत्पन्न करने के लिए पर्लिन शोर का उपयोग कर रहे हैं। इसलिए, किसी भी स्थिति X, वाई hieghtmap में, आप Z मान उत्पन्न करने के लिए 2 डी शोर फ़ंक्शन का उपयोग करते हैं।

तो, मान लेते हैं कि अपनी स्थिति की गणना इस प्रकार रहा है:

vec3 CalcPosition(in vec2 loc) { 
    float height = MyNoiseFunc2D(loc); 
    return vec3(loc, height); 
} 

यह एक 3 डी स्थिति उत्पन्न करता है। लेकिन स्थान इस स्थिति में क्या है? यही तो प्रश्न है।

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

ऐसा करने में, अब आपके पास 3 डी स्थिति है। एक्स और वाई मानों के लिए परिवर्तन सरल है (शोर फ़ंक्शन की जगह में परिवर्तन के विपरीत), लेकिन ज़ेड का क्या? यहां, आपको ऊंचाई पर किसी प्रकार का पैमाने लागू करना होगा। शोर फ़ंक्शन रेंज [0, 1) पर एक संख्या वापस कर देगा, इसलिए आपको इस श्रेणी को उसी मॉडल स्पेस पर स्केल करने की आवश्यकता है जो आपके एक्स और वाई मानों पर जा रहे हैं। यह आम तौर पर अधिकतम ऊंचाई चुनकर और उचित स्थिति को स्केल करके किया जाता है।

vec3 CalcPosition(in vec2 modelLoc, const in mat3 modelToNoise, const in mat4 noiseToModel) 
{ 
    vec2 loc = modelToNoise * vec3(modelLoc, 1.0); 
    float height = MyNoiseFunc2D(loc); 
    vec4 modelPos = noiseToModel * vec4(loc, height, 1.0); 
    return modelPos.xyz; 
} 

दो मैट्रिक्स शोर समारोह के अंतरिक्ष को बदलने, और फिर वापस परिणत: इसलिए, हमारी संशोधित calc स्थिति कुछ इस तरह लग रहा है। आपका वास्तविक कोड आपके उपयोग के मामले के आधार पर कम जटिल संरचनाओं का उपयोग कर सकता है, लेकिन एक पूर्ण affine परिवर्तन वर्णन करने के लिए सरल है।

ठीक है, अब हमने इसे स्थापित किया है, जो आपको ध्यान में रखना है, यह है: कुछ भी समझ में नहीं आता है जब तक आपको पता न हो कि यह कितनी जगह है। आपका सामान्य, आपकी स्थिति, कुछ भी महत्वपूर्ण नहीं है जब तक कि आप यह निर्धारित न करें कि यह कौन सी जगह है में।

यह फ़ंक्शन मॉडल स्पेस में स्थिति देता है। हमें मॉडल स्पेस में मानदंडों की गणना करने की आवश्यकता है। ऐसा करने के लिए, हमें 3 पदों की आवश्यकता है: कशेरुक की वर्तमान स्थिति, और दो स्थितियां जो वर्तमान स्थिति से थोड़ा ऑफसेट हैं। हमें प्राप्त होने वाली स्थितियों को मॉडल स्थान में होना चाहिए, या हमारा सामान्य नहीं होगा। आप के बाद इन दोनों कार्यों विलय कर सकते हैं जाहिर है

void CalcDeltas(in vec2 modelLoc, const in mat3 modelToNoise, const in mat4 noiseToModel, out vec3 modelXOffset, out vec3 modelYOffset) 
{ 
    vec2 loc = modelToNoise * vec3(modelLoc, 1.0); 
    vec2 xOffsetLoc = loc + vec2(delta, 0.0); 
    vec2 yOffsetLoc = loc + vec2(0.0, delta); 
    float xOffsetHeight = MyNoiseFunc2D(xOffsetLoc); 
    float yOffsetHeight = MyNoiseFunc2D(yOffsetLoc); 
    modelXOffset = (noiseToModel * vec4(xOffsetLoc, xOffsetHeight, 1.0)).xyz; 
    modelYOffset = (noiseToModel * vec4(yOffsetLoc, yOffsetHeight, 1.0)).xyz; 
} 

,:

इसलिए, हम निम्नलिखित समारोह की आवश्यकता है।

delta मूल्य शोर बनावट के इनपुट की जगह में एक छोटा ऑफसेट है। इस ऑफ़सेट का आकार आपके शोर फ़ंक्शन पर निर्भर करता है; यह उस ऊंचाई को वापस करने के लिए काफी बड़ा होना चाहिए जो वास्तविक वर्तमान स्थिति द्वारा लौटाए गए व्यक्ति से काफी अलग है। लेकिन इसे छोटे होने की आवश्यकता है कि आप शोर वितरण के यादृच्छिक हिस्सों से नहीं खींच रहे हैं।

आपको अपने शोर समारोह को जानना चाहिए।

अब आप तीन स्थानों है कि (वर्तमान स्थिति, एक्स-ऑफसेट, और y ऑफसेट) मॉडल अंतरिक्ष में, आप शीर्ष सामान्य गणना कर सकता है मॉडल अंतरिक्ष में: यहाँ से

vec3 modelXGrad = modelXOffset - modelPosition; 
vec3 modelYGrad = modelYOffset - modelPosition; 

vec3 modelNormal = normalize(cross(modelXGrad, modelYGrad)); 

, सामान्य चीजें करते हैं। लेकिन कभी भी अपने विभिन्न वैक्टरों की जगहों को ट्रैक रखने के लिए भूल जाते हैं।

ओह, और एक और बात: यह vertex शेडर में किया जाना चाहिए। ज्यामिति शेडर में ऐसा करने का कोई कारण नहीं है, क्योंकि गणना में से कोई भी अन्य शीर्षकों को प्रभावित नहीं करता है। जीपीयू की समांतरता आपके लिए काम करने दें।

+0

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

+0

मुझे यह दृष्टिकोण के साथ काम मिल गया। हालांकि, इसे काम करने के लिए मुझे 4 ऑफसेट वैक्टर बनाने और ऑफ़सेट के बीच ग्रेडियेंट का उपयोग करने की आवश्यकता थी (मॉडलपोजिशन के साथ ऑफ़सेट के ढाल नहीं)। और उचित दिशा में प्रकाश प्राप्त करने के लिए मुझे मॉडलएक्सग्राड और मॉडल वाईग्राड के क्रॉस उत्पाद को लेने का आदेश बदलना पड़ा (केवल इस समाधान में आने वाले अन्य लोगों के लिए उल्लेख करना)। समन्वय अंतरिक्ष के साथ इसे बहुत अच्छी तरह से समझाने के लिए धन्यवाद ... इससे मदद मिली। इसके अलावा, मैं यह उल्लेख करना चाहता हूं कि मैं ज्यामिति शेडर में ऐसा कर रहा था क्योंकि मैं गतिशील रूप से ज्यामिति शेडर में इलाके को छेड़छाड़ कर रहा हूं – Nitrex88

8

सामान्य टेंगेंट (ढलान के रूप में भी जाना जाता है) के लिए लंबवत वेक्टर है। एक समारोह की ढलान इसकी व्युत्पन्न है; एन आयामों के लिए इसके एन आंशिक डेरिवेटिव्स। तो आप एक केंद्र बिंदु पी के आसपास शोर का नमूना देते हैं और पी ± (δx, 0) और पी ± (0, δy) पर, δx के साथ, δy जितना संभव हो उतना छोटा हो जाता है, लेकिन संख्यात्मक स्थिरता के लिए काफी बड़ा होता है। यह आपको प्रत्येक दिशा में स्पर्शक पैदा करता है। फिर आप उनमें से क्रॉस उत्पाद लेते हैं, परिणाम को सामान्य करते हैं और पी

+1

+1: यह सही प्रकार का दृष्टिकोण है, हालांकि मुझे नहीं पता कि एक शेडर में क्या करना व्यावहारिक है। –

+0

यह उत्तर अन्य बातों (मूल रूप से) के समान ही कह रहा है, है ना? किसी भी मामले में मैं कल कोशिश कर रहा हूं और देखता हूं कि यह काम करता है या नहीं। – Nitrex88

+2

@ नाइट्रेक्स 88: @ निकोल बोलास का जवाब आपको मेरे जैसा ही बता रहा है, लेकिन अधिक विस्तृत और विस्तृत रूप में। वह निश्चित रूप से सही है कि आपको ट्रैक करना है कि आप किस स्थान पर हैं। हालांकि यदि हम इसे कार्यों के परिप्रेक्ष्य से देखते हैं, तो यह आंशिक डेरिवेटिव्स, यानी ग्रेडियेंट्स तक उबाल जाता है। आप शोर नमूना समन्वय "wiggle", और परिणामी शोर मूल्य तदनुसार wiggles। फिर यह आउटपुट विग्लॉग स्पेस वैक्टर को आउटपुट विग्लॉग स्पेस से संबंधित करने का मामला है। – datenwolf

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