UnityShader 实现简单的体积光

30 篇文章 7 订阅
22 篇文章 4 订阅

现实中的体积光效果:

在这里插入图片描述
在这里插入图片描述
在生活中,我们常会看到类似这样的效果,也就是丁达尔效应。

其他游戏中的使用

例如深海迷航中的使用(P.S. 游戏真的很好玩,续集的零度之下也是非常nice的)
在这里插入图片描述
在这里插入图片描述

Unity中的简单实现

在用Unity来渲染MMD的时候想加一点科幻的光雾效果,之前做崩坏3童谣渲染时候就用到过,所以最先想到的就是体积光(GodRay)。
先上几张截图吧
在这里插入图片描述
在这里插入图片描述
可能这一张看的不是很清楚。。。

Shader源码

Shader "Kirk/Shaft"
{
	Properties
	{
		_Shaftcolor("Shaft color", Color) = (1,0.8068966,0,0)
		_Opacityshift("Opacity shift", Range( 0.01 , 1)) = 1
		_Frequency("Frequency", Range( 0 , 3)) = 0
		_FrequencyScale("Frequency Scale", Range( 0 , 0.5)) = 0.5
		_Emmisionlevel("Emmision level", Range( 0.01 , 50)) = 0.01
		_Texture2blend("Texture 2 blend", Range( 0 , 1)) = 0.5
		_Texture3blend("Texture 3 blend", Range( 0 , 1)) = 0.5
		_Noise_level("Noise_level", Range( 0 , 1)) = 0.15
		_Texture1tiling("Texture1 tiling", Vector) = (1,1,0,0)
		_Texture2tiling("Texture2 tiling", Vector) = (1,1,0,0)
		_Texture3tiling("Texture3 tiling", Vector) = (1,1,0,0)
		_Texture4tiling("Texture4 tiling", Vector) = (1,1,0,0)
		_Texture1speed("Texture1 speed", Vector) = (0.08,0,0,0)
		_Texture2speed("Texture2 speed", Vector) = (0.1,0,0,0)
		_Texture3speed("Texture3 speed", Vector) = (-0.1,0,0,0)
		_Texture4speed("Texture4 speed", Vector) = (-0.1,0.1,0,0)
		_Texture1("Texture1", 2D) = "white" {}
		_Texture2("Texture2", 2D) = "white" {}
		_Texture3("Texture3", 2D) = "white" {}
		_Texture4("Texture4", 2D) = "white" {}
		[HideInInspector] _texcoord( "", 2D ) = "white" {}
		[HideInInspector] __dirty( "", Int ) = 1
	}

	SubShader
	{
		Tags{ "RenderType" = "Transparent"  "Queue" = "Transparent+0" "IgnoreProjector" = "True" "IsEmissive" = "true"  }
		Cull Off
		CGINCLUDE
		#include "UnityShaderVariables.cginc"
		#include "UnityPBSLighting.cginc"
		#include "Lighting.cginc"
		#pragma target 4.6
		struct Input
		{
			float2 uv_texcoord;
		};

		uniform sampler2D _Texture1;
		uniform float2 _Texture1speed;
		uniform float2 _Texture1tiling;
		uniform sampler2D _Texture2;
		uniform float2 _Texture2speed;
		uniform float2 _Texture2tiling;
		uniform float _Texture2blend;
		uniform sampler2D _Texture3;
		uniform float2 _Texture3speed;
		uniform float2 _Texture3tiling;
		uniform float _Texture3blend;
		uniform sampler2D _Texture4;
		uniform float2 _Texture4speed;
		uniform float2 _Texture4tiling;
		uniform float _Noise_level;
		uniform float4 _Shaftcolor;
		uniform float _Emmisionlevel;
		uniform float _Frequency;
		uniform float _FrequencyScale;
		uniform float _Opacityshift;

		void surf( Input i , inout SurfaceOutputStandard o )
		{
			float2 uv_TexCoord32 = i.uv_texcoord * _Texture1tiling + float2( 0,0 );
			float2 panner35 = ( uv_TexCoord32 + _Time.y * _Texture1speed);
			float2 uv_TexCoord41 = i.uv_texcoord * _Texture2tiling + float2( 0,0 );
			float2 panner42 = ( uv_TexCoord41 + _Time.y * _Texture2speed);
			float4 lerpResult93 = lerp( tex2D( _Texture1, panner35 ) , tex2D( _Texture2, panner42 ) , _Texture2blend);
			float2 uv_TexCoord46 = i.uv_texcoord * _Texture3tiling + float2( 0,0 );
			float2 panner48 = ( uv_TexCoord46 + _Time.y * _Texture3speed);
			float4 lerpResult94 = lerp( lerpResult93 , tex2D( _Texture3, panner48 ) , _Texture3blend);
			float2 uv_TexCoord112 = i.uv_texcoord * _Texture4tiling + float2( 0,0 );
			float2 panner114 = ( uv_TexCoord112 + _Time.y * _Texture4speed);
			float4 lerpResult121 = lerp( float4( 0,0,0,0 ) , tex2D( _Texture4, panner114 ) , lerpResult94.r);
			float4 lerpResult120 = lerp( lerpResult94 , lerpResult121 , _Noise_level);
			float4 _textures75 = lerpResult120;
			float4 blendOpSrc33 = _textures75;
			float4 blendOpDest33 = _Shaftcolor;
			float4 _shaft77 = ( saturate( ( blendOpSrc33 * blendOpDest33 ) ));
			o.Albedo = _shaft77.rgb;
			float4 _emmision79 = ( _shaft77 * _Emmisionlevel );
			o.Emission = _emmision79.rgb;
			float _frequency71 = (sin( ( _Time.y * _Frequency ) )*_FrequencyScale + _FrequencyScale);
			float4 lerpResult72 = lerp( _textures75 , float4( 0,0,0,0 ) , _frequency71);
			float4 _opacity84 = ( lerpResult72 * _Opacityshift );
			o.Alpha = _opacity84.r;
		}

		ENDCG
		CGPROGRAM
		#pragma surface surf Standard alpha:fade keepalpha fullforwardshadows 

		ENDCG
		Pass
		{
			Name "ShadowCaster"
			Tags{ "LightMode" = "ShadowCaster" }
			ZWrite On
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 4.6
			#pragma multi_compile_shadowcaster
			#pragma multi_compile UNITY_PASS_SHADOWCASTER
			#pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
			#include "HLSLSupport.cginc"
			#if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )
				#define CAN_SKIP_VPOS
			#endif
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			#include "UnityPBSLighting.cginc"
			sampler3D _DitherMaskLOD;
			struct v2f
			{
				V2F_SHADOW_CASTER;
				float2 customPack1 : TEXCOORD1;
				float3 worldPos : TEXCOORD2;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};
			v2f vert( appdata_full v )
			{
				v2f o;
				UNITY_SETUP_INSTANCE_ID( v );
				UNITY_INITIALIZE_OUTPUT( v2f, o );
				UNITY_TRANSFER_INSTANCE_ID( v, o );
				Input customInputData;
				float3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz;
				fixed3 worldNormal = UnityObjectToWorldNormal( v.normal );
				o.customPack1.xy = customInputData.uv_texcoord;
				o.customPack1.xy = v.texcoord;
				o.worldPos = worldPos;
				TRANSFER_SHADOW_CASTER_NORMALOFFSET( o )
				return o;
			}
			fixed4 frag( v2f IN
			#if !defined( CAN_SKIP_VPOS )
			, UNITY_VPOS_TYPE vpos : VPOS
			#endif
			) : SV_Target
			{
				UNITY_SETUP_INSTANCE_ID( IN );
				Input surfIN;
				UNITY_INITIALIZE_OUTPUT( Input, surfIN );
				surfIN.uv_texcoord = IN.customPack1.xy;
				float3 worldPos = IN.worldPos;
				fixed3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) );
				SurfaceOutputStandard o;
				UNITY_INITIALIZE_OUTPUT( SurfaceOutputStandard, o )
				surf( surfIN, o );
				#if defined( CAN_SKIP_VPOS )
				float2 vpos = IN.pos;
				#endif
				half alphaRef = tex3D( _DitherMaskLOD, float3( vpos.xy * 0.25, o.Alpha * 0.9375 ) ).a;
				clip( alphaRef - 0.01 );
				SHADOW_CASTER_FRAGMENT( IN )
			}
			ENDCG
		}
	}
	Fallback "Diffuse"
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值