减少绘制调用的方法 VR资源

Raffles 2017-09-26 17:40:22
 
当我们开始制作 Academia(学术界)时,并没有真正考虑如何来管理我们的 sprites(精灵)。我们只使用了最快捷的方式,即一个个单独制作并将它们载入游戏中。游戏中的全部 sprites 存放于 SteamingAssets 。游戏运行时动态加载它们。这种方式与通常导入纹理不同。我设想未来模组制作者们可以添加自己的文件夹并添加机制来复写游戏图片。
 
理想化中,所有的游戏 sprites 应该在同一个大纹理贴图中。这将会允许所有游戏对象使用一个通用的材质,那样动态处理机可以真正进行处理了。如今游戏越来越大,使得将所有 sprites 至于一个 atlas(地图集)中更难。我们的艺术家们可不会同意这一做法,因为工作量实在是太大了。另外,我们也不再有这么多的时间。早期访问版将在今年9月8日发行。
 
一些例子,我们有个专门的文件夹
 
 
寻求解决方案的同时,我在想是否可以动态打包图片而不使用生成的 atlas 。那样的话就可以足够简便地重算打包好的 sprites 的 UV 值了。我在互联网上觅寻将三角形打包成一个大整体的最佳算法。结果发现这还真是个有趣的问题。有大量关于它的文章。而且,我还不需要自己的打包工具了。因为Unity 已经做好了一个
 
 
不过,还是需要些帮助的。我需要持续追踪打包纹理的轨迹。并且需要一个从打包好的整体里找出相同 sprite 的方法。该写写代码了!
 
 
下面是一个从打包好的纹理贴图里提取 “entry” 的类:
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class PackedTextureEntry {
 
    private readonly Texture2D atlas;
    private readonly Rect uvRect;
    private readonly Rect spriteRect;
    private readonly Sprite sprite;
 
    public PackedTextureEntry(Texture2D atlas, Rect uvRect) {
        this.atlas = atlas;
        this.uvRect = uvRect;
        this.spriteRect = new Rect(this.uvRect.x * this.atlas.width, this.uvRect.y * this.atlas.height,
            this.uvRect.width * this.atlas.width, this.uvRect.height * this.atlas.height);
        this.sprite = Sprite.Create(this.atlas, this.spriteRect, new Vector2(0.5f, 0.5f), 768);
    }
 
    public Texture2D Atlas {
        get {
            return atlas;
        }
    }
 
    public Rect UvRect {
        get {
            return uvRect;
        }
    }
 
    public Rect SpriteRect {
        get {
            return spriteRect;
        }
    }
 
    public Sprite Sprite {
        get {
            return sprite;
        }
    }
 
    public Sprite CreateSprite(Vector2 pivot) {
        return Sprite.Create(this.atlas, this.spriteRect, pivot, 768);
    }
 
}
 
 
基本上,它就是个生成的地图集和一个特定 sprite 入口的 UV 坐标系。Rect(矩形)在构造函数中是一个标准化的 UV(值从0到1)。不管怎样,Sprites 是通过像素创建的。所以为此我们需要一个新的 Rect,它就是 UV rect 乘以 atlas 的尺寸。这个类同样有一个预生成的 Sprite 定位在中心。
 
 
下面这个类是纹理贴图打包工具自身:
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class TexturePacker {
  
    // Contains the associated names of the added texture so we can easily query its entry after packing
    private List<string> names = new List<string>();
  
    // This contains the textures to pack
    // Used a list here so we could easily convert to array during packing
    private List<Texture2D> textures = new List<Texture2D>();
  
    // Keeps track of the packed entries
    private Dictionary<string, PackedTextureEntry> entriesMap = new Dictionary<string, PackedTextureEntry>();
  
    private Texture2D atlas;
  
    public TexturePacker() {
    }
  
    public void Add(string key, Texture2D texture) {
        this.names.Add(key);
        this.textures.Add(texture);
    }
  
    public void Pack() {
        this.atlas = new Texture2D(2, 2, TextureFormat.ARGB32, false); // Will expand on packing
        Rect[] rects = this.atlas.PackTextures(this.textures.ToArray(), 0, 8192, true);
  
        // Populate entries
        this.entriesMap.Clear();
        Assertion.Assert(this.names.Count == this.textures.Count);
        for(int i = 0; i < this.names.Count; ++i) {
            this.entriesMap[this.names[i]] = new PackedTextureEntry(this.atlas, rects[i]);
        }
  
        // Clear to save memory
        // These textures may also be released
        this.textures.Clear();
    }
  
    public PackedTextureEntry GetEntry(string key) {
        return this.entriesMap[key];
    }
  
}
 
 
用途是自身解释性的。创建以个打包工具的实例。添加你想要打包的纹理贴图,每个都与一个字符串钥匙相关。 Call Pack() 。 使用 GetEntry() 来获得与 sprite 关联的 PackedTextureEntry 的实例。
 
使用 PackedTextureEntry.Sprite 属性来获取打包好的纹理贴图中的 sprite 的权限。
 
 
01
02
03
04
05
06
07
08
09
10
11
TexturePacker packer = new TexturePacker();
  
// Let's just say you have a library of textures associated by name
foreach(TextureEntry entry in entries) {
    packer.Add(entry.Name, entry.Texture);
}
  
packer.Pack();
  
// Get a packed entry and use its sprite
PackedTextureEntry packedEntry = packer.Get("Grass");
spriteRenderer.sprite = packedEntry.Sprite;
 
 
就是这样啦!它真的很简单,但它的确处理了许多。
 
someobjects
99VR视界二维码
热门推荐
Hot Recommended
在线客服