Glow + Outline 轮廓描边,并做Blur处理

Qt5 - 动态加载Glow等特效 import QtQuick 2.0 import QtGraphicalEffects 1.0 Rectangle { width: 200; height: 200 color: "black" Text { id: text anchors.centerIn: parent text: "Hello Qt!" 阅读详情

原连接:http://www.cnblogs.com/dosomething/archive/2012/08/04/2622488.html

根据上面链接,写出的代码。

轮廓描边是游戏中的细节  但是一个有特色的效果还是会让人眼前一亮

Glow + Outline 的效果就像求生之路2和暗黑3的轮廓描边界一样  对轮廓描边后再进行模糊处理

如图: 求生之路2

 

暗黑3

  

一种思路为:

1、在RTT中绘制单一像素

2、对1绘制后的RTT进行blur处理

3、对2处理后的RTT与原始场景进行叠加

4、绘制原始模型

 

另一种思路:

1、绘制原始模型到RTT

2、对1绘制的RTT中原始模型进行Sobel描边

3、对2描边后的RenderTexture进行blur处理

4、叠加1和3的RenderTexture

5、4与场景进行叠加

 

在unity3d中的实现

1、场景图像渲染之前

 void OnPreRender

{

  ......

   另外添加一个摄像机A

  这里必须将GlowOutlineCamera摄像机关闭

  并且清除标识为纯色

  制定其渲染目标为RTT 

  清空其背景

  摄像机A在主摄像机渲染之前通过Shader去绘制指定渲染类型的GameObject   也就是需要描边的GameObject

  (即摄像机A.RenderWithShader(RTT, "XXXX");)

  ...... 

}

 

2、场景图像渲染之后 

void OnRenderImage(RenderTexture source, RenderTexture destination)

{

  ......

  将摄像机A所渲染的目标纹理进行blur处理

  将blur后的RTT与场景图像渲染后的RTT进行合成叠加

  拷贝到目的渲染纹理上

  ......

}

 

效果1  未被遮挡

效果2 被遮挡

效果3 描边相交  未被遮挡

效果4 描边相交  被遮挡

 

最后附上一张火炬之光2的轮廓描边效果  

unity实现起来要简单的多 不属于postprocess  

只需要对需要描边的物体写一个Rimlight边缘高光的shader即可  

国内好像有个unity制作的网页游戏也是用的这种方式描边

一下就是代码:

首先是主相机中的代码:

using UnityEngine;

public class GlowEffect : MonoBehaviour {
	
	public Material glowMaterial;
	public Shader glowReplaceShader;
	
	// Toggle between using the object's alpha channel for glow. This setting is good for mobile devices - 
	// it uses less memory and doesn't cause as many draw calls though it uses the object's alpha channel.
	public bool useAlphaChannelForGlow = false;
	
	// Toggle between using the simple glow effect. This setting is good for older mobile devices. 
	// sIt further reduces the amount of memory required and the number of draw calls.
	public bool useSimpleGlow = false;
	
	// The number of times the glow texture should be blurred. The more blur iterations the wider the glow. This value is only used if useSimpleGlow is false.
	public int blurIterations = 4;
	
	// The distance of the samples taken for the blurred glow. Too big of a value will cause noise in the blur. This value is only used if useSimpleGlow is false. 
	public float blurSpread = 1.0f;
	
	// Multiplies the glow color by this value.
	public float glowMultiplier = 1.2f;

    // Multiplies the glow color by this color.
    public Color glowColorMultiplier = Color.white;
	
	[HideInInspector]
	public RenderTexture postEffectsRenderTexture;
	
	private RenderTexture cameraRenderTexture;
	private Camera shaderCamera;
	private RenderTexture replaceRenderTexture;
	private RenderTexture blurA;
	private RenderTexture blurB;
	
	public void OnEnable()
	{
		if (!useAlphaChannelForGlow) {
			replaceRenderTexture = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
			replaceRenderTexture.wrapMode = TextureWrapMode.Clamp;
			replaceRenderTexture.useMipMap = false;
			replaceRenderTexture.isPowerOfTwo = true;
			replaceRenderTexture.filterMode = FilterMode.Bilinear;
			replaceRenderTexture.Create();
			
			glowMaterial.SetTexture("_Glow", replaceRenderTexture);
						
			shaderCamera = new GameObject("Glow Effect", typeof(Camera)).GetComponent<Camera>();
			shaderCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
		}
		
		if (!useSimpleGlow) {
			blurA = new RenderTexture(256, 256, 0, RenderTextureFormat.ARGB32);
			blurA.wrapMode = TextureWrapMode.Clamp;
			blurA.useMipMap = false;	
			blurA.filterMode = FilterMode.Bilinear;
			blurA.Create();	
			
			blurB = new RenderTexture(256, 256, 0, RenderTextureFormat.ARGB32);
			blurB.wrapMode = TextureWrapMode.Clamp;
			blurB.useMipMap = false;	
			blurB.filterMode = FilterMode.Bilinear;
			blurB.Create();
				
			if (blurIterations % 2 == 0) {
				glowMaterial.SetTexture("_Glow", blurA);
			} else {
				glowMaterial.SetTexture("_Glow", blurB);
			}
        }

#if !UNITY_EDITOR && (UNITY_IPHONE || UNITY_ANDROID)
		// this will be used as the target texture so it can be blitted to another camera
		cameraRenderTexture = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
		cameraRenderTexture.wrapMode = TextureWrapMode.Clamp;
		cameraRenderTexture.useMipMap = false;
		cameraRenderTexture.isPowerOfTwo = false;
		cameraRenderTexture.filterMode = FilterMode.Bilinear;
		cameraRenderTexture.Create();
		
		camera.targetTexture = cameraRenderTexture;
		camera.depthTextureMode = DepthTextureMode.None;
		
		// create a render texture to blit to the final camera
		postEffectsRenderTexture = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
		postEffectsRenderTexture.wrapMode = TextureWrapMode.Clamp;
		postEffectsRenderTexture.useMipMap = false;
		postEffectsRenderTexture.isPowerOfTwo = false;
		postEffectsRenderTexture.filterMode = FilterMode.Bilinear;
		postEffectsRenderTexture.Create();
#endif

        glowMaterial.SetFloat("_BlurSpread", blurSpread);
        glowMaterial.SetFloat("_GlowMultiplier", glowMultiplier);
        glowMaterial.SetColor("_GlowColorMultiplier", glowColorMultiplier);
	}
	
	public void OnDisable()
	{
		glowMaterial.mainTexture = null;
		GetComponent<Camera>().targetTexture = null;
		DestroyObject(shaderCamera);
		DestroyObject(blurA);
		DestroyObject(blurB);
	}
	
	public void OnPreRender()
	{
		if (!useAlphaChannelForGlow) {
			shaderCamera.CopyFrom(GetComponent<Camera>());
			shaderCamera.backgroundColor = Color.clear;
			shaderCamera.clearFlags = CameraClearFlags.SolidColor;
			shaderCamera.renderingPath = RenderingPath.Forward;
			shaderCamera.targetTexture = replaceRenderTexture;
			shaderCamera.RenderWithShader(glowReplaceShader, "RenderType");
		}
	}
	
	// UNITY_IPHONE and UNITY_ANDROID can't use OnRenderImage because the source and destination
    // render texture are in RGB565 format and we need the alpha layer.
#if !UNITY_EDITOR && (UNITY_IPHONE || UNITY_ANDROID)
    public void OnPostRender()
	{
		calculateGlow(cameraRenderTexture, postEffectsRenderTexture);
	}
#else
	public void OnRenderImage(RenderTexture source, RenderTexture destination)
	{
		calculateGlow(source, destination);	
	}
#endif
	
	private void calculateGlow(RenderTexture source, RenderTexture destination)
	{
		if (!useSimpleGlow) {
			// blur
			if (useAlphaChannelForGlow) {
				Graphics.Blit(source, blurB, glowMaterial, 2);
			} else {
				Graphics.Blit(replaceRenderTexture, blurB, glowMaterial, 1);
			}
			for (int i = 1; i < blurIterations; ++i) {
				if (i % 2 == 0) {
					Graphics.Blit(blurA, blurB, glowMaterial, 1); 
				} else {
					Graphics.Blit(blurB, blurA, glowMaterial, 1);
				}
			}
			// calculate glow
			Graphics.Blit(source, destination, glowMaterial, 0);
		} else {
			Graphics.Blit(source, destination, glowMaterial, (useAlphaChannelForGlow ? 4 : 3));
		}	
	}
}

接着就是Glow Material材质中的Shader代码:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// Main shader which computes the glow effect
Shader "Glow Effect/Glow Effect" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}

    SubShader {
		Pass { // pass 0 - glow using glow texture
			name "Glow"
			ZTest Always Cull Off ZWrite Off
			Fog { Mode Off }
			Blend Off
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest 
	
			#include "UnityCG.cginc"
	
			uniform sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			uniform sampler2D _Glow;
			uniform float _GlowMultiplier;
			uniform float4 _GlowColorMultiplier;
			
			struct v2f {
				half4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				half2 uv1 : TEXCOORD1;
			};	
			
			v2f vert (appdata_img v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
		       	o.uv = v.texcoord;
		       	o.uv1 = v.texcoord;
		       	
				#if UNITY_UV_STARTS_AT_TOP
				if (_MainTex_TexelSize.y < 0) {
					o.uv1.y = 1 - o.uv1.y;
				}
				#endif
				
				return o;
			}
			
			half4 frag (v2f i) : COLOR
			{
				half4 mainTex = tex2D(_MainTex, i.uv);
				half4 glow = tex2D(_Glow, i.uv1) * _GlowMultiplier * _GlowColorMultiplier;				
				return mainTex + glow;
			}
			ENDCG 
		} 
		
		pass { // pass 1 - blur the main texture
		    name "SimpleBlur"
			ZTest Always Cull Off ZWrite Off
			Fog { Mode Off }
			Blend Off
		
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest 
			
			#include "UnityCG.cginc"
				
			uniform sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			uniform float _BlurSpread;
				
			struct v2f {
				half4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				half2 uv2[4] : TEXCOORD1;
			};	
				
			v2f vert (appdata_img v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
		       	o.uv = v.texcoord;
		       	
		       	o.uv2[0] = v.texcoord + _MainTex_TexelSize.xy * half2(_BlurSpread, _BlurSpread);					
				o.uv2[1] = v.texcoord + _MainTex_TexelSize.xy * half2(-_BlurSpread, -_BlurSpread);
				o.uv2[2] = v.texcoord + _MainTex_TexelSize.xy * half2(_BlurSpread, -_BlurSpread);
				o.uv2[3] = v.texcoord + _MainTex_TexelSize.xy * half2(-_BlurSpread, _BlurSpread);
				return o;
			}	
			
			half4 frag ( v2f i ) : COLOR
			{
				half4 blur = tex2D(_MainTex, i.uv ) * 0.4;
				blur += tex2D(_MainTex, i.uv2[0]) * 0.15;
				blur += tex2D(_MainTex, i.uv2[1]) * 0.15;
				blur += tex2D(_MainTex, i.uv2[2]) * 0.15;	
				blur += tex2D(_MainTex, i.uv2[3]) * 0.15;
				return blur;
			}
				 			
			ENDCG	
		}
		
		pass { // pass 2 - blur the main texture and multiple the rgb channels by the alpha 
			name "BlurandAlphaMultRGB"
			ZTest Always Cull Off ZWrite Off
			Fog { Mode Off }
			Blend Off
					
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest 
			
			#include "UnityCG.cginc"
				
			uniform sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			uniform float _BlurSpread;
				
			struct v2f {
				half4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				half2 uv2[4] : TEXCOORD1;
			};	
				
			v2f vert (appdata_img v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
		       	
		       	o.uv = v.texcoord;
		       	o.uv2[0] = v.texcoord + _MainTex_TexelSize.xy * half2(_BlurSpread, _BlurSpread);					
				o.uv2[1] = v.texcoord + _MainTex_TexelSize.xy * half2(-_BlurSpread, -_BlurSpread);
				o.uv2[2] = v.texcoord + _MainTex_TexelSize.xy * half2(_BlurSpread, -_BlurSpread);
				o.uv2[3] = v.texcoord + _MainTex_TexelSize.xy * half2(-_BlurSpread, _BlurSpread);
					
				return o;
			}	
	
			half4 frag ( v2f i ) : COLOR
			{
				half4 mainTex = tex2D(_MainTex, i.uv);
				mainTex *= mainTex.a * 0.4f;
				half4 blur = mainTex;
				
				mainTex = tex2D(_MainTex, i.uv2[0]);
				mainTex *= mainTex.a * 0.15;
				blur += mainTex;
				
				mainTex = tex2D(_MainTex, i.uv2[1]);
				mainTex *= mainTex.a * 0.15;
				blur += mainTex;
				
				mainTex = tex2D(_MainTex, i.uv2[2]);
				mainTex *= mainTex.a * 0.15;
				blur += mainTex;
				
				mainTex = tex2D(_MainTex, i.uv2[3]);
				mainTex *= mainTex.a * 0.15;
				blur += mainTex;
				
				return blur;
				
			}		
			ENDCG
		}
		
		pass { // pass 3 - blur the glow texture and apply that glow to the main texture 
			name "SimpleBlurandGlow"
			ZTest Always Cull Off ZWrite Off
			Fog { Mode Off }
			Blend Off
					
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest 
			
			#include "UnityCG.cginc"
				
			uniform sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			uniform sampler2D _Glow;
			uniform half4 _Glow_TexelSize;
			uniform float _GlowMultiplier;
			uniform float4 _GlowColorMultiplier;
				
			struct v2f {
				half4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				half2 uv1 : TEXCOORD1;
				half2 uv2[4] : TEXCOORD2;
			};	
				
			v2f vert (appdata_img v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
		       	
		       	o.uv = v.texcoord;
		       	o.uv1 = v.texcoord;
		       	o.uv2[0] = v.texcoord + _Glow_TexelSize.xy * half2(2.5,2.5);					
				o.uv2[1] = v.texcoord + _Glow_TexelSize.xy * half2(-2.5,-2.5);
				o.uv2[2] = v.texcoord + _Glow_TexelSize.xy * half2(2.5,-2.5);
				o.uv2[3] = v.texcoord + _Glow_TexelSize.xy * half2(-2.5,2.5);
				
				#if UNITY_UV_STARTS_AT_TOP
				if (_MainTex_TexelSize.y < 0) {
					o.uv1.y = 1 - o.uv1.y;
					o.uv2[0].y = 1 - o.uv2[0].y;
					o.uv2[1].y = 1 - o.uv2[1].y;
					o.uv2[2].y = 1 - o.uv2[2].y;
					o.uv2[3].y = 1 - o.uv2[3].y;
				}
				#endif
					
				return o;
			}	
	
			half4 frag ( v2f i ) : COLOR
			{	
				half4 blur = tex2D(_Glow, i.uv1 ) * 0.3;	
				blur += tex2D(_Glow, i.uv2[0]) * 0.175;	
				blur += tex2D(_Glow, i.uv2[1]) * 0.175;	
				blur += tex2D(_Glow, i.uv2[2]) * 0.175;
				blur += tex2D(_Glow, i.uv2[3]) * 0.175;
				blur *= _GlowMultiplier * _GlowColorMultiplier;
				
				return tex2D(_MainTex, i.uv) + blur;
			}		
			ENDCG
		}
		
		Pass { // pass 4 - apply a glow to the blurred main texture based on the alpha channel of the glow
			name "SimpleBlurGlowFromAlpha"
			ZTest Always Cull Off ZWrite Off
			Fog { Mode Off }
			Blend Off
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest 
			
			#include "UnityCG.cginc"
				
			uniform sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			uniform float _GlowMultiplier;
			uniform float4 _GlowColorMultiplier;
				
			struct v2f {
				half4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				half2 uv2[4] : TEXCOORD1;
			};	
				
			v2f vert (appdata_img v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos (v.vertex);
		       	
		       	o.uv = v.texcoord;
		       	o.uv2[0] = v.texcoord + _MainTex_TexelSize.xy * half2(2.5,2.5);					
				o.uv2[1] = v.texcoord + _MainTex_TexelSize.xy * half2(-2.5,-2.5);
				o.uv2[2] = v.texcoord + _MainTex_TexelSize.xy * half2(2.5,-2.5);
				o.uv2[3] = v.texcoord + _MainTex_TexelSize.xy * half2(-2.5,2.5);
				 
				return o;
			}	
	
			half4 frag ( v2f i ) : COLOR
			{
				half4 blur = tex2D(_MainTex, i.uv ) * 0.3;
				blur += tex2D(_MainTex, i.uv2[0]) * 0.175;
				blur += tex2D(_MainTex, i.uv2[1]) * 0.175;
				blur += tex2D(_MainTex, i.uv2[2]) * 0.175;
				blur += tex2D(_MainTex, i.uv2[3]) * 0.175;
				blur *= _GlowMultiplier * _GlowColorMultiplier;
			
				return tex2D(_MainTex, i.uv) + blur * blur.a;
			}	
			ENDCG
		}
	}

Fallback Off

}

然后就是glow Replace Shader代码(该部分代码主要用于勾画需要glow对象的轮廓):

Shader "Hidden/Glow Effect/Glow Replace" {
    SubShader
	{
        Tags { "RenderType" = "Glow" }
        Pass {
			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"

			uniform sampler2D _GlowTex;
			uniform float4 _GlowColorMult;

			half4 frag(v2f_img i) : COLOR
			{
				return tex2D(_GlowTex,i.uv) * _GlowColorMult;
			}
			ENDCG
        } 
    } 
    
    SubShader {
        Tags { "RenderType" = "Opaque" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "Transparent" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader
	{
        Tags { "RenderType" = "GlowTransparent" }
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
        
        Pass {
			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"
				
			uniform sampler2D _GlowTex;
			uniform sampler2D _MainTex;
			uniform float4 _GlowColorMult;
				
			half4 frag(v2f_img i) : COLOR
			{
				return half4((tex2D(_GlowTex,i.uv).rgb * _GlowColorMult) + .0001, tex2D(_MainTex,i.uv).a);
			}
				
			ENDCG
        } 
    }
    
    SubShader {
        Tags { "RenderType" = "TransparentCutout" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "Background" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "Overlay" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "TreeOpaque" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "TreeTransparentCutout" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "TreeBillboard" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "Grass" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }
    
    SubShader {
        Tags { "RenderType" = "GrassBillboard" }
        Pass {    
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest
            #include "UnityCG.cginc"
            half4 frag(v2f_img i) : COLOR
            {
                return half4(0,0,0,0);
            }
            ENDCG
        }
    }	
	Fallback Off
}

最后的就是Golw对象本身的Shader代码:

// A simple unlit shader. _GlowTex is not used in this shader but it is used by the replacement shader.
Shader "Glow Effect/Glow"
{
	Properties
	{
		_MainTex ("Main Texture", 2D) = "white" {}
		_GlowTex ("Glow Texture", 2D) = "white" {}
		_GlowColorMult ("Glow Color Multiplier", Color) = (1, 1, 1, 1)
	}
    
    SubShader
	{
        Tags { "RenderType" = "Glow" "Queue" = "Geometry" }
        
        Pass {
        
			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"
			
			uniform sampler2D _MainTex;
			
			half4 frag(v2f_img i) : COLOR
			{
				return tex2D(_MainTex,i.uv);
			}
			
			ENDCG
        } 
    } 
	
	Fallback "Diffuse"
}

结束。实现之后呈现的效果是这样的:

Unity URP Sprite动态描边与发光ShaderGraph实战:高性能与抗锯齿方案 在游戏开发与图形渲染中,Shader是实现视觉特效的核心技术,它通过编写程序直接控制GPU的渲染管线,从而高效地处理像素与顶点数据。其原理在于对纹理采样、颜色计算和混合模式进行精细操控,以实现丰富的视觉效果。Shader的技术价值在于能以极低的CPU开销,实现诸如动态光照、后处理、风格化渲染等复杂效果,是提升游戏画面表现力的关键。在2D/3D游戏、UI界面和影视特效等应用场景中,Shader被广泛用于角色描边、发光光晕、水面折射等效果。本文聚焦于Unity URP管线下的Sprite渲染,针对移动端性能优化 阅读详情

相关推荐

Unity描边技术全解析:从法线外扩到屏幕空间边缘检测实战

描边(Outline)是计算机图形学中用于勾勒物体轮廓、增强视觉层次的核心技术。其基本原理是通过识别模型或场景中的边缘信息,在轮廓处叠加一层颜色或特效。从早期的顶点法线外扩,到如今主流的屏幕空间深度/法线边缘检测,描边技术的演进始终围绕着性能、质量和平台兼容性的平衡。在实时渲染领域,高效的描边方案能显著提升交互反馈的清晰度与视觉风格的表现力,广泛应用于游戏角色高亮、卡通渲染(Cel-Shading)、场景视觉引导以及UI特效等场景。本文聚焦于Unity引擎,深入剖析包括法线外扩、屏幕空间后处理在内的多种主流

weixin_30776545的博客 284

three.js实现物体描边效果-shader

three.js 实现物体描边效果-shader 在游戏中描边效果非常常见,比如选中物体或者人物的时候会出现。 描边效果的原理是在物体的外包包裹了一层,就需要描边的物体比实际的物体大一点点。所以需要牵涉到顶点,就是需要把物体顶点往法线的方向扩展一点点。需要修改vertexShader。 ...

X01动力装甲的专栏 7901

Unity URP高亮系统配置与优化:Highlight Plus V21实战指南

在Unity游戏开发中,物体高亮是实现交互反馈、任务指引和技能特效的核心视觉技术。其原理通常基于屏幕后处理或轮廓渲染,通过修改深度、法线或颜色缓冲区来增强目标物体的视觉显著性。这项技术的价值在于提升用户体验的直观性和沉浸感,广泛应用于角色选中、道具提示、敌人锁定等游戏交互场景。本文聚焦于Unity URP(通用渲染管线)环境下,如何高效配置与优化Highlight Plus V21插件,解决高亮效果不显示、性能开销大等常见问题,并深入探讨模糊迭代(Blur Passes)和渲染器特性(Renderer Fe

cqwmy840702的博客 2242

Glow + Outline 轮廓描边

轮廓描边是游戏中的细节  然则一个有特点的结果还是会让人面前一亮 Glow + Outline 的结果就像求生之路2和暗黑3的轮廓描鸿沟一样  对轮廓描边后再进行模糊处理惩罚 如图: 求生之路2   暗黑3    一种思路为: 1、在RTT中绘制单一像素 2、对1绘制后的RTT进行blur处理惩罚 3、对2处理惩罚后的RTT...

weixin_34378767的博客 305

text-shadow底层原理:渲染机制、高斯模糊与可访问性实践

text-shadow是CSS中唯一能对文本轮廓进行像素级独立渲染干预的原生属性,其本质并非简单装饰,而是触发浏览器图层合成阶段的Alpha混合操作。它依赖offset位移、blur-radius驱动的高斯模糊核采样(σ=blur/2)以及rgba透明度通道实现深色模式适配、动态主题过渡和WCAG合规性增强。相比box-shadow作用于盒模型,text-shadow仅影响文本位图,性能更优但不支持inset。在网页性能优化、设计系统建设及前端面试中,理解其合成层定位、多层叠加逻辑与跨浏览器差异(如Chro

weixin_30387423的博客 435

Unity后处理实现赛博朋克风格Spine动画外发光技术详解

在游戏开发中,后处理技术通过在渲染管线末端对屏幕图像进行全局处理,能显著提升视觉表现力。其核心原理是利用GPU对颜色缓冲区进行滤镜式加工,例如通过亮度阈值提取、高斯模糊等算法模拟真实的光学现象。这项技术的核心价值在于能以非侵入式方式,为游戏画面添加丰富的风格化效果,且参数可控性极强。在2D游戏开发领域,结合Spine骨骼动画系统,后处理技术能突破传统精灵叠加的限制,实现高质量的风格化外发光效果。本文聚焦于利用Unity后处理堆栈,为Spine动画元素动态附加赛博朋克风格的霓虹光晕,通过分层渲染与自定义Sha

weixin_30629653的博客 478

threejs 卷积描边处理

threejs 一个好用的自定义描边

Zz10566的博客 972

Unity交互高亮实战:Highlight Plus插件核心原理与性能优化指南

在Unity应用开发中,视觉反馈是提升用户体验的关键环节,它通过即时、清晰的交互响应,构建用户与虚拟世界的沟通桥梁。其核心原理通常涉及图形渲染管线,通过着色器(Shader)或后处理技术,在不修改原始模型的前提下,叠加轮廓、发光等视觉效果。这项技术的核心价值在于显著增强交互的直观性与沉浸感,广泛应用于游戏角色选中、场景可交互物体提示、数据可视化焦点突出等场景。针对实现过程中的性能挑战,如Draw Call优化与多渲染管线(URP/HDRP)兼容性,开发者常借助成熟的插件方案。本文以Highlight Plu

weixin_30530939的博客 413

THREE.js同时使用outlinePass和TransformControls,选中其他物体时,TransformControls辅助对象也加上了描边

使用this.scene时,选中其他物体时,transformControls描边显示。使用group时,选中其他物体时,transormControls控件就没有描边了。

qq_43999459的博客 875

Unity中2D Spine角色外发光与Bloom效果实现全解析

在2D游戏开发中,Shader是实现高级视觉特效的核心技术之一,它通过GPU编程直接控制像素的渲染过程。其基本原理是通过编写特定的着色器程序,对模型的顶点、纹理、光照等信息进行处理,从而生成丰富的画面效果。这项技术的核心价值在于能够突破固定渲染管线的限制,实现高度定制化的视觉效果,同时保持较高的运行效率。在游戏开发领域,Shader广泛应用于角色特效、场景氛围营造和UI动效等场景。本文聚焦于2D Spine角色的视觉增强,深入探讨如何通过自定义Shader实现基于Alpha通道扩张的外发光效果,并结合URP

diaoju3333的博客 551

最好用描边shader

在网上找到的在unity中使用最好的描边着色器shader。该文件里面总共有12个项目,2个为一组,共有6种表面着色器shader。 【功能】改着色器成功的解决了一般的描边shader存在有以下问题: 1,会丢失原来的材质 2,效果不好 【使用方法/注意事项】 1,文件夹需要保存在英文路径下,路径中不能包含中文字符 2,在导入时候,一个shader包含两个文件:xxx.shader和xxx.shader.meta.shader。这两个文件需要同时拖动到Assets下面包含的目录下

(转)【Unity3d】Glow + Outline 轮廓描边

转:http://www.cnblogs.com/dosomething/archive/2012/08/04/2622488.html 【Unity3d】Glow + Outline 轮廓描边 轮廓描边是游戏中的细节 但是一个有特色的效果还是会让人眼前一亮 Glow + Outline 的效果就像求生之路2和暗黑3的轮廓描边界一样 对轮廓描边后再进行模糊处理 如图: 求生之路...

weixin_30391339的博客 218

DIY天文摄影:如何用NMP溶剂安全去除佳能CMOS传感器的拜耳滤镜(附详细步骤)

本文为天文摄影爱好者提供了一份详尽的DIY指南,介绍如何使用NMP溶剂安全去除佳能CMOS传感器的拜耳滤镜,将其改造为高灵敏度单色相机。文章深入剖析了NMP溶剂的作用原理与关键风险,并系统性地拆解了从材料准备、分步操作到后期验证的完整实践流程,旨在帮助具备动手能力的爱好者实现深空天体摄影的进阶目标。

w3x4y的博客 308

Unity游戏开发:从零实现高性能后处理轮廓系统

在游戏开发中,轮廓渲染(Outline Rendering)是一种通过高亮物体边缘来增强视觉反馈和交互清晰度的关键技术。其核心原理通常基于图像处理中的边缘检测算法,通过分析深度、法线或物体ID信息的突变来识别边界。这项技术的价值在于能显著提升游戏的专业度和用户体验,广泛应用于角色选中、物品高亮、技能指示和解谜提示等场景。本文聚焦于Unity引擎,深入探讨了基于屏幕后处理(Post-processing)的轮廓系统实现方案,该方案通过渲染独立的轮廓遮罩图(ID Map)并利用Sobel算子进行边缘检测,实现了

weixin_33747129的博客 338

【Codesys】-扫描添加失败,手动添加第三方模块,真·DC模式的高速计数模块

欧姆龙耦合器(NX-ECC201)和高速计数模块(NX-EC0132)单独使用。扫描设备添加到Codesys中,会报错,无法自动添加。记录一下,以防忘记。高速的计数保证了位置的准确性,位置准确就能保证裁切的精度,一切的基础就在这儿了,奈何目前只有欧姆龙和倍福能做到这样的波形。

qq_35316470的博客 1388

Chapter 19 Digital Phase-Locked Loops

数字锁相环 Digital Phase-Locked Loops, 就是根据原来时钟信号, 产生新的时钟信号, which is locked or synchronized. (align 参考时钟边沿 or 在中间)

2304_76736886的博客 973

Unity高亮插件Highlight Plus:从原理到实战的性能优化指南

在游戏开发中,视觉反馈是提升用户体验的关键环节,其中物体高亮与描边效果是实现交互引导的核心技术。其原理通常基于屏幕后处理,通过深度与法线缓冲区检测边缘,或利用高斯模糊算法生成发光效果,从而在几乎不增加Draw Call的前提下实现高效渲染。这项技术的核心价值在于,它能够将复杂的图形学计算封装为易用的工具,显著降低开发门槛,并确保在移动端、VR等性能敏感场景下的流畅运行。在实际应用中,高亮效果广泛用于标识可交互物品、角色选中状态、技能范围提示以及解决视觉遮挡问题。本文以Unity Asset Store中广受

weixin_34416754的博客 434

单细胞测序数据分析——细胞通讯 CellChat

cellchat

G2530051386的博客 1万+

Unity URP高亮方案:Highlight Plus插件核心功能与实战配置指南

在Unity游戏开发中,视觉反馈系统是提升用户体验的关键环节,其中物体高亮效果常用于交互提示、目标指示等场景。其实现原理主要分为材质替换、几何体外扩和屏幕后处理三大技术路径。基于URP渲染管线的后处理方案,通过插入自定义Render Feature,利用深度与法线缓冲区进行边缘检测与图像处理,实现了非侵入式、效果统一且性能可控的高亮层。这一技术价值在于能显著提升项目的视觉品质与交互流畅度,尤其适用于角色扮演、动作冒险等需要强视觉引导的游戏类型。本文聚焦的Highlight Plus插件,正是这一方案的优秀实

weixin_33827590的博客 337

高通平台开发系列讲解(系统篇)系统关机流程

📢本篇章主要图解高通平台系统关机流程。

内核笔记 3212

Unity发光Shader六种效果原理与工程实践

发光效果是实时渲染中基础且高频的视觉传达技术,其本质涉及视角-法线夹角判别、深度缓冲差值计算、屏幕空间模糊、顶点几何位移等核心图形学原理。理解Rim Light边缘光、Inner Glow内发光、Outer Glow外发光等不同实现路径的技术差异,有助于构建稳定、可复用、跨平台兼容的Shader系统。在Unity URP管线中,正确处理ZWrite开关、深度采样精度、Alpha混合模式及多Pass渲染顺序,直接决定发光是否穿模、是否过曝、是否适配移动端。本文聚焦于六类典型发光效果的底层机制解析与参数工程化配

weixin_33847182的博客 182

手把手教你学Simulink——基于Simulink的全双工无线通信仿真建模示例

目录手把手教你学Simulink——基于Simulink的全双工无线通信仿真建模示例一、背景介绍二、所需工具和环境三、步骤详解步骤1:创建Simulink模型步骤2:设计输入信号步骤3:添加调制模块步骤4:添加自干扰消除模块步骤5:添加AWGN信道步骤6:添加接收端处理步骤7:添加解调模块步骤8:计算误码率(BER)步骤9:添加显示模块步骤10:设置仿真参数步骤11:运行仿真并分析结果四、总结 全双工(Full-Duplex)无线通信技术允许在同一频段上同时进行数据的发送和接收,这与传统的半双工(Half-

MHD0815的博客 182

Unity URP高亮效果实战:Highlight Plus V21配置与性能优化指南

在Unity游戏开发中,物体高亮与轮廓描边是常见的交互反馈技术,用于提示玩家选中、悬停或可交互状态。其核心原理通常基于屏幕后处理或模板缓冲技术,通过提取物体的深度与法线信息,在屏幕空间生成平滑的轮廓边缘。相比传统的全屏后处理方案,基于模板缓冲和深度-法线缓冲的现代渲染方法能有效避免边缘闪烁和深度穿透问题,显著提升性能与稳定性。这一技术在高频交互的VR/AR应用、RTS游戏以及3D解谜项目中具有重要价值,能够增强用户体验与操作直观性。本文以Unity URP管线和Highlight Plus V21资源为例,

chongkuachan8070的博客 408

【Java 实战】通过Redis实现购物车功能

以上就是今天要讲的内容,本文仅仅简单介绍了如何通过Redis实现购物车功能,以上方法亲测有效,希望能给大家一个参考。

~~~~~~~BUG FLY~~~~~~~~~ 9969

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: GitLab服务器搭建(Win10系统企业版,在Docker上部署GitLab的搭建)
下一篇: unity shader _MainTex_TexelSize 和 UNITY_UV_STARTS_AT_TOP 的作用
MonoBehaviour
博客等级 码龄10年 22粉丝 48原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值