2009-10-03 24 views
26

OpenGLとGLUTで遊び始めました。私はいくつかの点を描きたいが、問題はそれらが正方形になることであり、丸い点(黒丸)にしたいと思う。OpenGLで滑らかで大きなポイントを取得

は、これは私が何をすべきかです: 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

ターゲットプラットフォームが何であるかについては言及していません。 OpenGLの一部の機能(GL_POINT_SMOOTHなど)は広くサポートされていません。アプリケーションをコンシューマーグレードのビデオカードで広く使用する場合は、エキゾチックな拡張機能を使用する前にテストを行ってください。動作しているように見えても、パフォーマンスを確認してください。ソフトウェアモードになる可能性があります。 – Alan

+0

いいえ、私はちょうど趣味のような、openglで遊んで始めたと言いました;) –

+0

あなたのコードを自分のコンピュータで実行したいなら、是非、あなたのコンピュータ上で動作するものを実行してください。 OpenGLの大きな落とし穴は、特定のプラットフォームで仕様の大きな部分が正しく機能しなくなるということです。正確にはこれらの部分は非常によく文書化されていない秘密です。ソフトウェアモードのフォールバックは、サポートされていない機能をあいまいにする傾向があります。 – Alan

答えて

39

以前に言われたこととは違って、これは、限り、あなたは、OpenGL 1.4やGL_ARB_point_sprite拡張機能のサポートを持っているように、でもGL_POINTSプリミティブ型で、固定機能パイプラインを持つことも可能です。このドキュメント、またはあなたの選択したOpenGLコア仕様を参照してください。

ポイントを「クワッド」、つまりプレーンの形をしたポリゴンに変換します。変換される正確なプリミティブ型は、仕様では定義されていませんが、重要ではありません。重要なのは、GL_COORD_REPLACEが有効になっているとサーフェスのテクスチャ座標を自動的に生成するため、球状のRGBAテクスチャでテクスチャマップできることです。

EDIT:あなた(ポスター)が正しいようです。アンチエイリアス処理されたポイントは、その半径に対して丸められます。 (私は2003年からOpenGLを使っていましたが、これはわかりませんでした) GL_POINT_SMOOTHmultisample-ableのビジュアル/ピクセルフォーマットを持っていますが、丸い点があります。それでも、マルチサンプリングは遅くなる可能性があるので、私は両方を実装します。テクスチャードクワッドは安いです。

glXChooseFBConfig(にリストにこれら二つの属性を使用し、Xlibのとマルチサンプリングとビジュアルを要求するに):

GLX_SAMPLE_BUFFERS - その値はTrueでなければなりません。これはオン/オフ切り替えです。
GLX_SAMPLES - サンプル数。

)は、Win32のとピクセルフォーマットを要求ChoosePixelFormat()またはwglChoosePixelFormatARB(にリストにこれら二つの属性を使用するには:トグル、上記のように

WGL_SAMPLE_BUFFERS_ARB同じ。
WGL_SAMPLES_ARB上記と同じ、サンプル数。

それはあなたができることをOR glutInitDisplayModeからGLUT_MULTISAMPLEはGLUTにマルチサンプリング取得するフラグに思えるが、あなたはサンプルバッファの数を要求することはできません。

テストケースを使用してアルファブレンドクワッドを実装する方法は次のとおりです。

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

ごと断片アルファブレンディング+テクスチャを使用して、丸い点の画像:http://www.mechcore.net/images/gfx/sprite0.png
GL_POINT_SMOOTHとマルチサンプリングを使用して、丸い点の画像: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機能では不可能です。ドットは常に正方形です。

あなたは自分の円を描く(ケーキのように1個ずつ作成する)か、または "円"テクスチャを使ってGL_QUADを描画する必要があります。

よろしく、 アンドレ

+2

GL_POINT_SMOOTHはそれに適していますか? –

+0

OpenGLリファレンスによると、「アンチエイリアシングが有効な場合、ポイントラスタライズは、現在のポイントサイズに等しい直径を持ち、ポイントのxwywを中心とする円内にある領域と交差する各ピクセルの四角形に対してフラグメントを生成します。各フラグメントは**円領域と対応するピクセル正方形との交差のウィンドウ座標領域です** ** " –

+3

実際には可能ですが、OpenGLドライバにはそれがうまくいくかどうか。私のテストでは、nVidiaのハードウェア/ドライバではラウンドポイントが得られますが、ATI/AMDのハードウェア/ドライバでは、正方形のポイントが与えられます。 –

2

Madsの回答は、固定機能のパイプラインに必要なものすべてを提供します。しかし、ARB_point_spriteの拡張機能を提供していないシステムや実装が壊れているシステム(一部のATIドライバ)がある場合は、ジオメトリシェーダでもこの部分を解決できます。 ARB_geometry_shader4 拡張子を使用すると、ポイントプリミティブを2つの三角形に変換できます。この2つの三角形は、ARB_point_sprite拡張で作成されたクワッドとして使用できます。 OpenGL 3.2では、ジオメトリシェーダはすでにコアでサポートされており、拡張は必要ありません。 OpenGL wikiはtwo examplesです。

+0

+1ジオメトリシェーダについて言及してください。これは、サポートされていれば常に使用する必要があります(2009年も今日も同様です)。なぜなら、すべてのGPUでガードバンドがサポートされているわけではなく、GPUがサポートしているかどうかを知る方法がないからです。そうしないと、点と点のスプライトがクリップの四角形に近づくとポップアウトして飛び出します。点スプライトの中心点が矩形から外れると、点スプライトの目に見える半分が突然「消える」。さらに、ポイントサイズは通常約64ピクセルに制限されています。 – Damon

関連する問題