前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity3D学习笔记10——纹理数组

Unity3D学习笔记10——纹理数组

作者头像
charlee44
发布2022-10-05 16:05:46
1.6K0
发布2022-10-05 16:05:46
举报
文章被收录于专栏:代码编写世界

目录

1. 概述

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

2. 详论

2.1. 实现

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

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

代码语言:javascript
复制
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:

代码语言:javascript
复制
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的封装:

代码语言:javascript
复制
#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?

代码地址

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概述
  • 2. 详论
    • 2.1. 实现
      • 2.2. 注意
      • 3. 参考
      相关产品与服务
      GPU 云服务器
      GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于生成式AI,自动驾驶,深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档