2009-10-03 12 views
26

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

यह मैं क्या कर रहा है: Result of the above code

अंक दिखाने जहां की उम्मीद है, केवल उनके आकार गलत है:

void onInitialization() 
{ 
    glEnable(GL_POINT_SMOOTH); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glPointSize(6.0); 
}  

void onDisplay() 
{ 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glBegin(GL_POINTS); 
     glColor3f(0.95f, 0.207, 0.031f); 
    for (int i = 0; i < g_numPoints; ++i) 
    { 
     glVertex2f(g_points[i].X, g_points[i].Y); 
    } 
    glEnd(); 
    glFinish(); 
    glutSwapBuffers(); 
} 

यह परिणाम है।

+1

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

+0

नहीं, लेकिन मैंने उल्लेख किया कि मैंने ओपनग्ल के साथ खेलना शुरू किया, एक शौक की तरह;) –

+0

यदि आप बस अपने कोड को अपने कंप्यूटर पर चलाने के लिए चाहते हैं तो हर तरह से, अपने कंप्यूटर पर जो कुछ भी काम करता है। लेकिन यह समझना भी मूल्यवान है कि ओपनजीएल का एक बड़ा नुकसान यह है कि spec के बड़े हिस्से किसी दिए गए प्लेटफॉर्म पर सही तरीके से काम नहीं करेंगे। वास्तव में ये कौन सा हिस्सा एक बहुत ही खराब दस्तावेज रहस्य है। सॉफ़्टवेयर-मोड फ़ॉलबैक असमर्थित सुविधाओं को अस्पष्ट कर देगा। – Alan

उत्तर

39

के विपरीत क्या पहले कहा गया था, यह निश्चित समारोह पाइप लाइन के साथ संभव है andre, यहां तक ​​कि GL_POINTS आदिम प्रकार के साथ, जब तक आप ओपन 1.4 या GL_ARB_point_sprite विस्तार के लिए समर्थन के रूप में। इस दस्तावेज़, या अपनी पसंद के ओपनजीएल कोर विनिर्देश से परामर्श लें: http://www.opengl.org/registry/specs/ARB/point_sprite.txt

GL_ARB_point_sprite बिंदुओं को "quads" में परिवर्तित करता है, यानी एक विमान के रूप में एक बहुभुज। सटीक आदिम प्रकार को परिवर्तित करने के लिए इसे विनिर्देशन द्वारा परिभाषित नहीं किया जाता है, हालांकि यह महत्वपूर्ण नहीं है। महत्वपूर्ण यह है कि GL_COORD_REPLACE सक्षम होने पर सतह के लिए बनावट निर्देशांक स्वत: जेनरेट करता है, ताकि आप उन्हें गोलाकार आकार वाले आरजीबीए-बनावट के साथ बनावट बना सकें।

संपादित करें: ऐसा लगता है जैसे आप (पोस्टर) सही है। एंटी-एलाइज्ड अंक अपने त्रिज्या के संबंध में गोल हो जाते हैं। (मैंने 2003 से ओपनजीएल का उपयोग किया है, और मुझे यह नहीं पता था। [/ शर्मनाक]) तो GL_POINT_SMOOTH को सक्षम करते हुए आपके पास multisample-able विज़ुअल/पिक्सेलफॉर्मेट है, तो आपको गोल अंक मिलते हैं। फिर भी, बहुआयामी धीमा हो सकता है, इसलिए मैं दोनों को लागू करता हूं। बनावट quads सस्ते हैं।

Xlib साथ multisampling के साथ एक दृश्य के अनुरोध के लिए glXChooseFBConfig() के लिए सूची में इन दोनों विशेषताओं का उपयोग:

GLX_SAMPLE_BUFFERS - अपने मूल्य True होना चाहिए। यह एक चालू/बंद टॉगल है।
GLX_SAMPLES - नमूने की संख्या।

Win32 के साथ एक pixelformat के अनुरोध के लिए ChoosePixelFormat() या wglChoosePixelFormatARB (करने के लिए सूची में इन दो विशेषताओं का उपयोग):

WGL_SAMPLE_BUFFERS_ARB, उपरोक्त के समान एक टॉगल।
WGL_SAMPLES_ARB उपरोक्त के समान, नमूने की संख्या।

यह प्रतीत आप कर सकते हैं कि या झंडा GLUT_MULTISAMPLEglutInitDisplayMode को भरमार में multisampling प्राप्त करने के लिए, लेकिन आप नमूना बफ़र्स की संख्या का अनुरोध नहीं कर सकते हैं।

यहां बताया गया है कि आपके परीक्षण मामले का उपयोग करके अल्फा-मिश्रित क्वाड कैसे कार्यान्वित किए जा सकते हैं।

void onInitialization() 
{ 
    glEnable(GL_POINT_SPRITE); // GL_POINT_SPRITE_ARB if you're 
           // using the functionality as an extension. 

    glEnable(GL_POINT_SMOOTH); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glPointSize(6.0); 

    /* assuming you have setup a 32-bit RGBA texture with a legal name */ 
    glActiveTexture(GL_TEXTURE0); 
    glEnable(GL_TEXTURE_2D); 
    glTexEnv(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); 
    glTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
    glBindTexture(GL_TEXTURE_2D, texture_name); 
}  

void onDisplay() 
{ 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glBegin(GL_POINTS); 
     glColor4f(0.95f, 0.207, 0.031f, 1.0f); 
    for (int i = 0; i < g_numPoints; ++i) 
    { 
     glVertex2f(g_points[i].X, g_points[i].Y); 
    } 
    glEnd(); 
    glFinish(); 
    glutSwapBuffers(); 
} 

प्रति-टुकड़ा अल्फा सम्मिश्रण + बनावट का उपयोग कर गोल अंकों की छवि: GL_POINT_SMOOTH और multisampling का उपयोग करके गोल अंकों की http://www.mechcore.net/images/gfx/sprite0.png
छवि: http://www.mechcore.net/images/gfx/sprite1.png
एक छोटी सी नमूना है जो दोनों तकनीक से पता चलता मैं बना दिया। libSDL और libGLEW संकलित करने के लिए आवश्यक है:

#include <iostream> 
#include <exception> 
#include <memory> 
#include <SDL/SDL.h> 
#include <cmath> 
#include <GL/glew.h> 
#include <GL/glu.h> 

#define ENABLE_TEXTURE 
#define ENABLE_MULTISAMPLE 

int Width = 800; 
int Height = 600; 

void Draw(void); 
void Init(void); 

inline float maxf(float a, float b) 
{ 
    if(a < b) 
     return b; 
    return a; 
} 

inline float minf(float a, float b) 
{ 
    if(a > b) 
     return b; 
    return a; 
} 

GLuint texture_name; 

int main(void) 
{ 
    try { 
     SDL_Init(SDL_INIT_VIDEO); 
     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 
     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 
     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); 
     SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); 
     SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 
     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 
     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
     #ifdef ENABLE_MULTISAMPLE 
      SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); 
      SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); 
     #endif 
     SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); 
     SDL_SetVideoMode(Width, Height, 32, SDL_OPENGL); 

     glewInit(); 
     Init(); 

     SDL_Event event; 
     bool running = true; 

     while(running){ 
      while(SDL_PollEvent(&event)){ 
       switch(event.type) 
       { 
        case SDL_KEYDOWN: 
         if(event.key.keysym.sym == SDLK_ESCAPE) 
          running = false; 
        break; 
        case SDL_QUIT: 
         running = false; 
        break; 
       } 
      } 
      Draw(); 
      SDL_GL_SwapBuffers(); 
     } 
     SDL_Quit(); 
    } 
    catch(std::bad_alloc& e) 
    { 
     std::cout << "Out of memory. " << e.what() << std::endl; 
     exit(-1); 
    } 
    catch(std::exception& e) 
    { 
     std::cout << "Runtime exception: " << e.what() << std::endl; 
     exit(-1); 
    } 
    catch(...) 
    { 
     std::cout << "Runtime exception of unknown type." << std::endl; 
     exit(-1); 
    } 
    return 0; 
} 

void Init(void) 
{ 
    const GLint texWidth = 256; 
    const GLint texHeight = 256; 
    const float texHalfWidth = 128.0f; 
    const float texHalfHeight = 128.0f; 
    printf("INIT: \n"); 

    unsigned char* pData = new unsigned char[texWidth*texHeight*4]; 
    for(int y=0; y<texHeight; ++y){ 
     for(int x=0; x<texWidth; ++x){ 
      int offs = (x + y*texWidth) * 4; 
      float xoffs = ((float)x - texHalfWidth)/texHalfWidth; 
      float yoffs = ((float)y - texHalfWidth)/texHalfHeight; 
      float alpha = 1.0f - std::sqrt(xoffs*xoffs + yoffs*yoffs); 
      if(alpha < 0.0f) 
       alpha = 0.0f; 
      pData[offs + 0] = 255; //r 
      pData[offs + 1] = 0; //g 
      pData[offs + 2] = 0; //b 
      pData[offs + 3] = 255.0f * alpha; // * 
      //printf("alpha: %f\n", pData[x + y*texWidth + 3]); 
     } 
    } 

    #ifdef ENABLE_TEXTURE 
    glGenTextures(1, &texture_name); 
    glActiveTexture(GL_TEXTURE0); 
    glEnable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, texture_name); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData); 
    glEnable(GL_POINT_SPRITE); 
    glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); 
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    #endif 

    glPointSize(32.0f); 

    glMatrixMode(GL_PROJECTION); 
    glOrtho(0, Width, 0, Height, -1.0f, 1.0f); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glDisable(GL_DEPTH_TEST); 

    #ifdef ENABLE_MULTISAMPLE 
     glEnable(GL_POINT_SMOOTH); 
    #endif 

    GLenum e; 
    do{ 
     e = glGetError(); 
     printf("%s\n",gluErrorString(e)); 
    } while(e != GL_NO_ERROR); 

    delete [] pData; 
} 

void Draw(void) 
{ 
    const int gridWidth = 1024; 
    const int gridHeight = 1024; 
    float t1, t2; 

    t1 = t2 = (float)SDL_GetTicks() * 0.001f; 
    t1 = fmod(t1, 10.0f)/10.0f; 
    t2 = fmod(t2, 4.0f)/4.0f; 
    float scale = 0.5f + (-sin(t2 * 2.0 * M_PI) + 1.0f) * 1.2f; 
    //glColor4f(0.4f, 0.5f, 0.9f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glLoadIdentity(); 

    glTranslatef((Width>>1), (Height>>1), 0.0f); 
    glScalef(scale,scale,scale); 
    glRotatef(t1 * 360.0f, 0.0f, 0.0f, 1.0f); 

    glBegin(GL_POINTS); 
    for(int j=0; j<gridHeight; j+=64){ 
     for(int i=0; i<gridWidth; i+=64){ 
      glVertex2i(i-(gridWidth>>1),j-(gridHeight>>1)); 
     } 
    } 
    glEnd(); 
} 
+0

और संदर्भ के बारे में क्या मैंने दूसरी टिप्पणी में उद्धृत किया? अगर मैं इसे गलत समझ नहीं पाता हूं, तो यह सुझाव देता है कि GL_POINT_SMOOTH परिपत्र बिंदु बनाता है। या मैं करूँ? –

+0

हां, मैंने इसके बारे में पढ़ा और इसे आजमाया। मजेदार, मुझे नहीं पता था :-) –

+1

बहुत विस्तृत उत्तर के लिए धन्यवाद। –

0

एक निश्चित opengl फ़ंक्शन के साथ संभव नहीं है। डॉट्स हमेशा स्क्वायर होते हैं :)

आपको अपना खुद का सर्कल (इसे केक की तरह बनाकर, टुकड़े से टुकड़ा करके) खींचना है या एक "सर्कल" बनावट के साथ एक GL_QUAD खींचना है।

सादर,

+2

तो क्या GL_POINT_SMOOTH तब के लिए अच्छा है? –

+0

ओपनग्लिंग संदर्भ के अनुसार: "अगर एंटीअलाइजिंग सक्षम है, तो बिंदु रास्टराइजेशन प्रत्येक पिक्सेल वर्ग के लिए एक टुकड़ा उत्पन्न करता है जो सर्कल के भीतर स्थित क्षेत्र को छेड़छाड़ करता है जिसमें वर्तमान बिंदु आकार के बराबर व्यास होता है और बिंदु के xwyw पर केंद्रित होता है। कवरेज मान प्रत्येक टुकड़ा ** परिपत्र क्षेत्र के चौराहे वाले क्षेत्र के चौराहे क्षेत्र के चौराहे के विंडो समन्वय क्षेत्र है। ** " –

+3

दरअसल, यह संभव है, लेकिन यह ओपनजीएल चालक पर निर्भर करता है कि यह कितना अच्छा होगा (या यहां तक ​​कि भी) यह काम करेगा । मेरे परीक्षण में, यह एनवीडिया हार्डवेयर/ड्राइवर के साथ गोल बिंदु देता है, लेकिन अति/एएमडी हार्डवेयर/ड्राइवर के साथ, यह वर्ग अंक देता है। –

2

मैड्स 'जवाब सब कुछ आप की जरूरत है अगर आप तय समारोह पाइप लाइन के लिए जाना जा सकता है। हालांकि, अगर आपके पास ऐसी प्रणाली है जो ARB_point_sprite एक्सटेंशन या टूटा कार्यान्वयन (कुछ अति ड्राइवर) प्रदान नहीं करती है, तो आप इस भाग को ज्यामिति शेडर्स के साथ भी हल कर सकते हैं। ARB_geometry_shader4 एक्सटेंशन आपको एक बिंदु आदिम को दो त्रिकोणों में परिवर्तित करने की अनुमति देता है, जिसे ARB_point_sprite एक्सटेंशन द्वारा बनाए गए क्वाड के रूप में उपयोग किया जा सकता है। ओपनजीएल 3.2 पर, ज्यामिति शेडर्स पहले ही कोर में समर्थित हैं, कोई एक्सटेंशन आवश्यक नहीं है। ओपनजीएल विकी में two examples है।

+0

+1 ज्यामिति शेडर के उल्लेख के लिए +1, जो आपको समर्थित है अगर आपको समर्थित है (200 9 में और इसी तरह आज भी)। इसका कारण यह है कि सभी जीपीयू गार्ड बैंड का समर्थन नहीं करते हैं, और आपके पास यह जानने का कोई तरीका नहीं है कि वे क्या करते हैं या नहीं। यदि वे नहीं करते हैं, तो बिंदु और बिंदु sprites पॉप आयत के करीब ले जाने के रूप में पॉप और पॉप आउट होगा। जब बिंदु स्प्राइट का केंद्र बिंदु आयताकार से बाहर चला जाता है, तो बिंदु के दृश्यमान आधे भाग अचानक गायब हो जाते हैं। इसके अलावा, बिंदु आकार आमतौर पर लगभग 64px तक ही सीमित होते हैं। – Damon

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

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