Unity shader glsl着色器特效之 模拟海面海浪效果

news2025/2/22 21:49:06

一个简单的海浪效果,通过波的叠加实现水面起伏的动效,根据波峰斜率来为浪花着色,再根据法线贴图和水花贴图来和调整uv的平滑移动来增强海浪移动的细节。如果需要更逼真的效果可以考虑在满足浪花触发的地方添加粒子系统

前置效果图
因为是很久以前写的文章,贴图已经找不到了,随便PS了两张看看效果
请添加图片描述
请添加图片描述
inspector的可调项目
在这里插入图片描述

原理介绍

水波部分使用4个不同参数的Gerstner波叠加,不同波长(10m/5m/3m/7m)不同传播方向(0°/45°/90°/135°),动态计算顶点偏移量:

offset += GerstnerWave(10.0, 0.3, 1.2, 0.0, worldPos, tangent, binormal);

通过交叉计算切线/副切线生成基础法线,叠加噪声贴图增加细节:

float3 noiseNormal = UnpackNormal(tex2D(_NoiseTex, IN.uv_NoiseTex));
o.Normal = normalize(noiseNormal + o.Normal);

水花效果实现,基于表面坡度检测生成水花:

float slope = 1 - o.Normal.y;
float foam = saturate(slope * 5 - 0.7) * foamTex.r;

光源反馈采用菲涅尔反射效果:

float fresnel = pow(1.0 - saturate(dot(o.Normal, IN.viewDir)), 4);

动态镜面反射:

o.Smoothness = _Gloss * (1 - foam);

完整代码

Shader "Custom/OceanWave" {
    Properties {
        _MainColor ("Main Color", Color) = (0.1, 0.3, 0.6, 1)
        _FoamColor ("Foam Color", Color) = (1,1,1,1)
        _WaveScale ("Wave Scale", Range(0,2)) = 0.5
        _WaveSpeed ("Wave Speed", Range(0,5)) = 1.2
        _NoiseTex ("Noise Texture", 2D) = "white" {}
        _FoamTex ("Foam Texture", 2D) = "white" {}
        _Gloss ("Gloss", Range(0,1)) = 0.8
        _NoiseUVSpeed ("Noise UV Speed", Vector) = (0.1, 0.1, 0, 0) // 添加噪声纹理UV移动速度
        _FoamUVSpeed ("Foam UV Speed", Vector) = (0.1, 0.1, 0, 0)  // 添加水花纹理UV移动速度
    }

    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard vertex:vert addshadow
        #pragma target 3.0

        #include "UnityCG.cginc"

        struct Input {
            float3 worldPos;
            float3 viewDir;
            float2 uv_NoiseTex;
            float2 uv_FoamTex;
        };

        // 属性声明
        fixed4 _MainColor;
        fixed4 _FoamColor;
        sampler2D _NoiseTex;
        sampler2D _FoamTex;
        float _WaveScale;
        float _WaveSpeed;
        float _Gloss;
        float4 _NoiseUVSpeed;
        float4 _FoamUVSpeed;

        // Gerstner波函数
        float3 GerstnerWave(
            float wavelength,
            float amplitude,
            float speed,
            float direction,
            float3 position,
            inout float3 tangent,
            inout float3 binormal) {
            
            float k = 2 * UNITY_PI / wavelength;
            float c = sqrt(9.8 / k);
            float2 d = float2(sin(direction), cos(direction));
            float f = k * (dot(d, position.xz) - c * speed * _Time.y);
            float a = amplitude / k;

            tangent += float3(
                -d.x * d.x * (amplitude * sin(f)),
                d.x * (amplitude * cos(f)),
                -d.x * d.y * (amplitude * sin(f))
            );

            binormal += float3(
                -d.x * d.y * (amplitude * sin(f)),
                d.y * (amplitude * cos(f)),
                -d.y * d.y * (amplitude * sin(f))
            );

            return float3(
                d.x * (a * cos(f)),
                a * sin(f),
                d.y * (a * cos(f))
            );
        }

        // 顶点着色器
        void vert(inout appdata_full v, out Input o) {
            UNITY_INITIALIZE_OUTPUT(Input, o);
            
            float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
            float3 tangent = float3(1,0,0);
            float3 binormal = float3(0,0,1);
            float3 offset = 0;

            // 叠加四个不同参数的波浪
            offset += GerstnerWave(10.0, 0.3, 1.2, 0.0, worldPos, tangent, binormal);
            offset += GerstnerWave(5.0, 0.2, 1.5, 0.785, worldPos, tangent, binormal);
            offset += GerstnerWave(3.0, 0.1, 2.0, 1.570, worldPos, tangent, binormal);
            offset += GerstnerWave(7.0, 0.15, 1.0, 2.356, worldPos, tangent, binormal);

            // 计算法线
            float3 normal = normalize(cross(binormal, tangent));
            v.normal = mul((float3x3)unity_WorldToObject, normal);
            worldPos += offset;
            v.vertex.xyz = mul(unity_WorldToObject, float4(worldPos, 1)).xyz;
        }

        // 表面着色器
        void surf (Input IN, inout SurfaceOutputStandard o) {
            // 计算UV偏移
            float2 noiseUVOffset = _NoiseUVSpeed.xy * _Time.y;
            float2 foamUVOffset = _FoamUVSpeed.xy * _Time.y;

            // 应用UV偏移
            float2 noisyUV = IN.uv_NoiseTex + noiseUVOffset;
            float2 foamUV = IN.uv_FoamTex + foamUVOffset;

            // 基础颜色
            fixed4 mainColor = _MainColor;

            // 法线计算
            float3 noiseNormal = UnpackNormal(tex2D(_NoiseTex, noisyUV));
            o.Normal = normalize(noiseNormal + o.Normal);

            // 水花效果
            float slope = 1 - o.Normal.y;
            fixed4 foamTex = tex2D(_FoamTex, foamUV);
            float foam = saturate(slope * 5 - 0.7) * foamTex.r;

            // 菲涅尔反射
            float fresnel = pow(1.0 - saturate(dot(o.Normal, IN.viewDir)), 4);
            
            // 最终颜色合成
            o.Albedo = lerp(mainColor.rgb, _FoamColor.rgb, foam);
            o.Metallic = 0.0;
            o.Smoothness = _Gloss * (1 - foam);
            o.Alpha = mainColor.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303619.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在VSCode中接入deepseek

注册就送14元2000万tokens。 https://cloud.siliconflow.cn/i/rnbA6i6U各种大模型 下面介绍我是如如接入vscode的 左边生成一个key,呆会vscode要用,不然401. 打开vscod,电脑能上网。下插件。 下好要配置 点它一下。 要配置,全…

爱普生 SG-8101CE 可编程晶振在笔记本电脑的应用

在笔记本电脑的精密架构中,每一个微小的元件都如同精密仪器中的齿轮,虽小却对整体性能起着关键作用。如今的笔记本电脑早已不再局限于简单的办公用途,其功能愈发丰富多样。从日常轻松的文字处理、网页浏览,到专业领域中对图形处理…

神经网络剪枝技术的重大突破:sGLP-IB与sTLP-IB

神经网络剪枝技术的重大突破:sGLP-IB与sTLP-IB 在人工智能飞速发展的今天,深度学习技术已经成为推动计算机视觉、自然语言处理等领域的核心力量。然而,随着模型规模的不断膨胀,如何在有限的计算资源和存储条件下高效部署这些复杂的神经网络模型,成为了研究者们亟待解决的…

STM32MP157A单片机移植Linux驱动深入版

需求整理 在Linux设备树中新增leds节点&#xff0c;其有3个gpio属性&#xff0c;分别表示PE10对应led1&#xff0c;PF10对应led2&#xff0c;PE8对应led3&#xff0c;设备树键值对如下&#xff1a; leds { led1-gpio <&gpioe 10 0>; led2-gpio &l…

[大模型笔记]扣子-知识库搭建,并用Java-SDK调用的笔记

记录一下学习coze官方提供的java-sdk的过程 官方参考文档 一、搭建知识库 1、登录coze后&#xff0c;点击工作空间-资源库&#xff0c;点击右上角的资源&#xff0c;点击知识库 2、输入知识库名词以及知识库的描述 3、选择要上传的文档类型&#xff0c;点击创建并导入&…

Unity学习笔记-Unity了解,安装,简单配置(一)

Unity 是什么&#xff1f; Unity 是一款广受欢迎的跨平台游戏开发引擎&#xff0c;由 Unity Technologies 公司开发并推出。它以强大的功能和易用性&#xff0c;在游戏开发领域占据着举足轻重的地位&#xff0c;甚至可以说&#xff0c;它改变了游戏开发的格局。凭借其出色的跨…

LLaMA-Factory|微调大语言模型初探索(3),qlora微调deepseek记录

前言 上篇文章记录了使用lora微调llama-1b,微调成功,但是微调llama-8b显存爆炸,这次尝试使用qlora来尝试微调参数体量更大的大语言模型,看看64G显存的极限在哪里。 1.Why QLora? QLoRA 在模型加载阶段通过 4-bit 量化大幅减少了模型权重的显存占用。QLoRA 通过 反量化到 …

JEEWMS cgFormBuildController.do 方法mobileForm存在SQL注入

一:登录扫描 JeeWMS是一款免费开源的仓库管理系统,支持3PL和厂内物流,涵盖订单管理,仓储管理,计费管理,现场作业,RFID,AGV等功能。本文介绍了系统的简介,功能,安装,截图和链接,适合仓储企业和开发者参考。厦门市灵鹿谷科技有限公司JEEWMS jeecgFormDemoController…

python面试题整理

Python 如何处理异常&#xff1f; Python中&#xff0c;使用try 和 except 关键字来捕获和处理异常 try 块中放置可能会引发异常的代码&#xff0c;然后在except块中处理这些异常。 能补充一下finally的作用吗&#xff1f; finally 块中的代码无论是否发生异常都会执行&#xf…

深度学习之图像回归(二)

前言 这篇文章主要是在图像回归&#xff08;一&#xff09;的基础上对该项目进行的优化。&#xff08;一&#xff09;主要是帮助迅速入门 理清一个深度学习项目的逻辑 这篇文章则主要注重在此基础上对于数据预处理和模型训练进行优化前者会通过涉及PCA主成分分析 特征选择 后…

中文Build a Large Language Model (From Scratch) 免费获取全文

中文pdf下载地址&#xff1a;https://pan.baidu.com/s/1aq2aBcWt9vYagT2-HuxdWA?pwdlshj 提取码&#xff1a;lshj 原文、代码、视频项目地址&#xff1a;https://github.com/rasbt/LLMs-from-scratch 翻译工具&#xff1a;沉浸式翻译&#xff08;https://app.immersivetrans…

【鸿蒙开发】第四十四章 Map Kit(地图服务)

目录​​​​​​​ 1 Map Kit简介 1.1 场景介绍 2 开发准备 开通地图服务 3 创建地图 3.1 显示地图 3.1.1 接口说明 3.1.2 开发步骤 1、地图显示 2、设置地图属性 3、开启3D建筑图层 4、地图前后台切换 5、深色模式 3.2 切换地图类型 3.2.1 场景介绍 3.2.2 接…

EasyExcel 自定义头信息导出

需求&#xff1a;需要在导出 excel时&#xff0c;合并单元格自定义头信息(动态生成)&#xff0c;然后才是字段列表头即导出数据。 EasyExcel - 使用table去写入&#xff1a;https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write#%E4%BD%BF%E7%94%A8table%E…

DeepSeek 提示词:定义、作用、分类与设计原则

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

ubuntu环境编译ffmepg支持nvidia显卡加速

文章目录 1. 安装NVIDIA驱动2. 安装CUDA&NV-CODEC2.1 安装CUDA2.2 安装NV-CODEC 3. 编译ffmpeg3.1 安装依赖3.2 下载源码安装依赖3.3 验证 4. 使用 1. 安装NVIDIA驱动 安装依赖包 sudo apt install -y ubuntu-drivers-common编辑 /etc/modprobe.d/blacklist-nouveau.conf 文…

边缘安全加速(Edge Security Acceleration)

边缘安全加速&#xff08;Edge Security Acceleration&#xff0c;简称ESA&#xff09;是一种通过将安全功能与网络边缘紧密结合来提升安全性和加速网络流量的技术。ESA的目标是将安全措施部署到接近用户或设备的地方&#xff0c;通常是在网络的边缘&#xff0c;而不是将所有流…

SpringCould+vue3项目的后台用户管理的CURD【Taurus教育平台】

文章目录 一.SpringCouldvue3项目的后台用户管理的CURD【Taurus教育平台】 1.1 背景 二.用户列表&#xff08;分页查询&#xff09; 2.1 前端Vue3 &#xff08;Vue3-Element-Admin&#xff09;2.2 后端SpringCould 处理 三. 用户信息删除 3.1 前端Vue3 &#xff08;Vue3-Eleme…

ROS-相机话题-获取图像-颜色目标识别与定位-目标跟随-人脸检测

文章目录 相机话题获取图像颜色目标识别与定位目标跟随人脸检测 相机话题 启动仿真 roslaunch wpr_simulation wpb_stage_robocup.launch rostopic hz /kinect2/qhd/image_color_rect/camera/image_raw&#xff1a;原始的、未经处理的图像数据。 /camera/image_rect&#xff…

调用click.getchar()时Windows PyCharm无法模拟键盘输入

文章目录 问题描述解决方案参考文献 问题描述 调用 click.getchar() 时&#xff0c;Windows PyCharm 无法模拟键盘输入 解决方案 Run → Edit Configurations… → Modify options → Emulate terminal in output console 参考文献 Terminal emulator | PyCharm Documentati…

易基因: ChIP-seq+DRIP-seq揭示AMPK通过调控H3K4me3沉积和R-loop形成以维持基因组稳定性和生殖细胞完整性|NAR

原文&#xff1a;ChIP-seqDRIP-seq揭示AMPK通过调控H3K4me3沉积和R-loop形成以维持基因组稳定性和生殖细胞完整性&#xff5c;NAR 大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 在饥饿等能量胁迫条件下&#xff0c;生物体会通过调整…