Unity3D 实现六角形花纹效果

4 篇文章 0 订阅
2 篇文章 0 订阅
    今天为大家分享一下,如何做一个六角形花纹效果的小Demo。
    欢迎加我的学习交流群: 575561285
    
    好吧!废话不多讲,我直接上图操作!


    1.新建一个Unity3d 项目,新建一个CameraFilterPack_AAA_SuperHexagon.shader文件。
Shader "CameraFilterPack/AAA_Super_Hexagon" {
	Properties 
	{
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_TimeX ("Time", Range(0.0, 1.0)) = 1.0
		_Distortion ("_Distortion", Range(0.0, 1.0)) = 0.3
		_ScreenResolution ("_ScreenResolution", Vector) = (0.,0.,0.,0.)
		_Value ("_Value", Range(0.2, 10.0)) = 1
		_HexaColor ("_HexaColor", Color) = (1,1,1,1)
		_BorderSize ("_BorderSize", Range(-0.5, 0.5)) = 0.0
		_BorderColor ("_BorderColor", Color) = (1,1,1,1)
		_SpotSize ("_SpotSize", Range(0, 1.)) = 0.5
		_AlphaHexa ("_AlphaHexa", Range(0.2, 10.0)) = 1
		_PositionX ("_PositionX", Range(-0.5, 0.5)) = 0.0
		_PositionY ("_PositionY", Range(-0.5, 0.5)) = 0.0
		_Radius ("_Radius", Range(0, 1.)) = 0.5
	}
	SubShader 
	{
		Pass
		{
			ZTest Always
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#pragma target 3.0
			#include "UnityCG.cginc"
			
			
			uniform sampler2D _MainTex;
			uniform float _TimeX;
			uniform float _Distortion;
			uniform float4 _ScreenResolution;
			uniform float _Value;
			uniform float _BorderSize;
			uniform float4 _BorderColor;
			uniform float4 _HexaColor;
	
			uniform float _AlphaHexa;
				
			uniform float _PositionX;
			uniform float _PositionY;
			uniform float _Radius;			
			uniform float _SpotSize;			
			
		       struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };
 
            struct v2f
            {
                  half2 texcoord  : TEXCOORD0;
                  float4 vertex   : SV_POSITION;
                  fixed4 color    : COLOR;
           };   
             
  			v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color;
                
                return OUT;
            }
            

float hexDist(float2 a, float2 b){
	float2 p = abs(b-a);
	float s = 0.5;
	float c = 0.8660254;
	
	float diagDist = s*p.x + c*p.y;
	return max(diagDist, p.x)/c;
}

float2 nearestHex(float s, float2 st){
	float h = 0.5*s;
	float r = 0.8660254*s;
	float b = s + 2.0*h;
	float a = 2.0*r;
	float m = h/r;

	float2 sect = st/float2(2.0*r, h+s);
	float2 sectPxl = fmod(st, float2(2.0*r, h+s));
	
	float aSection = fmod(floor(sect.y), 2.0);
	
	float2 coord = floor(sect);
	if(aSection > 0.0){
		if(sectPxl.y < (h-sectPxl.x*m)){
			coord -= 1.0;
		}
		else if(sectPxl.y < (-h + sectPxl.x*m)){
			coord.y -= 1.0;
		}

	}
	else{
		if(sectPxl.x > r){
			if(sectPxl.y < (2.0*h - sectPxl.x * m)){
				coord.y -= 1.0;
			}
		}
		else{
			if(sectPxl.y < (sectPxl.x*m)){
				coord.y -= 1.0;
			}
			else{
				coord.x -= 1.0;
			}
		}
	}
	
	float xoff = fmod(coord.y, 2.0)*r;
	return float2(coord.x*2.0*r-xoff, coord.y*(h+s))+float2(r*2.0, s);
}



inline float2 screenDistort(float2 uv)
{
	uv -= float2(.5,.5);
	uv = uv*1.2*(1.0/1.2+2.*uv.x*uv.x*uv.y*uv.y);
	uv += float2(.5,.5);
	return uv;
}

float noise2(float n)
{
	return lerp(0,0.5,smoothstep(0.0,0.5,+fmod(n+0.5,1.0)));
}


float4 frag (v2f i) : COLOR
{
	float2 uv 		= i.texcoord.xy;
	float   s 		= _Value * _ScreenResolution.x/160.0;
	float2 nearest 	= nearestHex(s, i.texcoord.xy * _ScreenResolution.xy);
	float4 texel 	= tex2D(_MainTex, nearest/_ScreenResolution.xy);
	float4 texel2 	= tex2D(_MainTex, uv);
	uv = screenDistort(uv);
	float2 uv2;
	uv2 = uv.yy+float2(0.1*sin(_TimeX/3)*5,0.1*sin(_TimeX/5)*5);
	float3 video = tex2D(_MainTex,uv2).rgb;
	float vigAmt = 2.+.3*sin(15+5.*cos(5.));
	float vignette = (1.-vigAmt*(uv.y-.5)*(uv.y-.5))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5));
	video += (12.+fmod(uv.y*10.+_TimeX,1.))/13.;
	float2 center = float2(_PositionX,_PositionY);
	float dist2 = 1.0 - smoothstep( _Radius,_Radius+0.15*_SpotSize, length(center - uv));
	float dist 		= hexDist(i.texcoord.xy * _ScreenResolution.xy, nearest);
	float luminance = (texel.r + texel.g + texel.b)/3.0;
	float interiorSize = s*_BorderSize;//*(1-dist2*2);
	float interior = 1.0 - smoothstep(interiorSize-1.0, interiorSize, dist);
	float4 result;
	result.rgb=lerp(_BorderColor.rgb,texel.rgb,interior);
	float mem=1-noise2(_TimeX/4+uv.x);
	result.rgb+=float3(mem,mem,mem);
	result.rgb*=_HexaColor.rgb;
	result.rgb/=video.rgb/2;
	result /= vignette*2;
	result.rgb=lerp(result.rgb,texel2.rgb,dist2);
	result.rgb=lerp(result.rgb,texel2.rgb,1-_AlphaHexa);
	result.a=1.0;
	return float4(result);	
}
			
			ENDCG
		}
		
	}
}



    2.我们新建一个CameraFilterPack_AAA_SuperHexagon.cs组件 ,并且直接附加在摄像机对象上。

using UnityEngine;

[ExecuteInEditMode]
[AddComponentMenu ("Camera Filter Pack/AAA/Super Hexagon")]
public class CameraFilterPack_AAA_SuperHexagon : MonoBehaviour {
	#region Variables
	public Shader SCShader;
	[Range(0.0f, 1.0f)]
	public float _AlphaHexa = 1.0f;
	private float TimeX = 1.0f;
	private Vector4 ScreenResolution;
	private Material SCMaterial;
	[Range(0.2f, 10.0f)]
	public float HexaSize = 2.5f;
	public float _BorderSize = 1.0f;
	public Color _BorderColor = new Color (0.75f, 0.75f, 1, 1);
	public Color _HexaColor = new Color (0, 0.5f, 1, 1);
	public float _SpotSize = 2.5f;

	public static float ChangeBorderSize = 1.0f;
	public static Color ChangeBorderColor;
	public static Color ChangeHexaColor;
	public static float ChangeSpotSize = 1.0f;
	public static float ChangeAlphaHexa = 1.0f;
	public static float ChangeValue;
	public Vector2 center = new Vector2(0.5f,0.5f);
	public float Radius = 0.25f;

	public static Vector2 Changecenter;
	public static float ChangeRadius;
	

	#endregion
	
	#region Properties
	Material material
	{
		get
		{
			if(SCMaterial == null)
			{
				SCMaterial = new Material(SCShader);
				SCMaterial.hideFlags = HideFlags.HideAndDontSave;	
			}
			return SCMaterial;
		}
	}
	#endregion
	void Start () 
	{
		Changecenter = center;
		ChangeRadius = Radius;
		ChangeValue = HexaSize;
		ChangeAlphaHexa = _AlphaHexa;

		ChangeBorderSize = _BorderSize;
		ChangeBorderColor = _BorderColor;
		ChangeHexaColor = _HexaColor;
		ChangeSpotSize = _SpotSize;

		SCShader = Shader.Find("CameraFilterPack/AAA_Super_Hexagon");

		if(!SystemInfo.supportsImageEffects)
		{
			enabled = false;
			return;
		}
	}
	
	void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture)
	{
		if(SCShader != null)
		{
			TimeX+=Time.deltaTime;
			if (TimeX>100)  TimeX=0;
			material.SetFloat("_TimeX", TimeX);
			material.SetFloat("_Value", HexaSize);
			material.SetFloat("_PositionX", center.x);
			material.SetFloat("_PositionY", center.y);
			material.SetFloat("_Radius", Radius);
			material.SetFloat("_BorderSize", _BorderSize);
			material.SetColor("_BorderColor", _BorderColor);
			material.SetColor("_HexaColor", _HexaColor);
			material.SetFloat("_AlphaHexa", _AlphaHexa);
			material.SetFloat("_SpotSize", _SpotSize);
			material.SetVector("_ScreenResolution",new Vector4(sourceTexture.width,sourceTexture.height,0.0f,0.0f));
			Graphics.Blit(sourceTexture, destTexture, material);
		}
		else
		{
			Graphics.Blit(sourceTexture, destTexture);	
		}

	}
	void OnValidate()
{
		ChangeValue=HexaSize;
		Changecenter=center;
		ChangeRadius=Radius;
		ChangeBorderSize=_BorderSize;
		ChangeBorderColor=_BorderColor;
		ChangeHexaColor=_HexaColor;
		ChangeSpotSize=_SpotSize;
		ChangeAlphaHexa=_AlphaHexa;
}
	// Update is called once per frame
	void Update () 
	{
		if (Application.isPlaying)
		{
			HexaSize = ChangeValue;
			center = Changecenter;
			Radius = ChangeRadius;
			_BorderSize = ChangeBorderSize;
			_BorderColor = ChangeBorderColor;
			_HexaColor = ChangeHexaColor;
			_SpotSize = ChangeSpotSize;
			_AlphaHexa = ChangeAlphaHexa;
		}
		#if UNITY_EDITOR
		if (Application.isPlaying!=true)
		{
			SCShader = Shader.Find("CameraFilterPack/AAA_Super_Hexagon");
		}
		#endif

	}
	
	void OnDisable ()
	{
		if(SCMaterial)
		{
			DestroyImmediate(SCMaterial);	
		}
	}

}


    

    3.因为操作比较简单,我们直奔终点看效果吧!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值