Unity制作旋转光束
Unity制作旋转光束
大家好,我是阿赵。
这是一个在很多游戏里面可能都看到过的效果,在传送门、魔法阵、角色等脚底下往上散发出一束拉丝形状的光,然后在不停的旋转。
这次来在Unity引擎里面做一下这种效果。
一、准备材料
需要准备的素材很简单。
第一个是一个圆柱形的网格模型,删除了上下盖,然后展平UV。

第二个是一张噪声贴图

二、制作过程
1、控制形状
由于准备的输出是一个圆柱网格,但实际显示的效果是一个类似于扇形的形状。所以需要通过控制顶点来实现。原理很简单,UV的V坐标,是从模型的底部到顶部从0到1变化,所以只要沿着法线方向,乘以UV的V坐标,然后再乘以一个控制值,加到顶点坐标上,就能做到底部不变,越往上宽度越大了。
float3 vertexValue = ( v.normal * _normalScale * v.uv.y );
v.vertex.xyz += vertexValue;
o.vertex = UnityObjectToClipPos(v.vertex);
效果入下图

2、拉丝效果
先把噪声图赋给网格模型,得到这样的效果:

然后设置一下平铺次数

就得到了拉丝的效果了。

这里给固有色添加一个HDR的颜色叠加,然后把这个拉丝效果作为Alpha通道输入,设置Transparent透明渲染,就能得到这样的效果:

3、透明渐变效果
上面的效果太强烈,需要对它的透明度做一定的控制。先看看UV坐标的V坐标的实际范围:

之前提到过,V坐标是从模型底部到顶部从0到1变化。接下来就可以通过这个值做一些处理。
1.上下边缘控制
首先控制的是上下边缘,现在边缘太硬,我把它用两个SmoothStep,分别对应顶部和底部,让边缘变得柔和:
float tempOneMinueVal = ( 1.0 - i.uv.y );
float smoothstepResultV1 = smoothstep( _vMin , _vMax , ( tempOneMinueVal - _vOffset ));
float smoothstepResultV2 = smoothstep( _vMin2 , _vMax2 , i.uv.y);
float clampResult = clamp( min( min( smoothstepResultV1 , tempOneMinueVal ) , smoothstepResultV2 ) , 0.0 , 1.0 );

把这个上下边缘柔和的结果和原来的拉丝Alpha值相乘,得到了这个效果:

2.左右边缘控制
上面的效果已经很接近我们想要的效果了,但还差一点,左右边缘也很硬,所以用世界法线方向和观察方向做点乘,最后还是加一个SmoothStep,让左右边缘有个柔和渐变。
float3 worldNormal = i.worldNormal.xyz;
float3 worldViewDir = UnityWorldSpaceViewDir(i.worldPos);
worldViewDir = normalize(worldViewDir);
float dotResult = dot( worldNormal , worldViewDir );
float smoothstepResultEdge = smoothstep( _edgeMin , _edgeMax , abs( dotResult ));
计算结果是这样的左右两边渐变的变暗:

3.叠加遮罩
把上面的3个SmoothStep结果相乘,就得到了这样一个遮罩范围:

然后和拉丝的Alpha值相乘,得到了这样的效果:

4、遮挡问题解决
这里有一个半透明渲染的问题,在某些角度看,会出现错误显示:

这里我再复制一份网格模型:

然后两个网格模型使用不同的CullMode




然后两个网格模型一起显示,就得到了正确的效果:

三、Shader源码
Shader "azhao/LightColumn"
{Properties{[HDR]_emissCol("emissCol", Color) = (0,0,0,0)_emissScale("emissScale", Float) = 1_noiseTex("noiseTex", 2D) = "white" {}_flowSpeed("flowSpeed", Vector) = (0,0,0,0)_vOffset("vOffset", Float) = 0_edgeMin("edgeMin", Range( 0 , 1)) = 0_edgeMax("edgeMax", Range( 0 , 1)) = 1_vMin("vMin", Range( 0 , 1)) = 0_vMax("vMax", Range( 0 , 1)) = 1_normalScale("normalScale", Range(-2,2)) = 1 _vMin2("vMin2", Range( 0 , 1)) = 0_vMax2("vMax2", Range( 0 , 1)) = 1
[Enum(UnityEngine.Rendering.CullMode)]_CullMode("CullMode", Float) = 2}SubShader{Tags { "RenderType"="Opaque" }LOD 100CGINCLUDE#pragma target 3.0ENDCGBlend SrcAlpha One, SrcAlpha OneAlphaToMask OffCull [_CullMode]ColorMask RGBAZWrite OnZTest LEqualOffset 0 , 0Pass{Name "Unlit"Tags { "LightMode"="ForwardBase" }CGPROGRAM#ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX//only defining to not throw compilation error over Unity 5.5#define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input)#endif#pragma vertex vert#pragma fragment frag#pragma multi_compile_instancing#include "UnityCG.cginc"#include "UnityShaderVariables.cginc"struct appdata{float4 vertex : POSITION;float4 color : COLOR;float3 normal : NORMAL;float2 uv : TEXCOORD0;UNITY_VERTEX_INPUT_INSTANCE_ID};struct v2f{float4 vertex : SV_POSITION;float3 worldPos : TEXCOORD0;float2 uv : TEXCOORD1;float3 worldNormal : TEXCOORD2;UNITY_VERTEX_INPUT_INSTANCE_IDUNITY_VERTEX_OUTPUT_STEREO};uniform float _CullMode;uniform float _normalScale;uniform float4 _emissCol;uniform float _emissScale;uniform sampler2D _noiseTex;SamplerState sampler_noiseTex;uniform float2 _flowSpeed;uniform float4 _noiseTex_ST;uniform float _vMin;uniform float _vMax;uniform float _vOffset;uniform float _vMin2;uniform float _vMax2;uniform float _edgeMin;uniform float _edgeMax;v2f vert ( appdata v ){v2f o;UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);UNITY_TRANSFER_INSTANCE_ID(v, o);float3 worldNormal = UnityObjectToWorldNormal(v.normal);o.worldNormal = worldNormal; o.uv.xy = v.uv.xy; float3 vertexValue = ( v.normal * _normalScale * v.uv.y );v.vertex.xyz += vertexValue;o.vertex = UnityObjectToClipPos(v.vertex);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;return o;}half4 frag (v2f i ) : SV_Target{UNITY_SETUP_INSTANCE_ID(i);UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);float2 uv_noiseTex = i.uv.xy * _noiseTex_ST.xy + _noiseTex_ST.zw;float2 panner6 = ( 1.0 * _Time.y * _flowSpeed + uv_noiseTex);float tempOneMinueVal = ( 1.0 - i.uv.y );float smoothstepResultV1 = smoothstep( _vMin , _vMax , ( tempOneMinueVal - _vOffset ));float smoothstepResultV2 = smoothstep( _vMin2 , _vMax2 , i.uv.y);float clampResult = clamp( min( min( smoothstepResultV1 , tempOneMinueVal ) , smoothstepResultV2 ) , 0.0 , 1.0 );float3 worldNormal = i.worldNormal.xyz;float3 worldViewDir = UnityWorldSpaceViewDir(i.worldPos);worldViewDir = normalize(worldViewDir);float dotResult = dot( worldNormal , worldViewDir );float smoothstepResultEdge = smoothstep( _edgeMin , _edgeMax , abs( dotResult ));half4 finalColor = (float4((( _emissCol * _emissScale )).rgb , ( tex2D( _noiseTex, panner6 ).r * clampResult * smoothstepResultEdge )));return finalColor;}ENDCG}}}
相关文章:
Unity制作旋转光束
Unity制作旋转光束 大家好,我是阿赵。 这是一个在很多游戏里面可能都看到过的效果,在传送门、魔法阵、角色等脚底下往上散发出一束拉丝形状的光,然后在不停的旋转。 这次来在Unity引擎里面做一下这种效果。 一、准备材料 需要准备的素材很简…...
考研王道强化阶段(二轮复习)“算法题”备考打卡表 记录
问题:做408真题_2010_42题,即王道书 2.2.3_大题_10 思路: 回头补 代码: int moveL(SqlList &L,SqlList &S,int p) {// 健壮性表达if( L.len 0 ){return 0;}// 调用另外一个顺序表存储pos前面的元素for( int i0;i<p;…...
UE4/5数字人MetaHuman通过已有动画进行修改
目录 通过已有动画修改动画 开始制作 创建一个关卡序列 将动画序列烘焙到控制绑定 打开我们自己创建的动画序列 之后便是烘焙出来 通过已有动画修改动画 首先架设我们已经有相关的MetaHuman的动画,但是这个动画因为是外部导入进来的,所以可能会出…...
在Mac M2本地注册GitLab runner
最近在搞公司的CI/CD,简单记录下部分过程 安装runner sudo curl --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-arm64" 创建runner 这个步骤需要在gitlab中进行&am…...
「大数据-2.2」使用命令操作HDFS文件系统
目录 一、HDFS文件系统基本信息 1. HDFS的路径表达形式 2.HDFS和Linux的根目录的区分 二、 使用命令操作HDFS文件系统 0. Hadoop的两套命令体系 1. 创建文件夹 2. 查看指定目录下内容 3. 上传文件到HDFS指定目录下 4. 查看HDFS文件内容 5. 下载HDFS文件 6. 拷贝HDFS文件 7.…...
面试买书复习就能进大厂?
大家好,我是苍何。 现在进大仓是越来越难了,想通过简单的刷题面试背书,比几年前难的不少, 但也并非毫无希望,那究竟该如何准备才能有希望进大厂呢? 我总结了 4 点: 1、不差的学历背景 2、丰富…...
使用Http Interface客户端解析text/html类型参数
前言 Spring6和Spring Boot3的正式发布也有一段时间了,最低支持的java版本也是直接跳到了17。而且最近java21也出来了,作为一个javaer,你不会还在坚守java8吧? Http Interface是Spring6新推出的一个声明式http客户端,…...
Linux - linux命令进阶
打包压缩解压 基本概述 打包 将多数文件或目录汇总成一个整体 打包默认没有压缩功能,不节省磁盘空间 压缩 将大文件压缩成小文件 可以节省磁盘空间 打包压缩 将一堆零散的文件打包到一起,然后再压缩,可以节省磁盘空间 打包命令 命令格式 ta…...
排序篇(一)----插入排序
1.直接插入排序 插入排序的思想: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 你可以想像成打牌一样,比如说斗地主,一张一张的摸牌,然后把手上的这些牌变成手续的排列.…...
通俗讲解深度学习轻量网络MobileNet-v1/v2/v3
MobileNet网络是由google团队在2017年提出的,专注于移动端或者嵌入式设备中的轻量级CNN网络。相比传统卷积神经网络,在准确率小幅降低的前提下大大减少模型参数与运算量。(相比VGG16准确率减少了0.9%,但模型参数只有VGG的1/32)。MobileNet网络…...
mmpretrain学习笔记
深度学习模型的训练涉及几个方面 1、模型结构:模型有几层、每层多少通道数等 2、数据:数据集划分、数据文件路径、批大小、数据增强策略等 3、训练优化 :梯度下降算法、学习率参数、训练总轮次、学习率变化策略等 4、运行时:GPU、…...
rhel8 网络操作学习
一、查询dns服务器地址汇总 1.查询dns服务器地址: (1)方法一:执行命令 cat /etc/resolv.conf 执行结果如下: nameserver后面就是dns服务器的ip地址。 (2)方法2:查看/etc/syscon…...
有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表
用drf编写 1 有车型(CarModel),车厂(CarFactory),经销商(Distributor)三个表, 一个车厂可以生产多种车型,一个经销商可以出售多种车型,一个车型可以有多个经销商出售车型:车型名,车型…...
Python函数:chr()和ord()
两个函数是基于Unicode编码表进行进行字符与字码之间的转换。 chr()函数是通过字码转换成字符: 如图,坐标(1,4e10)丑 使用chr需要线将坐标相加得到:4e11 chr默认传入10进制的字码. 如图是各进制的字码。 也可以传入其他进制,不过需要在前面传入的参数最前…...
flink sql 使用
1.准备工作 安装flink 1.16.2 将以下jar包放到/data/cmpt/flink-1.16.2/lib 目录下 antlr-runtime-3.5.2.jar flink-connector-hive_2.12-1.16.2.jar flink-connector-jdbc-1.16.2.jar mysql-connector-java-6.0.6.jar hive-exec-3.1.3.jar libfb303-0.9.3.ja…...
面试官:谈谈 Go 泛型编程
大家好,我是木川 泛型编程是一种编程范式,它允许编写具有参数化类型的代码,从而增加代码的复用性和灵活性。在泛型编程中,你可以编写一段代码,使其适用于不同类型的参数,而不需要为每种类型编写不同的实现。…...
脚手架开发流程详解
开发流程 创建npm项目创建脚手架入口文件,最上方添加 #!/usr/bin/env/ node配置package.json,添加bin属性编写脚手架代码将脚手架发布到npm 使用流程 安装脚手架 npm install -g your-own-cli使用脚手架 your-own-cli脚手架开发难点解析 分包&…...
架构真题2021(四十三)
产品配置是指一个产品在其生命周期各个阶段所产生的各种形式(机器刻可读或人工可读)和各种版本()的集合。 需求规格说明、设计说明、测试报告需求规则说明、设计说明、计算机程序设计说明、用户手册、计算机程序文档、计算机程序…...
数据统计和分析怎么做?spss如何做好数据分析?
为什么要做数据分析?数据分析有什么意义?数据分析可以为企业和组织提供多方面的帮助,包括提高工作效率、优化业务流程、升职加薪、提高管理效率以及改进汇报效果等方面。 IBM SPSS Statistics 26是一款功能强大的统计分析软件,适用于Mac操作…...
【多线程】线程安全的集合类
文章目录 1. 多线程环境使用ArrayList1.1 自己使用同步机制1.2 Collections.synchronizedList(new ArrayList);1.3 使用 CopyOnWriteArrayList 2. 多线程使用队列3. 多线程环境使用哈希表3.1 HashTable3.2 ConcurrentHashMap3.3 Hashtable和HashMap、ConcurrentHashMap 之间的区…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
