博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
libgdx 3D 渲染优化
阅读量:5942 次
发布时间:2019-06-19

本文共 17246 字,大约阅读时间需要 57 分钟。

原文地址: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
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 @Override125 public void dispose () {126 modelBatch.dispose();127 instances.clear();128 assets.dispose();129 }130 131 @Override132 public void resize(int width, int height) {133 stage.getViewport().update(width, height, true);134 }135 136 @Override137 public void pause() {138 }139 140 @Override141 public void resume() {142 }143 }
View Code

以上代码中,关键部分是isVisible函数,该函数中计算了物件位置是否是在可视范围内。

这种算法稍稍有点瑕疵,运行即可看出效果。如果一个物件的位置不在可视范围内,但是此物件有一角却在,常理来说是应该显示的,而实际却没有显示出来。

上代码吧:

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 FrustumCullingTest implements ApplicationListener { 28     protected PerspectiveCamera cam; 29     protected CameraInputController camController; 30     protected ModelBatch modelBatch; 31     protected AssetManager assets; 32     protected Array
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 = 30f;//视角最远 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 GameObject shipInstance = new GameObject(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 GameObject 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 GameObject instance) {120 instance.transform.getTranslation(tempPosition);121 tempPosition.add(instance.center);122 return cam.frustum.boundsInFrustum(tempPosition, instance.dimensions);123 }124 125 @Override126 public void dispose () {127 modelBatch.dispose();128 instances.clear();129 assets.dispose();130 }131 132 @Override133 public void resize(int width, int height) {134 stage.getViewport().update(width, height, true);135 }136 137 @Override138 public void pause() {139 }140 141 @Override142 public void resume() {143 }144 145 146 147 public static class GameObject extends ModelInstance {148 public final Vector3 center = new Vector3();149 public final Vector3 dimensions = new Vector3();150 151 private final static BoundingBox bounds = new BoundingBox();152 153 public GameObject(Model model) {154 super(model);155 calculateBoundingBox(bounds);156 center.set(bounds.getCenter());157 dimensions.set(bounds.getDimensions());158 }159 }160 }

这个怎么算的,其实我想说:呵呵!我也不懂!!!谁整明白了请告诉我啊~

估计是看见一点就显示吧。反正是打到我们想要的效果了。

原文作者提到,当物件旋转时,可能会出现问题。贴一下原作最后的代码:

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 FrustumCullingTestC implements ApplicationListener { 28     protected PerspectiveCamera cam; 29     protected CameraInputController camController; 30     protected ModelBatch modelBatch; 31     protected AssetManager assets; 32     protected Array
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 = 30f;//视角最远 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 GameObject shipInstance = new GameObject(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 GameObject 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 GameObject instance) {120 instance.transform.getTranslation(tempPosition);121 tempPosition.add(instance.center);122 return cam.frustum.sphereInFrustum(tempPosition, instance.radius);123 }124 125 @Override126 public void dispose () {127 modelBatch.dispose();128 instances.clear();129 assets.dispose();130 }131 132 @Override133 public void resize(int width, int height) {134 stage.getViewport().update(width, height, true);135 }136 137 @Override138 public void pause() {139 }140 141 @Override142 public void resume() {143 }144 145 146 147 public static class GameObject extends ModelInstance {148 public final Vector3 center = new Vector3();149 public final Vector3 dimensions = new Vector3();150 public final float radius;151 152 private final static BoundingBox bounds = new BoundingBox();153 154 public GameObject(Model model) {155 super(model);156 calculateBoundingBox(bounds);157 center.set(bounds.getCenter());158 dimensions.set(bounds.getDimensions());159 radius = dimensions.len() / 2f;160 }161 }162 }

 

注:以上代码我都有改过,比如GameObject的构造方法。会不会有问题我真不清楚。

另外还有两点:

1. Camera的far属性能够影响可视范围,不要忘了。

2. far边缘像是被刀切了一样,一条线,far越近越明显,是否有办法根据物件和摄像机位置再次筛选是否渲染呢?

far是一条直线,摄像机正对的中点看得更远一下可能更真实。

转载于:https://www.cnblogs.com/hanhongmin/p/3866305.html

你可能感兴趣的文章
Dominating Patterns
查看>>
diamond types are not supported at this language level
查看>>
C++ BigInt模板手打
查看>>
解决方案、项目、程序集、命名空间
查看>>
Java温故而知新(1)集合类
查看>>
使用T2表中的值替换T1表的值
查看>>
以sysdba身份登录oracle报ORA-1031权限不足错误之完美分析
查看>>
mac navicat premium 使用技巧
查看>>
default.html
查看>>
课本学习笔记5:第七章 20135115臧文君
查看>>
C# 导出word文档及批量导出word文档(2)
查看>>
最大子数组
查看>>
网站(陆续更新)
查看>>
17个提升iOS开发效率的神器
查看>>
android 3.0+百度地图api地图如何移动到指定的经纬度处
查看>>
点权生成树(gentree)
查看>>
[POJ 3270]Cow Sorting
查看>>
Mysql分析-profile详解
查看>>
WebServiceHost 在ConsoleApplication中使用时添加命名空间添加不上,报错
查看>>
《蚁贼》
查看>>