A diferencia de lo que se dijo anteriormente, esto es posible con la tubería de función fija, incluso con el tipo primitivo GL_POINTS
, siempre y cuando usted tiene soporte para OpenGL 1.4 o la extensión GL_ARB_point_sprite
. Consulte este documento, o la especificación OpenGL núcleo de su elección: http://www.opengl.org/registry/specs/ARB/point_sprite.txt
GL_ARB_point_sprite
convierte puntos en "quads", es decir un polígono con la forma de un plano. El tipo primitivo exacto al que se convierte no está definido por la especificación, aunque no es importante. Lo que es importante es que GL_COORD_REPLACE
autogenera coordenadas de textura para la superficie cuando está habilitada, por lo que puede texturizarlas con una textura RGBA esférica.
EDITAR: Parece que usted (el póster) tiene razón. Los puntos antialias se redondean con respecto a su radio. (He usado OpenGL desde 2003, y no lo sabía. [/ Vergüenza]) Habilitando GL_POINT_SMOOTH
mientras tiene un formato visual/pixel multisample-able
, obtiene puntos redondeados. Aún así, la multimuestreo puede ser lenta, así que implementaría ambos. Los cuádriceps con textura son baratos.
Para solicitar una visual con multisampling con XLIB, utilice estos dos atributos de la lista para glXChooseFBConfig():
GLX_SAMPLE_BUFFERS
- su valor debe ser True
. Esta es una palanca de encendido/apagado.
GLX_SAMPLES
- el número de muestras.
Para solicitar una PixelFormat con Win32, utilice estos dos atributos de la lista para ChoosePixelFormat() o wglChoosePixelFormatARB():
WGL_SAMPLE_BUFFERS_ARB
Igual que el anterior, un conmutador.
WGL_SAMPLES_ARB
Igual que el anterior, el número de muestras.
que parezca que pueda O en la bandera GLUT_MULTISAMPLE
a glutInitDisplayMode
para obtener multisampling en GLUT, pero no se puede solicitar el número de buffers de muestra.
Así es como los cuádriceps alfa-combinados podrían implementarse utilizando su caso de prueba.
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();
}
Imagen de puntos redondeados utilizando alpha de mezcla per-fragmento + texturas: http://www.mechcore.net/images/gfx/sprite0.png
Imagen de puntos redondeados utilizando GL_POINT_SMOOTH
y multisampling: http://www.mechcore.net/images/gfx/sprite1.png
una pequeña muestra hice que muestra ambas técnicas. Requiere libSDL y libGLEW para compilar: Respuesta
#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();
}
No mencionó cuál es su plataforma de destino. Algunas características de OpenGL (como GL_POINT_SMOOTH) no son ampliamente compatibles. Si tiene la intención de que su aplicación se ejecute ampliamente en tarjetas de video de consumo, asegúrese de realizar pruebas antes de comprometerse con extensiones exóticas. Incluso si parece funcionar, verifica el rendimiento. Puede dejarte caer al modo de software. – Alan
No, pero mencioné que recién comencé a jugar con OpenGL, como un hobby;) –
Si solo quiere que su código se ejecute en su propia computadora, haga lo que sea que funcione en su computadora. Pero también es valioso entender que un gran escollo de OpenGL es que grandes partes de la especificación no funcionarán correctamente en una plataforma determinada. Exactamente qué partes son estos es un secreto muy mal documentado. Los retrocesos en modo software tienden a oscurecer las funciones no compatibles. – Alan