GLSL लाइट (गति, रंग और तीव्रता) सूत्र


17

मैं अपने Voxel इंजन में पॉइंट लाइट्स को लागू कर रहा हूं, और मैं प्रकाश स्रोत पर प्रकाश स्रोत के पास 100% से 0% तक प्रकाश का एक अच्छा प्रवाह प्राप्त करने के लिए वास्तव में संघर्ष कर रहा हूं।

मेरे पास फंक्शन के लिए 5 तर्क हैं:

  1. हल्के रंग (Vec3)
  2. प्रकाश की तीव्रता (प्रकाश से दूरी उस दूरी तक जहां फ़ॉलऑफ़ 100% है)
  3. प्रकाश से अंश की दूरी
  4. सामान्य से लेकर प्रकाश तक का कोण
  5. प्रकाश की स्थिति

क्या कोई मुझे सही दिशा में खंडित रंग की गणना के लिए एक समारोह बनाने के लिए धक्का दे सकता है?

मेरे एक प्रयोग की छवि:

Voxel Engine Per-Fragment Lighting Test

संपादित करें (बाइट द्वारा अनुरोध किया गया वर्तमान कोड) ध्यान दें कि यह मेरी तरफ से सिर्फ कुछ प्रयोग कोड है। मुझे एक वेबसाइट से फ्लोट एट मिला, और यह प्रकार काम करता है, लेकिन बिल्कुल सही। :

void main()
{
// Light color
vec3 torchColor = vec3(1.0f, 1.0f, 1.0f);

float lightAdd = 0.0f;
for (int i=0; i<5; i++) {
    vec3 pos = lights[i];
    if (pos.x == 0.0f) continue;

    float dist = distance(vertex_pos, pos);
    if (dist < 9) {
        float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
        vec3 surf2light = normalize(pos - vertex_pos);
        vec3 norm = normalize(normal);
        float dcont=max(0.0,dot(norm,surf2light));
        lightAdd += att*(dcont+0.4);
    }
}

vec3 textureColor = texture2D(texture, texture_coordinate).rgb;
vec3 torch_output = lightAdd * torchColor;

vec3 final_color = ((0.1+torch_output) * textureColor);

gl_FragColor = vec4(final_color, 1.0f); 
}

6
आप अभी भी " अच्छी दिखने , प्राकृतिक रोशनी पाने के लिए संघर्ष " और "काम करता है, लेकिन एकदम सही " जैसी चीजें कह रहे हैं । आपको विशिष्ट, सटीक भाषा शामिल करनी होगी। हम नहीं जानते कि आपके लिए क्या अच्छा दिख रहा है, या प्राकृतिक रोशनी आपको कैसी दिखती है, या क्या सही है।
MichaelHouse

2
क्या आपने हटाने की कोशिश की है if (dist < 9)? वैकल्पिक रूप से आप attएक ऐसे फंक्शन की गणना कर सकते हैं जो 1 है जब दूरी 0 है और 0 जब दूरी 9 है। उदाहरण के लिएmix(1.0, 0.0, dist / 9.0)
msell

जवाबों:


39

आपके द्वारा प्राप्त क्षीणन समारोह,

att = 1.0 / (1.0 + 0.1*dist + 0.01*dist*dist)

कंप्यूटर ग्राफिक्स में एक बहुत ही सामान्य है - या, अधिक सामान्यतः 1.0 / (1.0 + a*dist + b*dist*dist))कुछ tweakable मापदंडों aऔर के लिए b। यह समझने के लिए कि यह वक्र कैसे काम करता है यह मापदंडों के साथ अंतःक्रियात्मक रूप से खेलने के लिए सहायक है । यह वक्र अच्छा है क्योंकि यह बड़ी दूरी पर शारीरिक रूप से सही उलटा वर्ग कानून के पास जाता है, लेकिन यह कम दूरी पर अनंत तक नहीं पहुंचता है। वास्तव में, a = 0यह एक गोलाकार क्षेत्र प्रकाश का एक बहुत अच्छा मॉडल है।

हालांकि, इसका एक नुकसान यह है कि प्रकाश कभी भी किसी भी परिमित दूरी पर शून्य में नहीं जाता है। रीयलटाइम सीजी में व्यावहारिक उद्देश्यों के लिए हमें आम तौर पर एक सीमित दूरी पर रोशनी काटने की आवश्यकता होती है, जैसा कि आप if (dist < 9)खंड के साथ कर रहे हैं । हालांकि, 9 की त्रिज्या बहुत कम है - क्षीणन समारोह में आपकी सेटिंग्स के साथ, प्रकाश शून्य के करीब नहीं पहुंचता है जब तक कि लगभग 100 के आसपास न हो।

आप bक्षीणन समारोह में पैरामीटर से प्रकाश की त्रिज्या की गणना कर सकते हैं (चूंकि बड़ी दूरी पर द्विघात शब्द हावी है)। मान लें कि आप क्षीणन को कुछ कटौती तक पहुंचाना minLightचाहते हैं, जैसे 0.01। फिर सेट करें

radius = sqrt(1.0 / (b * minLight))

यह 100 के लिए एक त्रिज्या देता है b = 0.01और minLight = 0.01। वैकल्पिक रूप से, आप त्रिज्या सेट कर सकते हैं और bमिलान करने के लिए गणना कर सकते हैं :

b = 1.0 / (radius*radius * minLight)

के लिए radius = 9और minLight = 0.01, कि देता है b = 1.23। आप इसे किसी भी तरह से सेट कर सकते हैं, लेकिन कुंजी त्रिज्या और क्षीणन कार्य मिलान बनाने के लिए है ताकि आप प्रकाश को काट न दें जब तक कि क्षीणन कार्य पहले से ही बहुत कम न हो, इसलिए आपको तेज धार दिखाई नहीं देगी।


कहा कि सभी, वहाँ आप उपयोग कर सकते हैं वैकल्पिक क्षीणन कार्य कर रहे हैं। एक और काफी आम है:

att = clamp(1.0 - dist/radius, 0.0, 1.0); att *= att

या थोड़ा प्रशंसक:

att = clamp(1.0 - dist*dist/(radius*radius), 0.0, 1.0); att *= att

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


महान! हालांकि, मैं का उपयोग करेंगे maxसे अधिक clampप्रदर्शन के कारणों के लिए ही।
माइक वीनर

4
@ माइकाइयर क्लैम्पिंग [0, 1] वास्तव में कई GPU पर मुफ़्त है। यह इतना सामान्य ऑपरेशन है कि उनके पास यह एक निर्देश संशोधक के रूप में है।
नाथन रीड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.