سؤال

بدأت ألعب مع OpenGL و Full. أود أن أرسم بعض النقاط، لكن المشكلة هي أنها تتحول إلى المربعات، وأود أن يكون لهم نقاط مستديرة (الدوائر المملوءة).

هذا ما افعله:

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();
}

هذه هي النتيجة:Result of the above code

النقاط تظهر حيث من المتوقع، شكلها فقط خطأ.

هل كانت مفيدة؟

المحلول

على عكس ما قيل سابقا، هذا ممكن مع خط أنابيب الوظائف الثابتة، حتى مع GL_POINTS النوع البدائي، طالما لديك دعم OpenGL 1.4 أو GL_ARB_point_sprite تمديد. استشر هذه الوثيقة، أو المواصفات الأساسية OpenGL التي تختارها: http://www.opengl.org/registry/specs/arb/point_sprite.txt.

GL_ARB_point_sprite يحول نقاط إلى "الكواد"، أي مضلع مع شكل طائرة. لا يتم تحديد النوع البدائي بالضبط يتم تحويله إلى المواصفات، على الرغم من أنه غير مهم. ما هو مهم هو ذلك GL_COORD_REPLACE يقوم بإنشاء إحداثيات الملمس تلقائيا للسطح عند تمكينه، حتى تتمكن من الملمس - رسمها مع نسيج RGBA على شكل سبأس.

تحرير: يبدو أنك (الملصق) صحيح. يتم تقريب نقاط مكافحة المستعثية فيما يتعلق بنصف دائرة نصف قطرها. (لقد استخدمت OpenGL منذ عام 2003، ولم أكن أعرف ذلك. [/ sheame]) لذا تمكين GL_POINT_SMOOTH بينما لديك multisample-able Visual / Pixelformat، تحصل على نقاط مدورة. لا يزال، يمكن أن يكون multisampling بطيئا، لذلك كنت أقوم بتطبيق كليهما. الكواد محكم رخيصة.

لطلب مرئي مع Multisaming مع XLIB, ، استخدم هذه الصفاتين في القائمة إلى glxchoosefbconfig ():

GLX_SAMPLE_BUFFERS - يجب أن تكون قيمتها True. وبعد هذا هو خارج / قبالة التبديل.
GLX_SAMPLES - عدد العينات.

لطلب pixelformat مع win32, ، استخدم هذه الصفاتين في القائمة إلى choosepixelformat () أو wglchoosepixelformathb ():

WGL_SAMPLE_BUFFERS_ARB نفس أعلاه، تبديل.
WGL_SAMPLES_ARB نفس أعلاه، عدد العينات.

يبدو أنه يمكنك أو في العلم GLUT_MULTISAMPLE ل glutInitDisplayMode للحصول على multisampling في وفرة, ، ولكن لا يمكنك طلب عدد المخازن المؤقتة عينة.

فيما يلي كيفية تنفيذ Quads Alpha-Blended باستخدام حالة الاختبار الخاصة بك.

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();
}

صورة النقاط الدائرية باستخدام نسيج ألفا المزج +
(مصدر: mechcore.net.)
صورة النقاط الدائرية باستخدام GL_POINT_SMOOTH و multisampling:
(مصدر: mechcore.net.)
عينة صغيرة قمت بها والتي تبيع كلا التقنيتين. يتطلب 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();
}

نصائح أخرى

توفر إجابة Mads كل ما تحتاجه إذا ذهبت لخط أنابيب الوظيفة الثابتة. ومع ذلك، إذا كان لديك نظام لا يوفر ARB_point_sprite تمديد أو مع تطبيق مكسور (بعض برامج تشغيل ATI)، يمكنك حل هذا الجزء أيضا مع تظليل الهندسة. ال ARB_geometry_shader4يتيح لك التمديد تحويل نقطة بدائية إلى مثلثين، والتي يمكن استخدامها كقاولت ARB_point_sprite تمديد. على OpenGL 3.2، يتم دعم تظليل الهندسة بالفعل في النواة، أي ملحق مطلوب. ويكي OpenGL لديه مثالين.

غير ممكن مع وظيفة OpenGL ثابتة. النقاط هي دائما مربع :)

يجب عليك رسم دائرة خاصة بك (عن طريق بناءها مثل كعكة أو قطعة قطعة) أو ارسم gl_quad مع نسيج "دائرة" على.

مع أطيب التحيات، أندريه

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top