1. 程式人生 > >openGL之光照1---openGL學習筆記(九)

openGL之光照1---openGL學習筆記(九)

 光的的成分包括三種:

 ①環境光:(ambient)沒有方向,向四周均勻發散,全域性因素。

 ②散射光:(diffuse)具有方向性,根據入射光角度均勻反射開來,物體表面的顏色主要取決於散射光。

 ③鏡面光:(specular)具有很強的方向性。

opneGL中的光照同樣是狀態機,所以要使用光照,就要:

gl.glEnable(GL10.GL_LIGHTING);

在啟用了光照之後,就要對三種光進行設定,如果沒有對任何一種光進行設定的話,我們所繪製的物體將會很難看得清楚,這裡我們先來看全域性環境光。

設定光:gl.glLightModelfv();

兩個引數,第一個為光的型別,第二個為指定光資料的緩衝區。光與顏色類似,都是由r,g,b,a四個值組成,所以,我們要指定光資料的緩衝區

,就要先定義一個數組來指定各個分量的值。

float [] global_ambient = {1,1,1,1};
然後將這個陣列轉換成浮點緩衝區,就是第二個引數了。

為方便觀察,我們設定一個透明的Dialog附在已經寫好的Renderer上面,通過複選按鈕控制是否開啟光照,通過Seekbar控制r,g,b各分量值,如下圖所示:

首先在Layout中畫好xml,然後在Mainactivity中建立一個Dialog:

private void buildDialog() {
    d = new Dialog(this,android.R.style.Theme_Translucent_NoTitleBar_Fullscreen
); d.setContentView(R.layout.light_setting); d.show(); }
注:主題要為透明,不然看不見後面的效果。

然後就需要為複選框和三個seekbar加監聽器了,發現如果一個一個加監聽器很麻煩,所以就要用到反射:

try{
    Class clazz = R.id.class;
Field [] fs = clazz.getDeclaredFields();
CheckBox box = null;
SeekBar bar = null;
    for( Field f : fs ){
        int id = (Integer)f.get
(null); View view = d.findViewById(id); if( view != null ){ if( view instanceof CheckBox ){ box = (CheckBox) view; box.setOnCheckedChangeListener(box1); }else if( view instanceof SeekBar ){ bar = (SeekBar) view; bar.setOnSeekBarChangeListener(bar1); } } } } catch (Exception e) { e.printStackTrace(); }
然後在監聽器中對Checkbox和SeekBar進行處理就OK。

執行效果圖:

附程式碼:

public class MyLightingRenderer extends AbstractRenderer{
    @Override
public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//設定清屏色
gl.glColor4f(1f, 1f, 1f, 1f);//設定繪圖顏色
gl.glMatrixMode(GL10.GL_MODELVIEW);//模型檢視矩陣
gl.glLoadIdentity();//載入單位矩陣
GLU.gluLookAt(gl, 0, 0, 5, 0, 0, 0, 0, 1, 0);//放置眼球位置
gl.glRotatef(xRotate, 1, 0, 0);//x軸旋轉角度
gl.glRotatef(yRotate, 0, 1, 0);//y軸旋轉角度
gl.glClear(GL10.GL_DEPTH_BUFFER_BIT);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glColor4f(1f,1f,1f,1f);
/*********************光照**************************/
if(open_lighting){
            //啟用光照
gl.glEnable(GL10.GL_LIGHTING);
}else{
            //禁止光照
gl.glDisable(GL10.GL_LIGHTING);
}
        float [] global_ambient = {r,g,b,a,};
//設定全域性環境光
gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT,BufferUtils.arr2FloatBuffer(global_ambient));
//畫一個球
BufferUtils.drawSphere(gl,0.4f,8,8);
}
}
public class MainActivity extends Activity {
    private AbstractRenderer renderer;
MyGLSurfaceView view;
    private Dialog d;
    private Resources r;
    protected void onCreate(Bundle savedInstanceState) {
        r = this.getResources();
        super.onCreate(savedInstanceState);
view = new MyGLSurfaceView(this);
//render渲染器
renderer = new MyLightingRenderer();
//        view.setEGLConfigChooser(5,6,5,0,8,8);
view.setRenderer(renderer);
//        view.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//預設渲染模式,持續渲染。
//        view.setRenderMode( GLSurfaceView.RENDERMODE_WHEN_DIRTY );//髒渲染(命令渲染)髒渲染模式下ondrawframe()方法只調用一次。
setContentView(view);
buildDialog();
addCheckBoxEvent();
}

    //新增複選框事件
private void addCheckBoxEvent() {
        //匿名內部類:box監聽
CompoundButton.OnCheckedChangeListener box1 = new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                /*
                //通過反射實現                try {
                    int id = buttonView.getId();
                    String name = r.getResourceName( id );
                    Log.i("xiaoyu",name);
                    name.substring(name.lastIndexOf("_") + 1);
                    Class clazz = renderer.getClass();
                    Field f = clazz.getField(name);
                    f.setAccessible(true);
                    f.set(renderer,isChecked);
                } catch (Exception e) {
                    e.printStackTrace();
                }*/
renderer.open_lighting = isChecked;
}
        };
//seekbar監聽
final SeekBar.OnSeekBarChangeListener bar1 = new SeekBar.OnSeekBarChangeListener(){
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                float scale = (float)progress/(float)seekBar.getMax();
                switch (seekBar.getId()){
                    case R.id.sb_r:
                        renderer.r = scale;
                    case R.id.sb_g:
                        renderer.g = scale;
                    case R.id.sb_b:
                        renderer.b = scale;
}
            }
            public void onStartTrackingTouch(SeekBar seekBar) {

            }
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        };
/**************************利用反射給CheckBox和三個SeekBar加監聽器*********************************/
try {
            Class clazz = R.id.class;
Field [] fs = clazz.getDeclaredFields();
CheckBox box = null;
SeekBar bar = null;
            for( Field f : fs ){
                int id = (Integer)f.get(null);
View view = d.findViewById(id);
                if( view != null ){
                    if( view instanceof CheckBox ){
                        box = (CheckBox) view;
box.setOnCheckedChangeListener(box1);
}else if( view instanceof SeekBar ){
                        bar = (SeekBar) view;
bar.setOnSeekBarChangeListener(bar1);
}
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
}

    }

    private void buildDialog() {
        d = new Dialog(this,android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
d.setContentView(R.layout.light_setting);
d.show();
}


    class MyGLSurfaceView extends GLSurfaceView{

        public MyGLSurfaceView(Context context) {
            super(context);
}

        public MyGLSurfaceView(Context context, AttributeSet attrs) {
            super(context, attrs);
}

        }





}