UnityShader应用——外发光实现

本文详细介绍了如何在Unity中使用Shader实现物体的外发光效果,包括通过调整法线方向顶点进行颜色计算的方法,以及如何将内外发光效果进行合成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习了一下实现物体外发光的Shader。分成两个Pass进行,第一个Pass渲染物体正面,剔除背面;第二个Pass渲染背面(剔除正面),通过扩展法线方向顶点,在进行颜色计算。
在这里插入图片描述

实现外发光的Pass
	//pass2 生成模型外部的光晕
		Pass
		{
			Name "OutLight"
			Tags {"LightMode" = "Always"}
			Cull Front     //不正面剔除会出错
			Blend SrcAlpha One

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			uniform float _Size;
			uniform float4 _AtmoColor;
			uniform float _OutLightPow;
			uniform float _OutLightStrength;

			struct v2f
			{	
				float3 normal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float4 vertex : SV_POSITION;
			};

			v2f vert(appdata_base v) 
			{
				v2f o;
				v.vertex.xyz += v.normal * _Size;    //进行法线方向的扩展
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.normal = v.normal;
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : COLOR
			{
				i.normal = normalize(i.normal);
				//视角观察方向
				float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);
				
				float4 color = _AtmoColor;

				color.a = pow(saturate(dot(viewDir, i.normal)), _OutLightPow);
				color.a *=  _OutLightStrength * dot(viewDir, i.normal);
				return color;
			}
			ENDCG
		}
将渲染队列设置为透明

在这里插入图片描述
如果不设置透明队列会出现下图这样的情况:
在这里插入图片描述

将Pass写进之前的内发光Shader中进行合成

内外发光合成效果是这样:
在这里插入图片描述

最后附上合成的Shader代码
Shader "Unlit/OutAndRimLight"
{
	Properties{
		_SpecularGlass("SpecularGlassStrength", Range(0,64)) = 32
		_ObjColor("ObjColor", color) = (1,1,1,1)
		_RimColor("RimColor", color) = (1,1,1,1)
		_RimStrength("RimStrength", Range(0.0001,3.0)) = 0.1

		_AtmoColor("Atmosphere Color", Color) = (0, 0.4, 1.0, 1)
		_Size("Size", Float) = 0.1
		_OutLightPow("LightPow", Float) = 5
		_OutLightStrength("Strength", Float) = 15
	}
		SubShader
	{


		Pass  //pass1 实现rim和贴图颜色
	{
		Tags{ "RenderType" = "Opaque" }

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		
		#include "UnityCG.cginc"
		#include "Lighting.cginc"

		struct appdata
	{
		float4 vertex : POSITION;
		float3 normal : NORMAL;
	};

	struct v2f
	{
		float3 worldNormal:NORMAL;
		float4 vertex : SV_POSITION;
		float3 worldPos : TEXCOORD1;
	};

	v2f vert(appdata_base v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
		o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		return o;
	}

	float _SpecularGlass;
	fixed4 _ObjColor;

	fixed4 _RimColor;
	float _RimStrength;

	fixed4 frag(v2f i) : SV_Target
	{
		fixed3 worldNormal = normalize(i.worldNormal);

	fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

	fixed3 diffuse = max(0.0, dot(worldNormal, worldLightDir));

	fixed3 diffuseColor = diffuse  * _LightColor0.xyz;

	//计算reflect方向
	fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
	//计算视角方向
	fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
	//specular分量
	fixed3 specular = pow(max(0.0, dot(reflectDir, viewDir)), _SpecularGlass);

	fixed3 specularColor = specular * _LightColor0.xyz;

	//环境光
	fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * _ObjColor;

	//RimLight
	fixed3 worldViewDir = normalize(viewDir);

	float rim = 1 - max(0, dot(worldViewDir, worldNormal));

	fixed3 rimColor = _RimColor * pow(rim, 1 / _RimStrength);


	return fixed4(diffuseColor + specularColor + ambient + rimColor, 0);
	}

		ENDCG
	}
	
	Pass  //pass2 实现OutLight
	{
		Name "AtmosphereBase"
		Tags{ "LightMode" = "Always" }
		
		Cull Front
		Blend SrcAlpha One

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"

		uniform float _Size;
		uniform float4 _AtmoColor;
		uniform float _OutLightPow;
		uniform float _OutLightStrength;

		struct v2f
		{
			float3 normal : TEXCOORD0;
			float3 worldPos : TEXCOORD1;
			float4 vertex : SV_POSITION;
		};

		v2f vert(appdata_base v)
		{
			v2f o;
			v.vertex.xyz += v.normal * _Size;
			o.vertex = UnityObjectToClipPos(v.vertex);
			o.normal = v.normal;
			o.worldPos = mul(unity_ObjectToWorld, v.vertex);
			return o;
		}
	
		fixed4 frag(v2f i) : COLOR
		{
			i.normal = normalize(i.normal);
			//视角观察方向
			float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);

			float4 color = _AtmoColor;

			color.a = pow(saturate(dot(viewDir, i.normal)), _OutLightPow);
			color.a *= _OutLightStrength*dot(viewDir, i.normal);
			return color;
		}
		ENDCG
	}
}
}

参考:
https://blog.youkuaiyun.com/v_xchen_v/article/details/78262919

### 如何在 Unity URP 中添加和配置发光效果 #### 创建并配置 URP 项目 为了确保能够顺利实现 Sprite 的发光效果,需确认当前使用的 Unity 版本为 2019.4 或更高版本,并且已经安装 Universal Render Pipeline (URP)[^3]。 #### 导入必要的资源包 对于想要快速集成发光效果的开发者来说,可以直接利用现成的 ShaderGraph 资源来简化开发过程。通过官方 Asset Store 或其他可信渠道下载包含所需功能的 ShaderGraph 文件,并按照提示将其导入至现有工程内[^2]。 #### 构建自定义着色器节点图 如果倾向于手动定制发光逻辑,则可以借助于 Unity 提供的强大工具——Shader Graph 来构建专属的效果。打开 Shader Graph 编辑窗口后,在其中加入合适的输入变量(例如顶点颜色、纹理坐标),并通过一系列运算操作最终输出带有辉光特性的像素色彩值[^1]。 ```csharp // 示例代码片段展示如何获取光照方向向量作为后续计算的基础之一 Vector3 lightDir = normalize(_MainLightPosition.xyz); ``` #### 设置材质属性 完成上述工作之后,下一步就是基于新创建好的 ShaderGraph 定义相应的 Material 对象了。选中目标物体所关联的标准 Unlit/Lit 类型材料球体,切换其对应的 Shader 字段指向刚才保存下来的自定义图形化脚本路径下;接着依据实际需求调节公开可调用参数列表里的各项数值设定,比如亮度等级、模糊半径等,直至满意为止。 #### 应用于场景对象 最后一步便是把精心准备过的 Materail 实例赋予待处理的游戏组件之上。这通常涉及到拖拽方式或是编程接口两种途径的选择。无论是哪种方法都能有效达成目的,即让选定范围内的精灵图像呈现出令人愉悦的部轮廓光芒散发现象。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值