2016-04-14 18 views
0

GLSLシェーダとVBOを使用してメッシュをレンダリングしていますが、VBOには4つの属性が格納されています。 positionXYZ、normalXYZ、textureUV、colourRGBA。 UVを除いてすべてが機能します(おそらく法線もありますが、まだそれらをテストする方法はありません)。テクスチャUVがシェーダに正しく送信されない

何が起こっているのですか、配列のテクスチャUV位置は、配列の通常のxおよびy位置にオフセットされています。配列は途中でVVVNNNTTCCCC(頂点位置、通常、テクスチャ、カラー)として構造化されています。問題がシェーダにVBOを送信するどこかにあることは確かです。私はVBOのデータが正しい順序であることを確かに知っています。

これは私のレンダリングコードです:ジオメトリがあり

#version 400 core 

in vec3 ppVertPosition; 
in vec3 ppVertNormal; 
in vec2 ppVertTexture; 
in vec4 ppVertColour; 

uniform sampler2D texture; 

void main() 
{ 
    gl_FragColor = texture2D(texture, ppVertTexture); 
} 

:バーテックスシェーダ

VBOクラス

public final class Mesh 
{ 
    public static final int FLOAT_SIZE_BYTES = 4; 
    public static final int FLOATS_PER_POSITION = 3; 
    public static final int FLOATS_PER_NORMAL = 3; 
    public static final int FLOATS_PER_TEXTURE = 2; 
    public static final int FLOATS_PER_COLOUR = 4; 
    public static final int VERTEX_SIZE_FLOATS = FLOATS_PER_POSITION + FLOATS_PER_NORMAL + FLOATS_PER_TEXTURE + FLOATS_PER_COLOUR; 
    public static final int VERTEX_SIZE_BYTES = VERTEX_SIZE_FLOATS * FLOAT_SIZE_BYTES; 

    public static final int POSITION_OFFSET_FLOATS = 0; 
    public static final int NORMAL_OFFSET_FLOATS = POSITION_OFFSET_FLOATS + FLOATS_PER_POSITION; 
    public static final int TEXTURE_OFFSET_FLOATS = NORMAL_OFFSET_FLOATS + FLOATS_PER_NORMAL; 
    public static final int COLOUR_OFFSET_FLOATS = TEXTURE_OFFSET_FLOATS + FLOATS_PER_TEXTURE; 
    public static final int POSITION_OFFSET_BYTES = POSITION_OFFSET_FLOATS * FLOAT_SIZE_BYTES; 
    public static final int NORMAL_OFFSET_BYTES = NORMAL_OFFSET_FLOATS * FLOAT_SIZE_BYTES; 
    public static final int TEXTURE_OFFSET_BYTES = TEXTURE_OFFSET_FLOATS * FLOAT_SIZE_BYTES; 
    public static final int COLOUR_OFFSET_BYTES = COLOUR_OFFSET_FLOATS * FLOAT_SIZE_BYTES; 
    public static final int POSITION_STRIDE_BYTES = VERTEX_SIZE_BYTES; 
    public static final int NORMAL_STRIDE_BYTES = VERTEX_SIZE_BYTES; 
    public static final int TEXTURE_STRIDE_BYTES = VERTEX_SIZE_BYTES; 
    public static final int COLOUR_STRIDE_BYTES = VERTEX_SIZE_BYTES; 

    public final static int VERTICES_PER_FACE = 3; 

    public static final int ATTRIBUTE_LOCATION_POSITION = 0; 
    public static final int ATTRIBUTE_LOCATION_NORMAL = 1; 
    public static final int ATTRIBUTE_LOCATION_TEXTURE = 2; 
    public static final int ATTRIBUTE_LOCATION_COLOUR = 3; 

    private int vaoID; 
    private int iboID; 
    private int indexCount; 

    private Mesh(int vaoID, int iboID, int indexCount) 
    { 
     this.vaoID = vaoID; 
     this.iboID = iboID; 
     this.indexCount = indexCount; 
    } 

    public void draw(AbstractShaderProgram shader, Texture texture) 
    { 
     glEnable(GL_TEXTURE_2D); 
     if (texture != null) texture.bind(shader); 
     else Texture.MISSING_TEXTURE.bind(shader); 

     glBindVertexArray(vaoID); 
     glEnableVertexAttribArray(ATTRIBUTE_LOCATION_POSITION); 
//  glEnableVertexAttribArray(ATTRIBUTE_LOCATION_NORMAL); 
//  glEnableVertexAttribArray(ATTRIBUTE_LOCATION_TEXTURE); 
//  glEnableVertexAttribArray(ATTRIBUTE_LOCATION_COLOUR); 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID); 
     glDrawElements(GL_TRIANGLES, indexCount, GL_FLOAT, 0); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

     glDisableVertexAttribArray(ATTRIBUTE_LOCATION_POSITION); 
//  glDisableVertexAttribArray(ATTRIBUTE_LOCATION_NORMAL); 
//  glDisableVertexAttribArray(ATTRIBUTE_LOCATION_TEXTURE); 
//  glDisableVertexAttribArray(ATTRIBUTE_LOCATION_COLOUR); 

     glBindVertexArray(0); 

     glDisable(GL_TEXTURE_2D); 
    } 

    public static Mesh compile(List<Face> faces) 
    { 
     if (faces.size() <= 0) 
      throw new RuntimeException("Failed to compile mesh. No faces were provided."); 

     HashMap<Vertex, Integer> indexMap = new HashMap<>(); 
     ArrayList<Vertex> vertices = new ArrayList<>(); 
     int vertexCount = 0; 


     for (Face face : faces) 
     { 
      for (Vertex vertex : face.getVertices()) 
      { 
       if (!indexMap.containsKey(vertex)) 
       { 
        indexMap.put(vertex, vertexCount++); 
        vertices.add(vertex); 
       } 
      } 
     } 

     int indicesCount = faces.size() * VERTICES_PER_FACE; 

     int dataSize = vertexCount * VERTEX_SIZE_FLOATS; 
     FloatBuffer vertexData = BufferUtils.createFloatBuffer(dataSize); 
     if (vertexData == null) 
      System.err.println("Failed to allocate FloatBuffer with size " + dataSize); 

     for (Vertex vertex : vertices) 
     { 
      vertexData.put(vertex.getPosition().x); 
      vertexData.put(vertex.getPosition().y); 
      vertexData.put(vertex.getPosition().z); 
//   vertexData.put(vertex.getNormal() == null ? 1.0F : vertex.getNormal().x); 
//   vertexData.put(vertex.getNormal() == null ? 1.0F : vertex.getNormal().y); 
//   vertexData.put(vertex.getNormal() == null ? 1.0F : vertex.getNormal().z); 
//   vertexData.put(vertex.getTexture() == null ? 0.0F : vertex.getTexture().x); 
//   vertexData.put(vertex.getTexture() == null ? 0.0F : vertex.getTexture().y); 
//   vertexData.put(vertex.getColour() == null ? 1.0F : vertex.getColour().getRGBA().x); 
//   vertexData.put(vertex.getColour() == null ? 1.0F : vertex.getColour().getRGBA().y); 
//   vertexData.put(vertex.getColour() == null ? 1.0F : vertex.getColour().getRGBA().z); 
//   vertexData.put(vertex.getColour() == null ? 1.0F : vertex.getColour().getRGBA().w); 
     } 
     vertexData.flip(); 

     IntBuffer indices = BufferUtils.createIntBuffer(indicesCount); 

     for (Face face : faces) 
     { 
      for (Vertex vertex : face.getVertices()) 
      { 
       int index = indexMap.get(vertex); 
       indices.put(index); 
      } 
     } 
     indices.flip(); 

     int vaoID = glGenVertexArrays(); 
     glBindVertexArray(vaoID); 

     int vboID = glGenBuffers(); 
     glBindBuffer(GL_ARRAY_BUFFER, vboID); 

     glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW); 

     glVertexAttribPointer(ATTRIBUTE_LOCATION_POSITION, FLOATS_PER_POSITION, GL_FLOAT, false, 0, 0); 
//  glVertexAttribPointer(ATTRIBUTE_LOCATION_NORMAL, FLOATS_PER_NORMAL, GL_FLOAT, false, NORMAL_STRIDE_BYTES, NORMAL_OFFSET_BYTES); 
//  glVertexAttribPointer(ATTRIBUTE_LOCATION_TEXTURE, FLOATS_PER_TEXTURE, GL_FLOAT, false, TEXTURE_STRIDE_BYTES, TEXTURE_OFFSET_BYTES); 
//  glVertexAttribPointer(ATTRIBUTE_LOCATION_COLOUR, FLOATS_PER_COLOUR, GL_FLOAT, false, COLOUR_STRIDE_BYTES, COLOUR_OFFSET_BYTES); 

     glBindBuffer(GL_ARRAY_BUFFER, 0); 
     glBindVertexArray(0); 

     int iboID = glGenBuffers(); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

     return new Mesh(vaoID, iboID, indicesCount); 
    } 
} 

#version 400 core 

in vec3 vertPosition; 
in vec3 vertNormal; 
in vec2 vertTexture; 
in vec4 vertColour; 

uniform mat4 projectionMatrix; 
uniform mat4 viewMatrix; 
uniform mat4 modelMatrix; 

out vec3 pVertPosition; 
out vec3 pVertNormal; 
out vec2 pVertTexture; 
out vec4 pVertColour; 

void main() 
{ 
    pVertPosition = vertPosition; 
    pVertNormal = vertNormal; 
    pVertTexture = vertTexture; 
    pVertColour = vertColour; 

    gl_Position = vec4(vec3(vertPosition.xy + vertTexture, vertPosition.z), 1.0); 
} 

フラグメントシェーダシェイダーのこれらの間には存在しますが、現在は冗長で、情報をフラグメントシェーダにまっすぐに伝えます(outとinの変数が一致しない理由です)。また、フラグメントシェーダの頂点位置にtextureUVが追加された理由は実際に渡されているテクスチャのUV値をデバッグします。これは、UVが通常のxyにオフセットされていることを私が知る方法です。私がテクスチャUVを通常のxyに入れると、それらは完全にうまく動作します。

追加したいコードがある場合は、それを追加します。あまりにも多くのコードがあるので、私はVBOクラス全体など、すべてを追加していません。私は、私が関連していると思われるものと、問題がどこにあるのかを含めただけです。

編集#1: vertPositionvertNormalのようなシェーダ内の可変ロケーションがバインドされています。これは、CT同じ結果\ EXをもたらしそうのように、レイアウトを使用して、頂点シェーダを変更し、それらを

glBindAttribLocation(program, Mesh.ATTRIBUTE_LOCATION_POSITION, "vertPosition"); 
glBindAttribLocation(program, Mesh.ATTRIBUTE_LOCATION_NORMAL, "vertNormal"); 
glBindAttribLocation(program, Mesh.ATTRIBUTE_LOCATION_TEXTURE, "vertTexture"); 
glBindAttribLocation(program, Mesh.ATTRIBUTE_LOCATION_COLOUR, "vertColour"); 

をバインドするために私のコードです。

layout(location = 0) in vec3 vertPosition; 
layout(location = 1) in vec3 vertNormal; 
layout(location = 2) in vec2 vertTexture; 
layout(location = 3) in vec4 vertColour; 

編集#2 は、私はそれの部分だけではなく、メッシュ全体のクラスを投稿することを決めました。 VBOではなくVAOを実装しようとしましたが、動作しません。

答えて

0

標準のパイプライン機能とカスタムシェーダー変数が混在しています。

glEnableClientState(GL_VERTEX_ARRAY);を呼び出すと、OpenGLは特定のデータバインドポイントを使用するように指示します。

glVertexPointer(を呼び出すと、OpenGLにその頂点を見つける場所が示されます。以前は正しいアレイを有効にして以来、すべてが良好です。

次に、頂点シェーダに到達し、in vec3 vertPosition;を使用しますが、GLSLはそこで頂点データを必要としているかどうかわかりません。確かに、名前は "vertPosition"ですが、GLSLはもちろん変数名に基づいて必要なデータを推測する必要はありません!代わりに、GLSLのデフォルトのパイプライン動作では、GL_VERTEX_ARRAYに結び付けられた既成のGLSL変数gl_Vertexを使用します。

なぜポジションでは機能しますか?あなたが定義した変数があらかじめ構築された定数を偶然に割り当てられていることをうかがいます。あなたは何をすべき

は、glEnableVertexAttribArrayglEnableClientStateを切り替えて、各変数に番号を割り当てることLayoutsを使用して、正しいデータにその番号をリンクするglVertexAttribPointerの代わりglVertexPointerを呼んでいます。

vertPositionのように宣言した変数は、偶然ではなく、あなたに指示したので、あなたのバッファ内の正しいデータを指しています!

これは、gl_Vertexのような既成の変数を使用し、glEnableClientStateのような関数を使用する現代のOpenGLで正しい方法は、その柔軟性に欠けると考えられています。

レイアウトを省略することもできます(誰にもないOGL 4+が必要なので)レイアウトを省略することもできますが、シェーダをリンクする前にもう少し作業が必要です。

幸運を祈る!

More info on converting your code

(私は実際にこれが問題であることを確認するためにコメントカント、これでイム権利を願っています)

+0

うーん、されている必要がありますが、それが動作する桁違いの運ではありません。私は 'vertPosition'、' vertNormal'などをバインドしましたが、私はそのコードをその質問に投稿しませんでした。ごめんなさい。私のコードは次のようになります: 'glBindAttribLocation(program、Mesh.ATTRIBUTE_LOCATION_POSITION、" vertPosition ");' – Kelan

+0

ハハ、大丈夫、残念です。クライアントステートを削除し、代わりに 'glEnableVertexAttribArray(Mesh.ATTRIBUTE_LOCATION_POSITION)'を使用することをお勧めします。それでも問題が発生する可能性があります。そしてあなたが指定したインデックスで 'glVertexAttribPointer'を使います。だから、glVertexAttribPointer(Mesh.ATTRIBUTE_LOCATION_POSITION .... ' – TWT

+0

glVertexAttribPointerは、glVertexPointerとそれ以外のものを置き換える必要があります。 – TWT

0

さて、私はそれが最後に...働いてしまいました。私は最初の問題がVBOで何の原因か分かりませんでしたが、VAOを使用するように切り替えてglClientStateでレンダリングしないとうまくいきました。私はVAOはそう、これまでどのようなラインだったものをレンダリングないで持っていた。また、問題:

glDrawElements(GL_TRIANGLES, indexCount, GL_FLOAT, 0); 

が、私はこのコードが含まれていませんでした申し訳ありません

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0); 
関連する問題