Почему этот пример зеркального освещения Android не работает так, как задумано? - PullRequest
2 голосов
/ 13 декабря 2010

Почему зеркальные блики не отображаются в двоичном коде, создаваемом следующим кодом?

package com.example.helloandroid;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;

public class TestRenderer implements Renderer {
    private FloatBuffer vb;
    private FloatBuffer mab, mdb, msb;

    private FloatBuffer lPos;
    private FloatBuffer lab, ldb, lsb;

    public TestRenderer() {
        vb = ByteBuffer.allocateDirect(24 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vb.put(new float[]{
            110.0f, 240.0f,
            110.0f, 190.0f,
            160.0f, 240.0f,
            160.0f, 190.0f,
            210.0f, 240.0f,
            210.0f, 190.0f,
            110.0f, 290.0f,
            110.0f, 240.0f,
            160.0f, 290.0f,
            160.0f, 240.0f,
            210.0f, 290.0f,
            210.0f, 240.0f});
        vb.position(0);
        mab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mab.put(new float[]{1.0f, 0.0f, 0.0f, 1.0f});
        mab.position(0);
        mdb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mdb.put(new float[]{0.0f, 1.0f, 0.0f, 1.0f});
        mdb.position(0);
        msb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        msb.put(new float[]{0.0f, 0.0f, 1.0f, 1.0f});
        msb.position(0);

        lPos = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        lPos.put(new float[]{160.0f, 240.0f, 10.0f, 1.0f});
        lPos.position(0);
        lab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // THIS WORKS..
        lab.put(new float[]{0.0f, 0.0f, 0.0f, 1.0f});
        lab.position(0);
        ldb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // SO DOES THIS..
        ldb.put(new float[]{0.0f, 0.0f, 0.0f, 1.0f});
        ldb.position(0);
        // BUT NOT THIS
        lsb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        lsb.put(new float[]{1.0f, 1.0f, 1.0f, 1.0f});
        lsb.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        gl.glEnable(GL10.GL_LIGHTING);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_AMBIENT, mab);
        gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_DIFFUSE, mdb);
        gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, msb);

        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lPos);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lab);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, ldb);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lsb);
        gl.glEnable(GL10.GL_LIGHT0);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(0.0f, width, 0.0f, height, -1.0f, 1.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -1.0f);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vb);
        gl.glNormal3f(0.0f, 0.0f, 1.0f);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 6);
        gl.glDrawArrays(GL10.GL_LINE_STRIP, 6, 6);
    }
}

Вот то, что я вижу из кода как есть (только с компонентом зеркального освещения): http://i.imgur.com/4kvIx.png

Только с компонентом окружающего освещения: http://i.imgur.com/80Tjx.png

С компонентом рассеянного освещения: http://i.imgur.com/r5PkO.png

Возможно, интерес представляет то, что параметры zNear / zFar в моем вызове glOrtho, похоже, ничего не обрезают. Правильно ли я настроил сцену, чтобы даже увидеть зеркальное выделение (я пытался расположить источник света около вершины)?

Ответы [ 2 ]

2 голосов
/ 04 марта 2011

OpenGL ES принимает только GL_FRONT_AND_BACK. Смотрите glMaterial здесь

http://www.khronos.org/opengles/sdk/1.1/docs/man/glMaterial.xml

2 голосов
/ 15 декабря 2010

Ну, после того, как я еще несколько часов ударился головой о стену, я выбрал новую идею - запускать код на устройстве, а не только в эмуляторе.Разве вы не знаете, после нескольких настроек, кажется, все работает нормально!

Вот новый пример с внесенными мною изменениями и улучшенная сцена для иллюстрации воспринятой проблемы:

package com.example.helloandroid;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;

public class TestRenderer implements Renderer {
    private int rows;
    private int cols;

    private FloatBuffer vb;
    private FloatBuffer mab, mdb, msb;

    private FloatBuffer lPos;
    private FloatBuffer lab, ldb, lsb;

    public TestRenderer(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;

        vb = ByteBuffer.allocateDirect(4 * (rows - 1) * cols * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        for(int row = 0; row < (rows - 1); ++row)
            for(int col = 0; col < cols; ++col) {
                vb.put(col * 320.0f / (cols - 1)); vb.put((row + 1) * 480.0f / (rows - 1));
                vb.put(col * 320.0f / (cols - 1)); vb.put(row * 480.0f / (rows - 1));
            }
        vb.position(0);
//      vb = ByteBuffer.allocateDirect(24 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
//      vb.put(new float[]{
//          0.0f, 50.0f,
//          0.0f, 0.0f,
//          50.0f, 50.0f,
//          50.0f, 0.0f,
//          100.0f, 50.0f,
//          100.0f, 0.0f,
//          0.0f, 100.0f,
//          0.0f, 50.0f,
//          50.0f, 100.0f,
//          50.0f, 50.0f,
//          100.0f, 100.0f,
//          100.0f, 50.0f});
//      vb.position(0);
        mab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mab.put(new float[]{1.0f, 0.0f, 0.0f, 1.0f});
        mab.position(0);
        mdb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mdb.put(new float[]{0.0f, 1.0f, 0.0f, 1.0f});
        mdb.position(0);
        msb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        msb.put(new float[]{0.0f, 0.0f, 1.0f, 1.0f});
        msb.position(0);

        lPos = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        lPos.put(new float[]{-180.0f, 0.0f, 300.0f, 1.0f});
        lPos.position(0);
        lab = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // THIS WORKS..
        lab.put(new float[]{0.1f, 0.0f, 0.0f, 1.0f});
        lab.position(0);
        ldb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // SO DOES THIS..
        ldb.put(new float[]{0.0f, 0.1f, 0.0f, 1.0f});
        ldb.position(0);
        // BUT NOT THIS
        lsb = ByteBuffer.allocateDirect(4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        lsb.put(new float[]{0.0f, 0.0f, 1.0f, 1.0f});
        lsb.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        gl.glEnable(GL10.GL_LIGHTING);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, mab);
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, mdb);
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, msb);
        gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 128.0f);

        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lPos);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lab);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, ldb);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lsb);
        gl.glEnable(GL10.GL_LIGHT0);

        gl.glDisable(GL10.GL_TEXTURE);
        gl.glFrontFace(GL10.GL_CCW);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
//      gl.glOrthof(0.0f, width, 0.0f, height, -1.0f, 1.0f);
        GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 999.0f, 1001.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        gl.glLoadIdentity();
        gl.glTranslatef(-160.0f, -240.0f, -1000.0f);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vb);
        gl.glNormal3f(0.0f, 0.0f, 1.0f);
        for(int row = 0; row < rows - 1; ++row) {
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 2 * row * cols, 2 * cols);
//          gl.glDrawArrays(GL10.GL_LINE_STRIP, 2 * row * cols, 2 * cols);
        }
//      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 6);
//      gl.glDrawArrays(GL10.GL_LINE_STRIP, 6, 6);
    }

}

Самая большая странность, с которой я столкнулся, - это необходимость переключиться с GL_FRONT на GL_FRONT_AND_BACK, я понятия не имею, почему он не будет работать только с GL_FRONT (или только с GL_BACK, который я также пробовал в случае, если мой перемотка была обратной или что-то в этом роде).

Вот новый пример на эмуляторе: i.imgur.com / ldAND.png

А на реальном устройстве: i.imgur.com / Ukqqm.PNG

...