पहली बार छाया मानचित्रण समस्याओं


9

मैंने पहली बार OpenGL में शेड्स का उपयोग करके बेसिक शैडो मैपिंग को लागू किया है और मैं कुछ समस्याओं का सामना कर रहा हूं। नीचे आप मेरे प्रस्तुत दृश्य का एक उदाहरण देख सकते हैं:

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

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

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

यहाँ मेरा शीर्ष shader है,


#version 150 core

uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 MVPMatrix;
uniform mat4 lightMVP;

uniform float scale;

in vec3 in_Position;
in vec3 in_Normal;
in vec2 in_TexCoord;

smooth out vec3 pass_Normal;
smooth out vec3 pass_Position;
smooth out vec2 TexCoord;
smooth out vec4 lightspace_Position;

void main(void){
    pass_Normal = NormalMatrix * in_Normal; 
    pass_Position = (ModelViewMatrix * vec4(scale * in_Position, 1.0)).xyz;
    lightspace_Position = lightMVP * vec4(scale * in_Position, 1.0);
    TexCoord = in_TexCoord;

    gl_Position = MVPMatrix * vec4(scale * in_Position, 1.0);
}

और मेरा टुकड़ा shader,


#version 150 core

struct Light{
    vec3 direction;
};

uniform Light light;
uniform sampler2D inSampler;
uniform sampler2D inShadowMap;

smooth in vec3 pass_Normal;
smooth in vec3 pass_Position;
smooth in vec2 TexCoord;
smooth in vec4 lightspace_Position;

out vec4 out_Color;


float CalcShadowFactor(vec4 lightspace_Position){

    vec3 ProjectionCoords = lightspace_Position.xyz / lightspace_Position.w;

    vec2 UVCoords;
    UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
    UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;

    float Depth = texture(inShadowMap, UVCoords).x;
    if(Depth < (ProjectionCoords.z + 0.001)) return 0.5;
    else return 1.0;
}

void main(void){

    vec3 Normal = normalize(pass_Normal);
    vec3 light_Direction = -normalize(light.direction);
    vec3 camera_Direction = normalize(-pass_Position);
    vec3 half_vector = normalize(camera_Direction + light_Direction);

    float diffuse = max(0.2, dot(Normal, light_Direction));
    vec3 temp_Color = diffuse * vec3(1.0);

    float specular = max( 0.0, dot( Normal, half_vector) );

    float shadowFactor = CalcShadowFactor(lightspace_Position);

    if(diffuse != 0 && shadowFactor > 0.5){
        float fspecular = pow(specular, 128.0);
        temp_Color += fspecular;
    }

    out_Color = vec4(shadowFactor * texture(inSampler, TexCoord).xyz * temp_Color, 1.0);
}

समस्याओं में से एक स्वयं छायांकन है जैसा कि आप चित्र में देख सकते हैं, टोकरे की अपनी छाया खुद पर डाली गई है। मैंने जो भी कोशिश की है वह बहुभुज ऑफसेट (यानी glEnable (POLYGON_OFFSET_FILL), glPolygonOffset (GLfloat, GLfloat) को सक्षम करने में सक्षम है, लेकिन यह ज्यादा नहीं बदला। जैसा कि आप टुकड़े टुकड़े में देखते हैं, मैंने 0.001 का स्थिर ऑफसेट मूल्य रखा है, लेकिन मुझे अधिक वांछनीय प्रभाव प्राप्त करने के लिए प्रकाश की दूरी के आधार पर मूल्य को बदलना होगा, जो बहुत आसान नहीं है। मैंने फ्रेम फेसर को रेंडर करते समय फ्रंट फेस कालिंग का उपयोग करने की भी कोशिश की, जो कि बहुत ज्यादा नहीं बदला।

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

थोड़ा घूमने से, मैं समझता हूं कि ये मुद्दे उस तुच्छ नहीं हैं। क्या किसी के पास इन समस्याओं के समाधान को लागू करने का कोई आसान तरीका है। क्या आप मुझे कुछ अतिरिक्त सुझाव दे सकते हैं?

कृपया मुझसे पूछें कि क्या आपको मेरे कोड की अधिक जानकारी चाहिए।

यहाँ टोकरे के एक क्लोज़-अप की छाया मानचित्रण के साथ और बिना तुलना की जाती है। आत्म-परछाई अधिक दिखाई देती है।


लगता है जैसे आपको अपनी समस्या का और अधिक विस्तार से वर्णन करना चाहिए। आपके पास अपनी समस्याओं के बारे में एक वाक्य है और अगला वाक्य एक के लिए एक फिक्स का सुझाव देता है। हमें बताएं कि वास्तव में क्या समस्याएं हैं और आपने पहले से ही इसे ठीक करने के लिए क्या किया है।
MichaelHouse

मैंने अपनी पोस्ट संपादित की, मुझे उम्मीद है कि अब यह बेहतर है।
ग्रिएवरहार्ट

जवाबों:


6

आपको उन बहुभुज को छाया नहीं देना चाहिए जो प्रकाश से सामना कर रहे हैं।

मैंने आपके खंड को नीचे कोड में बदल दिया है।

float CalcShadowFactor(vec4 lightspace_Position)
{

    vec3 ProjectionCoords = lightspace_Position.xyz / lightspace_Position.w;

    vec2 UVCoords;
    UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
    UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;

    float Depth = texture(inShadowMap, UVCoords).x;
    if(Depth < (ProjectionCoords.z + 0.001)) return 0.5;
    else return 1.0;
}

void main(void)
{

    vec3 Normal = normalize(pass_Normal);
    vec3 light_Direction = -normalize(light.direction);
    vec3 camera_Direction = normalize(-pass_Position);
    vec3 half_vector = normalize(camera_Direction + light_Direction);

    float fndotl = dot(Normal, light_Direction);
    float shadowFactor = CalcShadowFactor(lightspace_Position);
    float diffuse = max(0.0, fndotl) * shadowFactor + 0.2;
    vec3 temp_Color = vec3(diffuse);

    float specular = max( 0.0, dot( Normal, half_vector) );

    if(shadowFactor > 0.9){
        float fspecular = pow(specular, 128.0);
        temp_Color += fspecular;
    }

    out_Color = vec4(shadowFactor * texture(inSampler, TexCoord).xyz * temp_Color, 1.0);
}

8

सेल्फ-शैडोइंग के बारे में, मुझे यकीन नहीं है कि आप क्या जिक्र कर रहे हैं - मुझे आपके स्क्रीनशॉट में टोकरे पर कोई "छाया मुँहासे" दिखाई नहीं दे रहा है। यदि आपका मतलब है कि प्रकाश से दूर होने वाले चेहरे अंधेरे हैं, ठीक है, निश्चित रूप से वे हैं - उन्हें होना चाहिए! :) पक्ष का चेहरा थोड़ा अजीब लगता है, विकर्ण को आधा जलाया जाता है और आधा छायांकित होता है। यदि आप प्रकाश व्यवस्था के लिए N dot L का उपयोग कर रहे हैं, और आपके पास अच्छे मानदंड हैं (अर्थात इस घन पर कठोर मानदंड, सुचारू किए गए मानदंड नहीं) तो ऐसा नहीं होना चाहिए।

बहुभुज ऑफसेट और / या छाया के नक्शे में पीछे के चेहरे का उपयोग करना छाया के मुँहासे के लिए मानक समाधान (अच्छी तरह से ... वर्कअराउड वास्तव में) हैं।

प्रक्षेपण मैट्रिक्स के लिए, आपको कैमरे के रूप में प्रकाश के बारे में सोचना चाहिए। यदि यह एक बिंदु प्रकाश है, तो यह एक परिप्रेक्ष्य कैमरा होगा और यदि यह एक दिशात्मक प्रकाश है तो यह एक ऑर्थोग्राफ़िक कैमरे की तरह होगा। प्रक्षेपण मैट्रिक्स का निर्माण उसी तरह से करें जैसे आप कैमरे के लिए करते हैं, प्रकाश के क्षेत्र, पहलू अनुपात, आदि का उपयोग करते हुए।

पिक्सेल शेडर को केवल प्रकाश के दृश्य फ़्रिज़ में पिक्सेल खींचने के लिए प्रतिबंधित करने के लिए, एक बार जब आप छाया मानचित्र UVs की गणना करते हैं, तो यह देखें कि वे 0 और 1 के बीच हैं और discardयदि नहीं (या प्रकाश का रंग शून्य पर सेट करें)। दूसरा तरीका छाया मानचित्र की बनावट को "सीमा पर दबाना" मोड सेट करना और शून्य का एक सीमा रंग निर्धारित करना है, जो छाया मानचित्र के बाहर सब कुछ पूरी तरह से छायांकित हो जाएगा।


यहाँ बॉक्स का एक क्लोज़अप है और छाया मैपिंग लिंक के साथ और बिना तुलना करें । यहां सेल्फ-शैडोइंग ज्यादा दिखाई देती है। क्या आप बता सकते हैं कि आप दिशात्मक रोशनी के लिए एक परिप्रेक्ष्य कैमरा और दिशात्मक के लिए ऑर्थोग्राफ़िक का उपयोग क्यों करेंगे?
ग्रिएवरहार्ट

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

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

जो बिल्कुल एक जैसे दिखते हैं। आप शेष दृश्य के लिए बैक-फेस पुलिंग का उपयोग कर रहे हैं, है ना? तुमने किया क्या glEnable(GL_CULL_FACE)?
नाथन रीड

वे बिल्कुल समान नहीं हैं, बॉक्स को करीब से देखें। ऊपर की तस्वीर में, छाया रेखा उत्तल है, जबकि नीचे वाला एक अवतल है।
गरिवरहार्ट

3

रोशनी के बाहर के पिक्सेल गहरे रंग के होते हैं क्योंकि उन्हें रोशनी की गहराई बनावट के बाहर से नमूना लिया जाता है।

जब आप प्रक्षेपण मैट्रिक्स द्वारा वर्टेक्स को बदलते हैं तो आपको टुकड़े के क्लिप निर्देशांक [lightspace_Position] मिलते हैं। फिर आप इसे बनावट में परिवर्तित कर रहे हैं [UVCoords]। हालाँकि, किसी खंड के क्लिप स्पेस निर्देशांक अभी भी -1.0 से 1.0 सीमा (स्क्रीन से दूर और इसलिए क्लिप किए गए) के बाहर हो सकते हैं और इसलिए परिवर्तित बनावट निर्देशांक आपकी बनावट के 0.0 से 1.0 सीमा के बाहर हो सकते हैं।

इसे इस्तेमाल करे:

if(UVCoords.x >= 0.0 && UVCoords.x <= 1.0 && UVCoords.y >= 0.0 && UVCoords.y <= 1.0 && (Depth < (ProjectionCoords.z + 0.001)))
    return 0.5;

आप अपने [lightMVP] में भी एक पूर्वाग्रह मैट्रिक्स को गुणा कर सकते हैं और अपने खंडित शेड में समन्वय रूपांतरण करने से बच सकते हैं।


पूर्वाग्रह मैट्रिक्स आमतौर पर लोगों के जाने का तरीका है। यह टुकड़े टुकड़े में शाखाओं में बंटी कोड की तुलना में बहुत तेज है।
इयान यंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.