W przeciwieństwie do tego, co zostało powiedziane wcześniej, jest to możliwe z rurociągu stałej funkcji, nawet z GL_POINTS
prymitywnego rodzaju, tak długo, jak masz wsparcie dla OpenGL 1.4 lub przedłużenia GL_ARB_point_sprite
. Zapoznaj się z tym dokumentem lub z wybraną przez Ciebie specyfikacją rdzeniową OpenGL: http://www.opengl.org/registry/specs/ARB/point_sprite.txt
GL_ARB_point_sprite
zamienia punkty na "kwadraty", tj. Wielokąty o kształcie płaszczyzny. Dokładny typ, dla którego jest konwertowany, nie jest zdefiniowany w specyfikacji, ale nie jest ważny. Ważne jest to, że po włączeniu automatyczne generowanie współrzędnych tekstury dla powierzchni jest możliwe, dzięki czemu można je zamodelować za pomocą tekstury RGBA o kształcie kuli.
EDYCJA: Wygląda na to, że ty (plakat) masz rację. Punkty wygładzone są zaokrąglane zgodnie z ich promieniem. (Używam OpenGL od 2003 roku, a ja o tym nie wiedziałem. [/ Shame]) Włączając GL_POINT_SMOOTH
, gdy masz format wizualny/pikselowy multisample-able
, otrzymujesz zaokrąglone punkty. Mimo to, multisampling może być powolny, więc mógłbym wdrożyć oba. Teksturowane quady są tanie.
zażądać wizualny z wielowzorowość z Xlib, użyj tych dwóch atrybutów w liście do glXChooseFBConfig():
GLX_SAMPLE_BUFFERS
- jego wartość powinna być True
. To jest włączanie/wyłączanie.
GLX_SAMPLES
- liczba próbek.
Aby zażądać PixelFormat z Win32, użyj tych dwóch atrybutów w liście do ChoosePixelFormat() lub (wglChoosePixelFormatARB):
WGL_SAMPLE_BUFFERS_ARB
samo jak wyżej, przełącznik.
WGL_SAMPLES_ARB
Tak jak powyżej, liczba próbek.
Wydaje się, że można lub w flaga GLUT_MULTISAMPLE
do glutInitDisplayMode
uzyskania wielowzorowość w GLUT, ale nie można żądać liczbę buforów próbki.
Oto, w jaki sposób quady z mieszaniem alfa mogą zostać zaimplementowane za pomocą walizki testowej.
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();
}
Obraz zaokrąglonymi punktów, stosując mieszanie alfa + tekstury za-fragment: http://www.mechcore.net/images/gfx/sprite0.png
Obraz zaokrąglonymi punktów za pomocą GL_POINT_SMOOTH
i wielodobieranie: http://www.mechcore.net/images/gfx/sprite1.png
Nieco próbki i wykonany co wskazuje obu technik. Wymaga libSDL i libGLEW skompilować: odpowiedź
#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();
}
Nie wspomniałeś o swojej docelowej platformie. Niektóre funkcje OpenGL (takie jak GL_POINT_SMOOTH) nie są powszechnie obsługiwane. Jeśli zamierzasz, aby aplikacja działała szeroko na kartach wideo klasy konsumenckiej, sprawdź, zanim zdecydujesz się na egzotyczne rozszerzenia. Nawet jeśli wydaje się działać, sprawdź wydajność. To może spowodować przejście do trybu oprogramowania. – Alan
Nie, ale wspomniałem, że po prostu zacząłem grać z OpenGL, podobnie jak hobby;) –
Jeśli chcesz tylko, aby twój kod działał na twoim komputerze, to zrób wszystko, co działa na twoim komputerze. Ale warto też zrozumieć, że główną pułapką OpenGL jest to, że duże części specyfikacji nie będą działać poprawnie na żadnej platformie. Dokładnie to, które to części są bardzo słabo udokumentowanym sekretem. Fallouty w trybie programowym mają tendencję do ukrywania nieobsługiwanych funkcji. – Alan