libgdx - 对于SpriteBatch中setProjectionMatrix() 的理解

在编程过程中,遇到了一个函数SpriteBatch::setProjectionMatrix(OrthographicCamera.combined)。经过一番搜索,终于理解了他的含义。这里保留一些信息,以便以后参考。

一 和 二 只是为了理解这个函数做了一些简单的铺垫。


一, 关于正交投影和透视投影

我们的世界是个立体的世界,但并不是所有的媒介都可以把我们看到的立体图像表现出来。

可以表现为正交投影,比如相机拍照片,它展现出来的是一个平面的二维的效果。

我们也可以用透视投影的方式,按照人眼观察事物的原则,例如近处大,远处小的方式,来画透视图。


它与我们的观察方式(视角  camera)有很大的关系,在libgdx定义了两种Camera

OrthographicCamera(正交) 和 PerspectiveCamera(透视)。


他们主要的作用都是通过该变人的视角在屏幕上表现出不同的绘图效果。


二,关于坐标系(笛卡尔坐标系和正交投影坐标系)


笛卡尔坐标系:我们上初中时学的平面几何基本都是以笛卡尔坐标系为基础,简单的理解就是原点在左下角,只有X轴,Y轴。


投影坐标系:当学习立体几何时,如果还是使用笛卡尔坐标系,它不能表现出空间的概念,这样就需要一个立体的坐标系来描述立体几何图形在空间中的位置关系。除了X轴,Y轴这时又多出了一个Z轴。



三,关于使用setProjectionMatrix


这个函数在 libgdx帮助文档中的描述是 " Sets the projection matrix to be used by this Batch. " 在当前的Batch使用投影矩阵,或者说使用合并后的投影与视图矩阵。当然这样理解起来很抽象。

下面会有两个简单的例子来描述一下使用这个函数和不使用这个函数的区别。


测试原图




1)  不使用 setProjectionMatrix。


代码和测试结果


package com.example.libgdx_sample_spirtebatch;


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer20;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;


public class SampleRender 
{
	public static int WIDTH = 320;
	public static int HEIGHT = 480;
	
    OrthographicCamera m_Cam;

	SpriteBatch batch = new SpriteBatch(5460);

	FPSLogger fps = new FPSLogger();
	ImmediateModeRenderer20 renderer = new ImmediateModeRenderer20(false, true, 0);
	
	private Animation m_MoveLeft;
	private Animation m_MoveRight;
    private float m_StateTime;

    Vector2 m_Pos = new Vector2();
    Texture m_bkg = null;
    
    private TextureRegion m_region;
    
	public SampleRender()
	{
		this.m_Cam = new OrthographicCamera(WIDTH, HEIGHT);
		this.m_Cam.position.set(WIDTH/2, HEIGHT/2, 0);
		m_StateTime = 0;
		createAnimations();
		//m_Pos.x = 0;
		//m_Pos.y = 0;
	}

	private void createAnimations()
	{
		m_bkg = new Texture(Gdx.files.internal("data1.png"));
		m_region=new TextureRegion(m_bkg);

		Texture TankTexture = new Texture(Gdx.files.internal("data.png"));
		TextureRegion[] split = new TextureRegion(TankTexture).split(32, 32)[0];
		TextureRegion[] mirror = new TextureRegion(TankTexture).split(32,32)[0];

		for (TextureRegion region : mirror)
			region.flip(true, false);

		m_MoveLeft = new Animation(0.1f, split[0], split[1]);
		m_MoveRight = new Animation(0.1f, mirror[0], mirror[1]);
	}
	
	
	Vector3 lerpTarget = new Vector3();
	public void render (float deltaTime)
	{
		//m_Cam.position.lerp(lerpTarget.set(m_Pos.x, m_Pos.y, 0), 2f * deltaTime);
		//m_Cam.update();
		m_StateTime += deltaTime;
		
		renderer.begin(m_Cam.combined, GL20.GL_LINES);
		renderer.end();

		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		// batch.setProjectionMatrix(m_Cam.combined);
		batch.begin();

		Animation anim = m_MoveLeft;
		batch.draw(m_region, 0, 0);
		batch.draw(anim.getKeyFrame(m_StateTime, true), 0, 0);
		batch.end();
	}

	public void dispose () 
	{
		batch.dispose();
	}
}

libgdx - 对于SpriteBatch中setProjectionMatrix() 的理解_第1张图片



在测试结果中,相机的设置为


    OrthographicCamera m_Cam;
    SpriteBatch batch = new SpriteBatch(5460);


public static int WIDTH = 320;
public static int HEIGHT = 480;
        this.m_Cam = new OrthographicCamera( WIDTH, HEIGHT);
this.m_Cam.position.set( WIDTH/2, HEIGHT/2, 0);


我们的绘图代码,图形的起始点都被定在了 (0,0)
batch.begin();
Animation anim = m_MoveLeft;
batch.draw(m_region, 0, 0);
batch.draw(anim.getKeyFrame(m_StateTime, true), 0, 0);
batch.end();

代码中并 没有使用 setProjectionMatrix,可以看到这时手机的屏幕使用的是笛卡尔坐标系。 以屏幕的 左下方为原点


2)  使用 setProjectionMatrix。


代码和测试结果

package com.example.libgdx_sample_spirtebatch;


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer20;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;


public class SampleRender 
{
	public static int WIDTH = 320;
	public static int HEIGHT = 480;
	
    OrthographicCamera m_Cam;

	SpriteBatch batch = new SpriteBatch(5460);

	FPSLogger fps = new FPSLogger();
	ImmediateModeRenderer20 renderer = new ImmediateModeRenderer20(false, true, 0);
	
	private Animation m_MoveLeft;
	private Animation m_MoveRight;
    private float m_StateTime;

    Vector2 m_Pos = new Vector2();
    Texture m_bkg = null;
    
    private TextureRegion m_region;
    
	public SampleRender()
	{
		this.m_Cam = new OrthographicCamera(WIDTH, HEIGHT);
		this.m_Cam.position.set(WIDTH/2, HEIGHT/2, 0);
		m_StateTime = 0;
		createAnimations();
		//m_Pos.x = 0;
		//m_Pos.y = 0;
	}

	private void createAnimations()
	{
		m_bkg = new Texture(Gdx.files.internal("data1.png"));
		m_region=new TextureRegion(m_bkg);

		Texture TankTexture = new Texture(Gdx.files.internal("data.png"));
		TextureRegion[] split = new TextureRegion(TankTexture).split(32, 32)[0];
		TextureRegion[] mirror = new TextureRegion(TankTexture).split(32,32)[0];

		for (TextureRegion region : mirror)
			region.flip(true, false);

		m_MoveLeft = new Animation(0.1f, split[0], split[1]);
		m_MoveRight = new Animation(0.1f, mirror[0], mirror[1]);
	}
	
	
	Vector3 lerpTarget = new Vector3();
	public void render (float deltaTime)
	{
		//m_Cam.position.lerp(lerpTarget.set(m_Pos.x, m_Pos.y, 0), 2f * deltaTime);
		//m_Cam.update();
		m_StateTime += deltaTime;
		
		renderer.begin(m_Cam.combined, GL20.GL_LINES);
		renderer.end();

		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		batch.setProjectionMatrix(m_Cam.combined);
		batch.begin();

		Animation anim = m_MoveLeft;
		batch.draw(m_region, 0, 0);
		batch.draw(anim.getKeyFrame(m_StateTime, true), 0, 0);
		batch.end();
	}

	public void dispose () 
	{
		batch.dispose();
	}
}



相机的设置和绘图代码部分是一样的,唯一的区别是我们调用了  batch.setProjectionMatrix(m_Cam.combined);

在当前的Batch使用 投影矩阵

这时可以看到,整个坐标系变成了以 手机屏幕中心为原点的投影坐标系。


你可能感兴趣的:(libgdx - 对于SpriteBatch中setProjectionMatrix() 的理解)