1. 概述

个人认为,纹理数组是一个非常有用的图形特性。纹理本质上是一个二维的图形数据;通过纹理数组,给图形数据再加上了一个维度。这无疑会带来一个巨大的性能提升:一次性传输大量的数据总是比分批次传输数据要快。

2. 详论

2.1. 实现

创建一个GameObject对象,并且加入Mesh Filter组件和Mesh Renderer组件。Mesh Filter我们可以设置Mesh为Quad,同时在Mesh Filter上挂一个我们新建的材质:

在这个GameObject对象上挂接一个我们创建的C#脚本:

using Unity.Collections;
using UnityEngine; [ExecuteInEditMode]
public class Note10Main : MonoBehaviour
{
public Texture2D texture1;
public Texture2D texture2; [Range(0.0f, 1.0f)]
public float weight; Material material; // Start is called before the first frame update
void Start()
{
MeshRenderer mr = GetComponent<MeshRenderer>();
material = mr.sharedMaterial; Texture2DArray texture2DArray = CreateTexture2DArray(); material.mainTexture = texture2DArray;
material.SetFloat("_Weight", weight);
} Texture2DArray CreateTexture2DArray()
{
Texture2DArray texture2DArray = new Texture2DArray(texture1.width, texture1.height, 2,
texture1.format, false); NativeArray<byte> pixelData1 = texture1.GetPixelData<byte>(0);
NativeArray<byte> pixelData2 = texture2.GetPixelData<byte>(0); texture2DArray.SetPixelData(pixelData1, 0, 0, 0);
texture2DArray.SetPixelData(pixelData2, 0, 1, 0); texture2DArray.Apply(false, false); return texture2DArray;
} // Update is called once per frame
void Update()
{
material.SetFloat("_Weight", weight);
}
}

这段C#脚本的意思是,通过传入两个Texture2d,生成一个texture2DArray;并且,将这个texture2DArray传入到材质中。需要注意的是纹理数组中的每个纹理的参数如宽、高等参数都需要一致,否则不能组成纹理数组。

材质使用我们自定义的Shader:

Shader "Custom/TextureArrayShader"
{
Properties
{
_MainTex ("Texture", 2DArray) = "" {}
_Weight ("Weight", float) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100 Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
}; UNITY_DECLARE_TEX2DARRAY(_MainTex);
float _Weight; v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
} fixed4 frag (v2f i) : SV_Target
{
fixed4 col0 = UNITY_SAMPLE_TEX2DARRAY(_MainTex, float3(i.uv, 0));
fixed4 col1 = UNITY_SAMPLE_TEX2DARRAY(_MainTex, float3(i.uv, 1));
return lerp(col0, col1, _Weight);
}
ENDCG
}
}
}

这里实现的效果是,将纹理数组中的两个纹理根据权重进行混合。权重值也是在C#脚本中传入到Shader中的。在编辑器中将权重调整到中间一点的位置(例如0.5):

Shader代码也很好理解,关键在于纹理数组相关的宏,其实是对hlsl或者glsl的封装:

#define UNITY_DECLARE_TEX2DARRAY(tex) Texture2DArray tex; SamplerState sampler##tex
#define UNITY_SAMPLE_TEX2DARRAY(tex,coord) tex.Sample (sampler##tex,coord) #define UNITY_DECLARE_TEX2DARRAY(tex) sampler2DArray tex
#define UNITY_SAMPLE_TEX2DARRAY(tex,coord) tex2DArray (tex,coord)

2.2. 注意

  1. 关于纹理数组的创建,也可以使用Graphics.CopyTexture()这个接口。这个接口是纯走GPU端的,效率应该回更高。
  2. 纹理数组这个特性在低端显卡上可能不支持,但是不一定就会非常耗费性能。可以考虑通过纹理数组的方式来合并渲染的批次。
  3. 纹理数组个数的限制并不是纹理单元个数。实际上一个纹理数组只会绑定到一个纹理单元上,而在本人GTX 1660 Ti的显卡上,纹理数组个数的限制是4096个。

3. 参考

  1. Texture2DArray 功能测试
  2. What are the limits of texture array size?

代码地址

Unity3D学习笔记10——纹理数组的更多相关文章

  1. Unity3D学习笔记2——绘制一个带纹理的面

    目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...

  2. Unity3D学习笔记12——渲染纹理

    目录 1. 概述 2. 详论 3. 问题 1. 概述 在文章<Unity3D学习笔记11--后处理>中论述了后处理是帧缓存(Framebuffer)技术实现之一:而另外一个帧缓存技术实现就 ...

  3. Unity3D学习笔记8——GPU实例化(3)

    目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1)&g ...

  4. thinkphp学习笔记10—看不懂的路由规则

    原文:thinkphp学习笔记10-看不懂的路由规则 路由这部分貌似在实际工作中没有怎么设计过,只是在用默认的设置,在手册里面看到部分,艰涩难懂. 1.路由定义 要使用路由功能需要支持PATH_INF ...

  5. 《C++ Primer Plus》学习笔记10

    <C++ Primer Plus>学习笔记10 <<<<<<<<<<<<<<<<<&l ...

  6. Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息

    </pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...

  7. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  8. matlab学习笔记10 一般运算符

    一起来学matlab-matlab学习笔记10 10_1一般运算符 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张 ...

  9. unity3d学习笔记(一) 第一人称视角实现和倒计时实现

    unity3d学习笔记(一) 第一人称视角实现和倒计时实现 1. 第一人称视角 (1)让mainCamera和player(视角对象)同步在一起 因为我们的player是生成的,所以不能把mainCa ...

随机推荐

  1. MySQL8新增降序索引

    MySQL8新增降序索引 桃花坞里桃花庵,桃花庵里桃花仙.桃花仙人种桃树,又摘桃花卖酒钱. 一.MySQL5.7 降序索引 MySQL在语法上很早就已经支持降序索引,但实际上创建的却仍然是升序索引,如 ...

  2. 6.Docker网络

    什么是 Docker网络 docker 不启动,默认网络情况 ens33 lo virbr0 在 CentOS7 的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的 ...

  3. Linux内网渗透

    Linux虽然没有域环境,但是当我们拿到一台Linux 系统权限,难道只进行一下提权,捕获一下敏感信息就结束了吗?显然不只是这样的.本片文章将从拿到一个Linux shell开始,介绍Linux内网渗 ...

  4. Golang 常见设计模式之单例模式

    之前我们已经看过了 Golang 常见设计模式中的装饰和选项模式,今天要看的是 Golang 设计模式里最简单的单例模式.单例模式的作用是确保无论对象被实例化多少次,全局都只有一个实例存在.根据这一特 ...

  5. 并发bug之源(一)-可见性

    CPU三级缓存 要聊可见性,这事儿还得从计算机的组成开始说起,我们都知道,计算机由CPU.内存.磁盘.显卡.外设等几部分组成,对于我们程序员而言,写代码主要关注CPU和内存两部分.放几张马士兵老师的图 ...

  6. 3.对互斥事件和条件概率的相互理解《zobol的考研概率论教程》

    tag:这篇文章没太多思考的地方,就是做个过渡 1.从条件概率来定义互斥和对立事件 2.互斥事件是独立事件吗? 3.每个样本点都可以看作是互斥事件,来重新看待条件概率 一.从条件概率来定义互斥和对立事 ...

  7. spring源码解析:元注解功能的实现

    前言 众所周知,spring 从 2.5 版本以后开始支持使用注解代替繁琐的 xml 配置,到了 springboot 更是全面拥抱了注解式配置.平时在使用的时候,点开一些常见的等注解,会发现往往在一 ...

  8. 基于web3D展示技术的煤矿巷道3D可视化系统

    地下开采离不开巷道工程.煤矿的生产.运输.排水.通风等各个环节都少不了巷道的支持.在煤矿智能化建设被提上日程的今天,巷道工程的智能化.可视化建设也成了行业趋势.尤其是复杂的井下作业环境,人员信息安全问 ...

  9. Sublime Text 3 如何清除上次打开文件记录

    打开顶部菜单栏:进入 Preferences => Settings-User修改如下: {"hot_exit": false,"remember_open_fil ...

  10. 重学ES系列之字符串方面的处理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...