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/registry/specs/ARB/point_sprite.txt
GL_ARB_point_sprite
convertit les points en « quadriceps », i.e. un polygone avec la forme d'un avion. Le type primitif exact auquel il est converti n'est pas défini par la spécification, bien qu'il ne soit pas important. Ce qui est important, c'est que GL_COORD_REPLACE
génère automatiquement des coordonnées de texture pour la surface lorsqu'il est activé, de sorte que vous pouvez les mapper en texture avec une texture RGBA en forme de sphère.
EDIT: Il semble que vous (l'affiche) a raison. Les points anti-aliasés sont arrondis par rapport à leur rayon. (Je l'ai utilisé OpenGL depuis 2003, et je ne savais pas. [/ Honte]) permettant ainsi GL_POINT_SMOOTH
alors que vous avez un visuel/pixelformat, multisample-able
vous obtenez des points arrondis. Cependant, le multi-échantillonnage peut être lent, donc j'implémenterais les deux. Les quads texturés sont bon marché.
Pour demander un visuel avec multisampling avec XLib, utiliser ces deux attributs dans la liste à glXChooseFBConfig():
GLX_SAMPLE_BUFFERS
- sa valeur doit être True
. C'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 drapeau GLUT_MULTISAMPLE
-glutInitDisplayMode
pour obtenir multiéchantillonnage dans GLUT, mais vous ne pouvez pas demander le nombre de tampons d'échantillons.
Voici comment quads alpha-mélangés pourraient être mis 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 en utilisant par fragment mélange alpha + textures: http://www.mechcore.net/images/gfx/sprite0.png
image de points arrondis en utilisant GL_POINT_SMOOTH
et multiéchantillonnage: http://www.mechcore.net/images/gfx/sprite1.png
Un petit échantillon I fait qui montre les deux 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();
}
Vous n'avez pas mentionné votre plateforme cible. Certaines fonctionnalités OpenGL (comme GL_POINT_SMOOTH) ne sont pas largement supportées. Si vous avez l'intention que votre application fonctionne largement sur des cartes vidéo grand public, assurez-vous de tester avant de vous engager dans des extensions exotiques. Même si cela semble fonctionner, vérifiez la performance. Il peut vous laisser tomber en mode logiciel. – Alan
Non, mais j'ai mentionné que je viens de commencer à jouer avec opengl, un peu comme un passe-temps;) –
Si vous voulez que votre code fonctionne sur votre propre ordinateur, faites tout ce qui fonctionne sur votre ordinateur. Mais il est également utile de comprendre que l'un des principaux inconvénients d'OpenGL est que de grandes parties de la spécification ne fonctionneront pas correctement sur une plate-forme donnée. Les parties exactes sont un secret très mal documenté. Les retards en mode logiciel ont tendance à masquer les fonctionnalités non prises en charge. – Alan