原文地址:http://blog.xoppa.com/3d-frustum-culling-with-libgdx/
非翻译,详细内容请见原文,捡点我能理解的说说吧~
关于矩阵之类的知识可以看一下 http://www.cppblog.com/lovedday/archive/2008/01/09/40813.html 我也不懂~~
渲染3D场景的时候,可见物件的数量要远远小于物件总数。
试想,在铺了一地地砖的时候,视角对着天,这时候需要渲染的地砖就没有了。摄像机照不到的地方,完全没有必要渲染。
只渲染可视视角范围内的物件,对于性能的提升是很大的。
直接上测试代码:
1 package com.mygdx.game; 2 3 import com.badlogic.gdx.ApplicationListener; 4 import com.badlogic.gdx.Gdx; 5 import com.badlogic.gdx.assets.AssetManager; 6 import com.badlogic.gdx.graphics.Camera; 7 import com.badlogic.gdx.graphics.Color; 8 import com.badlogic.gdx.graphics.GL20; 9 import com.badlogic.gdx.graphics.PerspectiveCamera; 10 import com.badlogic.gdx.graphics.g2d.BitmapFont; 11 import com.badlogic.gdx.graphics.g3d.Environment; 12 import com.badlogic.gdx.graphics.g3d.Model; 13 import com.badlogic.gdx.graphics.g3d.ModelBatch; 14 import com.badlogic.gdx.graphics.g3d.ModelInstance; 15 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; 16 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight; 17 import com.badlogic.gdx.graphics.g3d.utils.CameraInputController; 18 import com.badlogic.gdx.math.Vector3; 19 import com.badlogic.gdx.math.collision.BoundingBox; 20 import com.badlogic.gdx.scenes.scene2d.Stage; 21 import com.badlogic.gdx.scenes.scene2d.ui.Label; 22 import com.badlogic.gdx.utils.Array; 23 24 /** 25 * Created by HanHongmin on 14-7-24. 26 */ 27 public class FrustumCullingTestA implements ApplicationListener { 28 protected PerspectiveCamera cam; 29 protected CameraInputController camController; 30 protected ModelBatch modelBatch; 31 protected AssetManager assets; 32 protected Array<ModelInstance> instances = new Array(); 33 protected Environment environment; 34 protected boolean loading; 35 36 protected Stage stage; 37 protected Label label; 38 protected BitmapFont font; 39 protected StringBuilder stringBuilder; 40 private Vector3 tempPosition = new Vector3(); 41 42 @Override 43 public void create () { 44 stage = new Stage(); 45 font = new BitmapFont(); 46 label = new Label(" ", new Label.LabelStyle(font, Color.WHITE)); 47 stage.addActor(label); 48 stringBuilder = new StringBuilder(); 49 50 modelBatch = new ModelBatch(); 51 environment = new Environment(); 52 environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f)); 53 environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f)); 54 55 cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); 56 cam.position.set(0f, 7f, 10f); 57 cam.lookAt(0,0,0); 58 cam.near = 1f; 59 cam.far = 300f; 60 cam.update(); 61 62 camController = new CameraInputController(cam); 63 Gdx.input.setInputProcessor(camController); 64 65 assets = new AssetManager(); 66 assets.load("data/box.g3db", Model.class); 67 assets.load("data/box2.g3db", Model.class); 68 loading = true; 69 } 70 71 private void doneLoading() { 72 Model t1 = assets.get("data/box.g3db", Model.class); 73 Model t2 = assets.get("data/box2.g3db", Model.class); 74 75 for(int i=0;i<100;i++){ 76 for(int j=0;j<100;j++){ 77 Model t; 78 if((i+j)%2==0){ 79 t = t1; 80 }else{ 81 t=t2; 82 } 83 ModelInstance shipInstance = new ModelInstance(t); 84 shipInstance.transform.setToTranslation(i, j, 0);//设置位置 85 instances.add(shipInstance); 86 } 87 } 88 89 loading = false; 90 } 91 92 private int visibleCount; 93 @Override 94 public void render () { 95 if (loading && assets.update()) 96 doneLoading(); 97 camController.update(); 98 99 Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); 100 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 101 102 modelBatch.begin(cam); 103 visibleCount = 0; 104 for (final ModelInstance instance : instances) { 105 if (isVisible(cam, instance)) { 106 modelBatch.render(instance, environment); 107 visibleCount++; 108 } 109 } 110 modelBatch.end(); 111 112 stringBuilder.setLength(0); 113 stringBuilder.append(" FPS: ").append(Gdx.graphics.getFramesPerSecond()); 114 stringBuilder.append(" Visible: ").append(visibleCount); 115 label.setText(stringBuilder); 116 stage.draw(); 117 } 118 119 protected boolean isVisible(final Camera cam, final ModelInstance instance) { 120 instance.transform.getTranslation(tempPosition);//把位置信息放到tempPosition中 121 return cam.frustum.pointInFrustum(tempPosition);//frustum平截头体,表示的就是可视范围 122 } 123 124 @Override 125 public void dispose () { 126 modelBatch.dispose(); 127 instances.clear(); 128 assets.dispose(); 129 } 130 131 @Override 132 public void resize(int width, int height) { 133 stage.getViewport().update(width, height, true); 134 } 135 136 @Override 137 public void pause() { 138 } 139 140 @Override 141 public void resume() { 142 } 143 }