2011-12-22 14 views
5

मैं विश्वविद्यालय के लिए केवल कोर ओपनजीएल 3.3 का उपयोग करके वोल्फेंस्टीन 3 डी का क्लोन लिख रहा हूं और मैंने sprites के साथ एक समस्या में भाग लिया है, अर्थात् उन्हें सही ढंग से आधारित करने के लिए दूरी परकैमरे से दूरी पर आधारित प्वाइंट स्प्राइट्स का आकार

जो मैं कह सकता हूं, उससे ओजीएल के पिछले संस्करण वास्तव में आपके लिए ऐसा करेंगे, लेकिन उस कार्यक्षमता को हटा दिया गया है, और इसके सभी प्रयासों को फिर से लागू करने के लिए पूरी विफलता हुई है।

मेरा वर्तमान कार्यान्वयन दूरी पर पारगम्य है, मध्य सीमा पर बहुत शर्मीली नहीं है और नजदीक सीमा पर bizzare है।

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

Expected Result Actual Result

किसी को भी, जहां मैं गलत जा रहा हूँ करने के लिए मुझे प्रत्यक्ष कर सकते हैं, और इसका कारण बताएं?

कोड:
सी ++

// setup 
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); 
glEnable(GL_PROGRAM_POINT_SIZE); 

// Drawing 
glUseProgram(StaticsProg); 
glBindVertexArray(statixVAO); 
glUniformMatrix4fv(uStatixMVP, 1, GL_FALSE, glm::value_ptr(MVP)); 
glDrawArrays(GL_POINTS, 0, iNumSprites); 

शीर्ष shader

#version 330 core 

layout(location = 0) in vec2 pos; 
layout(location = 1) in int spriteNum_; 

flat out int spriteNum; 

uniform mat4 MVP; 

const float constAtten = 0.9; 
const float linearAtten = 0.6; 
const float quadAtten = 0.001; 

void main() { 
    spriteNum = spriteNum_; 
    gl_Position = MVP * vec4(pos.x + 1, pos.y, 0.5, 1); // Note: I have fiddled the MVP so that z is height rather than depth, since this is how I learned my vectors. 
    float dist = distance(gl_Position, vec4(0,0,0,1)); 
    float attn = constAtten/((1 + linearAtten * dist) * (1 + quadAtten * dist * dist)); 
    gl_PointSize = 768.0 * attn; 
} 

टुकड़ा shader

#version 330 core 

flat in int spriteNum; 

out vec4 color; 

uniform sampler2DArray Sprites; 

void main() { 
    color = texture(Sprites, vec3(gl_PointCoord.s, gl_PointCoord.t, spriteNum)); 
    if (color.a < 0.2) 
     discard; 
} 
+0

आप 'pos.x + 1' का उपयोग क्यों करते हैं? –

+0

मुझे लगता है कि ऐसा इसलिए है क्योंकि उन्होंने स्प्राइट सेंटर की स्थिति को बाएं से नीचे सेट किया है, लेकिन वह वास्तव में शीर्ष केंद्र में एंकर पॉइंट चाहता है। –

+0

मैं अनुलग्नक बिंदु को नीचे किनारे के केंद्र में रखना चाहता हूं, लेकिन संरेखण के मुद्दों के समूह के कारण मुझे सॉर्ट करने के लिए चारों ओर नहीं मिला है, मुझे कुछ चीजों को कुछ हद तक बदलना है। –

उत्तर

11

सबसे पहले, मुझे वास्तव में समझ में नहीं आता कि आप pos.x + 1 का उपयोग क्यों करते हैं।

अगला, जैसे नाथन ने कहा, आपको क्लिप-स्पेस पॉइंट का उपयोग नहीं करना चाहिए, बल्कि आंख-स्थान बिंदु। इसका मतलब है कि आप दूरी की गणना करने के लिए केवल मॉडलव्यू-ट्रांसफॉर्म पॉइंट (प्रक्षेपण के बिना) का उपयोग करें।

uniform mat4 MV;  //modelview matrix 

vec3 eyePos = MV * vec4(pos.x, pos.y, 0.5, 1); 

इसके अलावा मैं आपकी क्षीणन गणना पूरी तरह से समझ नहीं पा रहा हूं। इस समय एक उच्च constAtten मान का अर्थ कम क्षीणन है।आप क्यों नहीं बस मॉडल है कि ओपन के लिए बहिष्कृत बिंदु पैरामीटर का उपयोग किया का उपयोग नहीं करते:

float dist = length(eyePos); //since the distance to (0,0,0) is just the length 
float attn = inversesqrt(constAtten + linearAtten*dist + quadAtten*dist*dist); 

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

एक बेहतर तरीका इनपुट करने के लिए अपनी वस्तु अंतरिक्ष आकार है और सिर्फ पिक्सल में स्क्रीन स्थान आकार (जो क्या gl_PointSize वास्तव में है) वर्तमान दृश्य और प्रक्षेपण सेटअप का उपयोग पर आधारित है कि गणना:

uniform mat4 MV;    //modelview matrix 
uniform mat4 P;     //projection matrix 
uniform float spriteWidth;  //object space width of sprite (maybe an per-vertex in) 
uniform float screenWidth;  //screen width in pixels 

vec4 eyePos = MV * vec4(pos.x, pos.y, 0.5, 1); 
vec4 projCorner = P * vec4(0.5*spriteWidth, 0.5*spriteWidth, eyePos.z, eyePos.w); 
gl_PointSize = screenWidth * projCorner.x/projCorner.w; 
gl_Position = P * eyePos; 

यह spriteWidth की चौड़ाई के साथ एक बनावट क्वाड के रूप में प्रस्तुत किए जाने पर स्प्राइट हमेशा आकार प्राप्त होता है।

संपादित करें: बेशक आपको पॉइंट स्प्राइट्स की सीमाओं को ध्यान में रखना चाहिए। एक बिंदु स्प्राइट अपनी केंद्र स्थिति के आधार पर फिसल जाता है। इसका मतलब है कि जब उसका केंद्र स्क्रीन से बाहर निकलता है, तो पूरे स्प्राइट गायब हो जाते हैं। बड़े sprites के साथ (जैसे आपके मामले में, मुझे लगता है) यह वास्तव में एक समस्या हो सकती है।

इसलिए मैं आपको सरल बनावट वाले क्वाड का उपयोग करने का सुझाव दूंगा। इस तरह आप इस पूरे क्षीणन की समस्या को बाधित करते हैं, क्योंकि quads सिर्फ अन्य 3 डी ऑब्जेक्ट की तरह बदल जाते हैं। आपको केवल दर्शक की ओर घूर्णन को लागू करने की आवश्यकता है, जिसे या तो सीपीयू या कशेरुक शेडर में किया जा सकता है।

+0

कोड का आपका दूसरा बिट [यह] (http://i.imgur.com/EvTwW.png) का कारण बनता है, और मुझे पूरा यकीन नहीं है कि यह क्या कर रहा है। क्या आप इसे और समझा सकते हैं? मैं quads में भी देखेंगे। –

+0

@Lexi आपका पहला मतलब क्या है, पहला संपादन? –

+0

हाँ, projCorner वाला एक। –

1

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

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

5

पर Christian Rau's answer (पिछला संपादन), मैं एक ज्यामिति शेडर कि ViewSpace के बिलबोर्ड बनाता है, जो मेरे सभी समस्याओं का समाधान करने लगता है कार्यान्वित आधार पर:

Expected Result Actual Result

यहाँ shaders हैं: (नोट कि मैं संरेखण मुद्दा यह है कि एक्स के लिए 1 जोड़ने के लिए)

शीर्ष shader

मूल शेडर आवश्यक तय कर दी है
#version 330 core 

layout (location = 0) in vec4 gridPos; 
layout (location = 1) in int spriteNum_in; 

flat out int spriteNum; 

// simple pass-thru to the geometry generator 
void main() { 
    gl_Position = gridPos; 
    spriteNum = spriteNum_in; 
} 

ज्यामिति छायांकर्ता

#version 330 core 

layout (points) in; 
layout (triangle_strip, max_vertices = 4) out; 

flat in int spriteNum[]; 

smooth out vec3 stp; 

uniform mat4 Projection; 
uniform mat4 View; 

void main() { 
    // Put us into screen space. 
    vec4 pos = View * gl_in[0].gl_Position; 

    int snum = spriteNum[0]; 

    // Bottom left corner 
    gl_Position = pos; 
    gl_Position.x += 0.5; 
    gl_Position = Projection * gl_Position; 
    stp = vec3(0, 0, snum); 
    EmitVertex(); 

    // Top left corner 
    gl_Position = pos; 
    gl_Position.x += 0.5; 
    gl_Position.y += 1; 
    gl_Position = Projection * gl_Position; 
    stp = vec3(0, 1, snum); 
    EmitVertex(); 

    // Bottom right corner 
    gl_Position = pos; 
    gl_Position.x -= 0.5; 
    gl_Position = Projection * gl_Position; 
    stp = vec3(1, 0, snum); 
    EmitVertex(); 

    // Top right corner 
    gl_Position = pos; 
    gl_Position.x -= 0.5; 
    gl_Position.y += 1; 
    gl_Position = Projection * gl_Position; 
    stp = vec3(1, 1, snum); 
    EmitVertex(); 

    EndPrimitive(); 
} 

टुकड़ा shader

#version 330 core 

smooth in vec3 stp; 

out vec4 colour; 

uniform sampler2DArray Sprites; 

void main() { 
    colour = texture(Sprites, stp); 
    if (colour.a < 0.2) 
     discard; 
} 
+2

तो ईसाई राउ का जवाब यह है कि आप कहां हैं, फिर भी आप अपना जवाब स्वीकार करते हैं? वाह, वह प्रयास किए जाने के बाद अविश्वसनीय रूप से विचारहीन है। लोगों को मंजूरी देने के लिए रास्ता। –

+0

@ निकविकगिल मैंने वास्तव में इसके बारे में सोचा नहीं था कि ईमानदार होना। मैंने अपना जवाब बनाया और स्वीकार कर लिया क्योंकि मैंने सोचा था कि यह मेरी समस्या के साथ किसी और के लिए अधिक सहायक होगा। स्वीकृत उत्तर को पुन: असाइन करने में आपके विचार के बदले में –

+0

+1 आपके उत्तर पर +1। वैसे भी आपका वोट शायद अधिक वोटों के साथ खत्म हो जाएगा। –

0

कम से कम OpenGL ES 2.0 में, वहाँ gl_PointSize पर अधिकतम आकार सीमा ओपन कार्यान्वयन द्वारा लगाए गए है। आप ALIASED_POINT_SIZE_RANGE के साथ आकार पूछ सकते हैं।

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

  • कोई संबंधित समस्या नहीं^_^