2016-04-21 18 views
0

OpenGL 3.3でSuzanne(Blenderから)をレンダリングしようとしていますが、バッファデータが正しくないようです。私が手にこの:glBufferDataとglBufferSubDataオフセット

https://gyazo.com/85c1e87fcc4eab128ca37b1a0cb1deaa

マイ輸入者は、単一のフロートとしてのstd ::ベクトルに頂点データを挿入します。私も、単純なテクスチャーで球をレンダリングしようとした

https://gyazo.com/ab82f9acb6854a49fccc527ed96cc4e8

if(line.substr(0,2) == "v ") 
{ 
/** Vertex position */ 
    std::istringstream s(line.substr(2)); 
    float v[3]; 
    s >> v[0]; s >> v[1]; s >> v[2]; 

    this->vertices.push_back(v[0]); 
    this->vertices.push_back(v[1]); 
    this->vertices.push_back(v[2]); 
} 

私のセットアップは、配列バッファは、次のように

glGenBuffers(1, &this->vbo); 
glBindBuffer(GL_ARRAY_BUFFER, this->vbo); 

glBufferData(GL_ARRAY_BUFFER, 
    sizeof(float)*(this->vertices.size()+this->textures.size()+this->normals.size()), 
    NULL, 
    GL_STATIC_DRAW); 

そして私も同じ方法(もちろんGL_ELEMENT_ARRAY_BUFFER)のインデックスを挿入glBufferSubData

glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*this->vertices.size(), this->vertices.data()); 
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*this->vertices.size(), sizeof(float)*this->textures.size(), this->textures.data()); 
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*(this->vertices.size()+this->textures.size()), sizeof(float)*this->normals.size(), this->normals.data()); 

を使用して実際のデータを挿入します。

私はその情報を指す:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size())); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size()+this->vt.size())); 

マイ頂点シェーダは、このようなデータになります:

layout(location = 0) in vec3 position; 
layout(location = 1) in vec2 texCoord; 
layout(location = 2) in vec3 normals; 

私はオフセットを台無しだろうか?

編集: 私は最大の問題を理解しました。私はobjファイルをインポートしやすいフォーマットに変換する外部のLuaプログラムを書いたが、データを使いこなし、 "f#/#/##/#/##/#/ (x-> y-> z)の代わりにこのファイル(x-> y-> z)のように見えるようにしました。

また、以下の応答のおかげでいくつかのエラーが修正されました!

+0

良いキャッチ!あなたがうまく働くことができてうれしいです。 – Exide

+0

ご協力いただきありがとうございます!すべてが今働いています。 :D私は、メッシュの "ワイヤフレーム"を描いているときに、glPolygonMode(GL_FRONT_AND_BACK、GL_LINE)の代わりにGL_LINE_LOOPを使用していたことに気づきました。したがって、余分な面はメッシュの内側にあります。ここに証拠があります:P https://gyazo.com/928640e745bfe3041798954f3f32079a – sheep

答えて

0

glVertexAttribPointerへのコールが正当なものである場合は、シェーダーが表示されず、100%確実にすることはできません。 1つのVBOでインターリーブされた頂点データを必要としているかどうかもわかりません。あなたが現在持っているのは、最初にすべての頂点位置をパックしてから、すべてのテクスチャ座標をパックし、最後にすべての法線をパックします。

データをインターリーブするには、各頂点がPPPTTNNNパターンを繰り返すように、最初にデータを1つの配列(またはベクトル)に配置します。 PPPが3位浮動小数点である場合、TTは2つのテックスコード浮動小数点であり、NNNは3つの通常浮動小数点です。

それは、この(パターンを説明するのを助けるために偽の種類、値、および間隔を使用して)のようなものになります。

float[] vertices = { 
/* pX, pY, pZ, tX, tY, nX, nY, nZ */ 
    1, 1, 1, 0, 0, 1, 1, 1,  // vertex 1 
    0, 0, 0, 1, 1, 0, 0, 0,  // vertex 2 
    1, 1, 1, 0, 0, 1, 1, 1,  // vertex 3 
    ... 
}; 

あなたがアップロードすることができ、あなたはverticesと呼ばれる単一のベクターにそれをすべて入れましょうを

glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW); 

また、各属性を独自のVBOに入れることもできます。データをGPUに保存する方法は、最終的にはあなた次第です。あなたが故意にデータを保管している場合は、コメントに私に教えてください。私は答えを更新します。

ここで、シェーダビット。

は、あなたがこのようになり、頂点シェーダを持っているとしましょう:

in vec3 position; 
in vec2 texcoord; 
in vec3 normal; 
out vec2 uv; 

void main() { 
    gl_Position = vec4(position, 1); 
    uv = texcoord; 
} 

そして、このようになりますフラグメントシェーダ:

in vec2 uv; 
uniform sampler2D image; 
out vec4 color; 

void main() { 
    color = texture(image, uv); 
} 

その後、あなたは以下のglVertexAttribPointer通話をしたいと思います。

int stride = (3 + 2 + 3) * sizeof(float); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)3); 
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)5); 

各呼び出しの最初のパラメータが異なる数。これは、頂点シェーダ内でそれぞれposition,texcoord,normalに対応します。

テクスチャ座標は通常floatのペア(例:vec2 texcoord)ですので、2番目のパラメータをtexcoord呼び出しの場合は2に変更しました。

最後に、インターリーブされた配列を使用する場合、最後のパラメータは頂点ごとのオフセットのみを指定する必要があります。したがって、それぞれ位置オフセット、テクスチャオフセット、およびノー​​マルオフセットに対して0,3および5が得られます。

これで、あなたはどこにいてもうまくいきます。

詳細については、docs.gl page on glVertexAttribPointerをご覧ください。

+0

お返事ありがとうございます!私はシェイダーで私の質問を更新します! objファイルからデータを取得する方法は、データをインターリーブするのではなく、単にデータを追加する方が簡単です。 – sheep

関連する問題