Unity中URP实现水体(水下的扭曲)

2024-02-26 06:44

本文主要是介绍Unity中URP实现水体(水下的扭曲),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、使用一张法线纹理,作为水下扭曲的纹理
    • 1、在属性面板定义一个纹理,用于传入法线贴图
    • 2、在Pass中,定义对应的纹理和采样器
    • 3、在常量缓冲区,申明修改 Tilling 和 Offset 的ST
    • 4、在顶点着色器,计算得到 应用了 ST 和 随时间流动的UV,用于纹理采样(_WaterSpeed是上篇文章中用到的)
    • 5、在片元着色器中,对其进行法线纹理进行采样
  • 二、实现水下扭曲的效果
    • 1、定义一个扰度值,控制扭曲水下的扭曲程度
    • 2、在URP设置中,开启抓屏
    • 3、在Pass中,定义抓屏的 纹理 和 采样器
    • 4、使用线性插值后的结果,进行抓屏的纹理采样
    • 5、最后,与上篇文章计算得到的水的颜色混合
    • 请添加图片描述
  • 三、最终代码


前言

在上篇文章中,我们实现了水体中 和 物体接触时,产生泡沫的效果。

  • Unity中URP实现水体效果(泡沫)

在这篇文章中,我们在上一篇文章的基础上来实现水下扭曲的效果。


一、使用一张法线纹理,作为水下扭曲的纹理

原理:

  • Unity中Shader的UV扭曲效果的实现

1、在属性面板定义一个纹理,用于传入法线贴图

_DistortTex(“DistortNormalTex”,2D) = “white”{}

在这里插入图片描述

2、在Pass中,定义对应的纹理和采样器

TEXTURE2D(_DistortTex);SAMPLER(sampler_DistortTex);

3、在常量缓冲区,申明修改 Tilling 和 Offset 的ST

half4 _DistortTex_ST;

4、在顶点着色器,计算得到 应用了 ST 和 随时间流动的UV,用于纹理采样(_WaterSpeed是上篇文章中用到的)

o.uv.xy = TRANSFORM_TEX(v.uv,_DistortTex)+_Time.y * _WaterSpeed;

5、在片元着色器中,对其进行法线纹理进行采样

half4 distortTex = SAMPLE_TEXTURE2D(_DistortTex,sampler_DistortTex,i.uv.xy);


二、实现水下扭曲的效果

原理:把抓取到的屏幕纹理,使用进行流动扭曲

  • Unity中URP下抓屏的 开启 和 使用

1、定义一个扰度值,控制扭曲水下的扭曲程度

  • 屏幕UV 和 法线纹理扭曲之间线性插值

float2 distortUV = lerp(screenUV,distortTex,_Distort);

2、在URP设置中,开启抓屏

在这里插入图片描述

3、在Pass中,定义抓屏的 纹理 和 采样器

TEXTURE2D(_CameraOpaqueTexture);SAMPLER(sampler_CameraOpaqueTexture);

4、使用线性插值后的结果,进行抓屏的纹理采样

half4 cameraOpaqueTex = SAMPLE_TEXTURE2D(_CameraOpaqueTexture,sampler_CameraOpaqueTexture,distortUV);

请添加图片描述
请添加图片描述

5、最后,与上篇文章计算得到的水的颜色混合

col *= cameraOpaqueTex;

请添加图片描述

三、最终代码

//水的深度
Shader "MyShader/URP/P4_8"
{Properties {[Header(Base)]_WaterColor1("WaterColor1",Color) = (1,1,1,1)_WaterColor2("WaterColor2",Color) = (1,1,1,1)_WaterSpeed("WaterSpeed",Range(0,1)) = 0.1[Header(Foam)]_FoamTex("FoamTex",2D) = "white"{} _FoamColor("FoamColor",Color) = (1,1,1,1)_FoamRange("FoamRange",Range(0,5)) = 1_FoamNoise("FoamNoise",Range(0,3)) = 1[Header(Distort)]_DistortTex("DistortNormalTex",2D) = "white"{}[PowerSlider(3)]_Distort("Distort",Range(0,0.5)) = 0}SubShader{Tags{//告诉引擎,该Shader只用于 URP 渲染管线"RenderPipeline"="UniversalPipeline"//渲染类型"RenderType"="Transparent"//渲染队列"Queue"="Transparent"}//Blend SrcAlpha OneMinusSrcAlphaZWrite OffPass{Name "Unlit"HLSLPROGRAM#pragma vertex vert#pragma fragment frag// Pragmas#pragma target 2.0// Includes#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"CBUFFER_START(UnityPerMaterial)half4 _WaterColor1;half4 _WaterColor2;half _FoamRange;half _WaterSpeed;half4 _FoamColor;half _FoamNoise;half4 _FoamTex_ST;half _Distort;half4 _DistortTex_ST;CBUFFER_ENDTEXTURE2D(_CameraDepthTexture);SAMPLER(sampler_CameraDepthTexture);TEXTURE2D(_FoamTex);SAMPLER(sampler_FoamTex);TEXTURE2D(_CameraOpaqueTexture);SAMPLER(sampler_CameraOpaqueTexture);TEXTURE2D(_DistortTex);SAMPLER(sampler_DistortTex);//struct appdata//顶点着色器的输入struct Attributes{float3 positionOS : POSITION;float2 uv : TEXCOORD0;};//struct v2f//片元着色器的输入struct Varyings{float4 positionCS : SV_POSITION;float4 uv : TEXCOORD0;// xy = distortUV,zw = foamUVfloat4 screenPos : TEXCOORD1;float3 positionVS : TEXCOORD2;float3 positionWS : TEXCOORD3;};//v2f vert(Attributes v)//顶点着色器Varyings vert(Attributes v){Varyings o = (Varyings)0;o.positionWS = TransformObjectToWorld(v.positionOS);o.positionVS = TransformWorldToView(o.positionWS);o.positionCS = TransformWViewToHClip(o.positionVS);o.screenPos = ComputeScreenPos(o.positionCS);//计算得到泡沫纹理采样需要的顶点世界空间下的坐标值的流动效果o.uv.zw += o.positionWS.xz *_FoamTex_ST.xy + _Time.y * _WaterSpeed;//计算得到水下扭曲纹理的流动UVo.uv.xy = TRANSFORM_TEX(v.uv,_DistortTex)+_Time.y * _WaterSpeed;return o;}//fixed4 frag(v2f i) : SV_TARGET//片元着色器half4 frag(Varyings i) : SV_TARGET{//1、水的深度//获取屏幕空间下的 UV 坐标float2 screenUV = i.positionCS.xy / _ScreenParams.xy;half depthTex = SAMPLE_TEXTURE2D(_CameraDepthTexture,sampler_CameraDepthTexture,screenUV).x;//深度图转化到观察空间下float depthScene = LinearEyeDepth(depthTex,_ZBufferParams);//获取水面模型顶点在观察空间下的Z值(可以在顶点着色器中,对其直接进行转化得到顶点观察空间下的坐标)float4 depthWater = depthScene + i.positionVS.z;//2、水的颜色,线性插值得到水 和 接触物体的水的 颜色的过度half4 waterColor = lerp(_WaterColor1,_WaterColor2,depthWater);//3、水面泡沫//对泡沫纹理进行采样(这里使用顶点世界空间下的坐标进行纹理采样,防止水体缩放影响泡沫的平铺和重复方式)half4 foamTex = SAMPLE_TEXTURE2D(_FoamTex,sampler_FoamTex,i.uv.zw);foamTex = pow(foamTex,_FoamNoise);//这里增加一个调整深度图范围的功能half4 foamRange = depthWater * _FoamRange;//使用泡沫纹理 和 泡沫范围 比较得到泡沫遮罩half4 foamMask = step(foamRange,foamTex);//给泡沫加上颜色half4 foamColor = foamMask * _FoamColor;half4 col = foamColor + waterColor;//4、水下的扭曲half4 distortTex = SAMPLE_TEXTURE2D(_DistortTex,sampler_DistortTex,i.uv.xy);float2 distortUV = lerp(screenUV,distortTex,_Distort);half4 cameraOpaqueTex = SAMPLE_TEXTURE2D(_CameraOpaqueTexture,sampler_CameraOpaqueTexture,distortUV);col *= cameraOpaqueTex;//水的高光//水的反射//水的焦散return col;}ENDHLSL}}FallBack "Hidden/Shader Graph/FallbackError"
}

这篇关于Unity中URP实现水体(水下的扭曲)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/747984

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

SpringBatch数据写入实现

《SpringBatch数据写入实现》SpringBatch通过ItemWriter接口及其丰富的实现,提供了强大的数据写入能力,本文主要介绍了SpringBatch数据写入实现,具有一定的参考价值,... 目录python引言一、ItemWriter核心概念二、数据库写入实现三、文件写入实现四、多目标写入

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件