Unity通过深度图做有交互效果的水泡沫

这篇具有很好参考价值的文章主要介绍了Unity通过深度图做有交互效果的水泡沫。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

通过深度图做交互水泡沫

大家好,我是阿赵。
这里做一个有交互效果的水面,物体浸入水面时,会根据物体的形状,有一圈水泡沫的效果,并且水泡沫的形状会跟随这物体变化。由于想做得稍微完整一点,又不想其他效果太强泡沫的风头,所以简单加了一个水面纹理流动的效果,却没有加水的反射高光之类的效果,主要是突出泡沫。
而这篇文章主要想说明的就是怎样获取深度图,和怎样求出模型重叠的部分和重叠的边缘。
unity气泡效果,unity,游戏引擎,深度图,水泡沫

一、场景的搭建。

unity气泡效果,unity,游戏引擎,深度图,水泡沫

这个场景很简单,只是一个用Cube围起来的水池,然后有一个水面的面片,水里面有一个球和一个Cube立方体。
为了能让最后的泡沫形状变化看得更容易,所以我给球和立方体简单的做了一个动画,球是在水中浮沉,然后立方体是在水面移动。

二、深度图计算

unity气泡效果,unity,游戏引擎,深度图,水泡沫

在Unity渲染的过程中,是会产生一张深度图信息的。
通过在Shader里面声明深度图,可以获取得到
//声明获取摄像机深度图
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
uniform float4 _CameraDepthTexture_TexelSize;
然后因为需要和屏幕渲染的图形深度匹配,所以还需要用屏幕坐标的齐次坐标去采样这张深度图
//计算齐次坐标
float4 screenPosNorm = screenPos / screenPos.w;
screenPosNorm.z = (UNITY_NEAR_CLIP_VALUE >= 0) ? screenPosNorm.z : screenPosNorm.z * 0.5 + 0.5;
//采样深度贴图,由于深度图并不是线性渐变过渡的,所以用LinearEyeDepth转换成线性变化
float screenDepthVal = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screenPosNorm.xy).r);

由于深度图只需要r通道的信息,所以看起来是红色深浅渐变的一种效果。

忽略了颜色,只看黑白作为深度,会是这样。
unity气泡效果,unity,游戏引擎,深度图,水泡沫
说明一下,对于眼睛观察的角度来说,这个深度图是非线性效果,所以不会出现很明显的线性渐变,这里需要使用LinearEyeDepth去把这个深度值转换成线性。

接下来,如果我们用屏幕的齐次坐标和深度相减然后去绝对值,可以求出模型边缘相交的部分
float distanceDepthVal = abs((screenDepthVal - LinearEyeDepth(screenPosNorm.z));
unity气泡效果,unity,游戏引擎,深度图,水泡沫

这时候看到黑色的部分就是模型穿插的部分,范围比较大,把整个球和立方体插入水中的部分都看到了。
我们可以通过一个距离值来控制一下黑色的范围:
float distanceDepthVal = abs((screenDepthVal - LinearEyeDepth(screenPosNorm.z)) / (distance));
unity气泡效果,unity,游戏引擎,深度图,水泡沫

这时候,就还有刚刚开始相交的小部分地方会有黑色。
由于我们想在边缘叠加东西,所以一般来说会用取反的方法,把黑白翻转,变成这样
unity气泡效果,unity,游戏引擎,深度图,水泡沫

然后再给白色的部分叠加泡沫的贴图。我这里就随便给一张噪声图来模拟了泡沫了:
unity气泡效果,unity,游戏引擎,深度图,水泡沫

再加上衬托用的水基础波纹的颜色,结果会变成这样:

unity气泡效果,unity,游戏引擎,深度图,水泡沫

上面计算模型相交的深度渐变的过程,一般成为DepthFade,我把它独立成一个方法,以后有需要就可以复用。其实DepthFade是一种比较常用的技术,所以在ASE之类的编辑器里面,直接就有现成的节点可以用
unity气泡效果,unity,游戏引擎,深度图,水泡沫文章来源地址https://www.toymoban.com/news/detail-664695.html

三、完整Shader:

Shader "azhao/WaterDepth"
{
	Properties
	{
		_distance("distance", Range( 0 , 2)) = 0
		_WaterColor("WaterColor", Color) = (0.5471698,0.5471698,0.5471698,0)
		_noiseMap("noiseMap", 2D) = "white" {}
		_speed("speed", Vector) = (0,0,0,0)
		_speed2("speed2", Vector) = (0,0,0,0)
		_depthMul("DepthMul", Range( 0 , 2)) = 1
		_WaterTex("WaterTex", 2D) = "white" {}
		_water1Mul("water1Mul", Range( 0 , 1)) = 0
		_water2Mul("water2Mul", Range( 0 , 1)) = 0
		_alpha("alpha", Range( 0 , 1)) = 1

	}
	
	SubShader
	{
		
		
		Tags { "Queue"="Transparent" }
	LOD 100


		Blend SrcAlpha OneMinusSrcAlpha
		Cull Back
		ZWrite Off
		Pass
		{
			Name "Unlit"
			Tags { "LightMode"="ForwardBase" }
			CGPROGRAM
	
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"



			struct appdata
			{
				float4 vertex : POSITION;
				float4 color : COLOR;
				float2 uv : TEXCOORD0;

			};
			
			struct v2f
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
				float4 screenUV : TEXCOORD1;

			};

			uniform float4 _WaterColor;
			uniform sampler2D _WaterTex;
			uniform float4 _WaterTex_ST;
			uniform float2 _speed;
			uniform float _water1Mul;
			uniform float2 _speed2;
			uniform float _water2Mul;
			uniform sampler2D _noiseMap;
			uniform float4 _noiseMap_ST;
			
			uniform float _distance;
			uniform float _depthMul;
			uniform float _alpha;
			//声明获取摄像机深度图
			UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
			uniform float4 _CameraDepthTexture_TexelSize;

			//计算相交深度渐变的值
			float DepthFade(float4 screenPos, float distance)
			{
				//计算齐次坐标
				float4 screenPosNorm = screenPos / screenPos.w;
				screenPosNorm.z = (UNITY_NEAR_CLIP_VALUE >= 0) ? screenPosNorm.z : screenPosNorm.z * 0.5 + 0.5;
				//采样深度贴图,由于深度图并不是线性渐变过渡的,所以用LinearEyeDepth转换成线性变化
				float screenDepthVal = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screenPosNorm.xy).r);
				//关键的一步,屏幕的齐次坐标的z轴同样转换成线性,然后和深度图的值相减
				float distanceDepthVal = abs((screenDepthVal - LinearEyeDepth(screenPosNorm.z)) / (distance));
				return distanceDepthVal;
			}

			v2f vert ( appdata v )
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				//ComputeScreenPos一定要在顶点程序计算
				float4 screenPos = ComputeScreenPos(o.pos);
				o.screenUV = screenPos;				
				o.uv = v.uv;
				return o;
			}
			
			half4 frag (v2f i ) : SV_Target
			{
				float2 uv_WaterTex = i.uv.xy * _WaterTex_ST.xy + _WaterTex_ST.zw;
				float2 uv_noiseMap = i.uv.xy * _noiseMap_ST.xy + _noiseMap_ST.zw;
				//输入屏幕UV坐标和距离,计算需要显示的深度值
				float distanceDepthVal = DepthFade(i.screenUV, _distance);
				//通过深度值计算泡沫显示的范围
				float foamVal = (1-saturate(distanceDepthVal)) * _depthMul;
				//为了让边缘产生不规则,所以读取了一张噪声图,再乘以上面的泡沫深度值
				float4 foamCol = tex2D(_noiseMap, uv_noiseMap) * foamVal;

				//为了demo看起来稍微完整而加的2个水波纹叠加,不是重点,不用在意
				float4 waveCol1 = tex2D(_WaterTex, (uv_WaterTex + (_speed * _Time.y))) * _water1Mul;
				float4 waveCol2 = tex2D(_WaterTex, (uv_WaterTex + (_speed2 * _Time.y)))* _water2Mul;
				//最终颜色是水波纹+泡沫
				float3 finalRGB = (_WaterColor*(waveCol1 + waveCol2) + foamCol).rgb;
				finalRGB = clamp(finalRGB, float3( 0,0,0 ) , float3( 1,1,1 ) );
				half4 finalCol =half4( finalRGB, _alpha);
				return finalCol;
			}
			ENDCG
		}
	}
}

到了这里,关于Unity通过深度图做有交互效果的水泡沫的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何通过代码在Unity设置URP通用渲染管线资源的画质选项、后处理效果、渲染分辨率、抗锯齿效果、Renderer Features等效果并制作一个可以设置它们的UI

       Hello喔 这里是没有鱼的猫先生,本期文章的主题佬们有看到标题了 QWQ    当使用Urp管道项目时,我们需要在一个Urp通用管线资源的项目中修改它的各种效果以玩家自己设置不同的画质需求,那下面这个通用脚本便诞生了,它也许并不适用于所有的场景,但是相信应用过它

    2024年02月09日
    浏览(42)
  • GAN(Generative Adversarial Network)作为深度学习领域中的一种生成模型,近年来在图像、音频等多种模态数据上取得了良好的效果。其核心思想就是通过博弈论中的对抗训练方式

    作者:禅与计算机程序设计艺术 GAN(Generative Adversarial Network)作为深度学习领域中的一种生成模型,近年来在图像、音频等多种模态数据上取得了良好的效果。其核心思想就是通过博弈论中的对抗训练方式,让两个网络(一个生成网络G和一个判别网络D)互相竞争,不断提升

    2024年02月07日
    浏览(46)
  • 10个常见渐变交互效果

    说明:这个案例创建了一个矩形区域,当鼠标悬停时,背景从完全透明到纯红色渐变,再从纯红色渐变到完全透明。 说明:这个案例创建了一个标题,当鼠标悬停时,文字颜色从红色渐变到蓝色,并且背景渐变也相应改变。 说明:这个案例创建了一个正方形区域,在其中心

    2024年02月12日
    浏览(43)
  • 毛玻璃动画交互效果

    从上述的效果展示页面结构来看,页面布局都是比较简单的,只是元素的动画交互比较麻烦。 第一个动画交互是两个圆相互交错来回运动。第二个动画交互是三角绕着圆进行 360 度旋转。 animation animation-delay 绝对定位布局 第一个动画是两个圆来回交互运动。 第二个动画交互

    2024年02月07日
    浏览(39)
  • 记录vue项目用到的水波纹 百分比 进度

     echarts-liquidfill  git地址:mirrors / ecomfe / echarts-liquidfill · GitCode 示例:echarts图表集 前置条件,安装echarts,同时还需要安装echarts-liquidfill 注意 :echarts-liquidfill@3 版本匹配 echarts@5 版本,echarts-liquidfill@2 版本匹配 echarts@4 版本 在main.js中引入 初始化图形方法

    2024年02月16日
    浏览(48)
  • Ajax(实现前后端交互效果)

    Ajax学习目标: 能够知道和服务器相关的基本概念;知道客户端和服务器通信的过程;什么是Ajax以及应用场景,知道接口和接口文档的概念。 1.客户端和服务器概念: 上网的本质目的:通过互联网的形式来获取和消费资源; 服务器:上网过程中,负责存放和对外提供资源的

    2024年02月05日
    浏览(50)
  • JavaScript实现液体流动效果和鼠标交互

    在现代Web应用中,动态效果和交互性已经成为了不可或缺的元素。在这篇博客中,我们将使用JavaScript创建一个液体流动效果,并添加鼠标交互功能,让用户能够与页面进行互动。 创建画布和粒子 首先,我们需要创建一个画布元素,用于绘制我们的液体流动效果。在HTML中添加

    2024年02月13日
    浏览(51)
  • C#实现3D模型的动画效果和交互设计

    介绍3D模型动画效果和交互功能的概念和作用 介绍3D模型动画效果和交互功能的概念和作用: 3D模型动画效果是指通过对3D模型进行动态的变化和运动,使其呈现出生动的效果,增强用户的视觉体验。交互功能则是指用户可以通过操作3D模型来实现一些特定的功能,例如旋转、

    2024年02月08日
    浏览(51)
  • Axure 折叠面板(手风琴)动态交互效果制作

    什么是折叠面板? 折叠面板可能是响应式设计中的最重要主力。这是一个非常有用的逐步呈现的模型——突出显示每个部分的重要细节,必要时利用点击来显示更多详细信息。因此,设计始终集中在最先显示的关键信息上,以便其他一切都易于访问。 效果预览地址:http://

    2024年02月05日
    浏览(52)
  • web前端之小功能聚集、简单交互效果

    效果图 html style 效果图 html style 效果图 html JavaScript style html style

    2024年03月23日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包