2011-01-29 6 views
0

私はアンドロイドプラットフォーム上のOpenGL三角形にテクスチャマッピングを適用する正しい方法を理解しようとしています。 私は奇妙な振る舞いを見つけました。テクスチャマッピングは、頂点を指定する順序によって影響を受けるようです。アンドロイドのOpenGLテクスチャマッピングはどのように頂点順に影響を受けますか?

ここに具体的な問題があります。この写真では、テクスチャ、三角形や希望のマッピングを見ることができます:(私は申し訳ありませんが、単一のリンクに2枚の画像を合成しなければならなかった)

combined images

実際のテクスチャ画像は2x2のPNGです。

コードは基本的にレンダラーとモデルの2つのクラスに細分されています。

[...] 
public void onSurfaceCreated(GL10 gl, EGLConfig config) 
{ 
    glDisable(GL_DITHER); 
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer); 
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer); 
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer); 
    gl.glEnable(GL10.GL_LIGHT0); 

    gl.glShadeModel(GL10.GL_SMOOTH); 
    gl.glClearColor(0.0f, 0.5f, 0.5f, 1f); 

    // per rimuovere superfici nascoste 
    gl.glClearDepthf(1.0f); 
    gl.glEnable(GL10.GL_DEPTH_TEST); 
    gl.glDepthFunc(GL10.GL_LEQUAL); 

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 

    // caricamento texture 
    glEnable(GL_TEXTURE_2D); 
    int[] textures = new int[1]; 
    gl.glGenTextures(1, textures, 0); 

    textureId = textures[0]; 
    gl.glBindTexture(GL_TEXTURE_2D, textureId); 

    gl.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    gl.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    gl.glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 

    for (Drawable m : models) { // the models are kept in a Vector 
     if (m.getTextureLoader() != null) 
      m.getTextureLoader().load(gl); 
    } 
} 

  • これは、OpenGLの初期化である

レンダラ(ここで私はまだ完全には理解していなかったことで多くのものがあり、私はちょうど例から、このコードを採用します

ここでフレームレンダリング機能(実際の描画はm.draw(gl)呼び出しで行われます):

public void onDrawFrame(GL10 gl) 
{ 
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, 
      GL_MODULATE); 

    // Clear Screen And Depth Buffer 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
    gl.glLoadIdentity(); 
    gl.glEnable(GL10.GL_LIGHTING); 
    gl.glTranslatef(0.0f, -1.2f, -z); // just a little translation in order to see the complete drawing 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, textureId); 

    gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE); 
    gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE); 

    for (Drawable m : models) { 
     m.draw(gl); 
    } 

    gl.glLoadIdentity(); 
} 
ここ
  • モデル

はモデルクラスです:

public class OneTriangle implements Drawable { 

    Context  context; 
    FloatBuffer textureMappingBuffer; 
    FloatBuffer vertexBuffer; 
    ShortBuffer facesIdxBuffer; 

    public OneTriangle(Context context) { 
     this.context = context; 
     float[] v = { 
       -2, 2, 0, //A 
       2, 2, 0,//B 
       -2, -2, 0 };//C 
    //correct 
    /* 
     short[] idx = {0,1,2}; 
     float[] vt ={ 
       0,0,//red 
       1,0,//green 
       0,1};//yellow 
       */ 

    //wrong 
     short[] idx = {1,2,0}; 
     float[] vt ={ 
       1,0,//green 
       0,1,//yellow 
       0,0//red 
       }; 
     { 
      ByteBuffer vBuf = ByteBuffer.allocateDirect(v.length * Float.SIZE/8); 
      vBuf.order(ByteOrder.nativeOrder()); 
      vertexBuffer = vBuf.asFloatBuffer(); 
      vertexBuffer.put(v); 
      vertexBuffer.position(0); 
     } 

     { 
      ByteBuffer fBuf = ByteBuffer.allocateDirect(idx.length * Short.SIZE/8); 
      fBuf.order(ByteOrder.nativeOrder()); 
      facesIdxBuffer = fBuf.asShortBuffer(); 
      facesIdxBuffer.put(idx); 
      facesIdxBuffer.position(0); 
     } 
     { 
      ByteBuffer vBuf = ByteBuffer.allocateDirect(vt.length * Float.SIZE/8); 
      vBuf.order(ByteOrder.nativeOrder()); 
      textureMappingBuffer = vBuf.asFloatBuffer(); 
      textureMappingBuffer.put(vt); 
      textureMappingBuffer.position(0); 
     } 
    } 

    public void draw(GL10 gl) 
    { 
     glEnableClientState(GL_VERTEX_ARRAY); 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

     glVertexPointer(3, GL_FLOAT, 0, vertexBuffer); 
     glTexCoordPointer(2, GL_FLOAT, 0, textureMappingBuffer); 
     glDrawElements(GL_TRIANGLES, facesIdxBuffer.capacity(), GL_UNSIGNED_SHORT, facesIdxBuffer); 

     glDisableClientState(GL_VERTEX_ARRAY); 
     glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    } 

    public TextureLoader getTextureLoader() 
    { 
     return new AssetTextureLoader(context, "tetraedro.png"); 
    } 

} 

、最終的にはここでプロジェクトに「資産」フォルダからテクスチャファイルを読み込むAssetTextureLoaderクラスは、(の清掃されます退屈な例外処理コード):

public class AssetTextureLoader implements TextureLoader { 
    private Context context; 
    private String filename; 

    public AssetTextureLoader(Context context, String filename) { 
     this.context = context; 
     this.filename = filename; 
    } 

    public void load(GL10 gl) 
    { 
     InputStream is; 
     is = context.getResources().getAssets().open(filename); 
     Bitmap bitmap = BitmapFactory.decodeStream(is); 
     is.close(); 
     Log.d("texture loader", "internal format:" + GLUtils.getInternalFormat(bitmap)+", type: "+GLUtils.getType(bitmap)); 
     GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0); 
     bitmap.recycle(); 
    } 
} 

OneTriangleクラスで見ることができるように、A-B-C順序の頂点と赤 - 緑 - 黄の順のマッピングを基本的にリストするコメント付きの「正しい」初期化があります。そのコードは正しいテクスチャマッピングを生成します。

次に、「間違った」セクションの頂点の順序を変更しようとしました:B-C-Aと緑 - 黄 - 赤。 Aは常に赤にマップされ、Bは緑にマップされ、Cは黄にマップされるため、全く同じ出力を得ることが期待されます。しかし、代わりに私は全く異なる出力を得る。ここで

あなたは2つの出力を見ることができます:

(前の画像の第二部を参照)しかし、それ以上はあります!このようにモデルの初期化をもう一度変更すると:

 //should be wrong but is correct 
     short[] idx = {1,0,2}; 
     float[] vt ={ 
       0,0,//red 
       1,0,//green 
       0,1};//yellow 

..私は正しいマッピングを取得します!実際、idx配列の任意の順序を選択することはできますが、問題はありません.vt配列が特定のr-g-y順序である限り、正しいイメージが得られます。

なぜopenglが私に敵対的なのですか?

非常に長い投稿には申し訳ありませんが、間違い(ある場合)が実装のどこにでも隠れることがあります。

答えて

2

頂点属性(位置、色、テクスチャ座標など)間のマッピングは、属性がそれぞれの配列に現れるので常に1:1です。これは、v i番目の位置が、vtのテクスチャ座標の i番目のテクスチャに常に対応することを意味します。 glDrawElementsに渡されるインデックスは、要素によって定義された頂点を、位置だけでなく、,の頂点属性配列から指定できるようにします。

この動作は、Androidだけでなく、すべてのプラットフォームでOpenGLおよびOpenGL ESに適用されることに注意してください。

+0

ありがとうございました。私はコードの束を書き直さなければならなかったが、今は完全に動作する! – hariseldon78

関連する問題