Unity制作旋转光束

这篇具有很好参考价值的文章主要介绍了Unity制作旋转光束。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Unity制作旋转光束


  大家好,我是阿赵。
  这是一个在很多游戏里面可能都看到过的效果,在传送门、魔法阵、角色等脚底下往上散发出一束拉丝形状的光,然后在不停的旋转。
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  这次来在Unity引擎里面做一下这种效果。

一、准备材料

  需要准备的素材很简单。
  第一个是一个圆柱形的网格模型,删除了上下盖,然后展平UV。
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  第二个是一张噪声贴图
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

二、制作过程

1、控制形状

  由于准备的输出是一个圆柱网格,但实际显示的效果是一个类似于扇形的形状。所以需要通过控制顶点来实现。原理很简单,UV的V坐标,是从模型的底部到顶部从0到1变化,所以只要沿着法线方向,乘以UV的V坐标,然后再乘以一个控制值,加到顶点坐标上,就能做到底部不变,越往上宽度越大了。

float3 vertexValue = ( v.normal * _normalScale * v.uv.y );
v.vertex.xyz += vertexValue;
o.vertex = UnityObjectToClipPos(v.vertex);

效果入下图
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

2、拉丝效果

  先把噪声图赋给网格模型,得到这样的效果:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  然后设置一下平铺次数
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  就得到了拉丝的效果了。
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  这里给固有色添加一个HDR的颜色叠加,然后把这个拉丝效果作为Alpha通道输入,设置Transparent透明渲染,就能得到这样的效果:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

3、透明渐变效果

  上面的效果太强烈,需要对它的透明度做一定的控制。先看看UV坐标的V坐标的实际范围:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  之前提到过,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 );

unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  把这个上下边缘柔和的结果和原来的拉丝Alpha值相乘,得到了这个效果:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

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 ));

  计算结果是这样的左右两边渐变的变暗:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

3.叠加遮罩

  把上面的3个SmoothStep结果相乘,就得到了这样一个遮罩范围:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  然后和拉丝的Alpha值相乘,得到了这样的效果:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

4、遮挡问题解决

  这里有一个半透明渲染的问题,在某些角度看,会出现错误显示:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  这里我再复制一份网格模型:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

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

unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束

  然后两个网格模型一起显示,就得到了正确的效果:
unity3d光束,Unity引擎Shader效果,unity,游戏引擎,旋转光束文章来源地址https://www.toymoban.com/news/detail-778296.html

三、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 100

		CGINCLUDE
		#pragma target 3.0
		ENDCG
		Blend SrcAlpha One, SrcAlpha One
		AlphaToMask Off
		Cull [_CullMode]
		ColorMask RGBA
		ZWrite On
		ZTest LEqual
		Offset 0 , 0
		
		
		
		Pass
		{
			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_ID
				UNITY_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制作旋转光束的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Unity3D实现键盘控制小车左右方向旋转

    注:本文章是在已学课程的基础上实现的标题效果! 以下是学习控制物体旋转的简单方法: 代码在updata()函数中实现;  transform:指本脚所挂载的物体的位置信息,包含Position(位置)、Rotation(旋转)、Scale(缩放),此处通过\\\".\\\"来调用Rotate方法; Rotate:unity手册中描述如下,参数一:

    2024年01月18日
    浏览(59)
  • Unity3D制作天空盒

    1、下载并导入hdr高动态范围图像资源到Project视图中,然后将图片的“Texture Shape”修改为“Cube”。  3、将步骤1的图片拖入“Cubemap(HDR)”的框内。  4、最后将制作好的材质,直接拖入Scene窗口中。           

    2024年02月15日
    浏览(61)
  • Unity3D学习笔记——物理引擎

    1简介 刚体可以为游戏对象赋予物理特性,是游戏对象在物理系统的控制下接受推力和扭力,从而实现现实世界的物理学现象。 2属性 1简介 碰撞器是物理组件的一类,他与刚体一起促使碰撞发生 碰撞体是简单形状,如方块、球形或者胶囊形,在 Unity 3D 中每当一个 GameObjects

    2023年04月12日
    浏览(51)
  • Unity3D粒子系统之制作烟雾特效

    本文将会介绍如何使用Unity内的粒子系统制作烟雾效果。 如果想了解Unity粒子系统中的基础属性,可以看这篇博客:Unity3D 粒子系统之基础属性介绍 先附上预览图: 材质贴图 首先我们需要一张烟雾材质用的材质贴图,我是自己画的,可以参考下图自己画一张或者去网上找素材

    2024年02月02日
    浏览(55)
  • Unity3D粒子系统之制作火焰特效

    本文将会介绍如何使用Unity内的粒子系统制作烟雾效果。 如果想了解Unity粒子系统中的基础属性,可以看这篇博客:Unity3D粒子系统之基础属性介绍 先上预览图吧 用自己熟悉的绘画工具画一张类似这样的图片(相似即可,白灰色部分边缘不规则),注意一定要黑底。 将画好的

    2024年02月02日
    浏览(47)
  • 使用Unity3D制作2D游戏的重点做法

    官网上有提供一个 2D游戏的教学范例 ,这个游戏只不过把镜头摆放在横向位置跟随角色移动,游戏内物件运动时固定一个轴不动,使他像横轴式的2D游戏来玩,本质上其实还是个3D游戏,所以如果没有3D建模的话不就没办法做2D游戏了?其实这些并没有定论,就看制作者如何运

    2024年02月11日
    浏览(66)
  • Unity制作旋转光束

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

    2024年02月03日
    浏览(39)
  • Unity3D摄像机,键盘控制前后左右上下移动,鼠标控制旋转、放缩

    Unity3D中运行场景时,实现摄像机的前、后、左、右、上、下,以及鼠标滚轮的放缩,鼠标右键的旋转操作。亲测有效,可供参考。 按键功能介绍:W——前;S——后;A——左;D——右;Q——下降;E——上升;鼠标右键——旋转;鼠标滚轮——放缩。 Tourcamera脚本需要挂在摄

    2024年02月11日
    浏览(62)
  • Unity3D项目之游戏场景小地图制作

    创建一个场景资源,可在asset store资源商店下载,选择心仪场景。 链接:https://assetstore.unity.com/?locale=zh-CN 添加一个对象GameObject,命名为player,子物体包括:主摄像机,角色,后面步骤会添加一个plane。 添加一个地图摄像机,命名为MapCamera。修改属性projection为OrthoGraphic;Size为

    2024年02月11日
    浏览(80)
  • Unity3d 制作一个简单的NPC对话系统

    ​ 最近在自己写一个比较小的项目,虽然自己是一个策划,但是程序方面我觉得也是很有必要学一学的。 ​ 经过了接近一年的学习,也终于是可以独自写一些小的系统了。 ​ 这次自己写了一个比较简单的NPC对话系统,供大家参考。 进入对话区域 开始对话 Inspector面板可调

    2023年04月08日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包