我是靠谱客的博主 伶俐未来,最近开发中收集的这篇文章主要介绍Shader实现瓶内液体效果(原码),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在这里插入图片描述
继上一篇:Shader实现瓶内液体效果
https://blog.csdn.net/ww1351646544/article/details/98632525
私聊我同朋友还是不少,为了能和大家一起学习进步下面把完整原码发出来。
不明白的同学可以结合上面的文章阅读,也可以问我,谢谢。
欢迎指正点赞…!

2022年02月07日补充:
https://download.csdn.net/download/ww1351646544/79578284
继说明和原码说明后仍有部分小伙伴不明白,可以此下载Demo进行参考。
在这里插入图片描述

SetWaterHeight
这个脚本挂在物体上,并且给他一个空物体以确定水平线的高度,这个空物体也要在主物体的子级下。

using System.Collections.Generic;
using UnityEngine;

public class SetWaterHeight : MonoBehaviour
{
    public Transform Target;
    private MeshRenderer m;
    private Material material;
    private Vector3 LastPos;
    private List<float> ArrLastPos;
    private float force;
    private float damp;
    private float JitterScale;

    // Use this for initialization
    void Start()
    {
        m = transform.GetComponent<MeshRenderer>();
        if (m != null) material = m.material;
        LastPos = transform.position;
        ArrLastPos = new List<float>();
    }

    // Update is called once per frame
    void Update()
    {
        if (material != null && Target != null)
        {
            __SetCurrentPos();
            __TheJitter();
        }
        if (Input.GetMouseButtonDown(0))
        {
            damp = 0.3f;
        }
    }

    /// <summary>
    /// 设置当前位置
    /// </summary>
    private void __SetCurrentPos()
    {
        material.SetFloat("_LevelOfWaterX", Target.position.x);
        material.SetFloat("_LevelOfWaterY", Target.position.y);
        material.SetFloat("_LevelOfWaterZ", Target.position.z);
    }

    /// <summary>
    /// 抖动计算
    /// </summary>
    private void __TheJitter()
    {
        //顺序不可变
        if (transform.position == LastPos && ArrLastPos.Count != 0)
        {
            float distance = 0;
            for (int i = 0; i < ArrLastPos.Count; i++)
            {
                distance += ArrLastPos[i];
            }
            distance /= ArrLastPos.Count;
            damp = distance * 15f;

            ArrLastPos = new List<float>();
        }

        if (transform.position != LastPos)
        {
            ArrLastPos.Add(Vector3.Distance(transform.position, LastPos));
            LastPos = transform.position;
        }

        if (damp != 0)
        {
            force += 0.5f;
            if (damp < 0.005f)
            {
                damp = 0;
            }

            JitterScale = Mathf.Sin(force) * damp;
            material.SetFloat("_LevelOfWaterOffsetScale", JitterScale);
            damp *= 0.95f;
        }
    }
}

ChemicalWarp_Move_Color

Shader "GiraffeShader/ChemicalWarp_Move_Color" {
Properties {
		_MainTex ("Main Tex", 2D) = "white" {}
		//玻璃的法线纹理
		_BumpMap ("Normal Map", 2D) = "bump" {}
		//折射图扭曲程度
		_Distortion ("Distortion", Range(0, 10000)) = 10
		//折射效果
		_RefractAmount ("Refract Amount", Range(0.0, 1.0)) = 0.5
		//流动速度
		_WaveSpeed("WaveSpeed",Range(-2.0, 2.0))=1
		//附加颜色
		_AdditionColor("AdditionColor",Color) = (1,1,1,1)
		//水面偏移比例
		_LevelOfWaterOffsetScale("LevelOfWaterOffsetScale",Range(-1,1)) = 0
		//水平面高度X
		_LevelOfWaterX("LevelOfWaterX",float) = 0
		//水平面高度Y
		_LevelOfWaterY("LevelOfWaterY",float) = 0
		//水平面高度Z
		_LevelOfWaterZ("LevelOfWaterZ",float) = 0
	}
	SubShader {
		// 因为玻璃的,这里我们需要做透明混合
		Tags { "Queue"="Transparent" "RenderType"="Opaque" }
		Cull Off
		//关闭深度写入
		//ZWrite off
		//源因子:透明度            目标因子:1-源因子透明度
		//最后会把源因子和目标因子相乘得到最终结果
		//Blend SrcAlpha OneMinusSrcAlpha
		//这是一个抓取屏幕图像的Pass,会把图像存进_RefractionTex这个变量中
		GrabPass { "_RefractionTex" }
		
		Pass {		
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			
			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _BumpMap;
			float4 _BumpMap_ST;
			float _Distortion;
			fixed _RefractAmount;
			sampler2D _RefractionTex;
			float4 _RefractionTex_TexelSize;
			float _WaveSpeed;
			float4 _AdditionColor;
			float _LevelOfWaterOffsetScale;
			float _LevelOfWaterX;
			float _LevelOfWaterY;
			float _LevelOfWaterZ;

			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 tangent : TANGENT; 
				float2 texcoord: TEXCOORD0;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float4 scrPos : TEXCOORD0;
				float4 uv : TEXCOORD1;
				float4 TtoW0 : TEXCOORD2;  
			    float4 TtoW1 : TEXCOORD3;  
			    float4 TtoW2 : TEXCOORD4; 
				float4 objpos:TEXCOORD5;
			};
			
			v2f vert (a2v v) {
				v2f o;
				
				o.pos = UnityObjectToClipPos(v.vertex);
				//TRANSFORM_TEX 想当于 v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
				
				//世界空间下顶点位置
				float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
				//世界空间下法线位置
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
				//世界空间下切线位置
				fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
				//世界空间副切线位置
				fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 
				
				//这里的TtoW0、TtoW1、TtoW2 的xyz列排构成了一个转置到世界空间的矩阵
				o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);  
				o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);  
				o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);  

				o.objpos = v.vertex;
				
				//齐次坐标系下的屏幕坐标值
				o.scrPos = ComputeGrabScreenPos(o.pos);
				
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target {

				//世界坐标下的位置第一组纹理坐标的分量
				float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);

				//float3 unreal = float3(_LevelOfWaterX,_LevelOfWaterY,_LevelOfWaterZ);
				//float curHeight= UnityWorldToObjectDir(unreal).y;
				//与中心点距离(_LevelOfWaterOffsetScale是有正负值的摆动比例)
				float centerDistance = (worldPos.x -_LevelOfWaterX)*_LevelOfWaterOffsetScale;
				//波动值影响裁剪高度
				float heightOffset = _LevelOfWaterY +centerDistance;
				//高于指定高度则裁剪
				if(worldPos.y>heightOffset)clip(-1);
					
				//return fixed4(1,0,0,1);
				fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

				i.uv.z+=_SinTime.x*_WaveSpeed;
				i.uv.w-= _CosTime.x*_WaveSpeed;

				// 取切线空间中的法线
				fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));	
				
				// 计算切线空间中的偏移
				float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;

				i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
				fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;
				
				// 把法线转到世界空间
				bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
				//反射光计算 根据入射光方向,和顶点法向量,计算反射光方向向量。
				fixed3 reflDir = reflect(-worldViewDir, bump);
				//取主图颜色
				fixed4 texColor = tex2D(_MainTex, i.uv.xy);
				
				//调节一下扭曲的程度,得到最终的颜色
				fixed3 finalColor = texColor * (1 - _RefractAmount) + refrCol * _RefractAmount;
				finalColor *=_AdditionColor;
			
				return fixed4(finalColor, 1);
			}
			
			ENDCG
		}
	}
	FallBack "Diffuse"
}

最后

以上就是伶俐未来为你收集整理的Shader实现瓶内液体效果(原码)的全部内容,希望文章能够帮你解决Shader实现瓶内液体效果(原码)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部