Getting smooth, big points in OpenGL

匿名 (未验证) 提交于 2019-12-03 01:06:02

问题:

I started playing around with OpenGL and GLUT. I would like to draw some points, but the problem is that they turn out to be squares, and I would like them to be round dots (filled circles).

This is what I do:

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 

This is the result:

The points show up where expected, only their shape is wrong.

回答1:

Unlike what was said previously, this is possible with the fixed-function pipeline, even with the GL_POINTS primitive type, as long as you have support for OpenGL 1.4 or the GL_ARB_point_sprite extension. Consult this document, or the OpenGL core specification of your choice : http://www.opengl.org/registry/specs/ARB/point_sprite.txt

GL_ARB_point_sprite converts points into "quads", i.e a polygon with the form of a plane. The exact primitive type it gets converted to is not defined by the specification, though it is not important. What is important is that GL_COORD_REPLACE auto-generates texture coordinates for the surface when enabled, so you can texture-map them with a sphere-shaped RGBA-texture.

EDIT: It seems like you (the poster) is right. Anti-aliased points get rounded with respect to their radius. (I've used OpenGL since 2003, and I didn't know this. [/shame]) So enabling GL_POINT_SMOOTH while you have a multisample-able visual/pixelformat, you get rounded points. Still, multisampling can be slow, so I'd implement both. Textured quads are cheap.

To request a visual with multisampling with XLib, use these two attributes in the list to glXChooseFBConfig():

GLX_SAMPLE_BUFFERS - its value should be True. This is an on/off toggle.
GLX_SAMPLES - the number of samples.

To request a pixelformat with Win32, use these two attributes in the list to ChoosePixelFormat() or wglChoosePixelFormatARB():

WGL_SAMPLE_BUFFERS_ARB Same as above, a toggle.
WGL_SAMPLES_ARB Same as above, the number of samples.

It seem that you can OR in the flag GLUT_MULTISAMPLE to glutInitDisplayMode to get multisampling in GLUT, but you can't request the number of sample buffers.

Here is how alpha-blended quads could be implemented using your test case.

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 

Image of rounded points using per-fragment alpha blending + textures: http://www.mechcore.net/images/gfx/sprite0.png
Image of rounded points by using GL_POINT_SMOOTH and multisampling: http://www.mechcore.net/images/gfx/sprite1.png
A little sample I made which shows both techniques. Requires libSDL and libGLEW to compile:

#include  #include  #include  #include   #include  #include  #include   #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; }  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 >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>1),j-(gridHeight>>1));         }     }     glEnd(); }


回答2:

Mads' answer provides everything you need if you go for the fixed function pipeline. However, if you have a system that does not provide the ARB_point_sprite extension or with a broken implementation (some ATI drivers), you can solve this part also with geometry shaders. The ARB_geometry_shader4 extension allows you to convert a point primitive to two triangles, which can be used as the quad created by the ARB_point_sprite extension. On OpenGL 3.2, geometry shaders are already supported in core, no extension needed. The OpenGL wiki has two examples.



回答3:

Not possible with a fixed opengl function. Dots are always square :)

You have to draw your own circle (by building it up like a cake, piece by piece) or draw a GL_QUAD with a "circle" texture on.

best regards, andre



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!