Obtenir des points lisses, grands en OpenGL
Question
J'ai commencé à jouer avec OpenGL et GLUT. Je voudrais tirer quelques points, mais le problème est qu'ils se révèlent être des places, et je les aime à être des points ronds (cercles pleins).
Voici ce que je fais:
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();
}
Ceci est le résultat:
Les points où apparaissent attendu, que leur forme ne va pas.
La solution
Contrairement à ce qui a été dit précédemment, cela est possible avec la conduite à fonction fixe, même avec le GL_POINTS
type primitif, aussi longtemps que vous avez le support d'OpenGL 1.4 ou l'extension GL_ARB_point_sprite
. Consultez ce document, ou la spécification de base OpenGL de votre choix: http: // www .opengl.org / registre / spécifications / ARB / point_sprite.txt
GL_ARB_point_sprite
convertit les points en « quad », i.e. un polygone ayant la forme d'un avion. Le type primitif exact où elle est convertie en est pas défini par la spécification, mais il n'a pas d'importance. Ce qui est important est que l'auto-génère GL_COORD_REPLACE
coordonnées de texture pour la surface lorsqu'elle est activée, vous pouvez-carte texture avec une texture RGBA en forme de sphère.
EDIT:. Il semble que vous (l'affiche) est droite Points anticrénelage se arrondi par rapport à leur rayon. (Je l'ai utilisé OpenGL depuis 2003, et je ne savais pas. [/ Honte])
Permettant ainsi GL_POINT_SMOOTH
si vous avez un multisample-able
visuel / pixelformat, vous obtenez des points arrondis. Pourtant, MultiSampling peut être lent, donc je mettre en œuvre à la fois. quadriceps texturés ne coûtent pas cher.
Pour obtenir un visuel avec multiéchantillonnage avec XLib , utiliser ces deux attributs dans la liste à glXChooseFBConfig ():
GLX_SAMPLE_BUFFERS
- sa valeur doit être True
. Ceci est une bascule on / off.
GLX_SAMPLES
-. le nombre d'échantillons
Pour demander une pixelformat avec Win32 , utiliser ces deux attributs dans la liste à ChoosePixelFormat () ou wglChoosePixelFormatARB ():
WGL_SAMPLE_BUFFERS_ARB
comme ci-dessus, une bascule.
WGL_SAMPLES_ARB
comme ci-dessus, le nombre d'échantillons.
Il semble que vous pouvez ou dans le GLUT_MULTISAMPLE
de drapeau glutInitDisplayMode
pour obtenir multiéchantillonnage dans GLUT , mais vous ne pouvez pas demander le nombre de tampons d'échantillons.
Voici comment alpha-quadriceps mélangés pourraient être mises en œuvre en utilisant votre cas de test.
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();
}
Image de points arrondis à l'aide de mélange alpha par fragment + textures:
(source: mechcore.net )
Image de points arrondis à l'aide GL_POINT_SMOOTH
et multiéchantillonnage:
(source: mechcore.net )
Un petit échantillon que je fait qui montre à la fois techniques. LibSDL et nécessite libGLEW à compilent:
#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();
}
Autres conseils
La réponse de Mads fournit tout ce dont vous avez besoin si vous allez pour le pipeline de fonction fixe. Toutefois, si vous avez un système qui ne fournit pas l'extension de ARB_point_sprite
ou avec une mise en œuvre brisée (certains pilotes ATI), vous pouvez résoudre cette partie aussi avec les shaders de géométrie. ARB_geometry_shader4
extension vous permet de convertir un point primitif à deux triangles, qui peuvent être utilisés comme le quad créé par l'extension ARB_point_sprite
. OpenGL 3.2, shaders de géométrie sont déjà pris en charge dans le noyau, aucune extension nécessaire. Le wiki OpenGL a deux exemples .
Pas possible avec une fonction opengl fixe. Les points sont toujours carrés:)
Vous devez dessiner votre propre cercle (en le construisant comme un gâteau, morceau par morceau) ou dessiner une GL_QUAD avec une texture « cercle » sur.
Cordialement, andre