目录
课时56:FragmentShader-片段级模型动态变色3
课时56:FragmentShader-片段级模型动态变色3
1.CheckVertex
public MeshFilter[] filters;
[ContextMenu("GetMaxVertex")]
private void GetMaxVertex()
{
foreach (var filter in filters)
{
var vertices = filter.mesh.vertices;
var max = vertices.Max(i => i.x);
var min = vertices.Min(i => i.x);
print(string.Format("{0} maxX:{1},minX:{2}", filter.name, max, min));
}
}
和教程有所不同,大体是这样的。
2.汽车模型
教程是一辆汽车模型,用于动态变色的,找模型找了一会。
找unity模型插件资源比找max模型方便,max模型的vray版本不统一,我的老是丢失材质。
Realistic Car HD 02 1.0.unitypackage:
3.修改shader,需要调整方向
效果:
设置个枚举变量
[Enum(X,1,Y,2,Z,3)] _Dir("Dir", Int) = 1
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
if (_Dir == 1) {
o.y = v.vertex.x;
}
if (_Dir == 2) {
o.y = v.vertex.y;
}
if (_Dir == 3) {
o.y = v.vertex.z;
}
return o;
}
效果:
门的部分和车主体是不同的模型,用模型坐标,就不连贯了,自己管自己的,除非模型上处理一下,合并成一个模型。
而用世界坐标的话,参数比较难设置,物体的绝对位置必须清楚,还和模型角度有关,除非和代码结合,用基于整个模型的局部坐标来设置参数。
用屏幕坐标:
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
if (_Dir == 1) {
o.y = v.vertex.x;
}
if (_Dir == 2) {
o.y = v.vertex.y;
}
if (_Dir == 3) {
o.y = v.vertex.z;
}
return o;
}
先不管了。
3.光照
前面的颜色是没有任何光照的,车体上的细节在一片纯色下面根本看不到。
方案是创建surfaceShader+vertex函数
默认的surfaceShader:
Shader "Custom/NewSurfaceShader 17"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
https://docs.unity3d.com/Manual/SL-SurfaceShaderExamples.html
需要的话,有空得把这些例子看看
移植改造后
Shader "Custom/NewSurfaceShader 17"
{
Properties
{
_MainColor("MainColor",color) = (1,1,1,1)
_SecondColor("SecondColor",color) = (1,1,1,1)
_CenterY("CenterY",range(-3,3)) = 0
[Enum(X,1,Y,2,Z,3)] _Dir("Dir", Int) = 1
_R("R",range(0,1)) = 0.1
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
//LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows vertex:vert
//#pragma surface surf Standard vertex:vert
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
fixed4 _MainColor;
fixed4 _SecondColor;
float _CenterY;
float _R;
int _Dir;
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
//float4 pos;
float y;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void vert (inout appdata_full v, out Input o) {
//UNITY_INITIALIZE_OUTPUT(Input,o);
//o.customColor = abs(v.normal);
o.uv_MainTex=v.texcoord.xy;
o.y=v.vertex.x;
float3 p = v.vertex;
//float3 p = o.pos;
if (_Dir == 1) {
o.y = p.x;
}
if (_Dir == 2) {
o.y = p.y;
}
if (_Dir == 3) {
o.y = p.z;
}
//return o;
}
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) ;
//o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
float d = IN.y - _CenterY;//到分界线的距离,(-0.5,0.5)
float s = abs(d);//距离的绝对值
float u = d / s;//1:在上方,-1:在下方
float f = s / _R;//距离相对于过渡区域的比例,在过渡区域内(0,1),在过渡区域外(1,...)
f = saturate(f);//限制在(0,1)范围,大于1的也是1,在过渡区域外则是 两种颜色之一,不融合。
float g = u * f;//给系数一个正负
//float l = g;
float l = g / 2 + 0.5;//从-1到1变成0,1
//在分界线上时,f=0,g=0,l=0.5,融合。
//在红色那边是,f=1,g=1,l=1;
//黄色那边,f=-1,g=-1,l=0;
o.Albedo= lerp(_SecondColor,_MainColor, l);
//o.Albedo= fixed4(1,0,0,1);
// if(IN.y>_CenterY)
// {
// o.Albedo=_MainColor;
// }
// else{
// o.Albedo=_SecondColor;
// }
}
ENDCG
}
FallBack "Diffuse"
}
1.添加属性
2.Input中添加y
3.通过vertex:vert,设置顶点函数
4.通过out Input o,将参数传递给surf
5.不知道v.vertex是模型坐标还是世界坐标...
最终效果配合脚本可以实现汽车整体涂色改变。
颜色有点暗,在最后乘上一个系数
o.Albedo= lerp(_SecondColor,_MainColor, l)* _Intensity;