【问题标题】:Is it possible to use OpenGL point sprites to simulate billboard sprites?是否可以使用 OpenGL 点精灵来模拟广告牌精灵?
【发布时间】:2010-10-28 19:26:03
【问题描述】:

我试图在 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 );

【问题讨论】:

    标签: opengl point-sprites


    【解决方案1】:

    这是我如何使我的穷人缩放点大小的方法:

    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】:

      抛开 GLSL 不谈,使用距离衰减做你想做的事非常简单。在透视投影中看到事物的投影尺寸如何随着距离的二次方减小,您只需要使用二次因子即可。

      如果您想在距眼睛 150 个单位的距离处使用手动设置的点大小,只需使用 1/(150^2) 作为二次因子(常数和线性因子为零 - - 如果有的话,您可能希望使用一些小的数字(例如 0.01)作为常数因子,以避免潜在的被零除)。

      【讨论】:

        【解决方案3】:

        根据我的经验,点大小衰减不值得麻烦。您最好编写一个非常简单的 GLSL 顶点着色器,根据您自己执行的一些计算手动设置点大小。我花了大约半天的时间从头开始学习实现这一目标所需的所有 GLSL。

        GLSL 代码可能只有这几行代码:

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

        其中psize 是用户选择的磅值参数。

        【讨论】:

          【解决方案4】:

          看看 pmviewer.sourceforge.net 的代码是使用点精灵,每个点都有自己的颜色和大小来模拟体积渲染: 顶点着色器是:

          顶点着色器

            // 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);
              }
          

          像素着色器

          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);
          
              };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-04-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-07
            相关资源
            最近更新 更多