Android OpenGLES 1.0照明:镜面反射光仅照射对象的一侧

Android OpenGLES 1.0照明:镜面反射光仅照射对象的一侧,android,opengl-es,Android,Opengl Es,我正在开发一个带有OpenGLES的android应用程序,但当我添加镜面反射光时,对象只会照射对象的一侧,而我使用相同的代码,并对其进行了一些修改,以适应glut,效果很好 这是我在活动中的代码 private Handler handler = new Handler(); private Handler handlerz = new Handler(); private ArrayList<Bottle> objecttable = new ArrayList<Bottl

我正在开发一个带有OpenGLES的android应用程序,但当我添加镜面反射光时,对象只会照射对象的一侧,而我使用相同的代码,并对其进行了一些修改,以适应glut,效果很好

这是我在活动中的代码

private Handler handler = new Handler();
private Handler handlerz = new Handler();
private ArrayList<Bottle> objecttable = new ArrayList<Bottle>();
private boolean start = true;
//ambientlight color
private float[] amblightcolor = {0.5f,0.5f,0.5f,1};
//diffuselight color
private float[] diflightcolor = {1f,1f,1f,1};
//specularlight color
private float[] specularcolor = {1,1,1,1};
//Position of light
private float[] lightpos = {0.0f,0.0f,1f,0};
//direction of light
private float[] lightdir = { 0.0f, 0.0f, -1.0f };
//FloatBuffer to use from light array
private FloatBuffer ambientlight;
private FloatBuffer diffuselight;
private FloatBuffer specularlight;
private FloatBuffer positionlight;
private FloatBuffer lightdirection;
private Random r = new Random();
private Runnable runnable = new Runnable() {
     public void run() {
        //Make every bottle in list spin more 1 angle for every 50 ms
         for (Bottle b : objecttable){
             b.angle += 1;
             if (b.angle == 360)
                 b.angle = 0;
         }
      handler.postDelayed(this, 50);
     }
};
private Runnable runnablez = new Runnable() {
     public void run() {
    //Make every bottle in list move in z axis and if bottle's z is more than 0 it reset to -10 and random position
     if (!start){
         if (!objecttable.isEmpty())
             for (Bottle b : objecttable){
                 if (b.cz >= 0){
                    float factorx;
                    float factory;
                    if (r.nextBoolean())
                        factorx = r.nextFloat();
                    else
                        factorx = r.nextFloat() *-1;
                    if (r.nextBoolean())
                        factory = r.nextFloat();
                    else
                        factory = r.nextFloat() *-1;
                    b.cx = factorx;
                    b.cy = factory;
                    b.cz = -10;
                 }
                 else
                    //move rate = speed
                     b.cz += b.speed;
             }
     }
      handler.postDelayed(this, 10);
     }
};

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Panel p = new Panel(this);
    p.setRenderer(new Renderer());
    setContentView(p);
    handler.post(runnable);
    handlerz.post(runnablez);
    //Set model to draw from data
    Bottle.setModel(this);
}
public class Panel extends GLSurfaceView{
    public Panel(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
}
public class Renderer implements GLSurfaceView.Renderer{

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // TODO Auto-generated method stub
        GLES10.glShadeModel(GLES10.GL_SMOOTH);
        GLES10.glClearDepthf(1.0f);
        GLES10.glEnable(GLES10.GL_DEPTH_TEST);
        //initial light properties
        initlight();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // TODO Auto-generated method stub
        GLES10.glViewport(0, 0, width, height);
        GLES10.glMatrixMode(GLES10.GL_PROJECTION);
        GLES10.glLoadIdentity();
        GLU.gluPerspective(gl, 45.0f,
                (float) width / (float) height,
                0.1f, 100.0f);
        GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
        GLES10.glLoadIdentity();
    }

    @Override
    public void onDrawFrame(GL10 arg0) {
        // TODO Auto-generated method stub
        // At begining of program
        if (start){
            initDrawing();
            start = false;
        }
        else
            drawobject();
    }
    //Make a list for bottle there are new 5 bottles to add with random position
    private void initDrawing(){
        for (int i=0;i<5;i++){
            float factorx;
            float factory;
            if (r.nextBoolean())
                factorx = r.nextFloat();
            else
                factorx = r.nextFloat() *-1;
            if (r.nextBoolean())
                factory = r.nextFloat();
            else
                factory = r.nextFloat() *-1;
            objecttable.add(new Bottle(factorx,factory,-10-i,(short) (20*i)));
        }
    }
    //initial light properties
    private void initlight(){
        ByteBuffer ambl = ByteBuffer.allocateDirect(amblightcolor.length * 4);
        ambl.order(ByteOrder.nativeOrder());
        ambientlight = ambl.asFloatBuffer();
        ambientlight.put(amblightcolor);
        ambientlight.position(0);

        ByteBuffer difl = ByteBuffer.allocateDirect(diflightcolor.length * 4);
        difl.order(ByteOrder.nativeOrder());
        diffuselight = difl.asFloatBuffer();
        diffuselight.put(diflightcolor);
        diffuselight.position(0);

        ByteBuffer spcl = ByteBuffer.allocateDirect(specularcolor.length * 4);
        spcl.order(ByteOrder.nativeOrder());
        specularlight = spcl.asFloatBuffer();
        specularlight.put(specularcolor);
        specularlight.position(0);

        ByteBuffer lpos = ByteBuffer.allocateDirect(lightpos.length * 4);
        lpos.order(ByteOrder.nativeOrder());
        positionlight = lpos.asFloatBuffer();
        positionlight.put(lightpos);
        positionlight.position(0);

        ByteBuffer ldir = ByteBuffer.allocateDirect(lightdir.length * 4);
        ldir.order(ByteOrder.nativeOrder());
        lightdirection = ldir.asFloatBuffer();
        lightdirection.put(lightdir);
        lightdirection.position(0);

        GLES10.glFrontFace(GLES10.GL_CCW);
        GLES10.glLightfv(GLES10.GL_LIGHT0, GLES10.GL_AMBIENT, ambientlight);
        GLES10.glLightfv(GLES10.GL_LIGHT0, GLES10.GL_DIFFUSE, diffuselight);
        GLES10.glLightfv(GLES10.GL_LIGHT0, GLES10.GL_SPECULAR, specularlight);
        GLES10.glLightfv(GLES10.GL_LIGHT0, GLES10.GL_POSITION, positionlight);
        GLES10.glLightfv(GLES10.GL_LIGHT0, GLES10.GL_SPOT_DIRECTION, lightdirection);
        GLES10.glLightf(GLES10.GL_LIGHT0,GLES10.GL_SPOT_CUTOFF,15.0f);
        GLES10.glMaterialfv(GLES10.GL_FRONT_AND_BACK, GLES10.GL_SPECULAR, specularlight);
        GLES10.glMaterialf(GLES10.GL_FRONT_AND_BACK, GLES10.GL_SHININESS,128);          
    }
    //draw every bottles in list using blend and light effect
    private void drawobject(){
            GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT);
            GLES10.glEnable(GLES10.GL_BLEND);
            GLES10.glBlendFunc (GLES10.GL_SRC_ALPHA, GLES10.GL_ONE_MINUS_SRC_ALPHA);
            GLES10.glEnable(GLES10.GL_LIGHTING);
            GLES10.glEnable(GLES10.GL_COLOR_MATERIAL);
            GLES10.glMaterialfv(GLES10.GL_FRONT_AND_BACK, GLES10.GL_SPECULAR, specularlight);
            GLES10.glMaterialf(GLES10.GL_FRONT_AND_BACK, GLES10.GL_SHININESS,128);
            GLES10.glEnable(GLES10.GL_LIGHT0);
            GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
            GLES10.glEnableClientState(GLES10.GL_NORMAL_ARRAY);
            for(Bottle b : objecttable)
                    b.draw();
            GLES10.glDisableClientState(GLES10.GL_VERTEX_ARRAY);
            GLES10.glDisableClientState(GLES10.GL_NORMAL_ARRAY); 
            GLES10.glDisable(GLES10.GL_BLEND);
            GLES10.glDisable(GLES10.GL_COLOR_MATERIAL);
            GLES10.glDisable(GLES10.GL_LIGHT0);
            GLES10.glDisable(GLES10.GL_LIGHTING);
    }
}
}

该程序将首先安装灯光,然后读取对象阵列列表中的数据,通过移动-z将其平移,并在x轴上旋转对象并绘制

图像应该是这样的过剩

正如你所看到的,它在瓶子的两侧发光,看起来像灯的位置是固定的

但这里是android模拟器

第一个是正确的,但当它翻转到瓶子的另一面时,它不会发光,看起来像光一直在移动,但我非常确定,在转换任何东西之前,我已经设置了灯光位置,并且在过多的情况下,它工作得很好

请帮我解决这个问题,或者给我一个镜面反射光的示例代码,它可以在android中很好地工作。我整天都在试图解决这个问题,但我不能 谢谢你的帮助,很抱歉我的英语不好

public class Bottle {
//center of bottle x , y and z
public float cx;
public float cy;
public float cz;
//Angle of bottle
public short angle = 0;
//bottle's speed to move in z axis
public float speed = 0.02f;
//3D model data
public static FloatBuffer vertexBuffer;
public static FloatBuffer normalBuffer;
//3D model object use to import wavefront model to this object and make it to vertexBuffer and normalBuffer
public static BottleMdl Model;
public Bottle(float x, float y,float z,short ang) {
    cx = x;
    cy = y;
    cz = z;
    angle = ang;
}
//Bottle draw
public void draw(){
    GLES10.glPushMatrix();
    //translate the center of bottle
    GLES10.glTranslatef(cx, cy, cz);
    //Rotate the bottle by angle for making it spin
    GLES10.glRotatef(angle, 1, 0, 0);
    GLES10.glColor4f(0.05f, 0.05f, 0.05f, 0.8f);
    GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);
    GLES10.glNormalPointer(GLES10.GL_FLOAT, 0, normalBuffer);
    GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, Model.numberofvertexs);
    GLES10.glPopMatrix();
}
//Set a model data to vertexbuffer and normalbuffer
public static void setModel(Context context){
    Model = new BottleMdl(context);
    ByteBuffer vbb = ByteBuffer.allocateDirect(Model.vertexs.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(Model.vertexs);
    vertexBuffer.position(0);

    ByteBuffer nbb = ByteBuffer.allocateDirect(Model.normals.length * 4);
    nbb.order(ByteOrder.nativeOrder());
    normalBuffer = nbb.asFloatBuffer();
    normalBuffer.put(Model.normals);
    normalBuffer.position(0);
}