OpenGLES 1.0 Lighting:镜面光仅照射物体的一侧

时间:2011-12-07 13:53:42

标签: android opengl-es

我正在开发一个带有OpenGLES的Android应用程序,但是当我添加一个镜面光时,该对象只会照亮对象的一侧,而我使用相同的代码和一点点修改,因为过剩而且可以正常工作。

这是我的活动代码

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);
    }
}

瓶类代码

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);
}

}

程序将首先安装灯光然后读取对象arraylist中的数据通过移动-z并在x轴上旋转对象并绘制来进行翻译。

图像应该是过剩的

http://i1187.photobucket.com/albums/z399/GalmTwo/glut_result.png

正如你所看到的那样,它在瓶子两侧闪耀,看起来就像光线位置固定一样

但是在android模拟器中

http://i1187.photobucket.com/albums/z399/GalmTwo/android_result.png

第一个是正确的,但当它翻转到瓶子的另一侧时,它看起来不像光一直在移动,但我非常确定我在变换任何东西之前设置了光位置并且在过剩中它工作正常

请帮我解决这个问题,或者给我一个镜像光的示例代码,可以在android中正常工作我试着整天解决这个问题,但我不能 谢谢你的帮助,抱歉我的英语不好。

0 个答案:

没有答案