문제
나는 OpenGL과 Glut와 함께 놀기 시작했다. 나는 몇 가지 점을 그려고 싶지만 문제는 그들이 사각형으로 판명되고, 둥근 점 (채워진 원)이되기를 원한다는 것입니다.
이것이 제가하는 것입니다:
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();
}
결과는 다음과 같습니다.
포인트는 예상되는 곳에 나타나고 모양 만 잘못되었습니다.
해결책
이전에 말한 것과 달리, 이것은 고정 기능 파이프 라인에서도 가능합니다. GL_POINTS
OpenGL 1.4 또는 GL_ARB_point_sprite
확대. 이 문서 또는 선택한 OpenGL 코어 사양을 참조하십시오. http://www.opengl.org/registry/specs/arb/point_sprite.txt
GL_ARB_point_sprite
포인트를 "쿼드"로 변환합니다. 즉, 평면 형태의 다각형입니다. 변환되는 정확한 원시 유형은 사양에 의해 정의되지 않지만 중요하지는 않습니다. 중요한 것은 그 것입니다 GL_COORD_REPLACE
활성화 된 경우 표면의 텍스처 좌표를 자동 생성하므로 구 모양의 RGBA 텍스트로 텍스처를 찍을 수 있습니다.
편집 : 당신 (포스터)이 옳은 것 같습니다. 반 알리 아스 포인트는 반경과 관련하여 둥글게됩니다. (2003 년부터 OpenGL을 사용했는데 이것을 몰랐습니다. [/shame]) So enable GL_POINT_SMOOTH
당신은있는 동안 multisample-able
Visual/PixelforMat, 당신은 둥근 포인트를 얻습니다. 그럼에도 불구하고 멀티 샘플링은 느려질 수 있으므로 둘 다 구현합니다. 텍스처 쿼드는 저렴합니다.
xlib로 멀티 샘플링으로 비주얼을 요청합니다,이 두 가지 속성을 목록에 glxchoosefbconfig ()로 사용하십시오.
GLX_SAMPLE_BUFFERS
- 가치가 있어야합니다 True
. 이것은 온/오프 토글입니다.
GLX_SAMPLES
- 샘플 수.
Win32로 pixelforMat을 요청합니다,이 두 가지 속성을 목록에서 선택하십시오.
WGL_SAMPLE_BUFFERS_ARB
위와 동일, 토글.
WGL_SAMPLES_ARB
위와 동일하게 샘플 수.
당신이 깃발을 할 수있는 것 같습니다 GLUT_MULTISAMPLE
에게 glutInitDisplayMode
Glut에서 멀티 샘플링을 얻으려면, 그러나 샘플 버퍼 수를 요청할 수는 없습니다.
테스트 케이스를 사용하여 알파 블렌드 쿼드를 구현하는 방법은 다음과 같습니다.
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();
}
프로 프레이트 알파 블렌딩 + 텍스처를 사용한 둥근 지점의 이미지 :
(원천: mechcore.net)
사용하여 둥근 포인트의 이미지 GL_POINT_SMOOTH
멀티 샘플링 :
(원천: mechcore.net)
두 기술을 모두 보여주는 작은 샘플. 컴파일하려면 libsdl 및 libglew가 필요합니다.
#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();
}
다른 팁
MADS의 답변은 고정 기능 파이프 라인을 찾으면 필요한 모든 것을 제공합니다. 그러나 제공하지 않는 시스템이있는 경우 ARB_point_sprite
확장 또는 구현이 깨진 구현 (일부 ATI 드라이버)을 사용하면 지오메트리 셰이더 로이 부분을 해결할 수 있습니다. 그만큼 ARB_geometry_shader4
Extension은 Point Primitive를 두 개의 삼각형으로 변환 할 수 있으며, 이는 두 개의 삼각형으로 변환 할 수 있습니다. ARB_point_sprite
확대. OpenGL 3.2에서 지오메트리 셰이더는 이미 코어에서 지원되며 확장자가 필요하지 않습니다. Opengl Wiki는 가지고 있습니다 두 가지 예.
고정 된 OpenGL 기능으로는 불가능합니다. 점들은 항상 정사각형입니다 :)
당신은 자신의 원을 그려야합니다 (케이크처럼 조각으로 쌓아서) "원"질감이 켜진 Gl_quad를 그립니다.
안부, 안드레