Можно ли использовать точечные спрайты OpenGL для имитации рекламных щитов? - PullRequest
10 голосов
/ 25 мая 2009

Я пытался установить точечные спрайты в OpenGL для изменения размера с расстоянием так же, как это делал бы билбордный спрайт, но я не могу получить значения в GL_POINT_DISTANCE_ATTENUATION_ARB, чтобы сделать что-нибудь полезное. Существует ли корреляция значений для этого, которая соответствовала бы данной проекции? Возможно ли то, что я пытаюсь сделать?

Используемый код визуализации:

glPointParameterfARB  = (PFNGLPOINTPARAMETERFARBPROC)wglGetProcAddress("glPointParameterfARB");
glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)wglGetProcAddress("glPointParameterfvARB");

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluPerspective(100.0, 800.0/600.0, 0.1, 10.0);

float quadratic[] =  { 5.0f, 0.1f, 10.0f };
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );

float maxSize = 0.0f;
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
if( maxSize > 100.0f )  maxSize = 100.0f;
glPointSize( maxSize );

glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.1f );
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.1f );
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );

glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );

glEnable( GL_POINT_SPRITE_ARB );

glScalef(0.75,1,1);
glTranslatef(0.00,0.0,-1.0);
glScalef(0.5,0.5,0.5);
glRotatef(counter*0.1+0.5,1.0,1.0,0.0);

glBegin( GL_POINTS );

for( int i = 0; i < 100; ++i )
{
    glColor4f( i%10*0.1, i/10*0.1, 0.5, 1.0f );

    glVertex3f( i%10*0.2-1.0,i/10*0.2-1.0,
    ((i%10-5)*(i%10-5)+(i/10-5)*(i/10-5))*0.01 );
}

glEnd();

glDisable( GL_POINT_SPRITE_ARB );

Ответы [ 4 ]

7 голосов
/ 24 июня 2009

Вот как я делаю подход моего бедняка к масштабированию размера точки:

void render() {
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_POINT_SPRITE);
    glActiveTexture(GL_TEXTURE0);
    glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);

    /* Activate shader program here */
    /* Send pointSize to shader program */

    glBegin(GL_POINTS);
        /* Render points here */
        glVertex3f(...);
    glEnd(GL_POINTS);
}

Вершинный шейдер:

uniform float pointSize;
void main() {
    gl_Position = ftransform();
    gl_PointSize = pointSize / gl_Position.w;
}

Вы можете делать все что угодно в фрагментном шейдере, но вам придется самостоятельно вычислять цвет, освещение и текстурирование.

2 голосов
/ 31 марта 2011

GLSL в стороне, делать то, что вы хотите, довольно просто с ослаблением расстояния. Видя, как проецируемый размер вещей уменьшается квадратично с расстоянием в перспективных проекциях, вам нужно использовать только квадратичный коэффициент.

Если вы хотите использовать размер точки, который вы вручную установили на расстоянии, скажем, 150 единиц от глаза, просто используйте 1 / (150 ^ 2) в качестве квадратичного коэффициента (и ноль для постоянных и линейных факторов - - если что, вы можете использовать небольшое число, например 0,01, для постоянного фактора, чтобы избежать потенциального деления на ноль).

1 голос
/ 26 мая 2009

По моему опыту затухание размера точки не стоит хлопот. Вам гораздо лучше написать очень простой вершинный шейдер GLSL, который устанавливает размер точки вручную в соответствии с некоторыми вычислениями, которые вы выполняете самостоятельно. Мне потребовалось около полдня, чтобы выучить с нуля весь GLSL, который мне был нужен, чтобы это произошло.

Код GLSL может быть таким простым, как эти несколько строк:

attribute float psize;

void main()
{   
    gl_FrontColor = gl_Color;
    gl_PointSize = psize;
    gl_Position = ftransform();
}

Где psize - параметр размера точки, который выбирает пользователь.

0 голосов
/ 25 января 2012

Просто посмотрите на pmviewer.sourceforge.net, код использует точечные спрайты, и каждая точка имеет свой цвет и размер для имитации объемного рендеринга Вершинный шейдер:

vertexShader

  // with ATI hardware, uniform variable MUST be used by output
    // variables. That's why win_height is used by gl_FrontColor
    attribute float a_hsml1;
    uniform float win_height;
    uniform vec4 cameralocin;
    void main()
    {
    vec4 position=gl_ModelViewMatrix*gl_Vertex;
    vec4 cameraloc=gl_ModelViewMatrix*cameralocin;
    float d=distance(vec3(cameraloc),vec3(position));
    float a_hsml=gl_Normal.x;
    float pointSize=win_height*a_hsml/d; // <- point diameter in
                                        //pixels (drops like sqrt(1/r^2))
    gl_PointSize=pointSize;
    gl_TexCoord[0]=gl_MultiTexCoord0;
    gl_Position=ftransform();
    gl_FrontColor=vec4(gl_Color.r,gl_Color.g,gl_Color.b,gl_Color.a);
    }

Pixelshader

uniform sampler2D splatTexture;
void main()
{
vec4 color = gl_Color * texture2D(splatTexture, gl_TexCoord[0].st);
gl_FragColor = color;\n"
}

Просто чтобы отправить частицы в gpu:

   void PutOneArrayToGPU(unsigned int m_vbo, float *hArray, unsigned int num)
{
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER,  sizeof(float) * num, hArray, GL_STATIC_DRAW);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
if ((unsigned)size != (sizeof(float) *num))
    {
    fprintf(stderr, "WARNING: Pixel Buffer Object allocation failed!\n");
    fprintf(stderr, "TurningOff the GPU accelerated rendering\n");
    flag_GpuRender=false;
    }
return flag_GpuRender;
}

Затем визуализируйте их:

  void DrawPointsByGPU()
    {
    glEnableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, m_vboPos);
    glVertexPointer(3, GL_FLOAT, 0, 0);

    glEnableClientState(GL_COLOR_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
    glColorPointer(4, GL_FLOAT, 0, 0);

    glEnableClientState(GL_NORMAL_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, m_vboHSML);
    glNormalPointer( GL_FLOAT, 3*sizeof(float), 0);

    glDrawArrays(GL_POINTS, 0, m_numParticles);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...