2016-04-03 1 views
0

この問題で私の頭が痛いです!私は単純な頂点とフラグメントのシェーダを持っていて、古いVaioのラップトップでは完全に(そしてそれでも)動作します。これはパーティクルシステム用で、ポイントスプライトと単一のテクスチャを使用してパーティクルを描画します。新しいGPUでシンプルなGLフラグメントシェーダーが奇妙に動作する

私のデスクトップ上では、はるか新しいグラフィックカード(Nvidia GTX 660)でプログラムを実行すると問題が発生します。私は、テクスチャを無視して単にinColorを渡すように、フラグメントシェーダーに絞り込んだと確信しています。すべてが期待どおりに機能します。

以下に示すように、シェーダの計算にテクスチャを含めると、そのシェーダが使用されている間に描画されたすべてのポイントが、カメラの位置に関係なく画面の中央に表示されます。

Example screenshot attached

あなたは、粒子容疑者シェーダを使用して死、そして右に正しくレンダリングuntextured粒子の全体の混乱を見ることができます。

バーテックスシェーダは、安全のために:

#version 150 core 
in vec3 position; 
in vec4 color; 

out vec4 Color; 

uniform mat4 view; 
uniform mat4 proj; 
uniform float pointSize; 

void main() { 
    Color = color; 
    gl_Position = proj * view * vec4(position, 1.0); 
    gl_PointSize = pointSize; 
} 

そして、私は問題であることを疑うが、実際、なぜ見ることができないフラグメントシェーダ:

#version 150 core 
in vec4 Color; 
out vec4 outColor; 
uniform sampler2D tex; 

void main() { 
    vec4 t = texture(tex, gl_PointCoord); 

    outColor = vec4(Color.r * t.r, Color.g * t.g, Color.b * t.b, Color.a * t.a); 
} 

Untexturedの粒子が同じ頂点シェーダを使います次のフラグメントシェーダ:

#version 150 core 
in vec4 Color; 
out vec4 outColor; 
void main() { 
    outColor = Color; 
} 

メインプログラムにはループ処理があります。SFML w 2つの関数を呼び出し、描画し、更新することができます。任意の時点でGLに触れていないアップデートは、引き分けは次のようになります。

void draw(sf::Window* window) 
{ 
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    sf::Texture::bind(&particleTexture); 

    for (ParticleEmitter* emitter : emitters) 
    { 
     emitter->useShader(); 
     camera.applyMatrix(shaderProgram, window); 
     emitter->draw(); 
    } 

} 

エミッタ - > useShader()エミッタに格納されたシェーダプログラムを指すGLuintを使用してglUseShader(ちょうど呼び出し)であります創造の対象。

camera.applyMatrix():

GLuint projUniform = glGetUniformLocation(program, "proj"); 
glUniformMatrix4fv(projUniform, 1, GL_FALSE, glm::value_ptr(projectionMatrix)); 
... 
GLint viewUniform = glGetUniformLocation(program, "view"); 
glUniformMatrix4fv(viewUniform, 1, GL_FALSE, glm::value_ptr(viewMatrix)); 

エミッタ - >それのentirityに()を描く:

glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    // Build a new vertex buffer object 
    int vboSize = particles.size() * vboEntriesPerParticle; 
    std::vector<float> vertices; 
    vertices.reserve(vboSize); 

    for (unsigned int particleIndex = 0; particleIndex < particles.size(); particleIndex++) 
    { 
     Particle* particle = particles[particleIndex]; 
     particle->enterVertexInfo(&vertices); 
    } 

    // Bind this emitter's Vertex Buffer 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    // Send vertex data to GPU 
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), &vertices[0], GL_STREAM_DRAW); 

    GLint positionAttribute = glGetAttribLocation(shaderProgram, "position"); 
    glEnableVertexAttribArray(positionAttribute); 
    glVertexAttribPointer(positionAttribute, 
     3, 
     GL_FLOAT, 
     GL_FALSE, 
     7 * sizeof(float), 
     0); 

    GLint colorAttribute = glGetAttribLocation(shaderProgram, "color"); 
    glEnableVertexAttribArray(colorAttribute); 
    glVertexAttribPointer(colorAttribute, 
     4, 
     GL_FLOAT, 
     GL_FALSE, 
     7 * sizeof(float), 
     (void*)(3 * sizeof(float))); 

    GLuint sizePointer = glGetUniformLocation(shaderProgram, "pointSize"); 
    glUniform1fv(sizePointer, 1, &pointSize); 

    // Draw 
    glDrawArrays(GL_POINTS, 0, particles.size()); 

そして最後に、粒子 - > enterVertexInfo()

vertices->push_back(x); 
vertices->push_back(y); 
vertices->push_back(z); 
vertices->push_back(r); 
vertices->push_back(g); 
vertices->push_back(b); 
vertices->push_back(a); 

を私はこれがすべてこれを行う効率的な方法ではないと確信していますが、これは私が1学期前に書いた授業の一部でした。私は実際にそのビデオを録画するために再訪しています。

すべてのシェーダがエラーなしでコンパイルおよびリンクされます。フラグメントシェーダで再生することで、gl_PointCoordを使用してパーティクル全体の単色を変えることができることが確認されているので、期待どおりに動作しています。パーティクルが画面の中央に描画されると、間違った場所にあるにもかかわらず、テクスチャが正しく描画され、正しくロードされてバインドされます。私は決してGL専門家ではないので、それは私が自分自身でやると思うほどのデバッグです。

これは古いノートパソコンではうまく動作しなかった場合、これはあまり迷惑にならないでしょう!

編集:コード

+0

私の賭けは依然としてクライアント側で未定義の動作になります。フラグメントシェーダの変更によって、unfiromの場所が変更されたり、属性の場所さえ変更される可能性もあります。ユニフォームとアトリビュートの設定のコードも投稿してください。 – derhass

+0

属性やユニフォームに関連するすべてのコードが含まれていると思いますが、シェイダーで遊んでいる間は、入力変数や出力変数には触れていません。新しいバグを導入しないようにしました。私が投稿したコードのすべての議論が何をしているかを覚えていないことを認めます。 –

+0

これまでのコードはOKです。しかし、テクスチャを持たないテクスチャには異なるシェーダを使用しているとします。つまり、両方のプログラム間で属性と均一な位置が混乱する可能性があります。 – derhass

答えて

1

としてのトンを含まは、カメラ関連の制服を設定するために使用したshaderProgram変数が使用されて実際のプログラムに依存しない、コメントで判明しました。その結果、テクスチャ化されたパーティクルを描画するときに、異なるプログラムに対して一様な場所が照会されました。

均一な場所の割り当てが完全に実装固有のもの、例えばNVIDIAはtexが実際に存在する(およびacttively使用される)であるかどうかそうviewの位置が依存して変化するであろう、均一な名前のアルファベット順に割り当てる傾向があります。他のインプリメンテーションでコードやその他のスキームに表示されている順序で割り当てられただけの場合は、偶然に動作する可能性があります。

関連する問題