您当前的位置: 首页 >> 智能 > >> 内容页

常用Shader写法-1 世界热头条

2023-03-24 20:55:17 来源:哔哩哔哩

声明标签:

[Header(分组名)]:分组并定义分组名


【资料图】

[Enum(CustomEnum1,1,CustomEnum2,2)]:枚举,类型为float

[IntRange]:将Range变量的调整范围改为整数

[Toggle]:在声明shader的float变量时,添加此声明可转换为勾选,默认值为(0,1)。计算时实现效果可使用lerp方法。

[MaterialToggle]:在声明shader的float变量时,添加此声明可转换为勾选,默认值为(0,1)。计算时实现效果可使用lerp方法。

[HDR]:在声明shader的Color变量时,添加此声明可将颜色更换为HDR模式

[Space(int值,省略默认为1)]:空间划分间隔

Range(0, 1):在声明shader的float变量时,将float替换为Range(min,max)可实现滑块效果

一些内置枚举,参考:

[Header(Option)]

[Enum(UnityEngine.Rendering.BlendOp)]  _BlendOp  ("BlendOp", Float) = 0

[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("SrcBlend", Float) = 1

[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("DstBlend", Float) = 0

[Enum(Off, 0, On, 1)]_ZWriteMode ("ZWriteMode", float) = 1

[Enum(UnityEngine.Rendering.CullMode)]_CullMode ("CullMode", float) = 2

[Enum(UnityEngine.Rendering.CompareFunction)]_ZTestMode ("ZTestMode", Float) = 4

[Enum(UnityEngine.Rendering.ColorWriteMask)]_ColorMask ("ColorMask", Float) = 15

[Header(Stencil)]

[Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp ("Stencil Comparison", Float) = 8

[Enum(UnityEngine.Rendering.StencilOp)]_StencilPass ("Stencil Pass", Float) = 0

[Enum(UnityEngine.Rendering.StencilOp)]_StencilFail ("Stencil Fail", Float) = 0

[Enum(UnityEngine.Rendering.StencilOp)]_StencilZFail ("Stencil ZFail", Float) = 0

方法:

Round:四舍五入

Clamp:限制大小

Muitply:相乘

dot():点乘

mul():相乘

lerp(x, y, z):插值。z为0则x,z为1则y。

reflect(x,y):基于向量y得到向量x的反射向量

pow(x,y):x的y次方

max(x,y):取x与y中更大的值

API:

UnityObjectToClipPos():传入顶点,传出裁剪空间顶点,用SV_POSITION存储。

UnityObjectToWorldNormal():传入法线,输出世界空间法线,用TEXCOORD存储。

unity_ObjectToWorld:矩阵,可用于转换顶点到世界空间下,用mul相乘。

_WorldSpaceCameraPos:世界空间摄像机坐标。

_WorldSpaceLightPos0:世界空间灯光向量。

公式:

兰伯特:

模型法线乘以光的反方向并归一化。

半兰伯特:

模型法线乘以光的反方向并乘以0.5再加上0.5。

Phong高光:

光方向与模型法线进行reflect得到光的反射方向后,点乘视角方向,得到高光。

BlinnPhong高光:

光方向乘以视角方向归一化的值,乘以法线得到Blinn高光。

Ramp贴图:

将兰伯特的值作为u坐标,再传入一个v坐标,合并作为贴图的uv。

屏幕空间贴图:

屏幕空间坐标转贴图uv。

屏幕空间贴图(可缩放):

屏幕空间坐标乘以深度的积转贴图uv。

网点效果:

屏幕坐标乘以缩放变量(也可继续乘以深度)后,取余,将0~1的值映射到-0.5~0.5,再取点的长度,可得程序化网点遮罩。(可用round使网点有清晰边缘)

环境光:

环境光可以通过给一个颜色来伪装环境光,具体实现方法:

上环境光可以通过法线的g通道得到

下环境光可以通过法线的g通道的负值得到

中间环境光可以通过1减上环境光减去下环境光得到

各个值归一化乘以颜色相加,得到环境光。

法线贴图:

输入结构添加TANGENT(切线),输出结构添加法线、切线、副切线,在顶点着色器计算三个线,在片元着色器通过UnpackNormal(tex2D(贴图,uv))转换法线贴图,将法线、切线、副切线合成为float3x3(切线、副切线、法线)结构,乘以贴图后的值,替换兰伯特光照的法线,得到法线效果。

TBN = Tangent BiTangent Normal = float3x3(切线、副切线、法线)

传入一个v,包含模型基础信息。

normal = UnityObjectToWorldNormal(v.normal);

tangentDir = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);

bitangentDir = normalize(cross(normal, tangentDir) * v.tangent.w);

菲涅尔效果:

模型法线点乘视角方向,再被1减去,得到菲涅尔效果。

顶点着色器中要将顶点转化到世界空间,片元着色器中可用摄像机坐标减去顶点坐标得到视角方向。

顶点转换到世界空间,可将顶点坐标添加一个值作为四维数,乘以矩阵 unity_ObjectToWorld 得到世界空间顶点。

摄像机坐标可用 _WorldSpaceCameraPos.xyz 获得

模型法线的绿通道乘以菲涅尔,可得到上下的菲涅尔效果。

Matcap贴图:

一种仿PBR效果的方式,可以有效节约资源,缺点是不适合动态物体。

世界空间法线与矩阵 UNITY_MATRIX_V 相乘,得到屏幕空间法线。将得到的三维数取x和y,乘以0.5加0.5,得到的值作为取样贴图的uv,即可得到效果。

Mip贴图:

一种仿反射天空效果的贴图方式。

声明Cube格式的贴图,再声明一个float作为LOD(模糊程度)

顶点着色器中要将顶点转化到世界空间,片元着色器中可用摄像机坐标减去顶点坐标得到视角方向。

顶点转换到世界空间,可将顶点坐标添加一个值作为四维数,乘以矩阵 unity_ObjectToWorld 得到世界空间顶点。

摄像机坐标可用 _WorldSpaceCameraPos.xyz 获得

再通过reflect得到负的视角方向基于法线的反射方向(视角方向为以模型顶点为起点,摄像机方向的矢量。它的负值即将方向变为反向,从摄像机到顶点)

得到的反射为float3,再添上声明的LOD作为float4,合并的值通过

texCUBElod(Mip贴图,合并的float4) 取得颜色得到结果。

阴影:

编写前须引入4个库:

#include "UnityCG.cginc"

#include "AutoLight.cginc"

#include "Lighting.cginc"

#pragma multi_compile_fwdbase

输入到裁剪空间的顶点坐标要固定名称为pos

输出结构内要声明

LIGHTING_COORD(X,Y)(x和y代指TEXCOORDX和TEXCOORDY)

顶点着色器中将坐标转换裁剪空间后,执行方法:

TRANSFER_VERTEX_TO_FRAGMENT(传出的值)

在片元着色器中取float值:LIGHT_ATTENUATION(传入值),乘以颜色即可。

关键词:
分享到:

Copyright   2015-2022 起点时尚网版权所有   备案号:皖ICP备2022009963号-12   联系邮箱: 39 60 29 14 2@qq.com