Unity3D学习笔记10——纹理数组
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. 注意
- 关于纹理数组的创建,也可以使用Graphics.CopyTexture()这个接口。这个接口是纯走GPU端的,效率应该回更高。
- 纹理数组这个特性在低端显卡上可能不支持,但是不一定就会非常耗费性能。可以考虑通过纹理数组的方式来合并渲染的批次。
- 纹理数组个数的限制并不是纹理单元个数。实际上一个纹理数组只会绑定到一个纹理单元上,而在本人GTX 1660 Ti的显卡上,纹理数组个数的限制是4096个。
3. 参考
Unity3D学习笔记10——纹理数组的更多相关文章
- Unity3D学习笔记2——绘制一个带纹理的面
目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...
- Unity3D学习笔记12——渲染纹理
目录 1. 概述 2. 详论 3. 问题 1. 概述 在文章<Unity3D学习笔记11--后处理>中论述了后处理是帧缓存(Framebuffer)技术实现之一:而另外一个帧缓存技术实现就 ...
- Unity3D学习笔记8——GPU实例化(3)
目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1)&g ...
- thinkphp学习笔记10—看不懂的路由规则
原文:thinkphp学习笔记10-看不懂的路由规则 路由这部分貌似在实际工作中没有怎么设计过,只是在用默认的设置,在手册里面看到部分,艰涩难懂. 1.路由定义 要使用路由功能需要支持PATH_INF ...
- 《C++ Primer Plus》学习笔记10
<C++ Primer Plus>学习笔记10 <<<<<<<<<<<<<<<<<&l ...
- Spring MVC 学习笔记10 —— 实现简单的用户管理(4.3)用户登录显示全局异常信息
</pre>Spring MVC 学习笔记10 -- 实现简单的用户管理(4.3)用户登录--显示全局异常信息<p></p><p></p>& ...
- Go语言学习笔记八: 数组
Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...
- matlab学习笔记10 一般运算符
一起来学matlab-matlab学习笔记10 10_1一般运算符 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张 ...
- unity3d学习笔记(一) 第一人称视角实现和倒计时实现
unity3d学习笔记(一) 第一人称视角实现和倒计时实现 1. 第一人称视角 (1)让mainCamera和player(视角对象)同步在一起 因为我们的player是生成的,所以不能把mainCa ...
随机推荐
- kNN-识别手写数字
最后,我们要进行手写数字分类任务,但是现在我们是用kNN算法,可能会比较慢 首先,完整地看完2.3.1和2.3.2的内容,然后找到trainingDigits和testDigits文件夹,大致浏览下 ...
- Java线程池ThreadPoolExecutor极简教程
ThreadPoolExecutor 简介 ThreadPoolExecutor 是 java.util.concurrent 包下的一个类,在jdk1.5版本引入,帮助开发人员管理线程并方便地执行并 ...
- 【Java面试】如何中断一个正在运行的线程?
一个去京东面试的工作了5年的粉丝来找我说: Mic老师,你说并发编程很重要,果然我今天又挂在一道并发编程的面试题上了. 我问他问题是什么,他说:"如何中断一个正在运行中的线程?". ...
- Vben Admin 源码学习:项目初始化
0x00 前言 Vue-Vben-Admin 是一个免费开源的中后台模版.使用了最新的vue3,vite2,TypeScript等主流技术开发,开箱即用的中后台前端解决方案考. 本系列本着学习参考的目 ...
- 使用 Nocalhost 开发 Rainbond 上的微服务应用
本文将介绍如何使用 Nocalhost 快速开发 Rainbond 上的微服务应用的开发流程以及实践操作步骤. Nocalhost 可以直接在 Kubernetes 中开发应用,Rainbond 可以 ...
- Servlet的本质
简介:Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层. 功能:使 ...
- Docker打包镜像并上传
Docker打包镜像并上传 登录 账号 docker login --username=yourusername 密码 yourPassword 推送到仓库 docker镜像打标签 docker ta ...
- Navicat 连接 MySQL
目录 简述 新建连接 常见错误 简述 Navicat 是一套快速.可靠和全面的数据库管理工具,专门用于简化数据库管理和降低管理成本.Navicat 图形界面直观,提供简便的管理方法,设计和操作 MyS ...
- 总结 到 GDOI 2021 这个阶段
截止本蒟蒻第一次体验省选(虽然是普及组) 本蒟蒻已经有了许多收获,却也有很多不足 优点 对一些学过的知识掌握还行 没了 缺点 会却做不出来 有一些题不难,却想不到正解 如 Day2 T1 ,就是移一下 ...
- python创建分类器小结
简介:分类是指利用数据的特性将其分成若干类型的过程. 监督学习分类器就是用带标记的训练数据建立一个模型,然后对未知数据进行分类. 一.简单分类器 首先,用numpy创建一些基本的数据,我们创建了8个点 ...