2009-05-25 10 views
10

ビルボードのスプライトと同じように、OpenGLでポイントスプライトを距離を使って変更しようとしていましたが、便利なことを行うにはGL_POINT_DISTANCE_ATTENUATION_ARBの値を取得できません。与えられた投影と一致する値の相関関係はありますか?私がしようとしていることは可能なのでしょうか?OpenGLポイントスプライトを使用して、広告板のスプライトをシミュレートすることはできますか?

が使用されているコードをレンダリング:私の経験ポイントサイズ減衰で

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

答えて

7

は、ここで私はポイントサイズを拡大縮小への私の貧乏人のアプローチを作る方法ですあなた自身の色、照明、テクスチャーを計算しなければなりません。

1

はトラブルの価値はありません。非常に単純なGLSL頂点シェーダを書く方がはるかに優れています。これは、自分で実行する計算に応じて手動でポイントサイズを設定します。これを実現するために必要なすべてのGLSLをゼロから学ぶためには、私は半日ほどかかりました。

GLSLコードは、これらの数行のように単純であってもよい:psizeは、ユーザが選択したポイントサイズパラメータである

attribute float psize; 

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

。あなたはフラグメントシェーダでやりたいが、あなた'LLでき

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

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

頂点シェーダ:

2

GLSLを脇に、遠くの減衰でかなりシンプルです。透視投影の投影距離が2次的にどのように縮小するかを見ると、2次の係数を使用するだけです。

視点から150単位離れた場所に手動で設定したポイントサイズを使用する場合は、2次要素として1 /(150^2)を使用します(定数と線形要素 - 何かがある場合は、潜在的な除算をゼロで避けるために、定数の場合は0.01のような小さな数値を使用することができます)。

0

だけでコードがポイントスプライトを使用しており、各ポイントは、ボリュームレンダリングをシミュレートするために、独自のカラーとサイズを持っている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" 
} 
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); 

    }; 
ただ、GPUに粒子を送信する
関連する問題