通过Unity渲染纹理实现屏幕效果

第八章 通过Unity渲染纹理实现屏幕效果 我们在这一章会学习下面的这些知识点: 设置屏幕效果脚本系统 在屏幕效果中使用亮度, 饱和度和对比度 在屏幕效果中使用基础的类Photoshop混合模式 屏幕效果中的覆盖混合模式 介绍 学习编写着色器最让人印象深刻的是创建你自己的屏幕效果的过程,也就是常说的后处理。有了这些屏幕效果,我们就可以用 Bloom,Motion Blur 和 HDR 效果等技术创建出一些惊奇的实时图像。当今游戏市场推出的大部分游戏在 景深(depth of field) 效果,辉光(bloom) 效果甚至 颜色修正(color correction) 效果上都大量使用了屏幕效果。 通过这个章节,你将会学习如何构建一个如何去控制这些屏幕效果的脚本系统。我们将会涵盖 渲染纹理(Render Texture),深度缓冲(depth buffer),以及如何创建一个类Photoshop感的效果,从而去控制游戏的最终渲染图片的效果。通过为你的游戏使用屏幕效果,你不经可以完成你的着色器编写知识,同时你还将会拥有在Unity中创自己那些不可思议的渲染器的能力。 设置屏幕效果脚本系统 创建屏幕效果是这么一个过程,我们先抓取一张全屏的图像(或者纹理),然后用一个着色器在GPU中去处理它的像素,之后再把它发回给Unity的渲染器并且应用到游戏的整个渲染好的图像上去。这样的话就允许我们实时的在游戏的渲染图片上进行逐像素操作了,从而使我们对艺术效果有更广的控制。 试想一下如果你不得不仔细检查并且调节你游戏中每一个游戏对象上的每个材质,而这么做仅仅是想调节游戏最终视效的对比度。尽管可行,但还是有点费事。通过利用屏幕效果,我们就可以整个的调整屏幕的最终效果,因此对于有些最终呈现我们能获得更强的 类Photoshop(Photoshop-like) 的控制。 为了建立起一个屏幕效果系统并且使它成功运行,我们需要准备一个脚本来跟游戏当前的渲染图片进行通信,这个 渲染图片(rendered image) 就是Unity中的 渲染纹理(Render Texture)。利用这个脚本将渲染纹理传给着色器,我们能创建一个灵活的系统来创建屏幕效果。对于我们的第一个屏幕效果,我们将创建一个非常简单的灰度效果,这个效果可以让我们的游戏看起来是黑白的效果。让我们拭目以待。 始前准备 为了构建好我们的屏幕效果系统并且顺利运行,我们需要为当前的Unity工程创建一些资产。为了获得这些,跟着下面的步骤走就对了: 1.在当前的项目中,我们创建一个名为 TestRenderImage.cs 的脚本。 2.创建一个新的着色器,命名为 ImageEffect.shader。 3.在场景中新建一个球体并且为其添加一个新的材质球,新材质可以任意,比如我们创建了一个简单的红色的,带有高光的材质球。 4.最后,创建一个新的方向光,然后保存场景。 当我们把所有的资源准备好后,就等于是简单的设置好了场景,看起来就跟下图一样: 操作步骤 为了让我们灰度屏幕效果能运行,我们需要一个脚本和着色器。我们将会在这里完成这新的两项并且给它们添加合适的代码从而生成我们的第一个屏幕效果。我们的首个任务就是完成C#脚本。这样可以让我们的整个系统跑起。在这之后,我们将会完成着色器的编写并且看到我们的屏幕效果。让我们通过下面的步骤完成我们的脚本和着色器: 1.打开 TestRenderImage.cs 这个脚本并且添加一些变量好让我们能保存导入的游戏对象和数据。在 TestRenderImage 这个类的最上面添加下面的代码: public class TestRenderImage : MonoBehaviour { #region Variables public Shader curShader; public float grayScaleAmount = 1....

April 2, 2023 · 3 min · 546 words · Link

针对移动设备修改着色器

针对移动设备修改着色器 我们在优化着色器这方面已经了解了较多的技术了,现在让我们来了解如何为移动设备编写高效,高质量的着色器代码。对于我们已经写好的着色器代码,通过一些小的修改让他们能在移动设备上高速运行好事比较简单的。这里包含了使用 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

实现范围体爆炸

实现范围体爆炸 对于实现游戏中的艺术效果,有时候需要在画质和运行效率上进行巧妙的权衡。在实现爆炸效果上尤其如此;因为它是很多游戏的核心效果,但是在它之后的一些物理计算通常都会超过现代计算机的算力。爆炸本质上就是一团温度非常高的火红气体;所以正确模拟它的唯一方式就是在游戏中用流体模拟来模拟它。正如你所想的一样,这在运行时是不可行的,在很多的游戏中都是通过粒子来模拟。当一个物体爆炸的时候,通常会同时产生很多的火花,烟雾和一些散落的碎片,这样可以获得一个比较像的爆炸。不幸的是,这种模拟方法很容易被看破而且可能不是很真实。这里我们会了解一种折中的技术来实现爆炸效果,并且画质更好:范围体爆炸(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

实现下雪效果着色器

实现下雪效果着色器 在游戏中模拟下雪效果一直都是一件有挑战的事情。大部分的游戏都会简单的直接在模型的纹理上包含雪,让这些模型看起来雪白。然而要是其中某个模型开始旋转了呢?雪并不是敷衍了事的表面工作;它应该被当做是一些材料的合理的堆积【意思是物体表面 的雪是雪花一点一点堆积起来的,而不是简简单单的给它一张白色的贴图】。在这个知识点中将会向你展示如何用一个着色器让你的模型看起来有种下雪的样子。 要完成这个效果有两个步骤。首先,对于朝向天空的三角面我们给它白色。其次,通过挤压顶点来模拟雪的堆积效果。你可以从下图看到最终的效果: 注意 本知识点并无意去创建那种超真实的下雪效果。它只是抛砖引玉,但在你的游戏当中,最终的效果定位,还是取决于你们的艺术家们,通过他们设置正确的纹理和参数来达到你的要求。 始前准备 这个效果完全基于着色器来实现,所以请按照下面的步骤操作: 1.为雪的效果创建一个新的着色器。 2.为这个着色器创建一个新的材质。 3.把这个材质添加到你想表现雪的效果的模型上去。 操作步骤 为了创建下雪的效果,请打开你的着色器,然后做以下的修改: 1.把下面的属性块替换掉你原来的着色器属性块: _MainColor("Main Color", Color) = (1.0,1.0,1.0,1.0) _MainTex("Base (RGB)", 2D) = "white" {} _Bump("Bump", 2D) = "bump" {} _Snow("Level of snow", Range(1, -1)) = 1 _SnowColor("Color of snow", Color) = (1.0,1.0,1.0,1.0) _SnowDirection("Direction of snow", Vector) = (0,1,0) _SnowDepth("Depth of snow", Range(0,1)) = 0 2.添加与属性块对应的变量: sampler2D _MainTex; sampler2D _Bump; float _Snow; float4 _SnowColor; float4 _MainColor; float4 _SnowDirection; float _SnowDepth; 3....

July 17, 2022 · 2 min · 232 words · Link