本教程将学习使用 libGDX 提供的3D API 的基础知识。本教程假设您已经熟悉 libGDX 的基本使用,libGDX的环境搭建可以点击这里查看。 我们创建如下代码:
public class MainGame implements ApplicationListener {
@Override
public void create () {
}
@Override
public void render () {
}
@Override
public void dispose () {
}
@Override
public void resume () {
}
@Override
public void resize (int width, int height) {
}
@Override
public void pause () {
}
}
首先,我们需要添加一个摄像机,摄像机可以从某个角度查看我们创建的3D场景。
public class MainGame implements ApplicationListener {
public PerspectiveCamera cam;
@Override
public void create () {
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(10f, 10f, 10f);
cam.lookAt(0,0,0);
cam.near = 1f;
cam.far = 300f;
cam.update();
}
...
}
上面代码中,我们创建了一个 PerspectiveCamera 摄像机,其视野为67度(这是常用的),并将纵横比设置为当前的宽度和高度。cam.position.set 将摄像机位置设置在坐标为(x=10, y=10, z=10)的位置(10个单位)。Z轴朝向玩家,也即是垂直屏幕。lookAt 将相机设置为朝(0, 0, 0)看,因为这是我们放置3D对象的位置。near 和 far 设置相机的最近和最远的值,以确保始终能看到我们的对象。最后,调用 update 更新相机,使我们所做的所有更改都能被相机反映出来。
现在,让我们往场景添加一些模型。这里我们简单的通过代码来创建一个简单的立方体模型,后面的教程我们在通过 3D 建模软件导出模型来使用。
public class MainGame implements ApplicationListener {
public PerspectiveCamera cam;
public Model model;
public ModelInstance instance;
@Override
public void create () {
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
...
cam.update();
ModelBuilder modelBuilder = new ModelBuilder();
model = modelBuilder.createBox(5f, 5f, 5f,
new Material(ColorAttribute.createDiffuse(Color.GREEN)),
Usage.Position | Usage.Normal);
instance = new ModelInstance(model);
}
@Override
public void dispose () {
model.dispose();
}
...
}
这里我们实例化一个ModelBuilder,它可以用来在代码上创建模型。然后我们创建一个简单的立方体模型,大小为 5x5x5。我们还向其添加了一个带有绿色漫反射颜色的材质,并向模型添加了 Usage.Position 和 Usage.Normal 组件。在创建模型时,Usage.Position是必要的。将Usage.Normal法线添加到长方体中,因此例如,照明可以正常工作。Usage是VertexAttribute的一个子类。
模型包含关于渲染内容的所有内容,并跟踪资源。它不包含渲染模型的位置等信息。因此,我们需要创建一个ModelInstance。ModelInstance包含模型应渲染的位置、旋转和缩放。默认情况下,这是在(0,0,0),所以我们只需创建一个ModelInstance,它应该在(0,0,0)处呈现。
接下来,我们来渲染创建的立方体模型:
public class MainGame implements ApplicationListener {
public PerspectiveCamera cam;
public ModelBatch modelBatch;
public Model model;
public ModelInstance instance;
@Override
public void create () {
modelBatch = new ModelBatch();
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
...
cam.update();
ModelBuilder modelBuilder = new ModelBuilder();
model = modelBuilder.createBox(5f, 5f, 5f,
new Material(ColorAttribute.createDiffuse(Color.GREEN)),
Usage.Position | Usage.Normal);
instance = new ModelInstance(model);
}
@Override
public void render () {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instance);
modelBatch.end();
}
@Override
public void dispose () {
modelBatch.dispose();
model.dispose();
}
...
}
这里我们添加了负责渲染的ModelBatch,并在create方法中对其进行初始化。在render方法中,我们清屏,调用 modelBatch.begin(cam),渲染我们的ModelInstance,然后调用modelBatch.end() 完成渲染。最后,我们需要处理modelBatch,以确保所有资源(如它使用的着色器)都已正确处理。
我们的立方体模型渲染效果出来了,但是看起来怪怪的,我们在渲染模型的时候可以加一个环境灯光:
public class MainGame implements ApplicationListener {
public Environment environment;
...
@Override
public void create () {
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
...
}
@Override
public void render () {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instance, environment);
modelBatch.end();
}
...
}
我们添加一个 Environmen t环境实例。我们构造它并设置环境光为(0.4,0.4,0.4),注意alpha值被忽略。然后我们添加一个方向光,颜色为(0.8,0.8,0.8),方向为(-1.0,-0.8f,0.2)。最后,我们在渲染模型时将环境传递给modelbatch。效果如下:
看起来好多了。libGDX 中我们可以使用自带的一个摄像机控制处理 CameraInputController 来控制我们的摄像机,以便我们可以从其他角度查看模型。
public class MainGame implements ApplicationListener {
...
public CameraInputController camController;
...
@Override
public void create () {
...
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
}
@Override
public void render () {
camController.update();
...
}
...
}
在这里,我们添加了一个CameraInputController,它是我们用cam作为参数创建的。我们还设置了 Gdx.input.setInputProcessor 为此camController,并确保在渲染调用中更新它。这就是添加基本相机控制器的全部内容。现在可以拖动以使相机旋转。