openGL之光照1---openGL學習筆記(九)
阿新 • • 發佈:2019-02-17
光的的成分包括三種:
①環境光:(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然後在監聽器中對Checkbox和SeekBar進行處理就OK。(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(); }
執行效果圖:
附程式碼:
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); } } }