针对移动设备修改着色器

针对移动设备修改着色器 我们在优化着色器这方面已经了解了较多的技术了,现在让我们来了解如何为移动设备编写高效,高质量的着色器代码。对于我们已经写好的着色器代码,通过一些小的修改让他们能在移动设备上高速运行好事比较简单的。这里包含了使用 approxview 或者 halfasview 光照函数变量等知识内容。我们可以减少所需的纹理数量并且对所用的纹理使用更好的压缩方式。这个知识点的最后,对于移动游戏,我们将会有一个优化很好的法线贴图,高光着色器。 始前准备 在开始前,我们先创建一个新的场景并且创建一些游戏对象用来使用我们的着色器: 创建一个新的场景并且添加一个默认球体和一个方向光。 创建一个新的材质球和着色器,并且把着色器应用到材质。 最后把材质应用到场景中的球体上。 当完成上面的步骤后,你的场景看起来大概更下图差不多: 操作步骤 在这个知识点中,我们会反复斟酌着色器中各种元素从而编写一个对移动平台友好着色器: 1.首先根据所需的纹理修改着色器的 属性块(Properties block)。在这个例子中,我们会使用一个alpha通道带有光滑纹理漫反射纹理,一张法线贴图,一个控制高光强度的滑动条。 Properties { _Diffuse ("Base (RGB) Specular Amount (A)", 2D) = "white" {} _SpecIntensity ("Specular Width", Range(0.01, 1)) = 0.5 _NormalMap ("Normal Map", 2D) = "bump" {} } 2.下一个任务是设置 #pragma 申明。这些声明会打开或者关闭 表面着色器(Surface Shader) 的一些具体特性,并且最终影响着色器的性能消耗,是高成本还是低成本。 CGPROGRAM #pragma surface surf MobileBlinnPhong exclude_path:prepass nolightmap noforwardadd halfasview 3.接着我们在 CGPROGRAM 中定义与 属性块(Properties block) 中对应的变量。这次对于高光强度这个滑动条,我们将使用 fixed 类型的变量,从而减少着色器的内存使用: sampler2D _Diffuse; sampler2D _NormalMap; fixed _SpecIntensity; 4....

March 26, 2023 · 1 min · 200 words · Link

着色器的性能分析

着色器的性能分析 我们现在知道该如何减少色器可能出现的内存消耗,让我们来了解一下在场景中,如何在大量同时运行的游戏对象,着色器和脚本等包含的大量着色器中,找出有问题的着色器。要在整个游戏中去找到某一个单独的游戏对象或者着色器可能会让人有点望而却步,但是Unity给我们提供了它内建的性能分析工具。它可以让我们知道在游戏中每一帧都发生了什么,CPU和GPU资源使用情况。 通过使用性能分析工具,我们可以使用其界面创建分析作业块,来单独分析诸如着色器、几何图新和一些一般渲染项。我们可以筛选出我们要寻找的影响性能的单个游戏对象。这让我们能够在运行时观察对象执行其功能时对 CPU和GPU的影响。 让我们来看看性能分析工具的不同部分和并且学习如何调试我们的场景,当然更重要的是如何调试我们的着色器。 操作步骤 使用性能分析工具的时候,你会在该窗口看到一些UI元素。在我们点击运行按钮前,让我们了解一下该如何从性能分析器中获取我们想要的信息: 1.首先,点击 Profiler 窗口中的 GPU Usage,CPU Usage 和 Rendering这几栏。你可以在窗口的左上角找到这几栏: 使用这几栏,我们可以看到跟游戏主要功能相关的不同的数据。CPU Usage 给我们展示的是我们大部分脚本在干什么,当然还有物理运算和总体渲染。GPU Usage 这一栏给我们的是光照,阴影和渲染队列等的详情信息。最后,Rendering 这一栏有每一帧中 drawcall 和游戏场景中集合体的数量这些信息。 点击其中的一栏,我们就可以把在 性能会话(profiling session) 中看到的数据类型单独分离出来分析。 2.现在,我们可以点击性能分析栏中的小颜色块然后点击编辑器的运行按钮或者用 Ctrl + P 快捷键运行场景。 这样选择性的查看,可以让我们更加深入的分析性能会话,因为这样我们可以选择我们想分析的内容。当场景运行的时候,再GPU使用(GPU Usage) 栏中取消其他所有的颜色小块的勾选,然后留下 Opaque 这一勾选。请注意这样我们就可以知道 Opaque 渲染队列中的游戏对象再渲染中花了多长时间了: 3.性能分析窗口中另一个非常好用的功能是可以在图形窗口中进行的拖拽操作。这个操作会自动暂停你的游戏,这样你就可以更细致的分析图形中某一个具体的波峰从而找出引起性能问题的具体项了。你可以在图形区域内点击或者拖拽移动来暂停游戏,从而了解这一功能的具体效果: 4.现在让我们把目光聚焦到性能分析窗口的下半部分,你会发现当我们选中GPU那一栏的时候这里会有一个下拉选择框。我们可以把它展开从而获得更多当前激活的性能会话中的详细信息,这种情况下我们可以知道有关于当前摄像机渲染情况和花费时间的更多信息: 它能让我们全面了解Unity在某一帧中内部工作都在处理什么。在这个例子中,我们能看到场景中的球体和我们优化过的着色器在绘制到屏幕上花了大概0.14毫秒,花了7个drawcall,并且这个处理每帧花费了大概3.1%的GPU时间。通过这些类型的信息我们可以去诊断和解决跟着色器性能相关的问题。让我们准备一个测试,看看如果我们给着色器添加一个额外的纹理并且用 lerp 函数把两张漫反射纹理混合到一块会造成什么样的影响。你将会在在性能分析器中看到清晰的影响。 5.修改着色器的 属性块(Properties block),然后添加下面的代码,这样就可以为我们的着色器添加另一个纹理了: Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} NormalMap ("Normal Map", 2D) = "bump" {} _BlendTex ("Blend Texture", 2d) = "white" {} } 6....

March 23, 2023 · 1 min · 153 words · Link

在2D游戏中实现水效果的着色器

在2D游戏中实现水效果的着色器 上一个知识点介绍的玻璃着色器它的效果是静态的;它的扭曲效果永远都不会改变。只要对着色器稍加修改,就可以将它转换成一个有动画的材质,它非常的适合2D游戏中的水体特效。在这个知识点将会使用 第五章,对表面着色器中的顶点使用动画 中类似的技术: 始前准备 这个知识点基于 使用抓取通道 知识点中描述的顶点和片元着色器,因为它很依赖抓取通道。 1.创建一个新的抓取通道着色器;你可以自己写一个新的着色器或者使用 使用抓取通道 这个知识点中用到的着色器作为开始。 2.为你的着色器创建一个对应的材质球。 3.将材质球应用到一个平面几何图形中,它将用来表示2D中的水。为了让这个效果起作用,您应该在其后渲染一些东西,以便可以看到类似水的扰动效果。 4.这个知识点需要一张噪音纹理,用来获得伪随机的值。选择一个无缝的噪音纹理很重要,比如由可以铺砌的2D的Perlin噪音生成的噪音纹理,如下图所示的那样。这是为了确保材质应用到一个很大的游戏对象中时,不会看到有任何不连续的割裂感。为了让效果起作用,纹理需要以 Repeat 模式导入。如果你想要让你的水体效果看起来平滑和连续,那么在 导入器(Inspector) 那里要设置成 Bilinear。这样设置能确保纹理能从着色器中正确的被采样: 操作步骤 你可以修改着色器中的代码来创建动画效果。请跟着下面的步骤走: 1.将下面的代码添加到着色器的属性块中: _NoiseTex("Noise text", 2D) = "white" {} _Colour ("Colour", Color) = (1,1,1,1) _Period ("Period", Range(0,50)) = 1 _Magnitude ("Magnitude", Range(0,0.5)) = 0.05 _Scale ("Scale", Range(0,10)) = 1 2.并且在次通道中添加与属性对应的变量 sampler2D _NoiseTex; fixed4 _Colour; float _Period; float _Magnitude; float _Scale; 3.为顶点函数定义下面 输出结构体(output structure): struct vertOutput { float4 vertex : POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; float4 worldPos : TEXCOORD1; float4 uvgrab : TEXCOORD2; }; 4....

February 26, 2023 · 3 min · 469 words · Link

移动设备着色器适配

第七章 移动设备着色器适配 在接下来的两章,我们将着手于让我们写的着色器对不同的平台都有较好的性能表现。我们不会讨论任何一个特殊的平台,我们将会分解着色器内的元素,这样的话我们就可以对它们进行调整,从而让它们对于移动平台有更好的优化并且通常来说对其他任何平台来说也更高效。这些技术涵盖了从 了解Unity提供的一些可以减少着色器内存溢出方面的内建变量 到 学习可以让我们的着色器代码更加高效的方法。这一章将会包含下面的这些知识点: 什么是低成本着色器 着色器的性能分析 针对移动设备修改着色器 介绍 学习如何优化着色器的艺术将会出现在你参与的任何游戏项目中。在任何产品中总有需要优化着色器的时候,或者需要用更少的纹理来产生相同的效果。作为一个技术美术或者着色器编程人员,你必须要理解这些核心的基本原理来优化你的着色器代码从而让你的游戏在提升性能表现的同时又能达到相同的视觉表现。有了这些知识也可以为你自己开始写着色器代码进行铺垫。比如,你知道使用你着色器的游戏将会运行在移动设备中,我们可以自动的设置所有的光照函数使用 half vector 作为视野方向,或者把所有的 浮点型变量类型(float variable types) 都设置成 fixed 类型 或 half 类型。前面提到的这些技术或者很多的其他技术,都可以让你的着色器在目标硬件上更加高效的运行。开始我们的着色器优化学习之旅吧。 什么是低成本着色器 我们首先问一个问题,什么是低成本的着色器,它回答起来可能有点困难因为有太多的元素可以可以让一个着色器变得更加高效了。它可以是你的变量使用的内存的大小。可以是你的着色器使用的纹理的大小。也可是一个工作良好的着色器,但是我们却只使用了相较之前一半的代码或者数据就获得了相同的视觉效果。我们将会在这个知识点中探索一些这样的技术并且会展示如何将这些技术结合起来从而让你的着色器更快更高效,并且不管是在移动设备还是在PC上都生成当今游戏中每个人都期望的高质量的视觉效果。 始前准备 在开始这个知识点之前,我们需要准备一些资源并且把它们放一块。所以让我们按照下面的几个任务来: 1.创建一个新的场景,并且在场景中添加一个球体和一个方向光。 2.创建一个新的着色器和材质球,并且把着色器应用到材质上。 3.然后把材质球应用到我们刚刚创建的球体。 4.最后,我们修改我们之前创建的着色器让它能使用漫反射纹理和法线贴图,并且创建一个自定义的光线函数。下面的代码展示的是修改后的着色器代码: Shader "Custom/MSA" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _NormalMap ("Normal Map", 2D) = "bump" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM sampler2D _MainTex; sampler2D _NormalMap; #pragma surface surf SimpleLambert struct Input { float2 uv_MainTex; float2 uv_NormalMap; }; inline float4 LightingSimpleLambert(SurfaceOutput s, float3 lightDir, float atten) { float diff = max(0, dot(s....

February 26, 2023 · 2 min · 327 words · Link

实现一个玻璃效果的着色器

实现一个玻璃效果的着色器 玻璃是一个非常复杂的材质;没必要对它刚到惊讶,在第四章,向PBR中添加透明度 这个知识点中,通过行为驱动开发创建测试用例和编写场景(Creating Test Cases and Writing Scenarios for Behavior Driven Development in Symfony) 我们已经创建了一个这样的着色器来模拟它了。然而,透明度没有办法复现玻璃的扭曲效果。大部分的玻璃自身是不完美的,所以当我们再看玻璃的时候会有扭曲效果。这个知识点我们将教你如何实现这样的效果。这个效果背后的思路是使用顶点和片元着色器以及抓取通道,然后对抓取纹理做一些修改并应用到它的UV数据中,从而实现扭曲效果。你可以从下面的图中看到效果,使用的是Unity标准资源库 (Unity Standard Assets) 中的玻璃染色纹理: 始前准备 这个知识点的步骤跟前一章中的有点像: 创建一个新的顶点和片元着色器。你可以复制前一个知识点 抓取通道 的着色器作为基础。 创建一个材质,用来承载着色器。 将材质球赋值给一个 quad,也可以是其他的扁平的几何图形,用来模拟玻璃。 然后再这个模拟的玻璃后面放一些其他的游戏物体,好观察扭曲效果。 操作步骤【原书有错,下面是纠正后的步骤和代码】 我们开始编辑顶点和片元着色器: 向着色器的属性快 ( Properties block) 中添加4个属性: Properties { _MainTex("Base (RGB) Trans (A)", 2D) = "white" {} _Colour("Colour", Color) = (1,1,1,1) _BumpMap("Noise text", 2D) = "bump" {} _Magnitude("Magnitude", Range(0,1)) = 0.05 } 在Pass通道中添加下面的这些变量 sampler2D _MainTex; sampler2D _BumpMap; float _Magnitude; sampler2D _GrabTexture; fixed4 _Colour; 将下面的纹理信息添加到输入和输出结构体中: struct vertInput { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct vertOutput { float4 vertex : SV_POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; float4 uvgrab : TEXCOORD1; }; 将UV数据从输入结构体赋值到输出结构体中: vertOutput vert(vertInput input) { vertOutput o; o....

February 10, 2023 · 1 min · 204 words · Link

使用抓取通道

使用抓取通道 在第四章,向PBR中添加透明度 这个知识点中,通过行为驱动开发创建测试用例和编写场景(Creating Test Cases and Writing Scenarios for Behavior Driven Development in Symfony),我们了解了材质是如何实现透明的。尽管一个透明材质可以在一个场景之上进行绘制,但是它不能改变在场景之下已经绘制的东西。这也意味着那些透明着色器(Transparent Shaders) 不能创建像从玻璃或者水里看到的那些常见的扭曲效果。为了模拟它们,我们需要介绍另一种叫做抓取通道(grab pass) 的技术。这个技术可以让我们获取到目前为止,已经绘制在屏幕上的信息,从而让我们的着色器没有限制的去使用(或者修改)它们。为了学习如何使用抓取通道,我们会创建一个材质球,来抓取它背后的渲染信息并且在屏幕上再次绘制它们。这让人感觉有点荒谬,这个材质用了一系列的操作,显示效果还是跟原来一样【作者的意思可能是在这个例子中,使用了抓取通道和没有使用的着色器,它们的显示效果是一样的】。 始前准备 这个知识点需要下面的一系列操作: 创建一个着色器,之后我们会对它进行初始化。 创建一个材质球,用来使用我们的着色器。 将材质球应用到一块扁平的几何图形上,比如Unity中的quad。然后将它放在某个物体的前面,能挡住你看后面的物体。当我们的着色器完成之后,这个quad将会变得透明。 操作步骤 为了能使用抓取通道,请你按照下面的步骤操作: 删除着色器的 属性快(Properties section);这个着色器将不会使用里面的任何东西。 在 SubShader 中,添加抓取通道: GrabPass{ } 在添加完抓取通道后,我们将需要添加下面这个额外的通道: Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _GrabTexture; struct vertInput { float4 vertex : POSITION; }; struct vertOutput { float4 vertex : POSITION; float4 uvgrab : TEXCOORD1; }; // Vertex function vertOutput vert(vertInput v) { vertOutput o; o....

January 2, 2023 · 1 min · 140 words · Link

片元着色器和抓取通道

第六章 片元着色器和抓取通道 到目前为止,我们都在折腾表面着色器(Surface Shaders)。它的设计初衷是简化我们的着色器编码工作,为艺术家提供一个有意义的工具。但是如果想让我们的着色器知识更上一层楼,我们就要前往**顶点(Vertex)和片元(Fragment)**着色器的知识岛屿冒险啦。 在这一章节,我们将会学习下面的一些知识点: 理解顶点和片元着色器 使用抓取通道 实现一个玻璃效果的着色器 在2D游戏中实现水效果的着色器 介绍 跟表面着色器(Surface Shaders)相比,顶点和片元着色器少了一些诸如,光是如何在物体表面反射的物理属性信息。所谓有失必有得,这样的话顶点和片元着色器就没有了物理规则的限制并且特别适合实现非真实的效果。这个章节将集中讲抓取通道的技术,这些技术可以让着色器来模拟形变效果。 理解顶点和片元着色器 理解顶点和片元着色器最好的方法就是你自己亲自创建一个。在这个知识点我们将展示如何编写一个这样的着色器,该着色器简单的将一张纹理应用到一个模型上并且通过给定的颜色进行乘积运算,效果就如同下图一样: 这里展示的着色器非常的简单,只是作为学习其他顶点和片元着色器基础。 始前准备 对于这个知识点,我们将需要一个新的着色器。我们按照下面的步骤来: 1.创建一个新的着色器。 2.创建一个新的材质并且把着色器应用于该材质。 操作步骤 在前面的所有章节中,我们总是能在**表面着色器(Surface Shaders)**的基础上进行修改。但在这里就不能再那样做了,因为表面着色器和片元着色器在结构上是不一样的。我们需要做如下的修改: 删除着色器上的所有属性,然后用下面的属性替换: Color ("Color", Color) = (1,0,0,1) // Red _MainTex ("Base texture", 2D) = "white" {} 删除 SubShader 块中的所有代码,然后用下面的代码替换: Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag half4 _Color; sampler2D _MainTex; struct vertInput { float4 pos : POSITION; float2 texcoord : TEXCOORD0; }; struct vertOutput { float4 pos : SV_POSITION; float2 texcoord : TEXCOORD0; }; vertOutput vert(vertInput input) { vertOutput o; o....

December 3, 2022 · 2 min · 267 words · Link

XLua框架,Unity3D,WEBGL,报错ArgumentException-Destination-array-was-not-long-enough

Unity使用XLua框架,打WEBGL包,运行时报错:ArgumentException: Destination array was not long enough 具体的错误如下: dangerArgumentException: Destination array was not long enough. Check destIndex and length, and the array's lower bounds {: .prompt-danger } 由于我们UI使用的时FGUI,所以这个错误的具体表现是: 错误表现 在编辑器中运行良好,没有任何问题 打包成WEBGL运行就报这个错,但不是每次都报错, 如果报错,那么UI逻辑是正常的,如果不报错,那么UI逻辑异常,比如按钮的绑定事件错乱 解决办法 我在XLua的Issue中,找到了大佬的解决办法。是XLua在释放资源时的Lock操作引起的。原issue地址。但是大佬的贴的代码,不能直接运行,需要稍加修改才行【大佬可能给的时伪代码】。我在这里把解决步骤归纳一下: 1.添加一个非锁互斥队列【也可以不用添加,就用系统的也行】: using System.Threading; namespace XLua { public class LockFreeQueue<T> { internal class SingleLinkNode<U> where U : T { public SingleLinkNode<U> Next; public U Item; } static private bool CAS<T>(ref T location, T comparand, T newValue) where T : class { return comparand == Interlocked....

October 31, 2022 · 2 min · 376 words · Link

Unity编辑器-persistentDataPath-dataPath-streamingAssetsPath

Unity中persistentDataPath, dataPath, streamingAssetsPath在不同的平台对应的路径 为了方便以后的开发,自己结合官方资料和自己的实际开发,把上面的路径变量在不同的平台对应的正式路径总结一下 Application.persistentDataPath 官方参考:https://docs.unity3d.com/2020.3/Documentation/ScriptReference/Application-persistentDataPath.html 对app是只读的,对玩家来说读写都可以,如果是IOS或者安卓,该路径指向设备的公共目录 app更新的时候,不会删除该目录,但是用户自己是可以对该目录增删改查的 平台 指向的位置 Windows Store Apps %userprofile%\AppData\Local\Packages&lt;productname>\LocalState Windows Editor and Standalone Player %userprofile%\AppData\LocalLow&lt;companyname>&lt;productname> WebGL /idbfs/<md5 hash of data path> 该路径是URL最后一个斜杠“/”和“?”之间的字符串 Linux $XDG_CONFIG_HOME/unity3d 或者$HOME/.config/unity3d iOS /var/mobile/Containers/Data/Application/<guid>/Documents tvOS 不支持且返回空字符串 Android 通常指向/storage/emulated/0/Android/data/<packagename>/files,有的老机型可能指向SD卡的路径 Mac 指向用户的Library目录,通常该目录是隐藏的,现在Unity是指向~/Library/Application Support/company name/product name Application.dataPath 官方参考:https://docs.unity3d.com/2020.3/Documentation/ScriptReference/Application-streamingAssetsPath.html 对玩家和app都是只读的,是指设备的游戏目录,只能读取 根据不同的平台,游戏目录不一样 平台 指向位置 Unity Editor <项目路径>/Assets Mac player <path to player app bundle>/Contents iOS player <path to player app bundle>/<AppName.app>/Data Win/Linux player <游戏的可执行文件的数据目录> (请注意Linux目录是大小写敏感的,window不是) WebGL 玩家数据目录的绝对URL(没有具体的文件名) Android 通常指向APK,如果你使用的是安卓分包,那么它指向OBB(也就是说游戏数据文件都保存到了OBB文件中) Windows Store Apps 是一个指向玩家数据目录的绝对路径 注意:PC上返回的路径是用反斜杠(“\”)做分割的...

October 27, 2022 · 1 min · 150 words · Link

实现范围体爆炸

实现范围体爆炸 对于实现游戏中的艺术效果,有时候需要在画质和运行效率上进行巧妙的权衡。在实现爆炸效果上尤其如此;因为它是很多游戏的核心效果,但是在它之后的一些物理计算通常都会超过现代计算机的算力。爆炸本质上就是一团温度非常高的火红气体;所以正确模拟它的唯一方式就是在游戏中用流体模拟来模拟它。正如你所想的一样,这在运行时是不可行的,在很多的游戏中都是通过粒子来模拟。当一个物体爆炸的时候,通常会同时产生很多的火花,烟雾和一些散落的碎片,这样可以获得一个比较像的爆炸。不幸的是,这种模拟方法很容易被看破而且可能不是很真实。这里我们会了解一种折中的技术来实现爆炸效果,并且画质更好:范围体爆炸(volumetric explosions)。这个知识点背后的思考是我们不再把爆炸当作是一系列粒子的模拟;它们现在进阶到3D物体了,而不仅仅是扁平的2D贴图。 始前准备 我们通过下面的几个步骤来讲解这个知识点: 为这个效果创建一个新的着色器 创建一个新的材质,并且关联该着色器 把这个材质关联到一个球体模型上。你可以在编辑器上直接创建一个球体模型,通过菜单 GameObject | 3D Object | Sphere。 注意 使用标准的Unity球体就可以很好的演示这个知识点,但是如果你想要更大范围的爆炸,那么你可能需要面数更多的球体。事实上,顶点函数只能修改网格的顶点。所有其他的点都可以通过修改相邻顶点的位置的方式来修改它们。顶点数越少,那么爆炸效果的精细度也就越低。 这个知识点中,你需要一个渐变纹理(ramp texture),这个纹理需要有你爆炸的所有颜色梯度。你可以用GIMP或者PhotoShop工具创建一个跟下面类似的纹理: 当你有了这个图片后,把它导入到你的Unity中。然后在检查器面板(Inspector)中,确保Filter Mode设置为Bilinear,然后Wrap Mode设置为Clamp。这两个设置是为了确保对渐变纹理平滑采样。 最后,你还需要一张噪音纹理(noisy texture)。你可以在网上搜索免费的噪音纹理。一般我们都使用Perlin noise。【这里我自己找到一个网站http://kitfox.com/projects/perlinNoiseMaker/】 操作步骤 这个效果我们分两步来实现:通过顶点函数改变几何形状,通过表面函数给与正确的颜色。这两个步骤如下: 添加下面的属性到着色器中: _RampTex("Color Ramp", 2D) = "white" {} _RampOffset("Ramp offset", Range(-0.5,0.5))= 0 _NoiseTex("Noise tex", 2D) = "gray" {} _Period("Period", Range(0,1)) = 0.5 _Amount("_Amount", Range(0, 1.0)) = 0.1 _ClipRange("ClipRange", Range(0,1)) = 1 添加相应变量,让着色器的Cg代码可以访问到它们: sampler2D _RampTex; half _RampOffset; sampler2D _NoiseTex; float _Period; half _Amount; half _ClipRange; 修改输入结构体(Input structure),这样可以让它接收渐变纹理的UV数据: struct Input { float2 uv_NoiseTex; }; 添加下面的顶点函数: void vert(inout appdata_full v) { float3 disp = tex2Dlod(_NoiseTex, float4(v....

October 23, 2022 · 2 min · 236 words · Link