[Unity]摘录笔记UnityShader(Shader消融效果)

前言:
附上冯乐乐的CSDN博客
个人博客
《Unity Shader入门精要》
《Unity Shaders and Effects Cookbook》

一、知识链接

二、Shader——消融效果
Unity-Shader-Demo中DissolveEnvironment场景解读
Shader脚本

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Kaima/Dissolve/ToPoint"
{
	Properties
	{
	    //主贴图
		_MainTex ("Texture", 2D) = "white" {}
		//噪波贴图
		_NoiseTex("Noise", 2D) = "white" {}
		//阈值
		_Threshold("Threshold", Range(0.0, 1.0)) = 0.5
		//边的长度
		_EdgeLength("Edge Length", Range(0.0, 0.2)) = 0.1
		//斜坡贴图
		_RampTex("Ramp", 2D) = "white" {}
		//开始的点位
		_StartPoint("Start Point", Vector) = (0, 0, 0, 0)
		//最大的距离
		_MaxDistance("Max Distance", Float) = 0
		//目标效果
		_DistanceEffect("Distance Effect", Range(0.0, 1.0)) = 0.5
	}
	SubShader
	{
		Tags { "Queue"="Geometry" "RenderType"="Opaque" }

		Pass
		{
			Tags {"LightMode" = "ForwardBase"}
			Cull Off 

			CGPROGRAM
		    //把 vert 当做了顶点 shader 的入口
			#pragma vertex vert
			//把 frag 当做了片元着色 shader 的入口
			#pragma fragment frag
			
			//说明使用 即包含unity自带的CG程序方法
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			//结构体
			struct appdata
			{
			    //位置
				float4 vertex : POSITION;
				//法线
				float3 normal : NORMAL;
				//第一套纹理uv坐标
				float2 uv : TEXCOORD0;
			};

			//经过转换后的信息结构体
			struct v2f
			{  //SV_POSITION语意则用于像素着色器,用来标识经过顶点着色器变换之后的顶点坐标。https://blog.csdn.net/sgnyyy/article/details/70039412
				float4 vertex : SV_POSITION;
		       //TEXCOORD0 :第一套纹理uv坐标
               //TEXCOORD1 :第二套纹理uv坐标
               //TEXCOORD2 :第三套纹理uv坐标
               //TEXCOORD3 :第四套纹理uv坐标
               //TEXCOORD4 :第五套纹理uv坐标
				float2 uvMainTex : TEXCOORD0;
				float2 uvNoiseTex : TEXCOORD1;
				float2 uvRampTex : TEXCOORD2;
				float3 worldPos : TEXCOORD3;
				float3 worldNormal : TEXCOORD4;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _NoiseTex;
			float4 _NoiseTex_ST;
			float _Threshold;
			float _EdgeLength;
			sampler2D _RampTex;
			float4 _RampTex_ST;
			float _MaxDistance;
			float4 _StartPoint;
			float _DistanceEffect;
			//顶点 shader 的入口
			v2f vert (appdata v)
			{
				v2f o;
				//UNITY_MATRIX_MVP	当前模型视图投影矩阵
				//Unity3d中Shader的一些关于矩阵变换的基本信息https://blog.csdn.net/yutyliu/article/details/56013807
				// UnityObjectToClipPos 替代了 mul(UNITY_MATRIX_MVP,*) https://forum.unity.com/threads/regarding-unity_matrix_mvp-and-unityobjecttoclippos.460940/
				o.vertex = UnityObjectToClipPos(v.vertex);

				// TRANSFORM_TEX;根据顶点的纹理坐标,计算出对应的纹理的真正的UV坐标;
				o.uvMainTex = TRANSFORM_TEX(v.uv, _MainTex);
				o.uvNoiseTex = TRANSFORM_TEX(v.uv, _NoiseTex);
				o.uvRampTex = TRANSFORM_TEX(v.uv, _RampTex);

				// mul(unity_ObjectToWorld, v.vertex)把顶点从模型空间(物体的本地坐标空间)转化到世界空间中
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				//Transforms normal from object to world space 从物体到世界空间的法线转换
				o.worldNormal = UnityObjectToWorldNormal(v.normal);

				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
			   
				float dist = length(i.worldPos.xyz - _StartPoint.xyz);
				float normalizedDist = 1 - saturate(dist / _MaxDistance);

				fixed cutout = tex2D(_NoiseTex, i.uvNoiseTex).r * (1 - _DistanceEffect) + normalizedDist * _DistanceEffect;
				clip(cutout -  );

				float degree = saturate((cutout - _Threshold) / _EdgeLength);
				fixed4 edgeColor = tex2D(_RampTex, float2(degree, degree));

				//加点漫反射
				fixed4 albedo = tex2D(_MainTex, i.uvMainTex);
				float3 worldNormal = normalize(i.worldNormal);
				float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed3 diffuse = _LightColor0.rgb * albedo.rgb * saturate(dot(worldNormal, worldLightDir));

				fixed4 finalColor = lerp(edgeColor, fixed4(diffuse, 1), degree);
				return fixed4(finalColor.rgb, 1);
			}
			ENDCG
		}
	}
}

主控脚本

using UnityEngine;
using System.Collections;

public class DissolveEnvironment : MonoBehaviour {
    public Vector3 dissolveStartPoint;
    [Range(0, 1)]
    public float dissolveThreshold = 0;
    [Range(0, 1)]
    public float distanceEffect = 0.6f;

	void Start () {
        //计算所有子物体到消融开始点的最大距离
        MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
        float maxDistance = 0;
        for(int i = 0; i < meshFilters.Length; i++)
        {
            float distance = CalculateMaxDistance(meshFilters[i].mesh.vertices);
            if (distance > maxDistance)
                maxDistance = distance;
        }
        //传值到Shader
        MeshRenderer[] meshRenderers = GetComponentsInChildren<MeshRenderer>();
        for(int i = 0; i < meshRenderers.Length; i++)
        {
            meshRenderers[i].material.SetVector("_StartPoint", dissolveStartPoint);
            meshRenderers[i].material.SetFloat("_MaxDistance", maxDistance);
        }
	}
	
	void Update () {
        //传值到Shader,为了方便控制所有子物体Material的值
        MeshRenderer[] meshRenderers = GetComponentsInChildren<MeshRenderer>();
        for (int i = 0; i < meshRenderers.Length; i++)
        {
            meshRenderers[i].material.SetFloat("_Threshold", dissolveThreshold);
            meshRenderers[i].material.SetFloat("_DistanceEffect", distanceEffect);
        }
    }

    //计算给定顶点集到消融开始点的最大距离
    float CalculateMaxDistance(Vector3[] vertices)
    {
        float maxDistance = 0;
        for(int i = 0; i < vertices.Length; i++)
        {
            Vector3 vert = vertices[i];
            float distance = (vert - dissolveStartPoint).magnitude;
            if (distance > maxDistance)
                maxDistance = distance;
        }
        return maxDistance;
    }
}

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值