2

Android の OpenGL ライティングで直面している興味深い問題を調べています。私は、3D オブジェクトを追加および操作できる 3D Viewer に取り組んでいます。さまざまな属性を持つライトを設定することもできます。Viewer で直面していた問題は、ライト (ポイント ライト) からの 3D オブジェクトのハイライトが奇妙な動作をすることでした。光源がカメラとまったく同じポイントにある場合、ハイライトは予想とは反対の方向に移動します。(したがって、オブジェクトを左に移動すると、ハイライトはオブジェクトの右端ではなく左端にも移動します。これは私が期待していたものです。)

ハイライトは左下にありますが、右側にあると思います

そこで、問題をさらに絞り込むために、正方形のみをレンダリングする小さなサンプル アプリケーションを作成し、その正方形をカメラ位置 (原点) を中心に回転させます。これは、ライトが配置される場所でもあります。これにより、すべての正方形がカメラに直接面するようになり、完全に強調表示されます。結果は次のようになりました。

点灯

これらのアーティファクトは、投影によって境界線に歪みが生じたために発生するのでしょうか?

最初の画像では、球体とカメラの間の距離は約 20 単位で、球体のサイズは約 2 です。ライトをオブジェクトに近づけると、期待どおりにハイライトがよりよく見えます。 . 2 番目のイメージでは、正方形が配置されている半径は 25 単位です。Android 3.1でOpenGL ES 1.1を使用しています(ES 2.0のシェーダーで動作させるのに苦労していたため)

ここに私が使用しているコードの一部があります:

public void onDrawFrame(GL10 gl) {
    // Setting the camera
    GLU.gluLookAt(gl, 0, 0, 0, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    for (int i = 0; i < 72; i++) {
        gl.glPushMatrix();
        gl.glRotatef(5f * i, 0, 1, 0);
        gl.glTranslatef(0, 0, -25);
        draw(gl);
        gl.glPopMatrix();
    }
}

public void draw(GL10 gl) {
    setMaterial(gl);
    gl.glEnable(GL10.GL_NORMALIZE);
    gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    gl.glFrontFace(GL10.GL_CCW);

    // Enable the vertex and normal state
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
    gl.glNormalPointer(GL10.GL_FLOAT, 0, mNormalBuffer);

    gl.glDrawElements(GL10.GL_TRIANGLES, mIndexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, mIndexBuffer);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);

}

// Setting the light
private void drawLights(GL10 gl) {
    // Point Light
    float[] position = { 0, 0, 0, 1 };
    float[] diffuse = { .6f, .6f, .6f, 1f };
    float[] specular = { 1, 1, 1, 1 };
    float[] ambient = { .2f, .2f, .2f, 1 };

    gl.glEnable(GL10.GL_LIGHTING);
    gl.glEnable(GL10.GL_LIGHT0);
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();

    gl.glLightfv(GL10.GL_LIGHT0, GL_POSITION, position, 0);
    gl.glLightfv(GL10.GL_LIGHT0, GL_DIFFUSE, diffuse, 0);
    gl.glLightfv(GL10.GL_LIGHT0, GL_AMBIENT, ambient, 0);
    gl.glLightfv(GL10.GL_LIGHT0, GL_SPECULAR, specular, 0);
}

private void setMaterial(GL10 gl) {
    float shininess = 30;
    float[] ambient = { 0, 0, .3f, 1 };
    float[] diffuse = { 0, 0, .7f, 1 };
    float[] specular = { 1, 1, 1, 1 };

    gl.glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse, 0);
    gl.glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient, 0);
    gl.glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular, 0);
    gl.glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
}   

アクティビティが開始されたとき(onSurfaceCreatedで)、最初にライトを設定し、正方形を描くたびにマテリアルを設定しています。

4

2 に答える 2

1

2番目の例(四角形)の効果は、OpenGLが使用するデフォルトの非ローカルビューアによるものです。デフォルトでは、目空間のビュー ベクトル (鏡面ハイライトの計算に使用される頂点からカメラへのベクトル) は、正規化された頂点位置ではなく、(0, 0, 1) ベクトルと見なされます。この近似は、頂点が画面の中央にある場合にのみ正しくなりますが、画面の境界に近づくほど不正確になります。

これを変更して、OpenGL が頂点からカメラまでの実数ベクトルを使用できるようにするには、glLightModel関数を使用します。

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

これが最初の問題 (球体) の原因でもあるかどうかはわかりませんが、試してみてください。

編集:GL_LIGHT_MODEL_LOCAL_VIEWER OpenGL ES では使用できないようです。この場合、もちろん、OpenGL ES 2.0 に切り替えてすべての照明計算を自分で行う以外に、この問題を回避する方法はありません。

于 2011-11-09T13:39:47.750 に答える
0

オブジェクトを動かしているとき、おそらくライトも動いています。

この回答を見てください http://www.opengl.org/resources/faq/technical/lights.htm#ligh0050

于 2011-11-09T11:48:53.310 に答える