概述
继上一篇: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实现瓶内液体效果(原码)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复