unity改变intensity_Unity Surface Shader——自定义顶点修改函数

本文通过一个飞毯效果的案例,详细讲解如何在Unity中使用Surface Shader自定义顶点函数,实现物体的动态起伏效果。内容包括Shader的编写,如定义Inspector属性、渲染类型和顺序、顶点函数及表面函数的实现,同时展示了最终的飞毯飞行效果和投影计算的准确性。
摘要由CSDN通过智能技术生成

拿一个飞毯效果作为讲解案例,开始之前先展示最终效果:最终效果

准备工作在新场景里创建两个Plane,一个名为Ground,一个名为Carpet,缩放到适合的大小

创建两个材质,跟两个Plane的名字保持一致,并赋予给上一步创建的Plane

自己找适合的地面贴图贴在Ground材质上即可

新建SurfaceShader,拖给Carpet材质,然后开始编写shader

定义Inspector属性

Properties

{

_MainTex ("Albedo (RGBA)", 2D) = "white" {}

_AlphaTest("AlphaTest", Range(0, 1)) = 0

_MetallicTex("Metallic", 2D) = "white"{}

_Metallic ("Intensity", Range(0,1)) = 0.0

_SmoothnessTex("Smoothness", 2D) = "white"{}

_Smoothness ("Intensity", Range(0,1)) = 0

_NormalTex("Normal", 2D) = "bump"

_Normal("Intensity", float) = 1

_Speed("Speed", float) = 1

_Frequency("Frequency", float) = 1

_Amplitude("Amplitude", float) = 1

}定义了物理材质常用的Albedo、Metallic、Smoothness、Normal

然后又定义了飞毯的飞行速度,波浪出现的频率和波浪起伏的高度

_AlphaTest属性是为了接下来传给alphatest,用于像素裁切

渲染类型、顺序、光照模型等一系列设置

Tags

{

"RenderType" = "Opaque"

"Queue" = "AlphaTest"

}

LOD 200

CULL Off

CGPROGRAM

#pragma surface surf Standard fullforwardshadows vertex:vert addshadow alphatest:_AlphaTest

#pragma target 3.0渲染类型为不透明

渲染顺序为透明度测试

CULL off:关闭模型面的剔除,这样模型的背面也会被渲染

使用默认的Standard光照模型

我们使用自定义的顶点函,命名为vert

修改了顶点函数之后,投影会出现跟模型不一致的现象,所以使用addshadow指令重新计算正确投影

透明类型为alphatest,然后把一开始定义的_AlphaTest属性传递过来,小于这个数值的像素会被裁切,大于这个数值的像素会被保留

定义属性和结构体

sampler2D _MainTex;

sampler2D _MetallicTex;

sampler2D _SmoothnessTex;

sampler2D _NormalTex;

struct Input

{

float2 uv_MainTex;

};

half _Smoothness;

half _Metallic;

float _Normal;

half _Speed;

half _Frequency;

half _Amplitude;在CG里重新定义之前的属性

定义Input结构体存储贴图坐标。

这里只是存储了Albedo贴图的坐标,接下来对所有贴图的采样都会使用Albedo的坐标,这么做有两大好处:减少插值寄存器的数量,节省性能消耗

在材质的Inspector上只需要修改Albedo即可调整所有贴图的UV坐标

定义顶点函数

void vert(inout appdata_full v)

{

float time = _Time.y * _Speed;

float offset = (sin(time + v.vertex.z * _Frequency)) * _Amplitude;

v.vertex.y += offset;

}这里使用了CG里提供的时间变量Time的y分量乘以_Speed属性,得到新的时间变量,以后我们就可以在材质的Inspector通过调节Speed属性控制飞毯的速度了

顶点z轴的坐标与_Frequency相乘,相当于对z轴进行了一个范围的缩放。然后跟time变量相加,是为了把顶点Z轴方向与时间结合在一起变为动态变量。经过sin处理之后,可以得出一个随时间推迟而循环浮动的偏移值。最后乘以_Amplitude属性可以控制偏移的大小

顶点的y方向加上这个偏移值,实现垂直方向上的上下浮动效果

定义表面函数

void surf (Input IN, inout SurfaceOutputStandard o)

{

fixed4 c = tex2D (_MainTex, IN.uv_MainTex);

o.Albedo = c.rgb;

o.Alpha = c.a;

o.Metallic = tex2D(_MetallicTex, IN.uv_MainTex) * _Metallic;

o.Smoothness = tex2D(_SmoothnessTex, IN.uv_MainTex) * _Smoothness;

fixed3 n = UnpackNormal(tex2D(_NormalTex, IN.uv_MainTex)).rgb;

n.x *= _Normal;

n.y *= _Normal;

o.Normal = n;

}

ENDCG使用Albedo贴图的坐标对所有的贴图进行采样,得出表面函数最终的输出变量

法线的x和y分量分别乘以_Normal属性,可以控制法线强度,最终输出到表面函数的法线变量

贴图

本次案例使用的是一张带有Alpha通道的贴图,Alpha通道用于透明测试。RGB通道A通道

Inspector参数设置

最后再展示一遍最终的效果:

从动图可以看出,地面上接受到了飞毯的动态投影,并且灯光也穿过了破洞,射在了地面上。

可以说投影计算的非常完美。

你可以使用Unity自带的RenderTexture来将ToonShader的效果输出为PNG图片。下面是一个简单的示例代码: ```csharp using UnityEngine; public class ToonShaderExporter : MonoBehaviour { public Shader toonShader; public RenderTexture renderTexture; public string outputFileName = "output.png"; private void Start() { // 创建RenderTexture,用于将ToonShader效果渲染到其中 renderTexture = new RenderTexture(Screen.width, Screen.height, 24); renderTexture.format = RenderTextureFormat.ARGB32; renderTexture.Create(); // 将相机的TargetTexture设置为renderTexture Camera.main.targetTexture = renderTexture; // 将ToonShader赋给相机的Material Camera.main.SetReplacementShader(toonShader, ""); // 渲染相机 Camera.main.Render(); // 恢复相机的TargetTexture为空 Camera.main.targetTexture = null; // 从renderTexture中读取像素数据 Texture2D texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false); RenderTexture.active = renderTexture; texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); texture.Apply(); RenderTexture.active = null; // 将像素数据保存为PNG图片 byte[] bytes = texture.EncodeToPNG(); System.IO.File.WriteAllBytes(outputFileName, bytes); // 销毁renderTexture和texture Destroy(renderTexture); Destroy(texture); } } ``` 将上述代码添加到一个空物体上,并将ToonShader赋给toonShader变量。然后运行游戏,代码会将ToonShader的效果渲染到RenderTexture,并将RenderTexture保存为PNG图片。最终的PNG图片会保存在Unity项目的根目录下,文件名为output.png。你可以根据需要修改输出文件名和路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值